diff options
Diffstat (limited to 'spiflash_n25q128.c')
-rw-r--r-- | spiflash_n25q128.c | 91 |
1 files changed, 63 insertions, 28 deletions
diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c index 6e35a41..c23f244 100644 --- a/spiflash_n25q128.c +++ b/spiflash_n25q128.c @@ -43,6 +43,14 @@ #define _n25q128_deselect(ctx) HAL_GPIO_WritePin(ctx->cs_n_port, ctx->cs_n_pin, GPIO_PIN_SET); +#define N25Q128_NUM_BYTES (N25Q128_PAGE_SIZE * N25Q128_NUM_PAGES) + +#if N25Q128_SECTOR_SIZE * N25Q128_NUM_SECTORS != N25Q128_NUM_BYTES || \ + N25Q128_SUBSECTOR_SIZE * N25Q128_NUM_SUBSECTORS != N25Q128_NUM_BYTES +#error Inconsistant definitions for pages / sectors / subsectors +#endif + + int _n25q128_get_wel_flag(struct spiflash_ctx *ctx); @@ -208,18 +216,30 @@ int n25q128_get_wip_flag(struct spiflash_ctx *ctx) return (spi_rx[1] & 1); } +/* Wait until the flash memory is done writing (wip = Write In Progress) */ +inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout) +{ + int i; + while (timeout--) { + i = n25q128_get_wip_flag(ctx); + if (i < 0) return 0; + if (! i) break; + HAL_Delay(10); + } + return 1; +} -int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) +static int n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) { + // check offset + if (byte_offset >= N25Q128_NUM_BYTES) return 0; + // tx buffer uint8_t spi_tx[4]; // result HAL_StatusTypeDef ok; - // check offset - if (sector_offset >= N25Q128_NUM_SECTORS) return 0; - // enable writing spi_tx[0] = N25Q128_COMMAND_WRITE_ENABLE; @@ -236,14 +256,11 @@ int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) int wel = _n25q128_get_wel_flag(ctx); if (wel != 1) return 0; - // calculate byte address - sector_offset *= N25Q128_SECTOR_SIZE; - - // send ERASE SUBSECTOR command - spi_tx[0] = N25Q128_COMMAND_ERASE_SECTOR; - spi_tx[1] = (uint8_t)(sector_offset >> 16); - spi_tx[2] = (uint8_t)(sector_offset >> 8); - spi_tx[3] = (uint8_t)(sector_offset >> 0); + // send command (ERASE SECTOR or ERASE SUBSECTOR) + spi_tx[0] = command; + spi_tx[1] = (uint8_t)(byte_offset >> 16); + spi_tx[2] = (uint8_t)(byte_offset >> 8); + spi_tx[3] = (uint8_t)(byte_offset >> 0); // activate, send command, deselect _n25q128_select(ctx); @@ -254,11 +271,29 @@ int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) // check if (ok != HAL_OK) return 0; + // wait for erase to finish + + if (! _wait_while_wip(ctx, 2000)) return 0; + // done return 1; } +int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) +{ + return n25q128_erase_something(ctx, N25Q128_COMMAND_ERASE_SECTOR, + sector_offset * N25Q128_SECTOR_SIZE); +} + + +int n25q128_erase_subsector(struct spiflash_ctx *ctx, uint32_t subsector_offset) +{ + return n25q128_erase_something(ctx, N25Q128_COMMAND_ERASE_SUBSECTOR, + subsector_offset * N25Q128_SUBSECTOR_SIZE); +} + + int _n25q128_get_wel_flag(struct spiflash_ctx *ctx) { // tx, rx buffers @@ -284,21 +319,8 @@ int _n25q128_get_wel_flag(struct spiflash_ctx *ctx) return ((spi_rx[1] >> 1) & 1); } -/* Wait until the flash memory is done writing (wip = Write In Progress) */ -inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout) -{ - int i; - while (timeout--) { - i = n25q128_get_wip_flag(ctx); - if (i < 0) return 0; - if (! i) break; - HAL_Delay(10); - } - return 1; -} - /* This function performs erasure if needed, and then writing of a number of pages to the flash memory */ -int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len) +int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len, const int auto_erase) { uint32_t page; @@ -306,8 +328,15 @@ int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t if ((offset % N25Q128_PAGE_SIZE) != 0) return -1; if ((len % N25Q128_PAGE_SIZE) != 0) return -2; - if ((offset % N25Q128_SECTOR_SIZE) == 0) { - /* first page in sector, need to erase sector */ + if (auto_erase && (offset % N25Q128_SECTOR_SIZE) == 0) { + /* + * first page in sector, need to erase sector + * + * So why do we only do this when the buffer starts on the + * sector, as opposed to performing this check for every page? + * Also, might be better to do this by subsectors rather than + * sectors. + */ if (! _wait_while_wip(ctx, 1000)) return -3; @@ -330,6 +359,12 @@ int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t */ } + /* + * Wait until last write finishes. + */ + + if (! _wait_while_wip(ctx, 1000)) return -7; + return 1; } |