我查看了 Stack Overflow 问题使用 SPI 接口初始化 microSD 卡,但没有没有看到任何与我的问题相匹配的答案(即我尚未尝试过的事情)。
我有一个类似的问题,我试图通过微控制器的 SPI 接口访问 SD 卡(特别是 HC908)。我尝试按照物理层简化规范 v2.00 中的流程图进行操作,它似乎在 Transcend 1 GB & 上正确初始化。 2 GB 和 AE&C 1 GB 卡。但我在相机上使用过的旧卡中的另外三张随机卡遇到了问题。
我的代码都是HC908汇编程序。我检查了 SPI 时钟线,在初始化期间它的运行频率约为 350kHz(HC908 在我的低 MCU 时钟速度下提供的唯一速度倍增器,落在 100 - 400kHz 窗口内)。
以下是未完成初始化例程的三张卡的结果(全部连续完成,无需更改任何代码或计时参数):
Canon 16Meg card (labeled as SD):
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (indicates idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
because illegal command branch to error routine
Send CMD13 [0x4D000000000D] (show status buffer) and Loop up to 8 times waiting for high bit on response to go low
R1= 0x05 (idle and illegal command)
非法命令标志是否卡住?我应该在 CMD8 之后做一些事情来清除该标志吗?
SanDisk UltraII 256Meg
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send 0xFF 4 times to read OCR
OCR = 0xFFFFFFFF
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Repeat the CMD1 50 times (my arbitrary number to wait until idle clears)
Every R1 response is 0x05 (idle and illegal command)
为什么OCR全是F?看起来一点也不合适。另外,为什么ACMD41和CMD1会响应非法命令? CMD1 是否失败,因为卡在 CMD55 之后等待有效的 ACMD,即使有非法命令响应?
SanDisk ExtremeIII 2G:
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x40000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? My loop shows the responses for each iteration and I got 0xFF 0xFF 0xC1 0x7F... is the card getting out of sync?)
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle and back in sync)
Send 0xFF 4 times to read OCR
OCR = 0x00FF80
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x5F (??? loop responses are 0xFF 0xFF 0xF0 0x5F... again out of sync?)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command, but back in sync???)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x00 (out of idle)
Send CMD9 [0x4900000000AF] (get CSD) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x3F (??? loop responses are 0xFF 0xFF 0xC1 0x3F... again out of sync?)
Code craps out because Illegal command bit is high.
那张卡到底出了什么问题?
有时是同步的,有时则不同步。 (上述模式是可重复的。)我已经确定了这一模式,并且没有看到 MOSI/MISO 传输之间出现任何恶意时钟周期。
I've had a look at Stack Overflow question Initialization of a microSD card using an SPI interface and didn't see any answers that matched my issue (that is, things I haven't already tried).
I have a similar issue where I'm trying to access a SD card through a microcontroller's SPI interface (specifically an HC908). I've tried following the flow charts in the Physical Layer Simplified Specification v2.00 and it seems to initialize correctly on Transcend 1 GB & 2 GB and an AE&C 1 GB card. But I'm having problems on three other random cards from my stash of old cards that I've used on my camera.
My code is all HC908 assembler. I scoped out the SPI clock line and during initialization it's running about 350 kHz (the only speed multiplier that the HC908 supplies at my low MCU clock speed that falls within the 100 - 400 kHz window).
Here are the results of the three cards that aren't completing my initialization routine (all done consecutively without changing any code or timing parameters):
Canon 16Meg card (labeled as SD):
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (indicates idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
because illegal command branch to error routine
Send CMD13 [0x4D000000000D] (show status buffer) and Loop up to 8 times waiting for high bit on response to go low
R1= 0x05 (idle and illegal command)
Is the illegal command flag stuck? Should I be doing something after CMD8 to clear that flag?
SanDisk UltraII 256Meg
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send 0xFF 4 times to read OCR
OCR = 0xFFFFFFFF
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Repeat the CMD1 50 times (my arbitrary number to wait until idle clears)
Every R1 response is 0x05 (idle and illegal command)
Why is OCR all F? Doesn't seem proper at all. Also, why does ACMD41 and CMD1 respond illegal command? Is CMD1 failing because the card is waiting for a valid ACMD after the CMD55 even with the illegal command response?
SanDisk ExtremeIII 2G:
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x40000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? My loop shows the responses for each iteration and I got 0xFF 0xFF 0xC1 0x7F... is the card getting out of sync?)
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle and back in sync)
Send 0xFF 4 times to read OCR
OCR = 0x00FF80
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x5F (??? loop responses are 0xFF 0xFF 0xF0 0x5F... again out of sync?)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command, but back in sync???)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x00 (out of idle)
Send CMD9 [0x4900000000AF] (get CSD) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x3F (??? loop responses are 0xFF 0xFF 0xC1 0x3F... again out of sync?)
Code craps out because Illegal command bit is high.
What on Earth is wrong with that card?
Sometimes it is in sync, other times not. (The above pattern is repeatable.) I've scoped this one out and I'm not seeing any rogue clock cycles going through between MOSI/MISO transfers.
发布评论
评论(3)
如果您启用了 CRC(使用 CMD59),那么是的,数据块将附加 CRC16。
有关详细信息,请参阅“物理层简化规范版本 2.00”的“总线传输保护”和“数据读取”章节。
If you enabled CRC (with CMD59), then yes, data blocks will have CRC16 appended.
For more info see "Physical Layer Simplified Specification Version 2.00", chapters "Bus Transfer Protection" and "Data Read".
这很重要:我在使用 SD/MMC 卡时遇到了很多麻烦,直到我发现我必须选择工作电压。
您可以通过发送 ACMD41 以及为卡提供的电压设置位来实现此目的。
注意:只能选择一位。
如果您不选择电压或选择多个电压,则在某些 SD 卡上它将在空闲状态下保持循环并且永远不会退出。
即:如果您的ACMD41一直发送响应0x01,则说明您没有选择电压。
电压位于 ACMD41 的 32 位参数位 23...8 中。
对于 3.2V ... 3.3V,这是位 20,因此您可以:
这是十六进制值 0x10,所以您的 ACMD41 看起来像这样...
0x69 0x40 0x10 0x00 0x00 0xCD
...或者如果它是 SDSC 卡...
0x69 0x00 0x10 0x00 0x00 0x5F
这是最常见值的简短(且不完整)表:
您不必必须在任何时间点将 CS 切换为高电平。您可以始终将其保持在较低水平。
This is important: I've had very much trouble with SD/MMC card, until I found out that I had to select an operating voltage.
You do so, by sending ACMD41 with the bit set for the voltage you're supplying the card with.
Note: Only a single bit may be selected.
If you don't select a voltage or select more than one, it will KEEP looping in idle-state and never exit on some SD cards.
That is: If your ACMD41 keeps sending response 0x01, you have not selected a voltage.
The voltage is in ACMD41's 32-bit parameter bits 23...8.
For 3.2V ... 3.3V, this is bit 20, so for instance you could:
That's hex-value 0x10, so your ACMD41 would look like this...
0x69 0x40 0x10 0x00 0x00 0xCD
...or if it's a SDSC card...
0x69 0x00 0x10 0x00 0x00 0x5F
Here's a short (and incomplete) table of the most common values:
You do NOT have to switch CS high at ANY point in time. You can keep it low ALL the time.
好吧...我发现了我的问题。对于遇到此问题的其他人,请务必记住在收到响应后发送额外的
0xFF
。这为卡提供了额外的八个时钟周期来为下一个命令做好准备。有些卡似乎不需要它(例如我正在使用的 Transcends),但其他卡则需要它。实际上,我在“写入命令”例程的开头放置了一个简单的循环,该循环发送
0xFF
直到它得到0xFF
作为响应,这样我就不必去我读取响应的所有不同位置,以确保我放置了额外的发送0xFF
。因为对于 SPI 模式下的 SD 卡(通常)而言,如果没有时钟周期到来,时间就会停止。我注意到但尚未找到答案的一件事(但到目前为止它没有造成任何损害),在我读取 CSR 的 16 个字节后,似乎还有另外 2 个字节的非 0xFF 结果...这是 CRC16 吗?奇怪的是,CSR 内置了 CRC...
OK... I found my problem. For anyone else who runs into this issue, it is important to remember to send an extra
0xFF
after getting responses. This gives the card an extra eight clock cycles to prepare itself for the next command. Some cards don't seem to need it (the Transcends that I'm using for example), but others require it.I actually put a simple loop at the beginning of my 'write command' routine that sends
0xFF
until it gets0xFF
as a response just so I don't have to go to all the different places where I read responses to make sure I put an extra send0xFF
. Because as far as the SD card is (usually) concerned in SPI mode, if there are no clock cycles coming in, time stands still.One thing that I noted and have yet to find an answer for (but so far it isn't hurting anything), after I read the 16 bytes of the CSR, there seem to be an additional 2 bytes of non-
0xFF
that comes out... Is that a CRC16? Odd since the CSR has a CRC built in...