session_start(); # -------------------------------------------------------------------------------------------------------- # Spinelli - 01/05/2017 # # Leitura DS Card # # # -------------------------------------------------------------------------------------------------------- if( !isset($_SESSION["logedin"]) ) { include "../../session_parm.inc"; } include "../../visitas/visitas.inc"; include "../../cab.inc"; # ------------------------------------------------------------------------------------------------------- # # ------------------------------------------------------------------------------------------------------- ?>
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.
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.
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".
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.
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 CODESPara 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ÃOAntes de usar o cartão, é necessário habilitá-lo. Isso consiste em seguir os seguintes procedimentos:
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ÃOApós a inicialização, podemos ler algumas informações sobre o cartão que estão contidas nos registradores internos OCR, CSD e CID |
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 |
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 |
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 |
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.
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. 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. |