由于 CRC 失败,SD 卡通过 SDIO 总线初始化出现问题
我有一个基于 ST MicroElectronics STM32F103VE 微控制器的定制板,并在微控制器的 SDIO 总线上插入了 MiniSD 卡。电气连接完全按照STM3210E-EVAL 板原理图,检查并重新检查,所以我坚信它们是正确的。不幸的是,我没有那个评估板来测试我遇到的是否是硬件问题,但看起来并非如此。对于下面的测试,我使用最近购买的金士顿 2 GB MicroSD 卡(型号 MBLYG2/2GB)(因此它应该符合最新的 SD 卡规格)以及随附的 MicroSD 转 MiniSD 适配器;尚未测试任何其他卡。
我遵循 SD 卡物理层简化规范来了解发生了什么。我使用的代码是 ST Micro 针对该微控制器的标准外设库附带的示例 SDIO 代码。它首先发送 CMD0 (GO_IDLE_STATE),然后发送 CMD8 (SEND_IF_COND),然后发送 ACMD41 (SD_SEND_OP_COND),这是通过发送 CMD55 (APP_CMD) 再发送 CMD41 来完成的。时钟线的时钟频率为 400 kHz,作为调试工作的一部分,我在 CMD0 和 CMD8 之间添加了大约 100 个时钟周期的延迟,因为我在某处读到过,至少在 SPI 中操作时需要这样做模式。除了下面提到的修改之外,代码与示例代码完全相同。
当我第一次尝试运行示例代码时,CMD55 遇到了一个问题,这恰好是因为微控制器正在缓冲对 CMD8 的响应,但示例代码没有检索 CMD8 的响应,因此在检查对 CMD55 的响应时,代码是实际上查看了对 CMD8 的响应并对此感到不安。我通过在发送 CMD55 之前清除微控制器的 SDIO 外设上的 CMDREND 标志来解决此问题,因此当代码检查对 CMD55 的响应时,它不再缓冲 CMD8 的响应。
下一个问题,也是我目前遇到的问题,是在对 CMD55 的响应中,卡状态字段 (COM_CRC_ERROR) 的第 23 位被设置,这表明根据规范,前一个命令的 CRC 检查失败。虽然微控制器自动计算 CRC,但我将逻辑分析仪连接到电路以验证其是否正确。我正在使用一个网络应用程序(抱歉,无法链接,因为我是新用户,但只是 Google 搜索“CRC ghsi”,这是第一个结果)使用多项式 x^7 + x^ 来验证 CRC 3 + 1 根据规格。这是逻辑分析仪的输出,由我格式化和注释:
// uC sends CMD0, CRC OK, no response:
01 000000 00000000000000000000000000000000 1001010 1
// uC sends CMD8, CRC OK, check byte = 0xAA:
01 001000 00000000000000000000000110101010 1000011 1
// SD card responds to CMD8, CRC OK, check byte echoed back = 0xAA:
00 001000 00000000000000000000000110101010 0001001 1
// uC sends CMD55, CRC OK:
01 110111 00000000000000000000000000000000 0110010 1
// SD card responds to CMD55, CRC OK, note card status bits 23, 8 and 5 set;
// bit 23 = COM_CRC_ERROR, bit 8 = READY_FOR_DATA and bit 5 = APP_CMD:
00 110111 00000000100000000000000100100000 0000100 1
另请注意,如果我在上述交换后立即第二次尝试 CMD55,则位 23 未设置:
// uC sends CMD55, CRC OK:
01 110111 00000000000000000000000000000000 0110010 1
// SD card responds to CMD55, CRC OK, bits 8 and 5 still set but 23 not set:
00 110111 00000000000000000000000100100000 1000001 1
请注意,我在发送 CMD55 之前尝试发送 CMD8 两次,但没有任何区别,第一个 CMD55 始终返回设置的位 23。我每次尝试都能重现这一点,所以我不认为这是故障或噪音的问题。考虑到 CRC 是由微控制器本身计算的,从外部实体(逻辑分析仪)看来它们看起来是正确的,并且已经在我上面提到的网站上进行了验证,我不认为卡的 CRC 检查会失败。
这在某种程度上是预料之中的吗?也许我应该在每个命令之间等待一定数量的时钟周期(我在某处读到它应该是 8 个周期,我相信我尊重这一点)?如果第一个 CMD55 失败并且仍在路上,我可以只发送第二个 CMD55,还是会产生任何负面后果?即使这解决了问题,我也非常想知道为什么 CRC 检查失败,因为我不认为我做错了什么。
I have a custom board based on an ST Microelectronics STM32F103VE microcontroller, with a MiniSD card plugged over the microcontroller's SDIO bus. The electrical connections were done exactly as found in the STM3210E-EVAL board schematics, checked and rechecked so I have strong confidence they are correct. Unfortunately I don't have that eval board to test whether what I'm experiencing is a hardware problem, but it doesn't seem so. For the tests below, I'm using a Kingston 2 GB MicroSD card (model MBLYG2/2GB) bought very recently (so it should comply with the newest SD card spec) with the supplied MicroSD to MiniSD adapter; haven't tested with any other cards yet.
I'm following the SD card physical layer simplified spec to understand what's going on. The code that I'm using is the example SDIO code that comes with ST Micro's standard peripheral library for this microcontroller. It starts out by sending CMD0 (GO_IDLE_STATE), then CMD8 (SEND_IF_COND), and then ACMD41 (SD_SEND_OP_COND), which is done by sending a CMD55 (APP_CMD) followed by CMD41. The clock line is clocked at 400 kHz, and as part of my debugging efforts, I've added a delay of about 100 clock cycles between CMD0 and CMD8, as I've read somewhere that it was required, at least when operating in SPI mode. Other than the modifications mentioned below, the code is exactly the same as the example code.
When I first tried to run the example code, CMD55 had a problem which happened to be because the microcontroller was buffering the response to CMD8, but the sample code didn't retrieve CMD8's response, so when checking the response to CMD55, the code was actually looking at the response to CMD8 and was upset by that. I fixed this problem by clearing the CMDREND flag on the microcontroller's SDIO peripheral before sending out CMD55, so when the code checked the response to CMD55, it no longer had CMD8's response buffered.
The next problem, and the one I'm currently stuck at, is that in the response to CMD55, bit 23 of the card status field (COM_CRC_ERROR) is set, which indicates the CRC check of the previous command failed according to the spec. Although the microcontroller automatically calculates the CRC, I hooked up a logic analyzer to the circuit to verify it was correct. I'm using a web app (sorry, can't link because I'm a new user, but just Google for "CRC ghsi" and it's the first result) to verify the CRCs, using the polynomial x^7 + x^3 + 1 as per the spec. This is the logic analyzer output, formatted and commented by me:
// uC sends CMD0, CRC OK, no response:
01 000000 00000000000000000000000000000000 1001010 1
// uC sends CMD8, CRC OK, check byte = 0xAA:
01 001000 00000000000000000000000110101010 1000011 1
// SD card responds to CMD8, CRC OK, check byte echoed back = 0xAA:
00 001000 00000000000000000000000110101010 0001001 1
// uC sends CMD55, CRC OK:
01 110111 00000000000000000000000000000000 0110010 1
// SD card responds to CMD55, CRC OK, note card status bits 23, 8 and 5 set;
// bit 23 = COM_CRC_ERROR, bit 8 = READY_FOR_DATA and bit 5 = APP_CMD:
00 110111 00000000100000000000000100100000 0000100 1
Also note that if I attempt CMD55 a second time immediately after the exchange above, bit 23 is unset:
// uC sends CMD55, CRC OK:
01 110111 00000000000000000000000000000000 0110010 1
// SD card responds to CMD55, CRC OK, bits 8 and 5 still set but 23 not set:
00 110111 00000000000000000000000100100000 1000001 1
Note that I tried sending CMD8 twice before sending CMD55, but it made no difference, the first CMD55 always returns bit 23 set. I can reproduce this every time I try, so I don't believe it's an issue with glitches or noise. Considering the CRCs are calculated by the microcontroller itself, they look correct as seen by an external entity (the logic analyzer), and have been verified on the website I mentioned above, I don't see how the card's CRC check could be failing.
Is this somehow expected? Maybe I should wait a set number of clock cycles between each command (somewhere I read it should be 8 cycles, and I believe I'm respecting that)? Can I just send a second CMD55 if the first fails and be on my way, or will there be any negative consequences? Even if that fixes the problem, I'd very much like to know why the CRC check is failing, as I don't think I'm doing anything wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我发现了问题。在我必须修改代码以刷新 CMD8 响应的缓冲区,以便 CMD55 读取正确的响应之后,我所做的每个测试都将逻辑分析仪连接到电路。移除逻辑分析仪后,代码开始工作——可能它向线路中注入了噪声。不需要延迟,但为了遵循规范,我在 CMD0 之前添加了 74 个以上时钟周期的延迟。
I found the problem. After I had to modify the code to flush the buffer for the CMD8 response, so that CMD55 read the correct response, every test I made had the logic analyzer hooked up to the circuit. After removing the logic analyzer, the code started working -- probably it was injecting noise into the lines. No delays were required, but just to follow the spec, I added a 74+ clock cycles delay before CMD0.
检查 STM 留言板。
AFAIK,这些错误已在外围库的最新版本(3.4.0)中修复。
Check the STM message boards.
AFAIK, the bugs have been fixed in the latest version (3.4.0) of the Peripheral Libraries.