Initialization of a microSD card using an SPI interface - embedded

I'm using a microSD card in an embedded design. The card is connected to a microcontroller using the SPI interface. It worked fine for all cards I've used before, but now my new card will not initialize. The card is a Transcend 2 GB microSD card (TS2GUSD).
After sending the initial clock train to switch to SPI mode, I do the following:
CMD0 (Argument 0, CRC 0x95) -> Response 0x01 -> OK
CMD8 (Argument 0x000001AA, CRC 0x87) -> Response 0x01 0x000001AA -> Means it's SDC V2+ card, the voltage range 2.7 V - 3.6 V is supported -> OK
Then I should send the ACMD41 command, but when sending the CMD55 (argument 0, CRC 0) that must precede CMD41, I get response 0x05 -> Illegal Command.
I've also tried to send CMD1 (for MMC cards), but it gives a similar illegal command response. The code works fine with my Sandisk 2 GB microSD card.
How do I fix this problem?

I seem to have found the issue. When I calculate the correct CRC for CMD55 and send that instead of a dummy CRC, the command is accepted (result 0x01). If you look at the physical layer specification in section 7.2.2, it explicitly says that:
The SPI interface is initialized in the CRC OFF mode in default. (except for commands CMD0 and CMD8).
This doesn't seem to be the case with this series of Transcend cards, thus violating the specification. Also in case of a CRC error the reply should be 0x09 instead of 0x05. I've tried to explicitly turn off CRC checking with CMD59, but that doesn't seem to help.
=> Calculating the correct CRC for (all?) commands makes the card work.
I'm in contact with Transcend support about this. If I learn something useful I'll you know here.
Note that I used other 2 GB Transcend cards before, but they were made in Taiwan, while the new one is made in Korea (and seems to be a Samsung card (MMAGR02GUDCA)).

I had almost the same issue. When sending ACMD41, I sent CMD55 followed by CMD41. The response for CMD55 was 0x01, indicating idle state and running the initialization process (this is normal, I think). CMD41 would respond with 0x05, indicating illegal command. It turns out that my particular card does the CRC check by default, even in SPI mode, and misreports CRC errors as illegal commands (i.e., it doesn't follow the SD spec). When I calculate the proper CRC, it works fine. Here is the CRC7 calculation code I used, it has worked well for me:
https://github.com/hazelnusse/crc7
Unless you have taken care to disable CRC checking, I think it is probably best to assume it isn't disabled and make sure you calculate the proper CRC for each command frame. From what I can tell, some cards disable it by default in SPI mode and others enable it, even though the SD specification states it should be disabled by default in SPI mode except for CMD8.

You said you used CRC 0 for the failing command. I assume that you meant that you sent the whole last byte as 0x00. Note that the CRC7 is only the first 7 bits of the last byte - the last bit called end bit should always be 1. So if you were sending 0x00 as the last byte, with 0 as the last bit, the failure would be understandable, and even the error code would make sense. If you send 1 as the last bit, it should work, ie. use something like 0x01 or 0xFF as the last byte.

It's normal, it's likely the internal charge-pump used to make erase voltage that takes longer than usual to be ready... you have to insist on the CMD55+ACMD41 combo until initialization finishes.
The CMD58 could also help you to check if you're supplying correct voltage levels (sometimes sockets have contact problems).

Sending CMD0 with chip select(0) alone does not initialize the card in SPI mode. This only sets SPI mode.
Card is not initialized until ACMD41 returns accepted. Then CRC is off by default.

Insert several dummy SPI cycles after CMD55 (0xFF sent+received) and before CMD41.
I had to do this for both my old test cards - 16MB Panasonic and Sandisk 64MB.
Note: I realize I'm quite late to the party, but I'm hoping it may help someone in future.

Related

Z80 Multibyte Commands in IM0

I'm trying just for the fun to design a more complex Z80 CP/M system with a lot of peripheral devices. When reading the documentation I stumbled over an (undocumented?) behaviour of the Z80 CPU, when accepting an interrupt in IM0.
When an interrupt occurs, the Z80 activates M1 and IORQ to signal the external device: "Hey, give me an opcode". All is well if the opcode is rst 00 or something like this. Now the documentation tells, ANY opcode of any command can be given to the cpu, for instance a CALL.
But now comes the undocumented part: "The first byte of a multi-byte instruction is read during the interrupt acknowledge cycle. Subsequent bytes are read in by a normal memory read sequence."
A "normal memory read sequence". How can I determine, if the CPU wants to get a byte from memory or instead the next byte from the device?
EDIT: I think, I found a (good?) solution: I can dectect the start of the interrupt acknowlegde cycle by analyzing IORQ and M1. Also I can detect the next "normal" opcode fetch by analyzing MREQ and M1. This way I can install a flip-flop triggered by these two ANDed signals, i.e. the flip-flop is 1 as long as the CPU reads data from the io-device. This 1 I can use to inhibit the bus drivers to and from the memory.
My intentions? I'm designing an interrupt controller with 8 prioritized inputs in a CPLD. It's registers hold a 16 bit address for each interrupt pin. Just for the fun :-)
My understanding is that the peripheral device is required:
to know how many bytes it needs to feed;
to respond to normal read cycles following the IORQ cycle; and
to arrange that whatever would normally respond to memory read cycles does not do so for the duration.
Also the behaviour was documented by Zilog in an application note, from which your quote originates (presumably uncredited).
In practice I guess 99.99% of IM0 users just use an RST and 99.99% of the rest use a known-size instruction like CALL xxxx.
(also I'm aware of a few micros that effectively guaranteed not to put anything onto the bus during an interrupt cycle, thereby turning IM0 into a synonym of IM1 owing to open collector output).
The interrupt behavior is reasonably documented in the Z80 manual:
Interupt modes, IM2 allows you to supply an 8-bit address to a 16-bit pointer. At least halfway to the desired 16-bit direct address.
How to set the interrupt modes
My understanding is that the M1 + IORQ combination is used since there was no pin left for a dedicated interrupt response. A fun detail is also that the Zilog I/O chips like PIO, SIO, CTC reads the RETI instruction (as the CPU fetches it) to learn that the CPU is ready to accept another interrupt.

SDHC SPI write issues

I've been trying to do an SD card interface with the LPC1766 SPI peripheral for a while and right now I'm stuck in a problem that I couldn't find the answer anywhere.
The problem is: SDHC cards are not responding to write and read commands as expected.
Everything works fine on the initialization that was based on Chan's flowchart and on an NXP application note. I can differentiate the cards versions, read the OCR, CID, CSD and determine their sizes.
After that step I start writing single blocks every one second and reading it back to check the data integrity. On a Kingston SDHC 4 GB Class 4 card I can send a first write command but on the second one the card does not even answer (0x00 or 0x01) to the CMD24. With a SanDisk 4 GB Class 4 card the results are different, every command is answered by the card, but I get only zeroes when reading the data back (I'm sure I'm not writing zeroes). If I use SDSC cards, everything works fine.
I'm aware that SDHC are block addressed and not byte addressed and that I need to send ACMD41 with the CCS on for SDHC. I also know that the clock frequency is not an issue (using 400 KHz to start and then 20 MHz to write/read), because I just turned on the CRC checking and all cards are accepting the commands and data. If I stop calculating the CRC all cards reject commands and data.
How do you connect your SD card? Depending on the mode/state the SD(HC) card needs an external pull-up resistor. Without that you read zero, so that may be your problem.

Guidelines for designing forward compatible communication protocols?

I'm working on a communication protocol between embedded devices. The protocol will definitely need new commands and fields in the future. What do I need to do to make sure I'm not painting myself into a corner?
This is a wide open question. Here are some random thoughts about it:
Leave spares.
Use a very basic header with a "number of bytes to follow" field.
If there are enumerated message types, make sure the type field can accomodate
growth.
If you use bitflags, leave spares.
Possibly include a "raw data" message, which can be used to wrap any protocol future generations think up.
In summary, Leave spares.
If at all possible, allow a human at one end of a cable to figure out what is at the other end of the cable.
Ideally, a human could hook up a dumb terminal and hit the keyboard three times (Enter Question-mark Enter), then a long, detailed message would come back describing what kind of machine it is, what is its model number, the name and phone number and web site of the organization that built it, the "official" protocol version number, and the unofficial build time:
__DATE__ ": " __TIME__
Also send the same detailed message every time the machine boots up.
If at all possible, try to design your protocol so that a human being with a dumb terminal can talk to your device.
The HTTP is one such human-readable protocol, and I suspect this is one of the reasons for its popularity.
Human-readable implies, among other things:
Limit yourself to characters that a human can read and type.
Avoid special control characters. Take advantage of the power of plain text.
Always send CR+LF at the end of each packet (as mandated by many Internet protocols).
Accept characters at any rate, from maximum-speed file upload from a PC to a non-touch-typing human slowly pecking at a keyboard.
You might also want to glance over the list of common protocols for embedded systems.
Perhaps one already meets your requirements?
Is there any reason to use something more difficult to decode than the standard Netstring format?
The question is a little too general for a clear answer. There are many aspects an embedded system may need to communicate like;
How many peers will it need to communicate with?
How much data does it need to communicate?
How tightly synchronized do the systems need to be?
What is the physical media for the protocol and what are the bandwidth limitations, and error susceptibility considerations?
All of these requirements and resource limitations will certainly constrain the system and then you can start to figure out what the protocol will need. Once you know these issues you can then project how some the requirements may change/expand in the future. From there you can design the protocol to accommodate(or not) the worst case use cases.
I would use HDLC. I have had good luck with it in the past. I would for a point to point serial just use the Asynchronous framing and forget about all of the other control stuff as it would probably be overkill.
In addition to using HDLC for the framing of the packet. I format my packet like the following. This is how options are passed using 802.11
U8 cmd;
U8 len;
u8 payload[len];
The total size of each command packet is len +2
You then define commands like
#define TRIGGER_SENSOR 0x01
#define SENSOR_RESPONSE 0x02
The other advantage is that you can add new commands and if you design your parser correctly to ignore undefined commands then you will have some backwards compatibility.
So putting it all together the packet would look like the following.
// total packet length minus flags len+4
U8 sflag; //0x7e start of packet end of packet flag from HDLC
U8 cmd; //tells the other side what to do.
U8 len; // payload length
U8 payload[len]; // could be zero len
U16 crc;
U8 eflag; //end of frame flag
The system will then monitor the serial stream for the flag 0x7e and when it is there you check the length to see if it is pklen >= 4 and pklen=len+4 and that the crc is valid. Note do not rely on just crc for small packets you will get a lot of false positives also check length. If the length or crc does not match just reset the length and crc and start with decoding the new frame. If it is a match then copy the packet to a new buffer and pass it to your command processing function. Always reset length and crc when a flag is received.
For your command processing function grab the cmd and len and then use a switch to handle each type of command. I also require that a certain events send a response so the system behaves like a remote procedure call that is event driven.
So for example the sensor device can have a timer or respond to a command to take a reading. It then would format a packet and send it to the PC and the PC would respond that it received the packet. If not then the sensor device could resend on a timeout.
Also when you are doing a network transfer you should design it as a network stack like the OSI modle. The HDLC is the data link layer and the RPC and command handling is the Application Layer.

SD card initialization using SPI

I saw a lot of information about MMC/SD cards and I tried to make a library to read this (modifying the Procyon AVRlib).
But I have some problems here. I don't change the original code and tried here. My problem is about the initialization of an SD card. I have two here, a 256 MB and another 1 GB.
I send the init commands in this order: CMD0, CMD55, ACMD41, and CMD1.
But the 256 MB SD card only returns a 0x01 response for each command. I send the CMD1 a lot of times and the 256 MB SD card always returns only 0x01, never 0x00.
The 1 GB SD is more crazy... CMD0 returns with 0x01. Nice, but the CMD55 command responds with 0x05. At other times it responds with 0xC1 and also sometimes responds with 0xF0 with a 0x5F in the next interation...
Around the Internet there is information and examples, but it is a bit confused. Here in my project, I must use a 1 GB card and I'm trying with a microSD card with an SD adapter (I think that this is not the problem).
How do I fix this problem?
PS: My problem is like the problem in Stack Overflow question Initializing SD card in SPI issues, but the solution didn't solve my problem. The 1 GB SD card only returns 0x01 ever... :cry:
Why do you need CMD1? And did you read the note below it, that says "CMD1 is a valid command for the thin (1.4 mm) standard size SD memory card only if used after re-initializing a card (not after power on reset)."?
About the 1 GB card, ideas that come to mind:
After every command (send command, get reply), do you send 8 dummy bytes before making CS high?
The values returned seem weird (0x05 doesn't have busy bit set, so WTF?), maybe there's a hardware issue?
Does the card work otherwise?
Maybe this helps a bit:
SD Specifications Part 1 Physical LayerSimplified Specification
A simple explanation of MMC/SD usage over SPI is provided here. I have used the associated FAT file-system library too and it works well.
However, the solution may not work for some makes of cards. For such cards, you may have to edit the procedure/library. That may be why your 1 GB card acts differently -- it may be a different make of card. The SPI mode of certain cards may not be that popular for commercial equipment, and thus may be more deviated in specification by some card manufacturers.
If you bit bang the commands and clocks, you may have more control and confidence that those procedures are correct. That is useful because you need some solid ground to build on to progress bit by bit. I found that the <400 kHz 80 clocks was critical on one card, but could run at more than 2 MHz on another.
Try to progress one command at a time that is reliable for both cards.

Protocols used to talk between an embedded CPU and a PC

I am building a small device with its own CPU (AVR Mega8) that is supposed to connect to a PC. Assuming that the physical connection and passing of bytes has been accomplished, what would be the best protocol to use on top of those bytes? The computer needs to be able to set certain voltages on the device, and read back certain other voltages.
At the moment, I am thinking a completely host-driven synchronous protocol: computer send requests, the embedded CPU answers. Any other ideas?
Modbus might be what you are looking for. It was designed for exactly the type of problem you have. There is lots of code/tools out there and adherence to a standard could mean easy reuse later. It also support human readable ASCII so it is still easy to understand/test.
See FreeModBus for windows and embedded source.
There's a lot to be said for client-server architecture and synchronous protocols. Simplicity and robustness, to start. If speed isn't an issue, you might consider a compact, human-readable protocol to help with debugging. I'm thinking along the lines of modem AT commands: a "wakeup" sequence followed by a set/get command, followed by a terminator.
Host --> [V02?] // Request voltage #2
AVR --> [V02=2.34] // Reply with voltage #2
Host --> [V06=3.12] // Set voltage #6
AVR --> [V06=3.15] // Reply with voltage #6
Each side might time out if it doesn't see the closing bracket, and they'd re-synchronize on the next open bracket, which cannot appear within the message itself.
Depending on speed and reliability requirements, you might encode the commands into one or two bytes and add a checksum.
It's always a good idea to reply with the actual voltage, rather than simply echoing the command, as it saves a subsequent read operation.
Also helpful to define error messages, in case you need to debug.
My vote is for the human readable.
But if you go binary, try to put a header byte at the beginning to mark the beginning of a packet. I've always had bad luck with serial protocols getting out of sync. The header byte allows the embedded system to re-sync with the PC. Also, add a checksum at the end.
I've done stuff like this with a simple binary format
struct PacketHdr
{
char syncByte1;
char syncByte2;
char packetType;
char bytesToFollow; //-or- totalPacketSize
};
struct VoltageSet
{
struct PacketHdr;
int16 channelId;
int16 voltageLevel;
uint16 crc;
};
struct VoltageResponse
{
struct PacketHdr;
int16 data[N]; //Num channels are fixed
uint16 crc;
}
The sync bytes are less critical in a synchronous protocol than in an asynchronous one, but they still help, especially when the embedded system is first powering up, and you don't know if the first byte it gets is the middle of a message or not.
The type should be an enum that tells how to intepret the packet. Size could be inferred from type, but if you send it explicitly, then the reciever can handle unknown types without choking. You can use 'total packet size', or 'bytes to follow'; the latter can make the reciever code a little cleaner.
The CRC at the end adds more assurance that you have valid data. Sometimes I've seen the CRC in the header, which makes declaring structures easier, but putting it at the end lets you avoid an extra pass over the data when sending the message.
The sender and reciever should both have timeouts starting after the first byte of a packet is recieved, in case a byte is dropped. The PC side also needs a timeout to handle the case when the embedded system is not connected and there is no response at all.
If you are sure that both platforms use IEEE-754 floats (PC's do) and have the same endianness, then you can use floats as the data type. Otherwise it's safer to use integers, either raw A/D bits, or a preset scale (i.e. 1 bit = .001V gives a +/-32.267 V range)
Adam Liss makes a lot of great points. Simplicity and robustness should be the focus. Human readable ASCII transfers help a LOT while debugging. Great suggestions.
They may be overkill for your needs, but HDLC and/or PPP add in the concept of a data link layer, and all the benefits (and costs) that come with a data link layer. Link management, framing, checksums, sequence numbers, re-transmissions, etc... all help ensure robust communications, but add complexity, processing and code size, and may not be necessary for your particular application.
USB bus will answer all your requirements. It might be very simple usb device with only control pipe to send request to your device or you can add an interrupt pipe that will allow you to notify host about changes in your device.
There is a number of simple usb controllers that can be used, for example Cypress or Microchip.
Protocol on top of the transfer is really about your requirements. From your description it seems that simple synchronous protocol is definitely enough. What make you wander and look for additional approach? Share your doubts and we will try to help :).
If I wasn't expecting to need to do efficient binary transfers, I'd go for the terminal-style interface already suggested.
If I do want to do a binary packet format, I tend to use something loosely based on the PPP byte-asnc HDLC format, which is extremely simple and easy to send receive, basically:
Packets start and end with 0x7e
You escape a char by prefixing it with 0x7d and toggling bit 5 (i.e. xor with 0x20)
So 0x7e becomes 0x7d 0x5e
and 0x7d becomes 0x7d 0x5d
Every time you see an 0x7e then if you've got any data stored, you can process it.
I usually do host-driven synchronous stuff unless I have a very good reason to do otherwise. It's a technique which extends from simple point-point RS232 to multidrop RS422/485 without hassle - often a bonus.
As you may have already determined from all the responses not directly directing you to a protocol, that a roll your own approach to be your best choice.
So, this got me thinking and well, here are a few of my thoughts --
Given that this chip has 6 ADC channels, most likely you are using Rs-232 serial comm (a guess from your question), and of course the limited code space, defining a simple command structure will help, as Adam points out -- You may wish to keep the input processing to a minimum at the chip, so binary sounds attractive but the trade off is in ease of development AND servicing (you may have to trouble shoot a dead input 6 months from now) -- hyperterminal is a powerful debug tool -- so, that got me thinking of how to implement a simple command structure with good reliability.
A few general considerations --
keep commands the same size -- makes decoding easier.
Framing the commands and optional check sum, as Adam points out can be easily wrapped around your commands. (with small commands, a simple XOR/ADD checksum is quick and painless)
I would recommend a start up announcement to the host with the firmware version at reset - e.g., "HELLO; Firmware Version 1.00z" -- would tell the host that the target just started and what's running.
If you are primarily monitoring, you may wish to consider a "free run" mode where the target would simply cycle through the analog and digital readings -- of course, this doesn't have to be continuous, it can be spaced at 1, 5, 10 seconds, or just on command. Your micro is always listening so sending an updated value is an independent task.
Terminating each output line with a CR (or other character) makes synchronization at the host straight forward.
for example your micro could simply output the strings;
V0=3.20
V1=3.21
V2= ...
D1=0
D2=1
D3=...
and then start over --
Also, commands could be really simple --
? - Read all values -- there's not that many of them, so get them all.
X=12.34 - To set a value, the first byte is the port, then the voltage and I would recommend keeping the "=" and the "." as framing to ensure a valid packet if you forgo the checksum.
Another possibility, if your outputs are within a set range, you could prescale them. For example, if the output doesn't have to be exact, you could send something like
5=0
6=9
2=5
which would set port 5 off, port 6 to full on, and port 2 to half value -- With this approach, ascii and binary data are just about on the same footing in regards to computing/decoding resources at the micro. Or for more precision, make the output 2 bytes, e.g., 2=54 -- OR, add an xref table and the values don't even have to be linear where the data byte is an index into a look-up table ...
As I like to say; simple is usually better, unless it's not.
Hope this helps a bit.
Had another thought while re-reading; adding a "*" command could request the data wrapped with html tags and now your host app could simply redirect the output from your micro to a browser and wala, browser ready --
:)