SD Cards - Características e Funcionamento




SD Cards, que daqui em diante chamaremos apenas de cartão, são dispositivos de memória que, do ponto de vista de um Host, se comportam como um disco rígido (HD), ou seja, o Host os vê como se fossem um conjunto de blocos ou setores de 512 bytes endereçáveis.

A partir daqui, abandonaremos o termo "bloco" e adotaremos o termo "setor" para nos referenciarmos ao uma sequência de 512 bytes do cartão.

O acesso a essa memória pode ser feito através dos protocolos I2C ou SPI sendo que, neste documento, trataremos apenas do acesso via módulo SPI.

No modo SPI o microcontrolador (Host) será o Master e o cartão será o Slave. No modo SPI, toda comunicação será iniciada pelo Master.

Muitos microcontroladores PIC possuem módulos SSP/SPI, com os quais podemos conectar um cartão usando basicamente 3 pinos: SCK (clock), SDI (entrada de dados) e SDO (saída de dados). Além desses 3 pinos, um quarto pino do microcontrolador deverá ser conectado ao pino CS ou Chip Select do cartão para poder ativá-lo e desativá-lo. Não confundir o pino CS do cartão com o pino SS do módulo SPI que só deve ser usado quando o microcontrolador funciona como Slave e isso não vem ao caso.

O pinoCS possui lógica negativa, ou seja, se estiver em nível baixo o cartão estará ativado e, se estiver em nível alto, o cartão estará desativado. Para saber como conectar dispositivos nas portas SPI, acesse /picmodules/mod_spi/" target="_blank">Comunicação usando a interface SPI.

Outra nomenclatura para os pinos de entrada e saída de dados, que evita muita confusão na hora de montar o circuito, pode ser encontrada como MISO Master-in-Slave-Out indicando que o pino SDI do Master conecta-se ao SDO do Slave e MOSI Master-out-Slave-in indicando que o pino SDO do Master conecta-se ao SDI do Slave.

Os cartões geralmente são do tipo SD, abreviatura de Secure Digital Card ou do tipo MicroSD. As duas figuras acima mostram alguns formatos desses cartões.



CARACTERÍSTICAS ELÉTRICAS E CONEXÕES

A figura ao lado mostra o esquema elétrico a ser seguido para operação em modo SPI onde os resistores pullups de 10K são obrigatórios mesmo para os pinos não usados. Apesar de não mostrada na figura, a tensão no pino VDD deve ser de aproximadamente 3,6V.

O protocolo SPI simplesmente envia um comando e aguarda uma resposta do cartão. Todo comando é sempre iniciado pelo Host. O cartão responde ao comando com uma série de bytes e, dependendo do comando, a resposta pode ser seguida de um byte de controle (token) que indica o início da transmissão de uma sequência de dados ou então uma condição de erro.


FORMATO DOS COMANDOS

Os comandos de uso geral são identificados como CMDxx e os comandos especificos de aplicação são identificados por ACMDxx, onde xx é o número do comando. Todos os comandos são enviados ao cartão num bloco de 6 bytes, iniciando pelo byte mais significativo (MSB), através da porta SDO do módulo SPI. O byte mais significativo (MSB) do comando sempre inicia por "01" seguidos de um número de comando de 6 bits. Assim, se estivermos enviando o comando CMD24 para gravar um setor no cartão, o primeiro byte do comando terá o valor 01 nos bits 7 e 6 seguido do valor 24 decimal, que se escreve 11000 em binário, nos bits de 5 a 0. Como o comando deve ter 6 bits, acrescentamos um zero a esquerda 011000 e montamos o byte 1 do comando que ficará com o valor 01011000 ou 0x58 em hexadecimal.

Em seguida, são enviados 4 bytes de argumento seguidos de um CRC de 7 bits e finalmente um bit de stop "1", conforme pode ser observado na figura "Formato dos comandos".




TABELA DE COMANDOS NO MODO SPI

As tabelas abaixo foram retiradas do documento

Sandisk Secure Digital Card - Product Manual - Document No. 80-13-00169 - December 2003
SanDisk Corporation - Corporate Headquarters - 140 Caspian Court - Sunnyvale, CA 94089
Phone (408)542-0500 - Fax (408) 542-0503 - www.sandisk.com


Essas tabelas mostram os principais comandos no modo SPI.
Um "Yes" na coluna "SPI Mode" indica que o comando é suportado no modo SPI.
Quando um comando não requer argumento, deve-se enviá-lo com zeros.
A coluna "Resp" contem o tipo de resposta enviada pelo comando.






TABELA DE COMANDOS ESPECÍFICOS DE APLICAÇÃO

A tebela abaixo descreve os comandos específicos de aplicação suportados pelo cartão.
Antes usar cada comando dessa tabela, deve-se enviar o comando CMD55 para avisar o cartão que um comando de aplicação será enviado em seguida.





RESPONSE CODES

Para cada tipo de comando o cartão responde com um tipo de resposta que, no modo SPI, são de 3 tipos: R1, R2 e R3 cujas descrições podem ser vistas nas tabelas ao lado.




INICIALIZAÇÃO DO CARTÃO

Antes de usar o cartão, é necessário habilitá-lo. Isso consiste em seguir os seguintes procedimentos:

  1. Ligar a alimentação do cartão.
  2. Aguardar um tempo de ao menos 5ms (milisegundos).
  3. Desabilitar o cartão levantando a linha CS, isto é, CS=1.
  4. Enviar ao menos 72 pulsos de clock ao cartão.
  5. Habilitar o cartão fazendo CS=0.
  6. Enviar o comando CMD0 [0x40, 0x00, 0x00, 0x00, 0x00, 0x95].
  7. Fazer uma leitura. O cartão deverá responder com 0xFF.
  8. Fazer uma leitura. O cartão deverá enviar resposta R1 que deverá ser 0x01.
  9. Enviar o comando CMD55 [0x77, 0x00, 0x00, 0x00, 0x00, 0xFF] até que o byte de resposta tenha o bit 7 zerado.
  10. Enviar o comando ACMD41 [0x69, 0x00, 0x00, 0x00, 0x00, 0xFF] e esperar a resposta 0x00 e, se não for 0x00, repetir CMD55.

Notar que, na sequência acima, o CRC do comando CMD0 deve ser obrigatoriamente 0x95.

Para os comandos CMD55 e ACMD41 os CRCs devem ser 0xFF e, em todos os comandos, os 4 bytes de argumento são sempre zero.

Os comandos CMD55 e ACMD41 devem ser enviados repetidamente um certo número arbitrário de vezes, digamos 100 vezes, e, se o cartão não enviar a resposta esperada, devemos assumir que está com problema.




OBTENDO INFORMAÇÕES SOBRE O CARTÃO

Após a inicialização, podemos ler algumas informações sobre o cartão que estão contidas nos registradores internos OCR, CSD e CID




INFORMAÇÕES NO REGISTRADOR OCR

Os 32 bits do registrador OCR informam a tensão de operação do cartão conforme figura ao lado. Para conseguir ler esse registro, o cartão deve estar sendo alimentado com uma tensão entre 2,0V a 3,6V . A sequência de comandos abaixo mostra como ler os 32 bits de informações do registrador OCR usando o comando CMD58. Esse comando retornará uma resposta do tipo R3 de 5 bytes, onde o byte 1 é semelhante a R1.

Send: 0x7A,0x00,0x00,0x00,0xFF - CMD58, Argumento, CRC=0xFF Read: 1 byte - NCR=0xFF Read: 5 bytes - Resposta R3 - byte 1 deve ser 0x00 - bytes 2 a 5 tem o OCR




















INFORMAÇÕES NO REGISTRADOR CSD

A sequência de comandos abaixo mostra como ler os 16 bytes de informações do registrador CSD usando o comando CMD9.
O layout do registrador CSD pode ser visto na figura abaixo.
Esse comando retornará uma resposta do tipo R1.

Send: 0x49,0x00,0x00,0x00,0x00 - CMD9, Argumento, CRC=0x00 Read: 1 byte - NCR=0xFF Read: 1 byte - Resposta R1 deve ser 0x00 Read: 1 byte até receber 0xFE - Espera chegar o token 0xFE (*)  Read: 1 byte x 16 - Recebe 16 bytes o CSD  Read: 1 byte CRC - Recebe CRC - primeiro byte Read: 1 byte CRC - Recebe CRC - segundo byte

(*) O token 0xFE pode ser esperado fazendo-se um loop um determinado número de vezes (por exemplo 100 vezes) ao fim do qual uma condição de erro pode ser assumida se o cartão não enviá-lo.



Layout do registrador CSD



INFORMAÇÕES NO REGISTRADOR CID

A sequência de comandos abaixo mostra como ler os 16 bytes de informações do registrador CID usando o comando CMD10. Esse comando retornará uma resposta do tipo R1.

Send: 0x4A,0x00,0x00,0x00,0x00 - CMD10, Argumento, CRC=0x00 Read: 1 byte - NCR=0xFF Read: 1 byte - Resposta R1 deve ser 0x00 Read: 1 byte até receber 0xFE - Espera chegar o token 0xFE (*)  Read: 1 byte x 16 - Recebe 16 bytes o CID  Read: 1 byte CRC - Recebe CRC - primeiro byte Read: 1 byte CRC - Recebe CRC - segundo byte


Layout do registrador CID



LEITURA DE UM SETOR

Para a leitura de um setor, é usado o comando CMD17 que transfere ao host um setor inteiro de 512 bytes. O argumento do comando deverá ser o endereço real do setor a ser lido, múltiplo de 512. Por exemplo, se quisermos ler o setor 5 do cartão, o endereço real será (5 * 512), ou seja 2560. Assim, o argumento deverá conter esse endereço em hexadecimal, ou seja, 0x00000A00. Para a leitura, os 7 bits de CRC devem ser sempre zeros e o stop bit deve ser 1.

A sequência abaixo mostra como deve ser feito o procedimento de leitura de um setor:

Send: 0x51,0x00,0x00,0xA0,0x00 - CMD17, endereço, CRC=0x00 Read: 1 byte - NCR=0xFF Read: 1 byte - Resposta R1 deve ser 0x00 Read: 1 byte até receber 0xFE - Espera chegar o token 0xFE (*)  Read: 1 byte x 512 - Recebe o setor de 512 bytes  Read: 1 byte CRC - Recebe CRC - primeiro byte Read: 1 byte CRC - Recebe CRC - segundo byte

(*) O token 0xFE pode ser esperado fazendo-se um loop um determinado número de vezes (por exemplo 100 vezes) ao fim do qual uma condição de erro pode ser assumida se o cartão não enviá-lo.

A transferência é sempre precedida pelo token inicial 0xFE ao qual segue os 512 bytes de dados do setor. Após os dados segue um CRC de 16 bits.




GRAVAÇÃO DE UM SETOR

A gravação de um setor é feita com o comando CMD24. O host deve primeiramente enviar o comando, em seguida o argumento de 4 bytes do endereço do setor a ser gravado que, do mesmo modo como na leitura, deve ser o endereço real do setor. A seguir, enviam-se os 7 bits do CRC zerados e o stop bit 1.

A sequência abaixo mostra como deve ser feito o procedimento de gravação de um setor:

Send: 0x58,0x00,0x00,0xA0,0x00 - CMD24, endereço, CRC=0x00 Read: 1 byte - NCR Read: 1 byte - Resposta R1 deve ser 0x00 Send: 1 byte de 0xFF - Envia GAP 0xFF Send: 1 byte de token 0xFE - Envia o token 0xFE Send: 1 byte x 512 - Envia 512 bytes do setor  Send: 1 byte CRC - Envia CRC - primeiro byte 0x00 Send: 1 byte CRC - Envia CRC - segundo byte 0x00 Read: 1 byte - Le o packet response (*) Read: 1 byte - Le até receber valor não nulo (**


(*) Logo após o envio do último CRC deve-se fazer uma leitura para receber o packet response.
Seja Y o valor recebido do cartão como packet response, o teste abaixo verifica se a gravação foi bem sucedida.

IF (Y   &   0x1F) >> 1  ==  0x02

então os dados foram gravados corretamente no cartão. Outros valores obtidos após essa operação podem ser 0x05 indicando o dado foi rejeitado devido a um erro no cartão ou 0x06 indicando erro no comando de gravação.

(**) Após receber e verificar o packet response, fica em loop de leitura até conseguir um byte de resposta diferente de zeros indicando que o cartão foi liberado.