test

How can I remove this one?

Committer:
dzbios
Date:
Tue Mar 19 14:47:28 2019 +0000
Revision:
0:76d6402d766d
test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dzbios 0:76d6402d766d 1 /* vim: set ai et ts=4 sw=4: */
dzbios 0:76d6402d766d 2
dzbios 0:76d6402d766d 3 #include "sdcard.h"
dzbios 0:76d6402d766d 4
dzbios 0:76d6402d766d 5 static void SDCARD_Select() {
dzbios 0:76d6402d766d 6 HAL_GPIO_WritePin(SDCARD_CS_GPIO_Port, SDCARD_CS_Pin, GPIO_PIN_RESET);
dzbios 0:76d6402d766d 7 }
dzbios 0:76d6402d766d 8
dzbios 0:76d6402d766d 9 void SDCARD_Unselect() {
dzbios 0:76d6402d766d 10 HAL_GPIO_WritePin(SDCARD_CS_GPIO_Port, SDCARD_CS_Pin, GPIO_PIN_SET);
dzbios 0:76d6402d766d 11 }
dzbios 0:76d6402d766d 12
dzbios 0:76d6402d766d 13 /*
dzbios 0:76d6402d766d 14 R1: 0abcdefg
dzbios 0:76d6402d766d 15 ||||||`- 1th bit (g): card is in idle state
dzbios 0:76d6402d766d 16 |||||`-- 2th bit (f): erase sequence cleared
dzbios 0:76d6402d766d 17 ||||`--- 3th bit (e): illigal command detected
dzbios 0:76d6402d766d 18 |||`---- 4th bit (d): crc check error
dzbios 0:76d6402d766d 19 ||`----- 5th bit (c): error in the sequence of erase commands
dzbios 0:76d6402d766d 20 |`------ 6th bit (b): misaligned addres used in command
dzbios 0:76d6402d766d 21 `------- 7th bit (a): command argument outside allowed range
dzbios 0:76d6402d766d 22 (8th bit is always zero)
dzbios 0:76d6402d766d 23 */
dzbios 0:76d6402d766d 24 static uint8_t SDCARD_ReadR1() {
dzbios 0:76d6402d766d 25 uint8_t r1;
dzbios 0:76d6402d766d 26 // make sure FF is transmitted during receive
dzbios 0:76d6402d766d 27 uint8_t tx = 0xFF;
dzbios 0:76d6402d766d 28 for(;;) {
dzbios 0:76d6402d766d 29 HAL_SPI_TransmitReceive(&SDCARD_SPI_PORT, &tx, &r1, sizeof(r1), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 30 if((r1 & 0x80) == 0) // 8th bit alwyas zero, r1 recevied
dzbios 0:76d6402d766d 31 break;
dzbios 0:76d6402d766d 32 }
dzbios 0:76d6402d766d 33 return r1;
dzbios 0:76d6402d766d 34 }
dzbios 0:76d6402d766d 35
dzbios 0:76d6402d766d 36 // data token for CMD9, CMD17, CMD18 and CMD24 are the same
dzbios 0:76d6402d766d 37 #define DATA_TOKEN_CMD9 0xFE
dzbios 0:76d6402d766d 38 #define DATA_TOKEN_CMD17 0xFE
dzbios 0:76d6402d766d 39 #define DATA_TOKEN_CMD18 0xFE
dzbios 0:76d6402d766d 40 #define DATA_TOKEN_CMD24 0xFE
dzbios 0:76d6402d766d 41 #define DATA_TOKEN_CMD25 0xFC
dzbios 0:76d6402d766d 42
dzbios 0:76d6402d766d 43 static int SDCARD_WaitDataToken(uint8_t token) {
dzbios 0:76d6402d766d 44 uint8_t fb;
dzbios 0:76d6402d766d 45 // make sure FF is transmitted during receive
dzbios 0:76d6402d766d 46 uint8_t tx = 0xFF;
dzbios 0:76d6402d766d 47 for(;;) {
dzbios 0:76d6402d766d 48 HAL_SPI_TransmitReceive(&SDCARD_SPI_PORT, &tx, &fb, sizeof(fb), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 49 if(fb == token)
dzbios 0:76d6402d766d 50 break;
dzbios 0:76d6402d766d 51
dzbios 0:76d6402d766d 52 if(fb != 0xFF)
dzbios 0:76d6402d766d 53 return -1;
dzbios 0:76d6402d766d 54 }
dzbios 0:76d6402d766d 55 return 0;
dzbios 0:76d6402d766d 56 }
dzbios 0:76d6402d766d 57
dzbios 0:76d6402d766d 58 static int SDCARD_ReadBytes(uint8_t* buff, size_t buff_size) {
dzbios 0:76d6402d766d 59 // make sure FF is transmitted during receive
dzbios 0:76d6402d766d 60 uint8_t tx = 0xFF;
dzbios 0:76d6402d766d 61 while(buff_size > 0) {
dzbios 0:76d6402d766d 62 HAL_SPI_TransmitReceive(&SDCARD_SPI_PORT, &tx, buff, 1, HAL_MAX_DELAY);
dzbios 0:76d6402d766d 63 buff++;
dzbios 0:76d6402d766d 64 buff_size--;
dzbios 0:76d6402d766d 65 }
dzbios 0:76d6402d766d 66
dzbios 0:76d6402d766d 67 return 0;
dzbios 0:76d6402d766d 68 }
dzbios 0:76d6402d766d 69
dzbios 0:76d6402d766d 70 static int SDCARD_WaitNotBusy() {
dzbios 0:76d6402d766d 71 uint8_t busy;
dzbios 0:76d6402d766d 72 do {
dzbios 0:76d6402d766d 73 if(SDCARD_ReadBytes(&busy, sizeof(busy)) < 0) {
dzbios 0:76d6402d766d 74 return -1;
dzbios 0:76d6402d766d 75 }
dzbios 0:76d6402d766d 76 } while(busy != 0xFF);
dzbios 0:76d6402d766d 77
dzbios 0:76d6402d766d 78 return 0;
dzbios 0:76d6402d766d 79 }
dzbios 0:76d6402d766d 80
dzbios 0:76d6402d766d 81 int SDCARD_Init(void) {
dzbios 0:76d6402d766d 82 /*
dzbios 0:76d6402d766d 83 Step 1.
dzbios 0:76d6402d766d 84
dzbios 0:76d6402d766d 85 Set DI and CS high and apply 74 or more clock pulses to SCLK. Without this
dzbios 0:76d6402d766d 86 step under certain circumstances SD-card will not work. For instance, when
dzbios 0:76d6402d766d 87 multiple SPI devices are sharing the same bus (i.e. MISO, MOSI, CS).
dzbios 0:76d6402d766d 88 */
dzbios 0:76d6402d766d 89 SDCARD_Unselect();
dzbios 0:76d6402d766d 90
dzbios 0:76d6402d766d 91 uint8_t high = 0xFF;
dzbios 0:76d6402d766d 92 for(int i = 0; i < 10; i++) { // 80 clock pulses
dzbios 0:76d6402d766d 93 HAL_SPI_Transmit(&SDCARD_SPI_PORT, &high, sizeof(high), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 94 }
dzbios 0:76d6402d766d 95
dzbios 0:76d6402d766d 96 SDCARD_Select();
dzbios 0:76d6402d766d 97
dzbios 0:76d6402d766d 98 /*
dzbios 0:76d6402d766d 99 Step 2.
dzbios 0:76d6402d766d 100
dzbios 0:76d6402d766d 101 Send CMD0 (GO_IDLE_STATE): Reset the SD card.
dzbios 0:76d6402d766d 102 */
dzbios 0:76d6402d766d 103 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 104 SDCARD_Unselect();
dzbios 0:76d6402d766d 105 return -1;
dzbios 0:76d6402d766d 106 }
dzbios 0:76d6402d766d 107
dzbios 0:76d6402d766d 108 {
dzbios 0:76d6402d766d 109 static const uint8_t cmd[] =
dzbios 0:76d6402d766d 110 { 0x40 | 0x00 /* CMD0 */, 0x00, 0x00, 0x00, 0x00 /* ARG = 0 */, (0x4A << 1) | 1 /* CRC7 + end bit */ };
dzbios 0:76d6402d766d 111 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 112 }
dzbios 0:76d6402d766d 113
dzbios 0:76d6402d766d 114 if(SDCARD_ReadR1() != 0x01) {
dzbios 0:76d6402d766d 115 SDCARD_Unselect();
dzbios 0:76d6402d766d 116 return -1;
dzbios 0:76d6402d766d 117 }
dzbios 0:76d6402d766d 118
dzbios 0:76d6402d766d 119 /*
dzbios 0:76d6402d766d 120 Step 3.
dzbios 0:76d6402d766d 121
dzbios 0:76d6402d766d 122 After the card enters idle state with a CMD0, send a CMD8 with argument of
dzbios 0:76d6402d766d 123 0x000001AA and correct CRC prior to initialization process. If the CMD8 is
dzbios 0:76d6402d766d 124 rejected with illigal command error (0x05), the card is SDC version 1 or
dzbios 0:76d6402d766d 125 MMC version 3. If accepted, R7 response (R1(0x01) + 32-bit return value)
dzbios 0:76d6402d766d 126 will be returned. The lower 12 bits in the return value 0x1AA means that
dzbios 0:76d6402d766d 127 the card is SDC version 2 and it can work at voltage range of 2.7 to 3.6
dzbios 0:76d6402d766d 128 volts. If not the case, the card should be rejected.
dzbios 0:76d6402d766d 129 */
dzbios 0:76d6402d766d 130 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 131 SDCARD_Unselect();
dzbios 0:76d6402d766d 132 return -1;
dzbios 0:76d6402d766d 133 }
dzbios 0:76d6402d766d 134
dzbios 0:76d6402d766d 135 {
dzbios 0:76d6402d766d 136 static const uint8_t cmd[] =
dzbios 0:76d6402d766d 137 { 0x40 | 0x08 /* CMD8 */, 0x00, 0x00, 0x01, 0xAA /* ARG */, (0x43 << 1) | 1 /* CRC7 + end bit */ };
dzbios 0:76d6402d766d 138 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 139 }
dzbios 0:76d6402d766d 140
dzbios 0:76d6402d766d 141 if(SDCARD_ReadR1() != 0x01) {
dzbios 0:76d6402d766d 142 SDCARD_Unselect();
dzbios 0:76d6402d766d 143 return -2; // not an SDHC/SDXC card (i.e. SDSC, not supported)
dzbios 0:76d6402d766d 144 }
dzbios 0:76d6402d766d 145
dzbios 0:76d6402d766d 146 {
dzbios 0:76d6402d766d 147 uint8_t resp[4];
dzbios 0:76d6402d766d 148 if(SDCARD_ReadBytes(resp, sizeof(resp)) < 0) {
dzbios 0:76d6402d766d 149 SDCARD_Unselect();
dzbios 0:76d6402d766d 150 return -3;
dzbios 0:76d6402d766d 151 }
dzbios 0:76d6402d766d 152
dzbios 0:76d6402d766d 153 if(((resp[2] & 0x01) != 1) || (resp[3] != 0xAA)) {
dzbios 0:76d6402d766d 154 SDCARD_Unselect();
dzbios 0:76d6402d766d 155 return -4;
dzbios 0:76d6402d766d 156 }
dzbios 0:76d6402d766d 157 }
dzbios 0:76d6402d766d 158
dzbios 0:76d6402d766d 159 /*
dzbios 0:76d6402d766d 160 Step 4.
dzbios 0:76d6402d766d 161
dzbios 0:76d6402d766d 162 And then initiate initialization with ACMD41 with HCS flag (bit 30).
dzbios 0:76d6402d766d 163 */
dzbios 0:76d6402d766d 164 for(;;) {
dzbios 0:76d6402d766d 165 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 166 SDCARD_Unselect();
dzbios 0:76d6402d766d 167 return -1;
dzbios 0:76d6402d766d 168 }
dzbios 0:76d6402d766d 169
dzbios 0:76d6402d766d 170 {
dzbios 0:76d6402d766d 171 static const uint8_t cmd[] =
dzbios 0:76d6402d766d 172 { 0x40 | 0x37 /* CMD55 */, 0x00, 0x00, 0x00, 0x00 /* ARG */, (0x7F << 1) | 1 /* CRC7 + end bit */ };
dzbios 0:76d6402d766d 173 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 174 }
dzbios 0:76d6402d766d 175
dzbios 0:76d6402d766d 176 if(SDCARD_ReadR1() != 0x01) {
dzbios 0:76d6402d766d 177 SDCARD_Unselect();
dzbios 0:76d6402d766d 178 return -5;
dzbios 0:76d6402d766d 179 }
dzbios 0:76d6402d766d 180
dzbios 0:76d6402d766d 181 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 182 SDCARD_Unselect();
dzbios 0:76d6402d766d 183 return -1;
dzbios 0:76d6402d766d 184 }
dzbios 0:76d6402d766d 185
dzbios 0:76d6402d766d 186 {
dzbios 0:76d6402d766d 187 static const uint8_t cmd[] =
dzbios 0:76d6402d766d 188 { 0x40 | 0x29 /* ACMD41 */, 0x40, 0x00, 0x00, 0x00 /* ARG */, (0x7F << 1) | 1 /* CRC7 + end bit */ };
dzbios 0:76d6402d766d 189 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 190 }
dzbios 0:76d6402d766d 191
dzbios 0:76d6402d766d 192 uint8_t r1 = SDCARD_ReadR1();
dzbios 0:76d6402d766d 193 if(r1 == 0x00) {
dzbios 0:76d6402d766d 194 break;
dzbios 0:76d6402d766d 195 }
dzbios 0:76d6402d766d 196
dzbios 0:76d6402d766d 197 if(r1 != 0x01) {
dzbios 0:76d6402d766d 198 SDCARD_Unselect();
dzbios 0:76d6402d766d 199 return -6;
dzbios 0:76d6402d766d 200 }
dzbios 0:76d6402d766d 201 }
dzbios 0:76d6402d766d 202
dzbios 0:76d6402d766d 203 /*
dzbios 0:76d6402d766d 204 Step 5.
dzbios 0:76d6402d766d 205
dzbios 0:76d6402d766d 206 After the initialization completed, read OCR register with CMD58 and check
dzbios 0:76d6402d766d 207 CCS flag (bit 30). When it is set, the card is a high-capacity card known
dzbios 0:76d6402d766d 208 as SDHC/SDXC.
dzbios 0:76d6402d766d 209 */
dzbios 0:76d6402d766d 210 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 211 SDCARD_Unselect();
dzbios 0:76d6402d766d 212 return -1;
dzbios 0:76d6402d766d 213 }
dzbios 0:76d6402d766d 214
dzbios 0:76d6402d766d 215 {
dzbios 0:76d6402d766d 216 static const uint8_t cmd[] =
dzbios 0:76d6402d766d 217 { 0x40 | 0x3A /* CMD58 */, 0x00, 0x00, 0x00, 0x00 /* ARG */, (0x7F << 1) | 1 /* CRC7 + end bit */ };
dzbios 0:76d6402d766d 218 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 219 }
dzbios 0:76d6402d766d 220
dzbios 0:76d6402d766d 221 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 222 SDCARD_Unselect();
dzbios 0:76d6402d766d 223 return -7;
dzbios 0:76d6402d766d 224 }
dzbios 0:76d6402d766d 225
dzbios 0:76d6402d766d 226 {
dzbios 0:76d6402d766d 227 uint8_t resp[4];
dzbios 0:76d6402d766d 228 if(SDCARD_ReadBytes(resp, sizeof(resp)) < 0) {
dzbios 0:76d6402d766d 229 SDCARD_Unselect();
dzbios 0:76d6402d766d 230 return -8;
dzbios 0:76d6402d766d 231 }
dzbios 0:76d6402d766d 232
dzbios 0:76d6402d766d 233 if((resp[0] & 0xC0) != 0xC0) {
dzbios 0:76d6402d766d 234 SDCARD_Unselect();
dzbios 0:76d6402d766d 235 return -9;
dzbios 0:76d6402d766d 236 }
dzbios 0:76d6402d766d 237 }
dzbios 0:76d6402d766d 238
dzbios 0:76d6402d766d 239 SDCARD_Unselect();
dzbios 0:76d6402d766d 240 return 0;
dzbios 0:76d6402d766d 241 }
dzbios 0:76d6402d766d 242
dzbios 0:76d6402d766d 243
dzbios 0:76d6402d766d 244 int SDCARD_GetBlocksNumber(uint32_t* num) {
dzbios 0:76d6402d766d 245 uint8_t csd[16];
dzbios 0:76d6402d766d 246 uint8_t crc[2];
dzbios 0:76d6402d766d 247
dzbios 0:76d6402d766d 248 SDCARD_Select();
dzbios 0:76d6402d766d 249
dzbios 0:76d6402d766d 250 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 251 SDCARD_Unselect();
dzbios 0:76d6402d766d 252 return -1;
dzbios 0:76d6402d766d 253 }
dzbios 0:76d6402d766d 254
dzbios 0:76d6402d766d 255 /* CMD9 (SEND_CSD) command */
dzbios 0:76d6402d766d 256 {
dzbios 0:76d6402d766d 257 static const uint8_t cmd[] =
dzbios 0:76d6402d766d 258 { 0x40 | 0x09 /* CMD9 */, 0x00, 0x00, 0x00, 0x00 /* ARG */, (0x7F << 1) | 1 /* CRC7 + end bit */ };
dzbios 0:76d6402d766d 259 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 260 }
dzbios 0:76d6402d766d 261
dzbios 0:76d6402d766d 262 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 263 SDCARD_Unselect();
dzbios 0:76d6402d766d 264 return -2;
dzbios 0:76d6402d766d 265 }
dzbios 0:76d6402d766d 266
dzbios 0:76d6402d766d 267 if(SDCARD_WaitDataToken(DATA_TOKEN_CMD9) < 0) {
dzbios 0:76d6402d766d 268 SDCARD_Unselect();
dzbios 0:76d6402d766d 269 return -3;
dzbios 0:76d6402d766d 270 }
dzbios 0:76d6402d766d 271
dzbios 0:76d6402d766d 272 if(SDCARD_ReadBytes(csd, sizeof(csd)) < 0) {
dzbios 0:76d6402d766d 273 SDCARD_Unselect();
dzbios 0:76d6402d766d 274 return -4;
dzbios 0:76d6402d766d 275 }
dzbios 0:76d6402d766d 276
dzbios 0:76d6402d766d 277 if(SDCARD_ReadBytes(crc, sizeof(crc)) < 0) {
dzbios 0:76d6402d766d 278 SDCARD_Unselect();
dzbios 0:76d6402d766d 279 return -5;
dzbios 0:76d6402d766d 280 }
dzbios 0:76d6402d766d 281
dzbios 0:76d6402d766d 282 SDCARD_Unselect();
dzbios 0:76d6402d766d 283
dzbios 0:76d6402d766d 284 // first byte is VVxxxxxxxx where VV is csd.version
dzbios 0:76d6402d766d 285 if((csd[0] & 0xC0) != 0x40) // csd.version != 1
dzbios 0:76d6402d766d 286 return -6;
dzbios 0:76d6402d766d 287
dzbios 0:76d6402d766d 288 uint32_t tmp = csd[7] & 0x3F; // two bits are reserved
dzbios 0:76d6402d766d 289 tmp = (tmp << 8) | csd[8];
dzbios 0:76d6402d766d 290 tmp = (tmp << 8) | csd[9];
dzbios 0:76d6402d766d 291 tmp = (tmp + 1) << 10;
dzbios 0:76d6402d766d 292 *num = tmp;
dzbios 0:76d6402d766d 293
dzbios 0:76d6402d766d 294 return 0;
dzbios 0:76d6402d766d 295 }
dzbios 0:76d6402d766d 296
dzbios 0:76d6402d766d 297 int SDCARD_ReadSingleBlock(uint32_t blockNum, uint8_t* buff) {
dzbios 0:76d6402d766d 298 uint8_t crc[2];
dzbios 0:76d6402d766d 299
dzbios 0:76d6402d766d 300 SDCARD_Select();
dzbios 0:76d6402d766d 301
dzbios 0:76d6402d766d 302 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 303 SDCARD_Unselect();
dzbios 0:76d6402d766d 304 return -1;
dzbios 0:76d6402d766d 305 }
dzbios 0:76d6402d766d 306
dzbios 0:76d6402d766d 307 /* CMD17 (SEND_SINGLE_BLOCK) command */
dzbios 0:76d6402d766d 308 uint8_t cmd[] = {
dzbios 0:76d6402d766d 309 0x40 | 0x11 /* CMD17 */,
dzbios 0:76d6402d766d 310 (blockNum >> 24) & 0xFF, /* ARG */
dzbios 0:76d6402d766d 311 (blockNum >> 16) & 0xFF,
dzbios 0:76d6402d766d 312 (blockNum >> 8) & 0xFF,
dzbios 0:76d6402d766d 313 blockNum & 0xFF,
dzbios 0:76d6402d766d 314 (0x7F << 1) | 1 /* CRC7 + end bit */
dzbios 0:76d6402d766d 315 };
dzbios 0:76d6402d766d 316 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 317
dzbios 0:76d6402d766d 318 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 319 SDCARD_Unselect();
dzbios 0:76d6402d766d 320 return -2;
dzbios 0:76d6402d766d 321 }
dzbios 0:76d6402d766d 322
dzbios 0:76d6402d766d 323 if(SDCARD_WaitDataToken(DATA_TOKEN_CMD17) < 0) {
dzbios 0:76d6402d766d 324 SDCARD_Unselect();
dzbios 0:76d6402d766d 325 return -3;
dzbios 0:76d6402d766d 326 }
dzbios 0:76d6402d766d 327
dzbios 0:76d6402d766d 328 if(SDCARD_ReadBytes(buff, 512) < 0) {
dzbios 0:76d6402d766d 329 SDCARD_Unselect();
dzbios 0:76d6402d766d 330 return -4;
dzbios 0:76d6402d766d 331 }
dzbios 0:76d6402d766d 332
dzbios 0:76d6402d766d 333 if(SDCARD_ReadBytes(crc, 2) < 0) {
dzbios 0:76d6402d766d 334 SDCARD_Unselect();
dzbios 0:76d6402d766d 335 return -5;
dzbios 0:76d6402d766d 336 }
dzbios 0:76d6402d766d 337
dzbios 0:76d6402d766d 338 SDCARD_Unselect();
dzbios 0:76d6402d766d 339 return 0;
dzbios 0:76d6402d766d 340 }
dzbios 0:76d6402d766d 341
dzbios 0:76d6402d766d 342
dzbios 0:76d6402d766d 343 int SDCARD_WriteSingleBlock(uint32_t blockNum, const uint8_t* buff) {
dzbios 0:76d6402d766d 344 SDCARD_Select();
dzbios 0:76d6402d766d 345
dzbios 0:76d6402d766d 346 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 347 SDCARD_Unselect();
dzbios 0:76d6402d766d 348 return -1;
dzbios 0:76d6402d766d 349 }
dzbios 0:76d6402d766d 350
dzbios 0:76d6402d766d 351 /* CMD24 (WRITE_BLOCK) command */
dzbios 0:76d6402d766d 352 uint8_t cmd[] = {
dzbios 0:76d6402d766d 353 0x40 | 0x18 /* CMD24 */,
dzbios 0:76d6402d766d 354 (blockNum >> 24) & 0xFF, /* ARG */
dzbios 0:76d6402d766d 355 (blockNum >> 16) & 0xFF,
dzbios 0:76d6402d766d 356 (blockNum >> 8) & 0xFF,
dzbios 0:76d6402d766d 357 blockNum & 0xFF,
dzbios 0:76d6402d766d 358 (0x7F << 1) | 1 /* CRC7 + end bit */
dzbios 0:76d6402d766d 359 };
dzbios 0:76d6402d766d 360 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 361
dzbios 0:76d6402d766d 362 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 363 SDCARD_Unselect();
dzbios 0:76d6402d766d 364 return -2;
dzbios 0:76d6402d766d 365 }
dzbios 0:76d6402d766d 366
dzbios 0:76d6402d766d 367 uint8_t dataToken = DATA_TOKEN_CMD24;
dzbios 0:76d6402d766d 368 uint8_t crc[2] = { 0xFF, 0xFF };
dzbios 0:76d6402d766d 369 HAL_SPI_Transmit(&SDCARD_SPI_PORT, &dataToken, sizeof(dataToken), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 370 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)buff, 512, HAL_MAX_DELAY);
dzbios 0:76d6402d766d 371 HAL_SPI_Transmit(&SDCARD_SPI_PORT, crc, sizeof(crc), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 372
dzbios 0:76d6402d766d 373 /*
dzbios 0:76d6402d766d 374 dataResp:
dzbios 0:76d6402d766d 375 xxx0abc1
dzbios 0:76d6402d766d 376 010 - Data accepted
dzbios 0:76d6402d766d 377 101 - Data rejected due to CRC error
dzbios 0:76d6402d766d 378 110 - Data rejected due to write error
dzbios 0:76d6402d766d 379 */
dzbios 0:76d6402d766d 380 uint8_t dataResp;
dzbios 0:76d6402d766d 381 SDCARD_ReadBytes(&dataResp, sizeof(dataResp));
dzbios 0:76d6402d766d 382 if((dataResp & 0x1F) != 0x05) { // data rejected
dzbios 0:76d6402d766d 383 SDCARD_Unselect();
dzbios 0:76d6402d766d 384 return -3;
dzbios 0:76d6402d766d 385 }
dzbios 0:76d6402d766d 386
dzbios 0:76d6402d766d 387 if(SDCARD_WaitNotBusy() < 0) {
dzbios 0:76d6402d766d 388 SDCARD_Unselect();
dzbios 0:76d6402d766d 389 return -4;
dzbios 0:76d6402d766d 390 }
dzbios 0:76d6402d766d 391
dzbios 0:76d6402d766d 392 SDCARD_Unselect();
dzbios 0:76d6402d766d 393 return 0;
dzbios 0:76d6402d766d 394 }
dzbios 0:76d6402d766d 395
dzbios 0:76d6402d766d 396 int SDCARD_ReadBegin(uint32_t blockNum) {
dzbios 0:76d6402d766d 397 SDCARD_Select();
dzbios 0:76d6402d766d 398
dzbios 0:76d6402d766d 399 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 400 SDCARD_Unselect();
dzbios 0:76d6402d766d 401 return -1;
dzbios 0:76d6402d766d 402 }
dzbios 0:76d6402d766d 403
dzbios 0:76d6402d766d 404 /* CMD18 (READ_MULTIPLE_BLOCK) command */
dzbios 0:76d6402d766d 405 uint8_t cmd[] = {
dzbios 0:76d6402d766d 406 0x40 | 0x12 /* CMD18 */,
dzbios 0:76d6402d766d 407 (blockNum >> 24) & 0xFF, /* ARG */
dzbios 0:76d6402d766d 408 (blockNum >> 16) & 0xFF,
dzbios 0:76d6402d766d 409 (blockNum >> 8) & 0xFF,
dzbios 0:76d6402d766d 410 blockNum & 0xFF,
dzbios 0:76d6402d766d 411 (0x7F << 1) | 1 /* CRC7 + end bit */
dzbios 0:76d6402d766d 412 };
dzbios 0:76d6402d766d 413 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 414
dzbios 0:76d6402d766d 415 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 416 SDCARD_Unselect();
dzbios 0:76d6402d766d 417 return -2;
dzbios 0:76d6402d766d 418 }
dzbios 0:76d6402d766d 419
dzbios 0:76d6402d766d 420 SDCARD_Unselect();
dzbios 0:76d6402d766d 421 return 0;
dzbios 0:76d6402d766d 422 }
dzbios 0:76d6402d766d 423
dzbios 0:76d6402d766d 424 int SDCARD_ReadData(uint8_t* buff) {
dzbios 0:76d6402d766d 425 uint8_t crc[2];
dzbios 0:76d6402d766d 426 SDCARD_Select();
dzbios 0:76d6402d766d 427
dzbios 0:76d6402d766d 428 if(SDCARD_WaitDataToken(DATA_TOKEN_CMD18) < 0) {
dzbios 0:76d6402d766d 429 SDCARD_Unselect();
dzbios 0:76d6402d766d 430 return -1;
dzbios 0:76d6402d766d 431 }
dzbios 0:76d6402d766d 432
dzbios 0:76d6402d766d 433 if(SDCARD_ReadBytes(buff, 512) < 0) {
dzbios 0:76d6402d766d 434 SDCARD_Unselect();
dzbios 0:76d6402d766d 435 return -2;
dzbios 0:76d6402d766d 436 }
dzbios 0:76d6402d766d 437
dzbios 0:76d6402d766d 438 if(SDCARD_ReadBytes(crc, 2) < 0) {
dzbios 0:76d6402d766d 439 SDCARD_Unselect();
dzbios 0:76d6402d766d 440 return -3;
dzbios 0:76d6402d766d 441 }
dzbios 0:76d6402d766d 442
dzbios 0:76d6402d766d 443 SDCARD_Unselect();
dzbios 0:76d6402d766d 444 return 0;
dzbios 0:76d6402d766d 445
dzbios 0:76d6402d766d 446 }
dzbios 0:76d6402d766d 447
dzbios 0:76d6402d766d 448 int SDCARD_ReadEnd() {
dzbios 0:76d6402d766d 449 SDCARD_Select();
dzbios 0:76d6402d766d 450
dzbios 0:76d6402d766d 451 /* CMD12 (STOP_TRANSMISSION) */
dzbios 0:76d6402d766d 452 {
dzbios 0:76d6402d766d 453 static const uint8_t cmd[] = { 0x40 | 0x0C /* CMD12 */, 0x00, 0x00, 0x00, 0x00 /* ARG */, (0x7F << 1) | 1 };
dzbios 0:76d6402d766d 454 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 455 }
dzbios 0:76d6402d766d 456
dzbios 0:76d6402d766d 457 /*
dzbios 0:76d6402d766d 458 The received byte immediataly following CMD12 is a stuff byte, it should be
dzbios 0:76d6402d766d 459 discarded before receive the response of the CMD12
dzbios 0:76d6402d766d 460 */
dzbios 0:76d6402d766d 461 uint8_t stuffByte;
dzbios 0:76d6402d766d 462 if(SDCARD_ReadBytes(&stuffByte, sizeof(stuffByte)) < 0) {
dzbios 0:76d6402d766d 463 SDCARD_Unselect();
dzbios 0:76d6402d766d 464 return -1;
dzbios 0:76d6402d766d 465 }
dzbios 0:76d6402d766d 466
dzbios 0:76d6402d766d 467 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 468 SDCARD_Unselect();
dzbios 0:76d6402d766d 469 return -2;
dzbios 0:76d6402d766d 470 }
dzbios 0:76d6402d766d 471
dzbios 0:76d6402d766d 472 SDCARD_Unselect();
dzbios 0:76d6402d766d 473 return 0;
dzbios 0:76d6402d766d 474 }
dzbios 0:76d6402d766d 475
dzbios 0:76d6402d766d 476
dzbios 0:76d6402d766d 477 int SDCARD_WriteBegin(uint32_t blockNum) {
dzbios 0:76d6402d766d 478 SDCARD_Select();
dzbios 0:76d6402d766d 479
dzbios 0:76d6402d766d 480 if(SDCARD_WaitNotBusy() < 0) { // keep this!
dzbios 0:76d6402d766d 481 SDCARD_Unselect();
dzbios 0:76d6402d766d 482 return -1;
dzbios 0:76d6402d766d 483 }
dzbios 0:76d6402d766d 484
dzbios 0:76d6402d766d 485 /* CMD25 (WRITE_MULTIPLE_BLOCK) command */
dzbios 0:76d6402d766d 486 uint8_t cmd[] = {
dzbios 0:76d6402d766d 487 0x40 | 0x19 /* CMD25 */,
dzbios 0:76d6402d766d 488 (blockNum >> 24) & 0xFF, /* ARG */
dzbios 0:76d6402d766d 489 (blockNum >> 16) & 0xFF,
dzbios 0:76d6402d766d 490 (blockNum >> 8) & 0xFF,
dzbios 0:76d6402d766d 491 blockNum & 0xFF,
dzbios 0:76d6402d766d 492 (0x7F << 1) | 1 /* CRC7 + end bit */
dzbios 0:76d6402d766d 493 };
dzbios 0:76d6402d766d 494 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)cmd, sizeof(cmd), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 495
dzbios 0:76d6402d766d 496 if(SDCARD_ReadR1() != 0x00) {
dzbios 0:76d6402d766d 497 SDCARD_Unselect();
dzbios 0:76d6402d766d 498 return -2;
dzbios 0:76d6402d766d 499 }
dzbios 0:76d6402d766d 500
dzbios 0:76d6402d766d 501 SDCARD_Unselect();
dzbios 0:76d6402d766d 502 return 0;
dzbios 0:76d6402d766d 503 }
dzbios 0:76d6402d766d 504
dzbios 0:76d6402d766d 505 int SDCARD_WriteData(const uint8_t* buff) {
dzbios 0:76d6402d766d 506 SDCARD_Select();
dzbios 0:76d6402d766d 507
dzbios 0:76d6402d766d 508 uint8_t dataToken = DATA_TOKEN_CMD25;
dzbios 0:76d6402d766d 509 uint8_t crc[2] = { 0xFF, 0xFF };
dzbios 0:76d6402d766d 510 HAL_SPI_Transmit(&SDCARD_SPI_PORT, &dataToken, sizeof(dataToken), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 511 HAL_SPI_Transmit(&SDCARD_SPI_PORT, (uint8_t*)buff, 512, HAL_MAX_DELAY);
dzbios 0:76d6402d766d 512 HAL_SPI_Transmit(&SDCARD_SPI_PORT, crc, sizeof(crc), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 513
dzbios 0:76d6402d766d 514 /*
dzbios 0:76d6402d766d 515 dataResp:
dzbios 0:76d6402d766d 516 xxx0abc1
dzbios 0:76d6402d766d 517 010 - Data accepted
dzbios 0:76d6402d766d 518 101 - Data rejected due to CRC error
dzbios 0:76d6402d766d 519 110 - Data rejected due to write error
dzbios 0:76d6402d766d 520 */
dzbios 0:76d6402d766d 521 uint8_t dataResp;
dzbios 0:76d6402d766d 522 SDCARD_ReadBytes(&dataResp, sizeof(dataResp));
dzbios 0:76d6402d766d 523 if((dataResp & 0x1F) != 0x05) { // data rejected
dzbios 0:76d6402d766d 524 SDCARD_Unselect();
dzbios 0:76d6402d766d 525 return -1;
dzbios 0:76d6402d766d 526 }
dzbios 0:76d6402d766d 527
dzbios 0:76d6402d766d 528 if(SDCARD_WaitNotBusy() < 0) {
dzbios 0:76d6402d766d 529 SDCARD_Unselect();
dzbios 0:76d6402d766d 530 return -2;
dzbios 0:76d6402d766d 531 }
dzbios 0:76d6402d766d 532
dzbios 0:76d6402d766d 533 SDCARD_Unselect();
dzbios 0:76d6402d766d 534 return 0;
dzbios 0:76d6402d766d 535 }
dzbios 0:76d6402d766d 536
dzbios 0:76d6402d766d 537 int SDCARD_WriteEnd() {
dzbios 0:76d6402d766d 538 SDCARD_Select();
dzbios 0:76d6402d766d 539
dzbios 0:76d6402d766d 540 uint8_t stopTran = 0xFD; // stop transaction token for CMD25
dzbios 0:76d6402d766d 541 HAL_SPI_Transmit(&SDCARD_SPI_PORT, &stopTran, sizeof(stopTran), HAL_MAX_DELAY);
dzbios 0:76d6402d766d 542
dzbios 0:76d6402d766d 543 // skip one byte before readyng "busy"
dzbios 0:76d6402d766d 544 // this is required by the spec and is necessary for some real SD-cards!
dzbios 0:76d6402d766d 545 uint8_t skipByte;
dzbios 0:76d6402d766d 546 SDCARD_ReadBytes(&skipByte, sizeof(skipByte));
dzbios 0:76d6402d766d 547
dzbios 0:76d6402d766d 548 if(SDCARD_WaitNotBusy() < 0) {
dzbios 0:76d6402d766d 549 SDCARD_Unselect();
dzbios 0:76d6402d766d 550 return -1;
dzbios 0:76d6402d766d 551 }
dzbios 0:76d6402d766d 552
dzbios 0:76d6402d766d 553 SDCARD_Unselect();
dzbios 0:76d6402d766d 554 return 0;
dzbios 0:76d6402d766d 555 }
dzbios 0:76d6402d766d 556
dzbios 0:76d6402d766d 557