changeset 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 590886732da9
files BSDmakefile fatfs/ffconf.h fatfs_sd.c sd.c stm32_eval.h
diffstat 5 files changed, 279 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/BSDmakefile	Wed Apr 03 23:34:20 2013 +1030
+++ b/BSDmakefile	Fri Apr 05 00:08:31 2013 +1030
@@ -21,6 +21,8 @@
 		tempctrl.c \
 		touch.c
 
+#SRCS+=		ccsbcs.c
+
 STM32LIBS=	usart gpio rcc rtc pwr bkp fsmc spi tim i2c crc sdio dma
 
 .for f in ${STM32LIBS}
--- a/fatfs/ffconf.h	Wed Apr 03 23:34:20 2013 +1030
+++ b/fatfs/ffconf.h	Fri Apr 05 00:08:31 2013 +1030
@@ -20,7 +20,7 @@
 /  data transfer. This reduces memory consumption 512 bytes each file object. */
 
 
-#define _FS_READONLY	01/* 0:Read/Write or 1:Read only */
+#define _FS_READONLY	0/* 0:Read/Write or 1:Read only */
 /* Setting _FS_READONLY to 1 defines read only configuration. This removes
 /  writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
 /  f_truncate and useless f_getfree. */
--- a/fatfs_sd.c	Wed Apr 03 23:34:20 2013 +1030
+++ b/fatfs_sd.c	Fri Apr 05 00:08:31 2013 +1030
@@ -32,21 +32,40 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
+#include "delay.h"
 #include "stm32f10x.h"
 #include "stm32_eval_sdio_sd.h"
 #include "diskio.h"
 
+#if 0
+#define DEBUG(fmt, ...) printf("%s: " fmt, __FUNCTION__, ## __VA_ARGS__)
+#else
+#define DEBUG(...)
+#endif
+
+char *sderr2str(SD_Error err);
+void dump_buf(uint8_t *buf, uint32_t size);
+
+static SD_CardInfo cardinfo;
+
 DSTATUS
 disk_initialize(BYTE pdrv) {
     SD_Error err;
     
+    DEBUG("disk_initialize(%d)\n", pdrv);
+    
     /* Only have 1 disk */
     if (pdrv != 0)
 	return STA_NOINIT;
     
     if ((err = SD_Init()) != SD_OK) {
-	printf("Failed init: %d\r\n", err);
+	printf("Failed init: %s\n", sderr2str(err));
+	return STA_NOINIT;
+    }
+    if ((err = SD_GetCardInfo(&cardinfo)) != SD_OK) {
+	printf("Get card info failed: %s\n", sderr2str(err));
 	return STA_NOINIT;
     }
 
@@ -55,6 +74,8 @@
 
 DSTATUS
 disk_status(BYTE pdrv) {
+    DEBUG("disk_status(%d)\n", pdrv);
+    
     if (pdrv != 0)
 	return STA_NOINIT;
 
@@ -65,6 +86,8 @@
 disk_read(BYTE pdrv, BYTE *buff, DWORD sector, BYTE count) {
     SD_Error err;
     
+    DEBUG("disk_read(%d, 0x%08x, %d, %d)\n", pdrv, buff, sector, count);
+
     if (pdrv != 0)
 	return STA_NOINIT;
 
@@ -73,29 +96,61 @@
     else
 	err = SD_ReadMultiBlocks(buff, sector * SD_BLOCK_SIZE, SD_BLOCK_SIZE, count);
     
+#ifdef SD_DMA_MODE
+    if ((err = SD_WaitReadOperation()) != SD_OK) {
+	printf("Wait returned %s\n", sderr2str(err));
+	goto read_exit;
+    }
+#endif
     if (err != SD_OK) {
-	printf("Read failed: %d\r\n", err);
+	printf("Read failed: %s\n", sderr2str(err));
 	return STA_NOINIT;
     }
     
+    while(SD_GetStatus() != SD_TRANSFER_OK)
+	;
+
     return RES_OK;
 }
 
 DRESULT
 disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, BYTE count) {
+    SD_Error err;
+    
+    DEBUG("disk_write(%d, 0x%08x, %d, %d)\n", pdrv, buff, sector, count);
     if (pdrv != 0)
-	return STA_NOINIT;
+	return RES_NOTRDY;
+
+    if (count == 1)
+	err = SD_WriteBlock(buff, sector * SD_BLOCK_SIZE, SD_BLOCK_SIZE);
+    else
+	err = SD_WriteMultiBlocks(buff, sector * SD_BLOCK_SIZE, SD_BLOCK_SIZE, count);
 
-    return RES_WRPRT;
+#ifdef SD_DMA_MODE
+    if ((err = SD_WaitReadOperation()) != SD_OK) {
+	printf("Wait returned %s\n", sderr2str(err));
+	goto read_exit;
+    }
+#endif
+    if (err != SD_OK) {
+	printf("Write failed: %s\n", sderr2str(err));
+	return RES_ERROR;
+    }
+    
+    while(SD_GetStatus() != SD_TRANSFER_OK)
+	;
+    
+    return RES_OK;
 }
 
 DRESULT
 disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
     WORD *wd;
     DWORD *dwd;
-    SD_CardInfo cardinfo;
     SD_Error err;
     
+    DEBUG("disk_ioctl(%d, %d, ...)\n", pdrv, cmd);
+    
     wd = buff;
     dwd = buff;
     
@@ -103,38 +158,27 @@
 	return STA_NOINIT;
     switch (cmd) {
 	case CTRL_SYNC:
-	    printf("Sync\r\n");
+	    DEBUG("Sync\n");
 	    break;
 
 	case GET_SECTOR_SIZE:
-	    printf("Get sector size\r\n");
 	    *wd = SD_BLOCK_SIZE;
+	    DEBUG("Get sector size (%d)\n", *wd);
 	    break;
 	    
 	case GET_SECTOR_COUNT:
-	    printf("Get sector count\r\n");
-
-	    if ((err = SD_GetCardInfo(&cardinfo)) != SD_OK) {
-		printf("Get card info failed: %d\r\b", err);
-		return RES_ERROR;
-	    }
 	    *dwd = cardinfo.CardCapacity / SD_BLOCK_SIZE;
+	    DEBUG("Get sector count (%d)\n", *dwd);
 	    break;
 	    
 	case GET_BLOCK_SIZE:
-	    printf("Get block size\r\n");
-
-	    if ((err = SD_GetCardInfo(&cardinfo)) != SD_OK) {
-		printf("Get card info failed: %d\r\b", err);
-		return RES_ERROR;
-	    }
-	    
 	    /* FatFS wants log2(blocksize) */
 	    *dwd = 0;
 	    while (cardinfo.CardBlockSize > 0) {
-		*dwd++;
+		*dwd = *dwd + 1;
 		cardinfo.CardBlockSize >>= 1;
 	    }
+	    DEBUG("Get block size (%d)\n", *dwd);
 	    break;
 
 	case CTRL_ERASE_SECTOR:
@@ -155,7 +199,20 @@
 */
 DWORD
 get_fattime(void) {
-    return 0;
+    struct tm now;
+    time_t t;
+    DWORD res;
+
+    t = time(NULL);
+    localtime_r(&t, &now);
+    res = ((now.tm_year - 80) << 25 |
+	   ((now.tm_mon + 1) << 21) |
+	   (now.tm_mday << 16) |
+	   (now.tm_hour << 11) |
+	   (now.tm_min << 5) |
+	   (now.tm_sec >> 1));
+
+    return res;
 }
 
 void *
--- a/sd.c	Wed Apr 03 23:34:20 2013 +1030
+++ b/sd.c	Fri Apr 05 00:08:31 2013 +1030
@@ -48,6 +48,8 @@
 static FATFS fsh;
 
 static void sd_domount(void);
+char *sderr2str(SD_Error err);
+void dump_buf(uint8_t *buf, uint32_t size);
 
 void
 sd_init(void) {
@@ -60,7 +62,7 @@
     FRESULT fserr;
 
     if ((err = SD_Init()) != SD_OK) {
-	printf("Failed init: %d\n", err);
+	printf("Failed init: %s\n", sderr2str(err));
 	return;
     }
     
@@ -82,7 +84,7 @@
     if (!strcmp(argv[0], "info")) {
 	SD_CardInfo cardinfo;
 	if ((err = SD_GetCardInfo(&cardinfo)) != SD_OK) {
-	    printf("Get card info failed: %d\r\b", err);
+	    printf("Get card info failed: %s\r\b", sderr2str(err));
 	} else {
 	    printf("Mfg ID %" PRIu8 ", OEM %" PRIu16 ", Prod1 %" PRIu32 ", Prod2 %" PRIu8 ", Rev %" PRIu8 ", SN %" PRIu32 ", Mfg %" PRIu16 "\n",
 		   cardinfo.SD_cid.ManufacturerID, cardinfo.SD_cid.OEM_AppliID,
@@ -93,7 +95,7 @@
 	}
     } else if (!strcmp(argv[0], "mount")) {
 	sd_domount();
-    } else if (!strcmp(argv[0], "read")) {
+    } else if (!strcmp(argv[0], "rdb")) {
 	uint32_t addr;
 	uint8_t *buf;
 	uint32_t i;
@@ -111,26 +113,63 @@
 	
 	/* If passed values not modulo 512 it hangs */
 	if ((err = SD_ReadBlock(buf, addr * SD_BLOCK_SIZE, SD_BLOCK_SIZE)) != SD_OK) {
-	    printf("Read block returned %d\n", err);
+	    printf("Read block returned %s\n", sderr2str(err));
 	    goto read_exit;
 	}
 	
 #ifdef SD_DMA_MODE
 	if ((err = SD_WaitReadOperation()) != SD_OK) {
-	    printf("Wait returned %d\n", err);
+	    printf("Wait returned %s\n", sderr2str(err));
 	    goto read_exit;
 	}
 #endif
 	while(SD_GetStatus() != SD_TRANSFER_OK)
 	    ;
 
-	for (i = 0; i < SD_BLOCK_SIZE; i += 16) {
-	    printf("0x%04lx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
-		   buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7],
-		   buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11], buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]);
+	dump_buf(buf, SD_BLOCK_SIZE);
+	
+      read_exit:
+	free(buf);
+    } else if (!strcmp(argv[0], "wrb")) {
+	uint32_t addr;
+	uint8_t *buf;
+	uint32_t i;
+	
+	if (argc < 3) {
+	    printf("Block to read and/or fill value(s) not specified\n");
+	    return;
+	}
+	addr = atoi(argv[1]);
+
+	if ((buf = malloc(SD_BLOCK_SIZE)) == NULL) {
+	    printf("Unable to allocate buffer\n");
+	    return;
 	}
 	
-      read_exit:
+	for (i = 0; i < SD_BLOCK_SIZE; i++) {
+	    //buf[i] = atoi(argv[(i % (argc - 2)) + 2]);
+	    if (i < argc - 2)
+		buf[i] = atoi(argv[i + 2]);
+	    else
+		buf[i] = 0;
+	}
+
+	/* If passed values not modulo 512 it hangs */
+	if ((err = SD_WriteBlock(buf, addr * SD_BLOCK_SIZE, SD_BLOCK_SIZE)) != SD_OK) {
+	    printf("Write block returned %s\n", sderr2str(err));
+	    goto write_exit;
+	}
+	
+#ifdef SD_DMA_MODE
+	if ((err = SD_WaitWriteOperation()) != SD_OK) {
+	    printf("Wait returned %s\n", sderr2str(err));
+	    goto write_exit;
+	}
+#endif
+	while(SD_GetStatus() != SD_TRANSFER_OK)
+	    ;
+
+      write_exit:
 	free(buf);
     } else if (!strcmp(argv[0], "erase")) {
 	uint32_t addr;
@@ -142,19 +181,24 @@
 	addr = atoi(argv[1]);
 	
 	if ((err = SD_Erase(addr * SD_BLOCK_SIZE, (addr + 1) * SD_BLOCK_SIZE)) != SD_OK) {
-	    printf("Erase block returned %d\n", err);
+	    printf("Erase block returned %s\n", sderr2str(err));
 	    goto read_exit;
 	}
 	
 #ifdef SD_DMA_MODE
 	if ((err = SD_WaitReadOperation()) != SD_OK) {
-	    printf("Wait returned %d\n", err);
+	    printf("Wait returned %s\n", sderr2str(err));
 	    goto read_exit;
 	}
 #endif
 	while(SD_GetStatus() != SD_TRANSFER_OK)
 	    ;
 	printf("Erased OK\n");
+    } else if (!strcmp(argv[0], "mkfs")) {
+	FRESULT fserr;
+	if ((fserr = f_mkfs(0, 0, 0)) != FR_OK) {
+	    printf("Unable to mkfs: %d\n", fserr);
+	}
     } else if (!strcmp(argv[0], "ls")) {
 	FRESULT fserr;
 	DIR d;
@@ -164,7 +208,7 @@
 	DWORD sn;
 	
 	if ((fserr = f_getlabel("", label, &sn)) != FR_OK) {
-	    printf("Unable to read label\n");
+	    printf("Unable to read label: %d\n", fserr);
 	} else {
 	    printf("Label: %s Serial: %d\n", label, sn);
 	}
@@ -212,6 +256,44 @@
 	while ((tmp = f_gets(buf, sizeof(buf), &f)) != NULL) {
 	    puts(tmp);
 	}
+
+	f_close(&f);
+	
+    } else if (!strcmp(argv[0], "wr")) {
+	FRESULT fserr;
+	FIL f;
+	
+	if (argc != 3) {
+	    printf("No file and/or text given\n");
+	    return;
+	}
+	
+	if ((fserr = f_open(&f, argv[1], FA_WRITE | FA_OPEN_ALWAYS)) != FR_OK) {
+	    printf("Failed to open file: %d\n", fserr);
+	    return;
+	}
+
+	if ((fserr = f_lseek(&f, f_size(&f))) != FR_OK) {
+	    printf("Failed to seek to end of file: %d\n", fserr);
+	    goto wr_out;
+	}
+	
+	f_puts(argv[2], &f);
+	f_putc('\n', &f);
+      wr_out:
+	f_close(&f);
+    } else if (!strcmp(argv[0], "rm")) {
+	FRESULT fserr;
+	
+	if (argc != 2) {
+	    printf("No file given\n");
+	    return;
+	}
+	
+	if ((fserr = f_unlink(argv[1])) != FR_OK) {
+	    printf("Failed to remove file: %d\n", fserr);
+	    return;
+	}
     } else {
 	printf("Unknown command\n");
     }
@@ -294,5 +376,105 @@
   return (uint32_t)DMA_GetFlagStatus(DMA2_FLAG_TC4);
 }
 
+char *
+sderr2str(SD_Error err) {
+    switch (err) {
+	case SD_CMD_CRC_FAIL:
+	    return "CMD_CRC_FAIL";
+	case SD_DATA_CRC_FAIL:
+	    return "DATA_CRC_FAIL";
+	case SD_CMD_RSP_TIMEOUT:
+	    return "CMD_RSP_TIMEOUT";
+	case SD_DATA_TIMEOUT:
+	    return "DATA_TIMEOUT";
+	case SD_TX_UNDERRUN:
+	    return "TX_UNDERRUN";
+	case SD_RX_OVERRUN:
+	    return "RX_OVERRUN";
+	case SD_START_BIT_ERR:
+	    return "START_BIT_ERR";
+	case SD_CMD_OUT_OF_RANGE:
+	    return "CMD_OUT_OF_RANGE";
+	case SD_ADDR_MISALIGNED:
+	    return "ADDR_MISALIGNED";
+	case SD_BLOCK_LEN_ERR:
+	    return "BLOCK_LEN_ERR";
+	case SD_ERASE_SEQ_ERR:
+	    return "ERASE_SEQ_ERR";
+	case SD_BAD_ERASE_PARAM:
+	    return "BAD_ERASE_PARAM";
+	case SD_WRITE_PROT_VIOLATION:
+	    return "WRITE_PROT_VIOLATION";
+	case SD_LOCK_UNLOCK_FAILED:
+	    return "LOCK_UNLOCK_FAILED";
+	case SD_COM_CRC_FAILED:
+	    return "COM_CRC_FAILED";
+	case SD_ILLEGAL_CMD:
+	    return "ILLEGAL_CMD";
+	case SD_CARD_ECC_FAILED:
+	    return "CARD_ECC_FAILED";
+	case SD_CC_ERROR:
+	    return "CC_ERROR";
+	case SD_GENERAL_UNKNOWN_ERROR:
+	    return "GENERAL_UNKNOWN_ERROR";
+	case SD_STREAM_READ_UNDERRUN:
+	    return "STREAM_READ_UNDERRUN";
+	case SD_STREAM_WRITE_OVERRUN:
+	    return "STREAM_WRITE_OVERRUN";
+	case SD_CID_CSD_OVERWRITE:
+	    return "OVERWRITE";
+	case SD_WP_ERASE_SKIP:
+	    return "WP_ERASE_SKIP";
+	case SD_CARD_ECC_DISABLED:
+	    return "CARD_ECC_DISABLED";
+	case SD_ERASE_RESET:
+	    return "ERASE_RESET";
+	case SD_AKE_SEQ_ERROR:
+	    return "AKE_SEQ_ERROR";
+	case SD_INVALID_VOLTRANGE:
+	    return "INVALID_VOLTRANGE";
+	case SD_ADDR_OUT_OF_RANGE:
+	    return "ADDR_OUT_OF_RANGE";
+	case SD_SWITCH_ERROR:
+	    return "SWITCH_ERROR";
+	case SD_SDIO_DISABLED:
+	    return "SDIO_DISABLED";
+	case SD_SDIO_FUNCTION_BUSY:
+	    return "SDIO_FUNCTION_BUSY";
+	case SD_SDIO_FUNCTION_FAILED:
+	    return "SDIO_FUNCTION_FAILED";
+	case SD_SDIO_UNKNOWN_FUNCTION:
+	    return "SDIO_UNKNOWN_FUNCTION";
+	case SD_INTERNAL_ERROR:
+	    return "INTERNAL_ERROR";
+	case SD_NOT_CONFIGURED:
+	    return "NOT_CONFIGURED";
+	case SD_REQUEST_PENDING:
+	    return "REQUEST_PENDING";
+	case SD_REQUEST_NOT_APPLICABLE:
+	    return "REQUEST_NOT_APPLICABLE";
+	case SD_INVALID_PARAMETER:
+	    return "INVALID_PARAMETER";
+	case SD_UNSUPPORTED_FEATURE:
+	    return "UNSUPPORTED_FEATURE";
+	case SD_UNSUPPORTED_HW:
+	    return "UNSUPPORTED_HW";
+	case SD_ERROR:
+	    return "ERROR";
+	case SD_OK:
+	    return "OK";
+	default:
+	    return "Unknown";
+    }
+}
 
-
+	
+void dump_buf(uint8_t *buf, uint32_t size) {
+    uint32_t i;
+    
+    for (i = 0; i < size; i += 16) {
+	printf("0x%04lx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
+	       buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7],
+	       buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11], buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]);
+    }
+}
--- a/stm32_eval.h	Wed Apr 03 23:34:20 2013 +1030
+++ b/stm32_eval.h	Fri Apr 05 00:08:31 2013 +1030
@@ -20,3 +20,4 @@
 void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize);
 void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize);
 
+