Line No. | Rev | Author | Line |
---|---|---|---|
1 | 6 | kaklik | /*! \file mmc.c \brief MultiMedia and SD Flash Card Interface. */ |
2 | //***************************************************************************** |
||
3 | // |
||
4 | // File Name : 'mmc.c' |
||
5 | // Title : MultiMedia and SD Flash Card Interface |
||
6 | // Author : Pascal Stang - Copyright (C) 2004 |
||
7 | // Created : 2004.09.22 |
||
8 | // Revised : 2006.06.12 |
||
9 | // Version : 0.1 |
||
10 | // Target MCU : Atmel AVR Series |
||
11 | // Editor Tabs : 4 |
||
12 | // |
||
13 | // NOTE: This code is currently below version 1.0, and therefore is considered |
||
14 | // to be lacking in some functionality or documentation, or may not be fully |
||
15 | // tested. Nonetheless, you can expect most functions to work. |
||
16 | // |
||
17 | // This code is distributed under the GNU Public License |
||
18 | // which can be found at http://www.gnu.org/licenses/gpl.txt |
||
19 | // |
||
20 | //***************************************************************************** |
||
21 | |||
22 | //----- Include Files --------------------------------------------------------- |
||
23 | #include <avr/io.h> // include I/O definitions (port names, pin names, etc) |
||
24 | #include <avr/interrupt.h> // include interrupt support |
||
25 | |||
26 | #include "global.h" // include our global settings |
||
27 | #include "spi.h" // include spi bus support |
||
28 | |||
29 | #include "rprintf.h" |
||
30 | |||
31 | #include "mmc.h" |
||
32 | |||
33 | // include project-specific hardware configuration |
||
34 | #include "mmcconf.h" |
||
35 | |||
36 | // Global variables |
||
37 | |||
38 | // Functions |
||
39 | |||
40 | void mmcInit(void) |
||
41 | { |
||
42 | // initialize SPI interface |
||
43 | spiInit(); |
||
44 | // release chip select |
||
45 | sbi(MMC_CS_DDR, MMC_CS_PIN); |
||
46 | sbi(MMC_CS_PORT,MMC_CS_PIN); |
||
47 | } |
||
48 | |||
49 | u08 mmcReset(void) |
||
50 | { |
||
51 | u08 i; |
||
52 | u08 retry; |
||
53 | u08 r1=0; |
||
54 | |||
55 | retry = 0; |
||
56 | do |
||
57 | { |
||
58 | // send dummy bytes with CS high before accessing |
||
59 | for(i=0;i<10;i++) spiTransferByte(0xFF); |
||
60 | // resetting card, go to SPI mode |
||
61 | r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0); |
||
62 | #ifdef MMC_DEBUG |
||
63 | rprintf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1); |
||
64 | #endif |
||
65 | // do retry counter |
||
66 | retry++; |
||
67 | if(retry>10) return -1; |
||
68 | } while(r1 != 0x01); |
||
69 | |||
70 | // TODO: check card parameters for voltage compliance |
||
71 | // before issuing initialize command |
||
72 | |||
73 | retry = 0; |
||
74 | do |
||
75 | { |
||
76 | // initializing card for operation |
||
77 | r1 = mmcSendCommand(MMC_SEND_OP_COND, 0); |
||
78 | #ifdef MMC_DEBUG |
||
79 | rprintf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1); |
||
80 | #endif |
||
81 | // do retry counter |
||
82 | retry++; |
||
83 | if(retry>100) return -1; |
||
84 | } while(r1); |
||
85 | |||
86 | // turn off CRC checking to simplify communication |
||
87 | r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0); |
||
88 | #ifdef MMC_DEBUG |
||
89 | rprintf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1); |
||
90 | #endif |
||
91 | |||
92 | // set block length to 512 bytes |
||
93 | r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512); |
||
94 | #ifdef MMC_DEBUG |
||
95 | rprintf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1); |
||
96 | #endif |
||
97 | |||
98 | // return success |
||
99 | return 0; |
||
100 | } |
||
101 | |||
102 | u08 mmcSendCommand(u08 cmd, u32 arg) |
||
103 | { |
||
104 | u08 r1; |
||
105 | |||
106 | // assert chip select |
||
107 | cbi(MMC_CS_PORT,MMC_CS_PIN); |
||
108 | // issue the command |
||
109 | r1 = mmcCommand(cmd, arg); |
||
110 | // release chip select |
||
111 | sbi(MMC_CS_PORT,MMC_CS_PIN); |
||
112 | |||
113 | return r1; |
||
114 | } |
||
115 | |||
116 | u08 mmcRead(u32 sector, u08* buffer) |
||
117 | { |
||
118 | u08 r1; |
||
119 | u16 i; |
||
120 | |||
121 | // assert chip select |
||
122 | cbi(MMC_CS_PORT,MMC_CS_PIN); |
||
123 | // issue command |
||
124 | r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9); |
||
125 | #ifdef MMC_DEBUG |
||
126 | rprintf("MMC Read Block R1=0x%x\r\n", r1); |
||
127 | #endif |
||
128 | // check for valid response |
||
129 | if(r1 != 0x00) |
||
130 | return r1; |
||
131 | // wait for block start |
||
132 | while(spiTransferByte(0xFF) != MMC_STARTBLOCK_READ); |
||
133 | // read in data |
||
134 | for(i=0; i<0x200; i++) |
||
135 | { |
||
136 | *buffer++ = spiTransferByte(0xFF); |
||
137 | } |
||
138 | // read 16-bit CRC |
||
139 | spiTransferByte(0xFF); |
||
140 | spiTransferByte(0xFF); |
||
141 | // release chip select |
||
142 | sbi(MMC_CS_PORT,MMC_CS_PIN); |
||
143 | // return success |
||
144 | return 0; |
||
145 | } |
||
146 | |||
147 | u08 mmcWrite(u32 sector, u08* buffer) |
||
148 | { |
||
149 | u08 r1; |
||
150 | u16 i; |
||
151 | |||
152 | // assert chip select |
||
153 | cbi(MMC_CS_PORT,MMC_CS_PIN); |
||
154 | // issue command |
||
155 | r1 = mmcCommand(MMC_WRITE_BLOCK, sector<<9); |
||
156 | #ifdef MMC_DEBUG |
||
157 | rprintf("MMC Write Block R1=0x%x\r\n", r1); |
||
158 | #endif |
||
159 | // check for valid response |
||
160 | if(r1 != 0x00) |
||
161 | return r1; |
||
162 | // send dummy |
||
163 | spiTransferByte(0xFF); |
||
164 | // send data start token |
||
165 | spiTransferByte(MMC_STARTBLOCK_WRITE); |
||
166 | // write data |
||
167 | for(i=0; i<0x200; i++) |
||
168 | { |
||
169 | spiTransferByte(*buffer++); |
||
170 | } |
||
171 | // write 16-bit CRC (dummy values) |
||
172 | spiTransferByte(0xFF); |
||
173 | spiTransferByte(0xFF); |
||
174 | // read data response token |
||
175 | r1 = spiTransferByte(0xFF); |
||
176 | if( (r1&MMC_DR_MASK) != MMC_DR_ACCEPT) |
||
177 | return r1; |
||
178 | #ifdef MMC_DEBUG |
||
179 | rprintf("Data Response Token=0x%x\r\n", r1); |
||
180 | #endif |
||
181 | // wait until card not busy |
||
182 | while(!spiTransferByte(0xFF)); |
||
183 | // release chip select |
||
184 | sbi(MMC_CS_PORT,MMC_CS_PIN); |
||
185 | // return success |
||
186 | return 0; |
||
187 | } |
||
188 | |||
189 | u08 mmcCommand(u08 cmd, u32 arg) |
||
190 | { |
||
191 | u08 r1; |
||
192 | u08 retry=0; |
||
193 | // send command |
||
194 | spiTransferByte(cmd | 0x40); |
||
195 | spiTransferByte(arg>>24); |
||
196 | spiTransferByte(arg>>16); |
||
197 | spiTransferByte(arg>>8); |
||
198 | spiTransferByte(arg); |
||
199 | spiTransferByte(0x95); // crc valid only for MMC_GO_IDLE_STATE |
||
200 | // end command |
||
201 | // wait for response |
||
202 | // if more than 8 retries, card has timed-out |
||
203 | // return the received 0xFF |
||
204 | while((r1 = spiTransferByte(0xFF)) == 0xFF) |
||
205 | if(retry++ > 8) break; |
||
206 | // return response |
||
207 | return r1; |
||
208 | } |
Powered by WebSVN v2.8.3