From d8826b1ad5487de9345b7dcaf6c75a45117ff538 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 31 Mar 2013 10:35:47 -0700 Subject: [PATCH] altos: Add SD card writing function Now that the FAT code seems to be operational, go back and add SD writing. Signed-off-by: Keith Packard --- src/drivers/ao_sdcard.c | 124 +++++++++++++++++++++++++++++++++++++--- src/drivers/ao_sdcard.h | 1 + 2 files changed, 118 insertions(+), 7 deletions(-) diff --git a/src/drivers/ao_sdcard.c b/src/drivers/ao_sdcard.c index 2174af1e..4eef6625 100644 --- a/src/drivers/ao_sdcard.c +++ b/src/drivers/ao_sdcard.c @@ -27,6 +27,7 @@ #define ao_sdcard_select() ao_gpio_set(AO_SDCARD_SPI_CS_PORT,AO_SDCARD_SPI_CS_PIN,AO_SDCARD_SPI_CS,0) #define ao_sdcard_deselect() ao_gpio_set(AO_SDCARD_SPI_CS_PORT,AO_SDCARD_SPI_CS_PIN,AO_SDCARD_SPI_CS,1) +#define SDCARD_DEBUG 0 static uint8_t initialized; static uint8_t present; @@ -170,6 +171,20 @@ ao_sdcard_send_if_cond(uint32_t arg, uint8_t send_if_cond_response[4]) return ret; } +static uint8_t +ao_sdcard_send_status(void) +{ + uint8_t ret; + + DBG ("send_status\n"); + ao_sdcard_select(); + ret = ao_sdcard_send_cmd(SDCARD_SEND_STATUS, 0); + ao_sdcard_recv_reply(NULL, 0); + if (ret != SDCARD_STATUS_READY_STATE) + DBG ("\tsend_if_cond failed %02x\n", ret); + return ret; +} + static uint8_t ao_sdcard_set_blocklen(uint32_t blocklen) { @@ -182,7 +197,6 @@ ao_sdcard_set_blocklen(uint32_t blocklen) if (ret != SDCARD_STATUS_READY_STATE) DBG ("\tsend_if_cond failed %02x\n", ret); return ret; - } static uint8_t @@ -364,7 +378,8 @@ ao_sdcard_read_block(uint32_t block, uint8_t *data) if (ret != SDCARD_STATUS_READY_STATE) goto bail; - if (ao_sdcard_wait_block_start() != 0xfe) { + /* Wait for the data start block marker */ + if (ao_sdcard_wait_block_start() != SDCARD_DATA_START_BLOCK) { ret = 0x3f; goto bail; } @@ -384,15 +399,110 @@ bail: uint8_t ao_sdcard_write_block(uint32_t block, uint8_t *data) { - /* Not doing anything until the file system code seems reasonable - */ - return 1; + uint8_t ret; + uint8_t response; + uint8_t start_block[2]; + int i; + + ao_sdcard_lock(); + if (!initialized) { + ao_sdcard_setup(); + initialized = 1; + if (sdtype != ao_sdtype_unknown) + present = 1; + } + if (!present) { + ao_sdcard_unlock(); + return 0; + } + if (sdtype != ao_sdtype_sd2block) + block <<= 9; + ao_sdcard_get(); + ao_sdcard_select(); + + ret = ao_sdcard_send_cmd(SDCARD_WRITE_BLOCK, block); + ao_sdcard_recv_reply(NULL, 0); + if (ret != SDCARD_STATUS_READY_STATE) + goto bail; + + /* Write a pad byte followed by the data start block marker */ + start_block[0] = 0xff; + start_block[1] = SDCARD_DATA_START_BLOCK; + ao_sdcard_send(start_block, 2); + + /* Send the data */ + ao_sdcard_send(data, 512); + + /* Fake the CRC */ + ao_sdcard_send_fixed(0xff, 2); + + /* See if the card liked the data */ + ao_sdcard_recv(&response, 1); + if ((response & SDCARD_DATA_RES_MASK) != SDCARD_DATA_RES_ACCEPTED) { + ret = 0x3f; + goto bail; + } + + /* Wait for the bus to go idle (should be done with an interrupt) */ + for (i = 0; i < SDCARD_IDLE_TIMEOUT; i++) { + ao_sdcard_recv(&response, 1); + if (response == 0xff) + break; + } + if (i == SDCARD_IDLE_TIMEOUT) + ret = 0x3f; +bail: + ao_sdcard_deselect(); + ao_sdcard_put(); + ao_sdcard_unlock(); + return ret == SDCARD_STATUS_READY_STATE; +} + +#if SDCARD_DEBUG +static uint8_t test_data[512]; + +static void +ao_sdcard_test_read(void) +{ + int i; + if (!ao_sdcard_read_block(1, test_data)) { + printf ("read error\n"); + return; + } + printf ("data:"); + for (i = 0; i < 18; i++) + printf (" %02x", test_data[i]); + printf ("\n"); } +static void +ao_sdcard_test_write(void) +{ + int i; + printf ("data:"); + for (i = 0; i < 16; i++) { + test_data[i]++; + printf (" %02x", test_data[i]); + } + printf ("\n"); + if (!ao_sdcard_write_block(1, test_data)) { + printf ("write error\n"); + return; + } +} + +static const struct ao_cmds ao_sdcard_cmds[] = { + { ao_sdcard_test_read, "x\0Test read" }, + { ao_sdcard_test_write, "y\0Test read" }, + { 0, NULL }, +}; +#endif + void ao_sdcard_init(void) { ao_spi_init_cs(AO_SDCARD_SPI_CS_PORT, (1 << AO_SDCARD_SPI_CS_PIN)); +#if SDCARD_DEBUG + ao_cmd_register(&ao_sdcard_cmds[0]); +#endif } - - diff --git a/src/drivers/ao_sdcard.h b/src/drivers/ao_sdcard.h index b9f737c5..35e81ced 100644 --- a/src/drivers/ao_sdcard.h +++ b/src/drivers/ao_sdcard.h @@ -63,6 +63,7 @@ ao_sdcard_init(void); #define SDCARD_CMD_TIMEOUT 100 #define SDCARD_IDLE_WAIT 100 #define SDCARD_BLOCK_TIMEOUT 100 +#define SDCARD_IDLE_TIMEOUT 1000 enum ao_sdtype { ao_sdtype_unknown, -- 2.30.2