diff options
| author | danicampora | 2015-02-06 15:35:48 +0100 |
|---|---|---|
| committer | Damien George | 2015-02-06 22:10:11 +0000 |
| commit | 8785645a952c03315dbf93667b5f7c7eec49762f (patch) | |
| tree | 267e2d572d87e92bfc0bfabf83859231152a2162 /cc3200/fatfs/src/drivers/sflash_diskio.c | |
| parent | 97f14606f528180d1482cffbe3571163a1dd9273 (diff) | |
cc3200: Add cc3200 port of MicroPython.
The port currently implements support for GPIO, RTC, ExtInt and the WiFi
subsystem. A small file system is available in the serial flash. A
bootloader which makes OTA updates possible, is also part of this initial
implementation.
Diffstat (limited to 'cc3200/fatfs/src/drivers/sflash_diskio.c')
| -rw-r--r-- | cc3200/fatfs/src/drivers/sflash_diskio.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/cc3200/fatfs/src/drivers/sflash_diskio.c b/cc3200/fatfs/src/drivers/sflash_diskio.c new file mode 100644 index 000000000..cb28913bf --- /dev/null +++ b/cc3200/fatfs/src/drivers/sflash_diskio.c @@ -0,0 +1,186 @@ +#include <stdint.h> +#include <stdbool.h> +#include "std.h" + +#include "mpconfig.h" +#include MICROPY_HAL_H +#include "simplelink.h" +#include "diskio.h" +#include "sflash_diskio.h" +#include "debug.h" +#include "modwlan.h" + +#ifdef USE_FREERTOS +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#endif + +#define SFLASH_TIMEOUT_MAX_MS 5500 +#define SFLASH_WAIT_TIME_MS 5 + +static _u8 sflash_block_name[] = "__NNN__.fsb"; +static _u8 *sflash_block_cache; +static bool sflash_init_done = false; +static bool sflash_cache_is_dirty; +static uint32_t sflash_ublock; +static uint32_t sflash_prblock; + + +static void print_block_name (_u32 ublock) { + char _sblock[4]; + snprintf (_sblock, sizeof(_sblock), "%03u", ublock); + memcpy (&sflash_block_name[2], _sblock, 3); +} + +static bool sflash_access (_u32 mode, _i32 (* sl_FsFunction)(_i32 FileHdl, _u32 Offset, _u8* pData, _u32 Len)) { + _i32 fileHandle; + bool retval = false; + + // wlan must be enabled in order to access the serial flash +#ifdef USE_FREERTOS + xSemaphoreTake (xWlanSemaphore, portMAX_DELAY); +#endif + if (0 == sl_FsOpen(sflash_block_name, mode, NULL, &fileHandle)) { + if (SFLASH_BLOCK_SIZE == sl_FsFunction (fileHandle, 0, sflash_block_cache, SFLASH_BLOCK_SIZE)) { + retval = true; + } + sl_FsClose (fileHandle, NULL, NULL, 0); + } +#ifdef USE_FREERTOS + xSemaphoreGive (xWlanSemaphore); +#endif + return retval; +} + +DRESULT sflash_disk_init (void) { + _i32 fileHandle; + SlFsFileInfo_t FsFileInfo; + + if (!sflash_init_done) { + // Allocate space for the block cache + ASSERT ((sflash_block_cache = mem_Malloc(SFLASH_BLOCK_SIZE)) != NULL); + + // Proceed to format the memory if not done yet + for (int i = 0; i < SFLASH_BLOCK_COUNT; i++) { + print_block_name (i); + #ifdef USE_FREERTOS + xSemaphoreTake (xWlanSemaphore, portMAX_DELAY); + #endif + // Create the block file if it doesn't exist + if (sl_FsGetInfo(sflash_block_name, 0, &FsFileInfo) < 0) { + if (!sl_FsOpen(sflash_block_name, FS_MODE_OPEN_CREATE(SFLASH_BLOCK_SIZE, 0), NULL, &fileHandle)) { + sl_FsClose(fileHandle, NULL, NULL, 0); + #ifdef USE_FREERTOS + xSemaphoreGive (xWlanSemaphore); + #endif + memset(sflash_block_cache, 0xFF, SFLASH_BLOCK_SIZE); + if (!sflash_access(FS_MODE_OPEN_WRITE, sl_FsWrite)) { + return RES_ERROR; + } + } + else { + // Unexpected failure while creating the file + #ifdef USE_FREERTOS + xSemaphoreGive (xWlanSemaphore); + #endif + return RES_ERROR; + } + } + #ifdef USE_FREERTOS + xSemaphoreGive (xWlanSemaphore); + #endif + } + sflash_init_done = true; + sflash_prblock = UINT32_MAX; + sflash_cache_is_dirty = false; + } + return RES_OK; +} + +DRESULT sflash_disk_status(void) { + if (!sflash_init_done) { + return STA_NOINIT; + } + return 0; +} + +DRESULT sflash_disk_read(BYTE *buff, DWORD sector, UINT count) { + uint32_t secindex; + + if (!sflash_init_done) { + return STA_NOINIT; + } + + if (sector + count > SFLASH_SECTOR_COUNT || count == 0) { + return RES_PARERR; + } + + for (int i = 0; i < count; i++) { + secindex = (sector + i) % SFLASH_SECTORS_PER_BLOCK; + sflash_ublock = (sector + i) / SFLASH_SECTORS_PER_BLOCK; + // See if it's time to read a new block + if (sflash_prblock != sflash_ublock) { + if (sflash_disk_flush() != RES_OK) { + return RES_ERROR; + } + sflash_prblock = sflash_ublock; + print_block_name (sflash_ublock); + if (!sflash_access(FS_MODE_OPEN_READ, sl_FsRead)) { + return RES_ERROR; + } + } + // Copy the requested sector from the block cache + memcpy (buff, &sflash_block_cache[(secindex * SFLASH_SECTOR_SIZE)], SFLASH_SECTOR_SIZE); + buff += SFLASH_BLOCK_SIZE; + } + return RES_OK; +} + +DRESULT sflash_disk_write(const BYTE *buff, DWORD sector, UINT count) { + uint32_t secindex; + int32_t index = 0; + + if (!sflash_init_done) { + return STA_NOINIT; + } + + if (sector + count > SFLASH_SECTOR_COUNT || count == 0) { + return RES_PARERR; + } + + do { + secindex = (sector + index) % SFLASH_SECTORS_PER_BLOCK; + sflash_ublock = (sector + index) / SFLASH_SECTORS_PER_BLOCK; + // Check if it's a different block than last time + if (sflash_prblock != sflash_ublock) { + if (sflash_disk_flush() != RES_OK) { + return RES_ERROR; + } + sflash_prblock = sflash_ublock; + print_block_name (sflash_ublock); + // Read the block into the cache + if (!sflash_access(FS_MODE_OPEN_READ, sl_FsRead)) { + return RES_ERROR; + } + } + // Copy the input sector to the block cache + memcpy (&sflash_block_cache[(secindex * SFLASH_SECTOR_SIZE)], buff, SFLASH_SECTOR_SIZE); + buff += SFLASH_BLOCK_SIZE; + sflash_cache_is_dirty = true; + } while (++index < count); + + return RES_OK; +} + +DRESULT sflash_disk_flush (void) { + // Write back the cache if it's dirty + if (sflash_cache_is_dirty) { + if (!sflash_access(FS_MODE_OPEN_WRITE, sl_FsWrite)) { + return RES_ERROR; + } + sflash_cache_is_dirty = false; + } + return RES_OK; +} + |
