请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 482|回复: 5
收起左侧

[有问必答] 请教407的SD卡读写问题

[复制链接]

32

主题

102

回帖

198

积分

初级会员

积分
198
发表于 2023-5-26 14:29:00 | 显示全部楼层 |阅读模式
看了ST官方代码,有一些疑问。
SD_PowerON 函数里有语句


问题一:发送ACMD41之前要发送CMD55,CMD55的作用是告诉卡,下个命令是特定应用命令,而不是标准
命令。 那前面这个地方光发一个CMD55,没有发ACMD,那这个CMD55什么用?

这是最难理解的

[C] 纯文本查看 复制代码
if (errorstatus == SD_OK)
  {//这个和下面ACMD41有关
    CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /*!< SD Card 2.0 */
    SDType = SD_HIGH_CAPACITY;
  }
  else
  {
    /*!< CMD55 */
    SDIO_CmdInitStructure.SDIO_Argument = 0x00;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);
    errorstatus = CmdResp1Error(SD_CMD_APP_CMD);
  }
  /*!< CMD55   这个地方光发一个CMD55,没有发ACMD,[size=5][color=#000000][b]那这个CMD55什么用[/b][/color][/size]*/
  SDIO_CmdInitStructure.SDIO_Argument = 0x00;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
  errorstatus = CmdResp1Error(SD_CMD_APP_CMD);

  /*!< If errorstatus is Command TimeOut, it is a MMC card */
  /*!< If errorstatus is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch)
     or SD card 1.x */
  if (errorstatus == SD_OK)
  {
    /*!< SD CARD */
    /*!< Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
    while ((!validvoltage) && (count < SD_MAX_VOLT_TRIAL))
    {
//[color=#8250df]发送ACMD41之前要发送CMD55,这个理解[/color]
      /*!< SEND CMD55 APP_CMD with RCA as 0 */
      SDIO_CmdInitStructure.SDIO_Argument = 0x00;
      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);

      errorstatus = CmdResp1Error(SD_CMD_APP_CMD);

      if (errorstatus != SD_OK)
      {
        return(errorstatus);
      }
//      ((uint32_t)0x80100000) ((uint32_t)0x40000000)参数如上
//给OCR的21位 30 31位写入1 21位为电压3.3——3.4
      SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType;
      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_OP_COND;
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);
//ACMD41的响应是R3,就是OCR寄存器
      errorstatus = CmdResp3Error();
      if (errorstatus != SD_OK)
      {
        return(errorstatus);
      }



问题二:不知道为什么用这种方式开启时钟,而且函数内部是用位带操作,前面SD_LowLevel_Init中已经用RCC_APB2PeriphClockCmd打开时钟了



[C] 纯文本查看 复制代码
 /*!< Enable SDIO Clock */
  SDIO_ClockCmd(ENABLE);//
函数内部
*(__IO uint32_t *) CLKCR_CLKEN_BB = (uint32_t)NewState;
/* Alias word address of CLKEN bit */
#define CLKCR_OFFSET              (SDIO_OFFSET + 0x04)
#define CLKEN_BitNumber           0x08
#define CLKCR_CLKEN_BB            (PERIPH_BB_BASE + (CLKCR_OFFSET * 32) + (CLKEN_BitNumber * 4))


问题三:为什么WAITRESP的00、10对应同样的内容,是印刷错误吗?
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_Wait_No是0x00000000,
对应RM手册寄存器
Bits 7:6 WAITRESP: Wait for response bits
They are used to configure whether the CPSM is to wait for a response, and if yes, which
kind of response.
00: No response, expect CMDSENT flag
01: Short response, expect CMDREND or CCRCFAIL flag
10: No response, expect CMDSENT flag
11: Long response, expect CMDREND or CCRCFAIL flag
问题四:为什么ACMD41保留位,也就是最高位是1,如代码所示
[C] 纯文本查看 复制代码
SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType;
#define SD_VOLTAGE_WINDOW_SD            ((uint32_t)0x80100000)

发送卡的支持信息(HCS),并要求卡通过命令线返回 OCR 寄存器内容。当卡收到 SEND_IF_COND 时,HCS 是有效的。保留位设为 0。CCS 位对应 OCR[30]
保留位应该是0啊。

问题四:清除static flag 为什么SDIO_STATIC_FLAGS的值没有覆盖SDIO_ICR寄存器里的全部位呢?
[C] 纯文本查看 复制代码
 /*!< Clear all the static flags */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);
#define SDIO_STATIC_FLAGS               ((uint32_t)0x000005FF)
[color=#24292f][backcolor=#ffffff][color=#8250df]SDIO[/color][color=#24292f]->[/color][color=#24292f]ICR[/color][color=#24292f] [/color][color=#b35900]=[/color][color=#24292f] [/color][color=#8a4600]SDIO_FLAG[/color][color=#24292f];[/color]
[/backcolor][/color]

0x5FF的二进制是0101 1111 1111,和ICR寄存器对应不起来啊

















回复

使用道具 举报

32

主题

102

回帖

198

积分

初级会员

积分
198
 楼主| 发表于 2023-5-26 16:06:17 | 显示全部楼层
问题5:读取SCR寄存器的时候为什么要这样写
[C] 纯文本查看 复制代码
while (!(SDIO->STA & (SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR)))
  {
    if (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
    {
      *(tempscr + index) = SDIO_ReadData();
      index++;
    }
  }

*(pscr + 1) = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) | ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24);

  *(pscr) = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) | ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24);


从fifo读的数据tempscr[0]赋值给了pscr[1],反过来的。FIFO先进先出,如果SD卡按顺序发过来F1,F2,那在读的时候tempscr[0] = F1   tempscr[1] = F2,顺序是正确的,为什么要反过来呢?另外后面各种移位运算,相当于进行了一次高位字节和低位字节的调换,和大小端有关?但是FIFO是32位宽的啊。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105942
QQ
发表于 2023-5-26 16:06:34 | 显示全部楼层

帮顶,我没有研究过SD驱动,都是直接用的官方驱动。

看HAL库的SD驱动,对比下,是否符合规范。

https://github.com/STMicroelectr ... /stm32f4xx_hal_sd.c

回复

使用道具 举报

32

主题

102

回帖

198

积分

初级会员

积分
198
 楼主| 发表于 2023-5-27 10:08:12 来自手机 | 显示全部楼层
eric2013 发表于 2023-5-26 16:06
帮顶,我没有研究过SD驱动,都是直接用的官方驱动。

看HAL库的SD驱动,对比下,是否符合规范。

我看你的发送,接收的dma配置经过优化了,buffersize和对齐方式都和官方驱动不一样,没搞懂什么原理。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105942
QQ
发表于 2023-5-27 10:24:09 | 显示全部楼层
伊森亨特 发表于 2023-5-27 10:08
我看你的发送,接收的dma配置经过优化了,buffersize和对齐方式都和官方驱动不一样,没搞懂什么原理。

第9条。

【烧脑技术贴】无法回避的字节对齐问题,从八个方向深入探讨(变量对齐,栈对齐,DMA对齐,结构体成对齐,Cache, RTOS双堆栈等)
https://www.armbbs.cn/forum.php? ... 9400&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

32

主题

102

回帖

198

积分

初级会员

积分
198
 楼主| 发表于 2023-5-30 11:10:08 | 显示全部楼层
问题一,多发送一次CMD55,我测试了一下,去掉了一个发送CMD55的过程,读写1个块还是正常的,SD卡可以正常初始化。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-3-29 17:06 , Processed in 0.368875 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表