Obsah:
Realizace
Popis pinů SD karty [1]
Pin | Name | Function (SD Mode) | Function (SPI Mode) |
1 | DAT3/CS | Data Line 3 | Chip Select/Slave (SS) |
2 | CMD/DI | Command Line | Mater Out Slave In (MOSI) |
3 | VSS1 | Ground | Ground |
4 | VDD | Supply Voltage | Supply Voltage |
5 | CLK | Clock | Clock (SCK) |
6 | VSS2 | Ground | Ground |
7 | DAT0/DO | Data Line 0 | Master In Slave Out (MISO) |
8 | DAT1/IRQ | Data Line 1 | Unused or IRQ |
9 | DAT2/NC | Data Line 2 | Unused |
Datové protokoly (módy) SD karty
Jednobitový protokol je synchronní sériový protokol s jedním datovým vodičem, jedním vodičem pro hodinový signál a jedním vodičem pro řízení. Čtyřbitový protokol je téměř identický s prvním protokolem, rozdíl je v paralelní čtyřbitové datové sběrnici. Oba tyto SD módy mají zabezpečený datový přenos pomocí CRC. Čtyřbitový SD mód má pro každý ze čtyřech datových vodičů nezávislý 16-i bitový CRC. Třetí protokol je protokol (mód) SPI. Tento protokol vychází z komunikace pomocí SPI (Serial Peripheral Interface).
Řízení komunikace [1]
Řízení je prováděno pomocí jednoduchého send-response protokolu. Řídící rámce jsou rozděleny na CMDXX (hlavní řídící rámce) a ACMDXX (aplikační řídící rámce), kde XX je číslo příslušného řídícího rámce (Command). Řídící rámec začíná datovou sekvencí 01, následovanou šesti bity řídícího příkazu a čtyřmi bajty argumentu řídícího příkazu (Command). Poté následuje 7-i bitový CRC se stop bitem 1.
First Byte | Bytes 2-5 | Last Byte | |||
0 | 1 | Command | Argument (MSB First) | CRC | 1 |
Každý řídící rámec (řídící příkaz) má odpovídající odezvu. Tyto odezvy jsou rozděleny pro SPI mód na typy R1, R2, R3.
R1:
Byte | Bit | Meaning |
1 | 7 | Start Bit, Always 0 |
6 | Parametr Error | |
5 | Address Error | |
4 | Erase Sequence Error | |
3 | CRC Error | |
2 | Illegal Command | |
1 | Erase Reset | |
0 | In Idle State |
R2:
Byte | Bit | Meaning |
1 | 7 | Start Bit, Always 0 |
6 | Parametr Error | |
5 | Address Error | |
4 | Erase Sequence Error | |
3 | CRC Error | |
2 | Illegal Command | |
1 | Erase Reset | |
0 | In Idle State | |
2 | 7 | Out of Range, CSD Service |
6 | Erase Parameter | |
5 | Write protect Violation | |
4 | Card ECC Failed | |
3 | Card Controller Error | |
2 | Unspecified Error | |
1 |
Write Protect Erase Skip, Lock/Ulock failded |
|
0 | Card Locked |
R3:
Byte | Bit | Meaning |
1 | 7 | Start Bit, Always 0 |
6 | Parametr Error | |
5 | Address Error | |
4 | Erase Sequence Error | |
3 | CRC Error | |
2 | Illegal Command | |
1 | Erase Reset | |
0 | In Idle State | |
2-5 | All | Operating Condition Register, MSB First |
Každá část komunikace (blok dat, čtení nebo zápis) začíná startovním rámcem s hodnotou 11111110, následován blokem dat, typicky o velikosti 512 bajtů, vše je zakončeno 16-i bitovým CRC. Při každém zápisu na kartu (po zápisu bloku dat) je generován Write Status rámec o délce jedno bajtu. Při chybném přečtení dat z karty je generován Read Error rámec.
Write Status Rámec:
Bit | Meaning |
7 | Unused |
6 | Unused |
5 | Unused |
4 | 0 |
3-1 |
010 - Data was accepted |
0 | 1 |
Read Error Rámec:
Bit | Meaning |
7 | 0 |
6 | 0 |
5 | 0 |
4 | Card locked |
3 |
Out of Range |
2 | Card ECC Failed |
1 | Card Controller Error |
0 | Unspecified Error |
Nejdůležitější SD řídící příkazy:
Command | Argument | Type Response | Popis |
CMD0 | None | R1 | Tell the card to reset and enter its idle state. |
CMD16 | 32-bit Block Length | R1 | Select the block length. |
CMD17 | 32-bit Block Address | R1 | Read a single block. |
CMD24 | 32-bit Block Address | R1 | Write a single block. |
CMD55 |
None |
R1 |
Next command will be application-specific (ACMDXX). |
CMD58 | None | R3 | Read OCR (Operating Conditions Register). |
ACMD41 | None | R1 | Initialize the card. |
Inicializace SD karty
Inicializace začíná v nastavení hodinového signálu SPI na 400kHz, což je vyžadováno pro kompatibilitu většiny SD a MCC paměťových karet. Poté musí být vysláno 74 taktů hodinového signálu z MCU (master). Pak kartu resetujeme příkazem CMD0 při aktivovaném CS vstupu karty (CS při úrovni L). CRC bajt pro příkaz CMD0 a nulový argumet příkazu je 0x95. Následují příkazy CMD55 a ACMD41. Je-li poté idle bit v úrovni L inicializace je dokončena a očekávají se další řídící rámce. Příkazem CMD58 můžeme například zjistit zda-li karta podporuje stejné napájecí napětí jako MCU, které je typicky v rozsahu 2,7V až 3,6V. Hodinový signál SPI nastavíme na maximální povolenou hodnotu.
Programová část:
Připojení SD karty k MCU:
#define DI 6 // Port B bit 6 (pin7): data in (data from MMC) #define DT 5 // Port B bit 5 (pin6): data out (data to MMC) #define CLK 7 // Port B bit 7 (pin8): clock #define CS 4 // Port B bit 4 (pin5): chip select for MMC
Inicializace SPI:
void ini_SPI(void) { DDRB &= ~(_BV(DI)); //vstup DDRB |= _BV(CLK); //výstup DDRB |= _BV(DT); //výstup DDRB |= _BV(CS); //výstup SPCR |= _BV(SPE); //SPI enable SPCR |= _BV(MSTR); //Master SPI mode SPCR &= ~(_BV(SPR1)); //fosc/16 SPCR |= _BV(SPR0); //fosc/16 SPSR &= ~(_BV(SPI2X)); //rychlost neni dvojnásobná PORTB &= ~(_BV(CS)); //CS SD karty enable }
Funkce k posílání a příjmu jednoho bajtu po SPI:
char SPI_sendchar(char chr) { char receivedchar = 0; SPDR = chr; while(!(SPSR & (1<<SPIF))); receivedchar = SPDR; return (receivedchar); }
Funkce k posílání příkazového rámce Command:
char Command(char cmd, uint16_t ArgH, uint16_t ArgL, char crc ) { SPI_sendchar(0xFF); SPI_sendchar(cmd); SPI_sendchar((uint8_t)(ArgH >> 8)); SPI_sendchar((uint8_t)ArgH); SPI_sendchar((uint8_t)(ArgL >> 8)); SPI_sendchar((uint8_t)ArgL); SPI_sendchar(crc); SPI_sendchar(0xFF); return SPI_sendchar(0xFF); // vrátí poslední přijatý bajt }
Inicializace karty:
void ini_SD(void) { char i; PORTB |= _BV(CS); //CS SD karty disable for(i=0; i < 10; i++) SPI_sendchar(0xFF); // posíláme 10*8=80 hodinových pulzů 400 kHz PORTB &= ~(_BV(CS)); //CS SD karty enable for(i=0; i < 2; i++) SPI_sendchar(0xFF); // posíláme 2*8=16 hodinových pulzů 400 kHz Command(0x40,0,0,0x95); // reset idle_no: if (Command(0x41,0,0,0xFF) !=0) goto idle_no; //idle = L? SPCR &= ~(_BV(SPR0)); //fosc/4 }
Zápis na kartu:
Funkce vrací hodnotu 1 pokud dojde k chybě, pokud proběhne zápis v pořádku funkce vrátí 0.
int write(void) { int i; uint8_t wbr; //Nastavení módu zápisu 512 bajtů if (Command(0x58,0,512,0xFF) !=0) { //Zjištění hodnoty response bajtu 0 = bez chyb return 1; //vrácená hodnota 1 = chyba } SPI_sendchar(0xFF); SPI_sendchar(0xFF); SPI_sendchar(0xFE); //doporučené vysílání zakončovací sekvence dle [2] //zápis dat z chars[512] na kartu uint16_t ix; char r1 = Command(0x58,0,512,0xFF); for (ix = 0; ix < 50000; ix++) { if (r1 == (char)0x00) break; r1 = SPI_sendchar(0xFF); } if (r1 != (char)0x00) { return 1; //vrácená hodnota 1 = chyba } //doporučená kontrolní smyčka dle [2] SPI_sendchar(0xFF); SPI_sendchar(0xFF); wbr = SPI_sendchar(0xFF); //write block response a testování na chybu wbr &= 0x1F; //nulování nejvyšších tří neurčitých bitů, 0b.0001.1111 if (wbr != 0x05) { // 0x05 = 0b.0000.0101 //chyba zápisu nebo chyba CRC return 1; } while(SPI_sendchar(0xFF) != (char)0xFF); //čekáme na dokončení operace zápisu na kartu return 0; }
Čtení z karty:
Funkce vrací hodnotu 1 pokud dojde k chybě, pokud proběhne zápis v pořádku funkce vrátí 0.
int read(void) { int i; uint16_t ix; char r1 = Command(0x51,0,512,0xFF); for (ix = 0; ix < 50000; ix++) { if (r1 == (char)0x00) break; r1 = SPI_sendchar(0xFF); } if (r1 != (char)0x00) { return 1; } //čtení z karty proběhne po přijetí startovacího rámce while(SPI_sendchar(0xFF) != (char)0xFE); for(i=0; i < 512; i++) { while(!(SPSR & (1<<SPIF))); chars[i] = SPDR; SPDR = SPI_sendchar(0xFF); } SPI_sendchar(0xFF); SPI_sendchar(0xFF); return 0; }
Doplnění kódu:
#include <avr/io.h> #include <avr/iom16.h> #include <avr/interrupt.h> #define FOSC 6400000 char chars[512]; int main(void) { ini_SPI(); ini_SD(); sei(); write(); read(); return 0; }
Závěr
MCU pracuje s kmitočtem oscilátoru 6,4 MHz. Funkce pro čtení a zápis jsou doplněny o kontrolní smyčku, dle doporučení [2]. Pro čtení z karty je možné využít sériové rozhraní USART a nastavit vyšší prioritu pro přerušení, tak aby nedošlo ke ztrátě dat při čtení a jejich současnému zpracování.
Literatura
- [1] SanDisk. Secure Digital Card Product Manual - Revision 1.7, Září 2003.
- [2] SD Card Association. http://sdcard.org/.
Komentáře
a co licence?
Dobry den, sd karty (v spi rezimu , vicemene jen jako nahradu za mmc) ve svych amaterskych navrzich pouzivam taky. Nicmene - pokud budu chtit takove zarizeni vyrabet a prodavat - nevztahuji se na mne licence SD Association? :-/
Driver pro win
Dobry den, nezajimal se nekdo z Vas o moznosti zpracovani dat dale na PC? Tzn. vyjmout kartu z embedded systemu (kde se data zapisovaly jednoduse jako bajty na urcite adresy - bez filesystemu) vlozit do ctecky karet na PC a pomoci nejakeho driveru je zpristupnit operacnimu systemu. Napsani driveru pro windows bude asi dost slozite, linux by mohl byt alternativou. Mozna ze se timto jiz nekdo zabyval a existuje hotove reseni. Myslim ze by to byl znacny prinos, v mnoha aplikacich by tim mohla odpadnout nutnost nejakeho rozhrani pro stahovani dat ze systemu.
Driver
Dobry den, nezajimal se nekdo z Vas o moznosti zpracovani dat dale na PC? Tzn. vyjmout kartu z embedded systemu (kde se data zapisovaly jednoduse jako bajty na urcite adresy - bez filesystemu) vlozit do ctecky karet na PC a pomoci nejakeho driveru je zpristupnit operacnimu systemu. Napsani driveru pro windows bude asi dost slozite, linux by mohl byt alternativou. Mozna ze se timto jiz nekdo zabyval a existuje hotove reseni. Myslim ze by to byl znacny prinos, v mnoha aplikacich by tim mohla odpadnout nutnost nejakeho rozhrani pro stahovani dat ze systemu.
write
ako funguje procedura write? Konkretne cast:
//zápis dat z chars[512] na kartu
dakujem
Podle me fungovat nemuze.
Podle me fungovat nemuze. Ale treba nam to autor vysvetli. :)