1 // SPI information obtained from SanDisk's SD card manual
2 // http://www.sandisk.com/pdf/oem/ProdManualSDCardv1.9.pdf
3
4 /*
5 Portions of this code were adapted and used from
6 Radig Ulrich <mail@ulrichradig.de>
7 */
8
9 #define TRUE (0x1)
10 #define FALSE (0x0)
11
12 #define R1_IN_IDLE_STATE (0x1) // The card is in idle state and running initializing process.
13 #define R1_ERASE_RESET (0x2) // An erase sequence was cleared before executing because of an out of erase sequence command was received.
14 #define R1_ILLEGAL_COMMAND (0x4) // An illegal command code was detected
15 #define R1_COM_CRC_ERROR (0x8) // The CRC check of the last command failed.
16 #define R1_ERASE_SEQ_ERROR (0x10) // An error in the sequence of erase commands occured.
17 #define R1_ADDRESS_ERROR (0x20) // A misaligned address, which did not match the block length was used in the command.
18 #define R1_PARAMETER (0x40) // The command's argument (e.g. address, block length) was out of the allowed range for this card.
19
20 #define READ_START_BLOCK (0b11111110)
21 #define WRITE_SINGLE_START_BLOCK (0b11111110)
22 #define WRITE_MULTIPLE_START_BLOCK (0b11111100)
23 #define WRITE_MULTIPLE_STOP_TRAN (0b11111101)
24 #define MMC_DR_MASK 0x1F
25 #define MMC_DR_ACCEPT 0x05
26
27 #define MSTR 4
28 #define SPR0 0
29 #define SPR1 1
30 #define SPE 6
31 #define SPI2X 0
32 #define SPIF 7
33
34 #define MMC_Write PORTB
35 #define MMC_Read PINB
36 #define MMC_Direction_REG DDRB
37
38 #define SPI_DI 6
39 #define SPI_DO 5
40 #define SPI_Clock 7
41 #define MMC_Chip_Select 0
42 #define SPI_SS 4
43
44 #define nop() #asm("nop")
45
46 //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
47 #define MMC_Disable() MMC_Write|= (1<<MMC_Chip_Select);
48
49 //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
50 #define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select);
51
52
53 inline void Write_Byte_MMC(UCHAR Byte)
54 {
55 SPDR = Byte;
56 while(!(SPSR & (1<<SPIF)));
57 }
58 inline UCHAR Read_Byte_MMC(void)
59 {
60 UCHAR Byte;
61 SPDR = 0xff;
62
63 while(!(SPSR & (1<<SPIF)));
64
65 Byte = SPDR;
66 return (Byte);
67 }
68
69 UCHAR Write_Command_MMC(UCHAR *CMD)
70 {
71 UCHAR a;
72 UCHAR tmp = 0xff;
73 UCHAR Timeout = 0;
74
75 // Raise chip select
76 MMC_Disable();
77
78 // Send an 8 bit pulse
79 Write_Byte_MMC(0xFF);
80
81 // Lower chip select
82 MMC_Enable();
83
84 // Send the 6 byte command
85 for (a = 0;a<0x06;a++)
86 {
87 Write_Byte_MMC(*CMD++);
88 }
89
90 // Wait for the response
91 while (tmp == 0xff)
92 {
93 tmp = Read_Byte_MMC();
94 if (Timeout++ > 100)
95 {
96 break;
97 }
98 }
99 // for some reason we need to delay here
100 delay_ms(1);
101
102 return(tmp);
103 }
104
105 UCHAR MmcInit()
106 {
107 UCHAR a,b, retry;
108 UCHAR CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
109
110 // Set certain pins to inputs and others to outputs
111 // Only SPI_DI (data in) is an input
112 MMC_Direction_REG &=~(1<<SPI_DI);
113 MMC_Direction_REG |= (1<<SPI_Clock);
114 MMC_Direction_REG |= (1<<SPI_DO);
115 MMC_Direction_REG |= (1<<MMC_Chip_Select);
116 MMC_Direction_REG |= (1<<SPI_SS);
117 MMC_Write |= (1<<MMC_Chip_Select);
118
119 // We need to wait for the MMC_Direction_REG to be ready
120 for(a=0;a<200;a++)
121 {
122 nop();
123 };
124
125 // Enable SPI in Master Mode with IDLE low and clock at 16E6/128
126 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
127 SPSR = (0<<SPI2X);
128
129 // We need to give the card about a hundred cycles to load
130 for (b = 0; b < 0x0f; ++b)
131 {
132 Write_Byte_MMC(0xff);
133 }
134
135 // Send the initialization commands to the card
136 retry = 0;
137
138 // Note, many examples check for (Write_Command_MMC(CMD) == R1_IN_IDLE_STATE)
139 // However, with our setup the card was in IDLE state and returning another command
140 while((Write_Command_MMC(CMD) & R1_IN_IDLE_STATE) == 0)
141 {
142 // fail and return
143 if (retry++ > 50)
144 {
145 return 1;
146 }
147 }
148
149 // Send the 2nd command
150 retry = 0;
151 CMD[0] = 0x41;
152 CMD[5] = 0xFF;
153 while( Write_Command_MMC (CMD) != 0)
154 {
155 if (retry++ > 50)
156 {
157 return 2;
158 }
159 }
160 // Set the SPI bus to full speed
161 SPCR = SPCR|(0<<SPR0)|(0<<SPR1);
162 SPSR = SPSR|(1<<SPI2X);
163
164 // Raise Chip Select
165 MMC_Disable();
166
167 return 0;
168 }
169
170 UCHAR mmc_write_sector (unsigned long addr,UCHAR *Buffer)
171 {
172 UCHAR tmp;
173 UINT a;
174
175 // Command to write a block to the memory card
176 UCHAR CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
177
178 // Encode the address to a 32-bit address
179 // Ignore the bottom byte of the address as we give the address of the sector
180 CMD[1] = ((addr & 0xFF000000) >> 24);
181 CMD[2] = ((addr & 0x00FF0000) >> 16);
182 CMD[3] = ((addr & 0x0000FF00) >> 8);
183
184 // Send the write command
185 tmp = Write_Command_MMC (CMD);
186 if (tmp != 0)
187 {
188 return(tmp);
189 }
190
191 // Wait a little bit
192 for (a = 0; a < 100; ++a)
193 {
194 Read_Byte_MMC();
195 }
196
197 // Send the start byte
198 Write_Byte_MMC(0xFE);
199
200 // Send all 512 bytes in the buffer
201 for (a = 0; a < 512; ++a)
202 {
203 Write_Byte_MMC(*Buffer++);
204 }
205
206 // Write CRC byte
207 Write_Byte_MMC(0xFF);
208 Write_Byte_MMC(0xFF);
209
210 // Wait for the write to complete
211 while (Read_Byte_MMC() != 0xff);
212
213 // Set MMC_Chip_Select to high
214 MMC_Disable();
215
216 return(0);
217 }
218
219 void MMC_Read_Block(UCHAR *CMD,UCHAR *Buffer,UINT Bytes)
220 {
221 UINT a;
222
223 // Send the read command
224 if (Write_Command_MMC(CMD) != 0)
225 {
226 return;
227 }
228
229 // Send the start byte
230 while (Read_Byte_MMC() != 0xfe);
231
232 // Read off all the bytes in the block
233 for (a = 0; a < Bytes; ++a)
234 {
235 *Buffer++ = Read_Byte_MMC();
236 }
237
238 // Read CRC byte
239 Read_Byte_MMC();
240 Read_Byte_MMC();
241
242 // Set MMC_Chip_Select to high
243 MMC_Disable();
244
245 return;
246 }
247
248 UCHAR mmc_read_sector (unsigned long addr, UCHAR *Buffer)
249 {
250 // Command to read a 512-byte sector
251 UCHAR CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
252
253
254 // Encode the address to a 32-bit address
255 // Ignore the bottom byte of the address as we give the address of the sector
256
257 //addr = addr << 9; //addr = addr * 512
258
259 CMD[1] = ((addr & 0xFF000000) >> 24);
260 CMD[2] = ((addr & 0x00FF0000) >> 16);
261 CMD[3] = ((addr & 0x0000FF00) >> 8);
262
263 MMC_Read_Block(CMD,Buffer,512);
264
265 return(0);
266 }