Mercurial > ~darius > hgwebdir.cgi > stm32temp
comparison sd.c @ 50:d7207a9d3c3b
Add write support. LFN still broken though.
Make sure we wait for the card to be done after a read or write (didn't seem to break reading but hosed writes).
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Fri, 05 Apr 2013 00:08:31 +1030 |
parents | ace431a0d0f5 |
children | 79c7892d07b3 |
comparison
equal
deleted
inserted
replaced
49:ace431a0d0f5 | 50:d7207a9d3c3b |
---|---|
46 #define FAT_SEC(t) (((t) & 0x001f) << 1) | 46 #define FAT_SEC(t) (((t) & 0x001f) << 1) |
47 | 47 |
48 static FATFS fsh; | 48 static FATFS fsh; |
49 | 49 |
50 static void sd_domount(void); | 50 static void sd_domount(void); |
51 char *sderr2str(SD_Error err); | |
52 void dump_buf(uint8_t *buf, uint32_t size); | |
51 | 53 |
52 void | 54 void |
53 sd_init(void) { | 55 sd_init(void) { |
54 sd_domount(); | 56 sd_domount(); |
55 } | 57 } |
58 sd_domount(void) { | 60 sd_domount(void) { |
59 SD_Error err; | 61 SD_Error err; |
60 FRESULT fserr; | 62 FRESULT fserr; |
61 | 63 |
62 if ((err = SD_Init()) != SD_OK) { | 64 if ((err = SD_Init()) != SD_OK) { |
63 printf("Failed init: %d\n", err); | 65 printf("Failed init: %s\n", sderr2str(err)); |
64 return; | 66 return; |
65 } | 67 } |
66 | 68 |
67 if ((fserr = f_mount(0, &fsh)) != FR_OK) { | 69 if ((fserr = f_mount(0, &fsh)) != FR_OK) { |
68 printf("Unable to mount FS\n"); | 70 printf("Unable to mount FS\n"); |
80 } | 82 } |
81 | 83 |
82 if (!strcmp(argv[0], "info")) { | 84 if (!strcmp(argv[0], "info")) { |
83 SD_CardInfo cardinfo; | 85 SD_CardInfo cardinfo; |
84 if ((err = SD_GetCardInfo(&cardinfo)) != SD_OK) { | 86 if ((err = SD_GetCardInfo(&cardinfo)) != SD_OK) { |
85 printf("Get card info failed: %d\r\b", err); | 87 printf("Get card info failed: %s\r\b", sderr2str(err)); |
86 } else { | 88 } else { |
87 printf("Mfg ID %" PRIu8 ", OEM %" PRIu16 ", Prod1 %" PRIu32 ", Prod2 %" PRIu8 ", Rev %" PRIu8 ", SN %" PRIu32 ", Mfg %" PRIu16 "\n", | 89 printf("Mfg ID %" PRIu8 ", OEM %" PRIu16 ", Prod1 %" PRIu32 ", Prod2 %" PRIu8 ", Rev %" PRIu8 ", SN %" PRIu32 ", Mfg %" PRIu16 "\n", |
88 cardinfo.SD_cid.ManufacturerID, cardinfo.SD_cid.OEM_AppliID, | 90 cardinfo.SD_cid.ManufacturerID, cardinfo.SD_cid.OEM_AppliID, |
89 cardinfo.SD_cid.ProdName1, cardinfo.SD_cid.ProdName2, | 91 cardinfo.SD_cid.ProdName1, cardinfo.SD_cid.ProdName2, |
90 cardinfo.SD_cid.ProdRev, cardinfo.SD_cid.ProdSN, | 92 cardinfo.SD_cid.ProdRev, cardinfo.SD_cid.ProdSN, |
91 cardinfo.SD_cid.ManufactDate); | 93 cardinfo.SD_cid.ManufactDate); |
92 printf("Capacity %" PRIu32 ", blocksize %" PRIu32 "\n", cardinfo.CardCapacity, cardinfo.CardBlockSize); | 94 printf("Capacity %" PRIu32 ", blocksize %" PRIu32 "\n", cardinfo.CardCapacity, cardinfo.CardBlockSize); |
93 } | 95 } |
94 } else if (!strcmp(argv[0], "mount")) { | 96 } else if (!strcmp(argv[0], "mount")) { |
95 sd_domount(); | 97 sd_domount(); |
96 } else if (!strcmp(argv[0], "read")) { | 98 } else if (!strcmp(argv[0], "rdb")) { |
97 uint32_t addr; | 99 uint32_t addr; |
98 uint8_t *buf; | 100 uint8_t *buf; |
99 uint32_t i; | 101 uint32_t i; |
100 | 102 |
101 if (argc != 2) { | 103 if (argc != 2) { |
109 return; | 111 return; |
110 } | 112 } |
111 | 113 |
112 /* If passed values not modulo 512 it hangs */ | 114 /* If passed values not modulo 512 it hangs */ |
113 if ((err = SD_ReadBlock(buf, addr * SD_BLOCK_SIZE, SD_BLOCK_SIZE)) != SD_OK) { | 115 if ((err = SD_ReadBlock(buf, addr * SD_BLOCK_SIZE, SD_BLOCK_SIZE)) != SD_OK) { |
114 printf("Read block returned %d\n", err); | 116 printf("Read block returned %s\n", sderr2str(err)); |
115 goto read_exit; | 117 goto read_exit; |
116 } | 118 } |
117 | 119 |
118 #ifdef SD_DMA_MODE | 120 #ifdef SD_DMA_MODE |
119 if ((err = SD_WaitReadOperation()) != SD_OK) { | 121 if ((err = SD_WaitReadOperation()) != SD_OK) { |
120 printf("Wait returned %d\n", err); | 122 printf("Wait returned %s\n", sderr2str(err)); |
121 goto read_exit; | 123 goto read_exit; |
122 } | 124 } |
123 #endif | 125 #endif |
124 while(SD_GetStatus() != SD_TRANSFER_OK) | 126 while(SD_GetStatus() != SD_TRANSFER_OK) |
125 ; | 127 ; |
126 | 128 |
127 for (i = 0; i < SD_BLOCK_SIZE; i += 16) { | 129 dump_buf(buf, SD_BLOCK_SIZE); |
128 printf("0x%04lx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i, | |
129 buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7], | |
130 buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11], buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]); | |
131 } | |
132 | 130 |
133 read_exit: | 131 read_exit: |
132 free(buf); | |
133 } else if (!strcmp(argv[0], "wrb")) { | |
134 uint32_t addr; | |
135 uint8_t *buf; | |
136 uint32_t i; | |
137 | |
138 if (argc < 3) { | |
139 printf("Block to read and/or fill value(s) not specified\n"); | |
140 return; | |
141 } | |
142 addr = atoi(argv[1]); | |
143 | |
144 if ((buf = malloc(SD_BLOCK_SIZE)) == NULL) { | |
145 printf("Unable to allocate buffer\n"); | |
146 return; | |
147 } | |
148 | |
149 for (i = 0; i < SD_BLOCK_SIZE; i++) { | |
150 //buf[i] = atoi(argv[(i % (argc - 2)) + 2]); | |
151 if (i < argc - 2) | |
152 buf[i] = atoi(argv[i + 2]); | |
153 else | |
154 buf[i] = 0; | |
155 } | |
156 | |
157 /* If passed values not modulo 512 it hangs */ | |
158 if ((err = SD_WriteBlock(buf, addr * SD_BLOCK_SIZE, SD_BLOCK_SIZE)) != SD_OK) { | |
159 printf("Write block returned %s\n", sderr2str(err)); | |
160 goto write_exit; | |
161 } | |
162 | |
163 #ifdef SD_DMA_MODE | |
164 if ((err = SD_WaitWriteOperation()) != SD_OK) { | |
165 printf("Wait returned %s\n", sderr2str(err)); | |
166 goto write_exit; | |
167 } | |
168 #endif | |
169 while(SD_GetStatus() != SD_TRANSFER_OK) | |
170 ; | |
171 | |
172 write_exit: | |
134 free(buf); | 173 free(buf); |
135 } else if (!strcmp(argv[0], "erase")) { | 174 } else if (!strcmp(argv[0], "erase")) { |
136 uint32_t addr; | 175 uint32_t addr; |
137 | 176 |
138 if (argc != 2) { | 177 if (argc != 2) { |
140 return; | 179 return; |
141 } | 180 } |
142 addr = atoi(argv[1]); | 181 addr = atoi(argv[1]); |
143 | 182 |
144 if ((err = SD_Erase(addr * SD_BLOCK_SIZE, (addr + 1) * SD_BLOCK_SIZE)) != SD_OK) { | 183 if ((err = SD_Erase(addr * SD_BLOCK_SIZE, (addr + 1) * SD_BLOCK_SIZE)) != SD_OK) { |
145 printf("Erase block returned %d\n", err); | 184 printf("Erase block returned %s\n", sderr2str(err)); |
146 goto read_exit; | 185 goto read_exit; |
147 } | 186 } |
148 | 187 |
149 #ifdef SD_DMA_MODE | 188 #ifdef SD_DMA_MODE |
150 if ((err = SD_WaitReadOperation()) != SD_OK) { | 189 if ((err = SD_WaitReadOperation()) != SD_OK) { |
151 printf("Wait returned %d\n", err); | 190 printf("Wait returned %s\n", sderr2str(err)); |
152 goto read_exit; | 191 goto read_exit; |
153 } | 192 } |
154 #endif | 193 #endif |
155 while(SD_GetStatus() != SD_TRANSFER_OK) | 194 while(SD_GetStatus() != SD_TRANSFER_OK) |
156 ; | 195 ; |
157 printf("Erased OK\n"); | 196 printf("Erased OK\n"); |
197 } else if (!strcmp(argv[0], "mkfs")) { | |
198 FRESULT fserr; | |
199 if ((fserr = f_mkfs(0, 0, 0)) != FR_OK) { | |
200 printf("Unable to mkfs: %d\n", fserr); | |
201 } | |
158 } else if (!strcmp(argv[0], "ls")) { | 202 } else if (!strcmp(argv[0], "ls")) { |
159 FRESULT fserr; | 203 FRESULT fserr; |
160 DIR d; | 204 DIR d; |
161 FILINFO fno; | 205 FILINFO fno; |
162 char *fn; | 206 char *fn; |
163 char label[12]; | 207 char label[12]; |
164 DWORD sn; | 208 DWORD sn; |
165 | 209 |
166 if ((fserr = f_getlabel("", label, &sn)) != FR_OK) { | 210 if ((fserr = f_getlabel("", label, &sn)) != FR_OK) { |
167 printf("Unable to read label\n"); | 211 printf("Unable to read label: %d\n", fserr); |
168 } else { | 212 } else { |
169 printf("Label: %s Serial: %d\n", label, sn); | 213 printf("Label: %s Serial: %d\n", label, sn); |
170 } | 214 } |
171 | 215 |
172 if ((fserr = f_opendir(&d, argc == 1 ? "\\" : argv[1])) != FR_OK) { | 216 if ((fserr = f_opendir(&d, argc == 1 ? "\\" : argv[1])) != FR_OK) { |
210 } | 254 } |
211 | 255 |
212 while ((tmp = f_gets(buf, sizeof(buf), &f)) != NULL) { | 256 while ((tmp = f_gets(buf, sizeof(buf), &f)) != NULL) { |
213 puts(tmp); | 257 puts(tmp); |
214 } | 258 } |
259 | |
260 f_close(&f); | |
261 | |
262 } else if (!strcmp(argv[0], "wr")) { | |
263 FRESULT fserr; | |
264 FIL f; | |
265 | |
266 if (argc != 3) { | |
267 printf("No file and/or text given\n"); | |
268 return; | |
269 } | |
270 | |
271 if ((fserr = f_open(&f, argv[1], FA_WRITE | FA_OPEN_ALWAYS)) != FR_OK) { | |
272 printf("Failed to open file: %d\n", fserr); | |
273 return; | |
274 } | |
275 | |
276 if ((fserr = f_lseek(&f, f_size(&f))) != FR_OK) { | |
277 printf("Failed to seek to end of file: %d\n", fserr); | |
278 goto wr_out; | |
279 } | |
280 | |
281 f_puts(argv[2], &f); | |
282 f_putc('\n', &f); | |
283 wr_out: | |
284 f_close(&f); | |
285 } else if (!strcmp(argv[0], "rm")) { | |
286 FRESULT fserr; | |
287 | |
288 if (argc != 2) { | |
289 printf("No file given\n"); | |
290 return; | |
291 } | |
292 | |
293 if ((fserr = f_unlink(argv[1])) != FR_OK) { | |
294 printf("Failed to remove file: %d\n", fserr); | |
295 return; | |
296 } | |
215 } else { | 297 } else { |
216 printf("Unknown command\n"); | 298 printf("Unknown command\n"); |
217 } | 299 } |
218 } | 300 } |
219 | 301 |
292 | 374 |
293 uint32_t SD_DMAEndOfTransferStatus(void) { | 375 uint32_t SD_DMAEndOfTransferStatus(void) { |
294 return (uint32_t)DMA_GetFlagStatus(DMA2_FLAG_TC4); | 376 return (uint32_t)DMA_GetFlagStatus(DMA2_FLAG_TC4); |
295 } | 377 } |
296 | 378 |
297 | 379 char * |
298 | 380 sderr2str(SD_Error err) { |
381 switch (err) { | |
382 case SD_CMD_CRC_FAIL: | |
383 return "CMD_CRC_FAIL"; | |
384 case SD_DATA_CRC_FAIL: | |
385 return "DATA_CRC_FAIL"; | |
386 case SD_CMD_RSP_TIMEOUT: | |
387 return "CMD_RSP_TIMEOUT"; | |
388 case SD_DATA_TIMEOUT: | |
389 return "DATA_TIMEOUT"; | |
390 case SD_TX_UNDERRUN: | |
391 return "TX_UNDERRUN"; | |
392 case SD_RX_OVERRUN: | |
393 return "RX_OVERRUN"; | |
394 case SD_START_BIT_ERR: | |
395 return "START_BIT_ERR"; | |
396 case SD_CMD_OUT_OF_RANGE: | |
397 return "CMD_OUT_OF_RANGE"; | |
398 case SD_ADDR_MISALIGNED: | |
399 return "ADDR_MISALIGNED"; | |
400 case SD_BLOCK_LEN_ERR: | |
401 return "BLOCK_LEN_ERR"; | |
402 case SD_ERASE_SEQ_ERR: | |
403 return "ERASE_SEQ_ERR"; | |
404 case SD_BAD_ERASE_PARAM: | |
405 return "BAD_ERASE_PARAM"; | |
406 case SD_WRITE_PROT_VIOLATION: | |
407 return "WRITE_PROT_VIOLATION"; | |
408 case SD_LOCK_UNLOCK_FAILED: | |
409 return "LOCK_UNLOCK_FAILED"; | |
410 case SD_COM_CRC_FAILED: | |
411 return "COM_CRC_FAILED"; | |
412 case SD_ILLEGAL_CMD: | |
413 return "ILLEGAL_CMD"; | |
414 case SD_CARD_ECC_FAILED: | |
415 return "CARD_ECC_FAILED"; | |
416 case SD_CC_ERROR: | |
417 return "CC_ERROR"; | |
418 case SD_GENERAL_UNKNOWN_ERROR: | |
419 return "GENERAL_UNKNOWN_ERROR"; | |
420 case SD_STREAM_READ_UNDERRUN: | |
421 return "STREAM_READ_UNDERRUN"; | |
422 case SD_STREAM_WRITE_OVERRUN: | |
423 return "STREAM_WRITE_OVERRUN"; | |
424 case SD_CID_CSD_OVERWRITE: | |
425 return "OVERWRITE"; | |
426 case SD_WP_ERASE_SKIP: | |
427 return "WP_ERASE_SKIP"; | |
428 case SD_CARD_ECC_DISABLED: | |
429 return "CARD_ECC_DISABLED"; | |
430 case SD_ERASE_RESET: | |
431 return "ERASE_RESET"; | |
432 case SD_AKE_SEQ_ERROR: | |
433 return "AKE_SEQ_ERROR"; | |
434 case SD_INVALID_VOLTRANGE: | |
435 return "INVALID_VOLTRANGE"; | |
436 case SD_ADDR_OUT_OF_RANGE: | |
437 return "ADDR_OUT_OF_RANGE"; | |
438 case SD_SWITCH_ERROR: | |
439 return "SWITCH_ERROR"; | |
440 case SD_SDIO_DISABLED: | |
441 return "SDIO_DISABLED"; | |
442 case SD_SDIO_FUNCTION_BUSY: | |
443 return "SDIO_FUNCTION_BUSY"; | |
444 case SD_SDIO_FUNCTION_FAILED: | |
445 return "SDIO_FUNCTION_FAILED"; | |
446 case SD_SDIO_UNKNOWN_FUNCTION: | |
447 return "SDIO_UNKNOWN_FUNCTION"; | |
448 case SD_INTERNAL_ERROR: | |
449 return "INTERNAL_ERROR"; | |
450 case SD_NOT_CONFIGURED: | |
451 return "NOT_CONFIGURED"; | |
452 case SD_REQUEST_PENDING: | |
453 return "REQUEST_PENDING"; | |
454 case SD_REQUEST_NOT_APPLICABLE: | |
455 return "REQUEST_NOT_APPLICABLE"; | |
456 case SD_INVALID_PARAMETER: | |
457 return "INVALID_PARAMETER"; | |
458 case SD_UNSUPPORTED_FEATURE: | |
459 return "UNSUPPORTED_FEATURE"; | |
460 case SD_UNSUPPORTED_HW: | |
461 return "UNSUPPORTED_HW"; | |
462 case SD_ERROR: | |
463 return "ERROR"; | |
464 case SD_OK: | |
465 return "OK"; | |
466 default: | |
467 return "Unknown"; | |
468 } | |
469 } | |
470 | |
471 | |
472 void dump_buf(uint8_t *buf, uint32_t size) { | |
473 uint32_t i; | |
474 | |
475 for (i = 0; i < size; i += 16) { | |
476 printf("0x%04lx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i, | |
477 buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7], | |
478 buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11], buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]); | |
479 } | |
480 } |