diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-05-08 09:14:40 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-05-08 09:14:40 +0000 |
commit | cc298608cc0d83dfbcce87c7c805f5107fecd7a6 (patch) | |
tree | fac3de0b08bd1b93b8bd8e022348eb33dff111ec /os/ex/Micron | |
parent | 2c33cd5ebc6f6dbfa5ae6d64a070fd2b3d1b799a (diff) | |
download | ChibiOS-cc298608cc0d83dfbcce87c7c805f5107fecd7a6.tar.gz ChibiOS-cc298608cc0d83dfbcce87c7c805f5107fecd7a6.tar.bz2 ChibiOS-cc298608cc0d83dfbcce87c7c805f5107fecd7a6.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9449 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/ex/Micron')
-rw-r--r-- | os/ex/Micron/n25q128.c | 59 | ||||
-rw-r--r-- | os/ex/Micron/n25q128.h | 30 |
2 files changed, 82 insertions, 7 deletions
diff --git a/os/ex/Micron/n25q128.c b/os/ex/Micron/n25q128.c index 079a565a7..03ebd6cc2 100644 --- a/os/ex/Micron/n25q128.c +++ b/os/ex/Micron/n25q128.c @@ -93,6 +93,13 @@ static void spi_send_cmd_addr(N25Q128Driver *devp, spiSend(devp->config->spip, 4, buf); } +static void spi_send_cmd(N25Q128Driver *devp, uint8_t cmd) { + uint8_t buf[1]; + + buf[0] = cmd; + spiSend(devp->config->spip, 1, buf); +} + static const flash_descriptor_t *get_attributes(void *instance) { N25Q128Driver *devp = (N25Q128Driver *)instance; SPIDriver *spip = devp->config->spip; @@ -149,6 +156,7 @@ static flash_error_t program(void *instance, flash_address_t addr, const uint8_t *pp, size_t n) { N25Q128Driver *devp = (N25Q128Driver *)instance; SPIDriver *spip = devp->config->spip; + flash_error_t err; osalDbgAssert(devp->state == FLASH_READY, "invalid state"); @@ -158,31 +166,69 @@ static flash_error_t program(void *instance, flash_address_t addr, #endif devp->state = FLASH_ACTIVE; - while (n > 0) { + while (n > 0U) { + uint8_t sts; + + /* Data size that can be written in a single program page operation.*/ size_t chunk = (size_t)(((addr | PAGE_MASK) + 1U) - addr); if (chunk > n) { chunk = n; } + /* Enabling write operation.*/ spiSelect(spip); + spi_send_cmd(devp, N25Q128_CMD_WRITE_ENABLE); + spiUnselect(spip); + (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ + /* Page program command.*/ + spiSelect(spip); spi_send_cmd_addr(devp, N25Q128_CMD_PAGE_PROGRAM, addr); spiSend(spip, chunk, pp); - spiUnselect(spip); + (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ + /* Operation end waiting.*/ + do { +#if N25Q128_NICE_WAITING == TRUE + osalThreadSleepMilliseconds(1); +#endif + /* Read status command.*/ + spiSelect(spip); + spi_send_cmd(devp, N25Q128_CMD_READ_STATUS_REGISTER); + spiReceive(spip, 1, &sts); + spiUnselect(spip); + } while ((sts & N25Q128_STS_BUSY) != 0U); + + /* Checking for errors.*/ + if ((sts & N25Q128_STS_ALL_ERRORS) != 0U) { + /* Clearing status register.*/ + (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ + spiSelect(spip); + spi_send_cmd(devp, N25Q128_CMD_CLEAR_FLAG_STATUS_REGISTER); + spiUnselect(spip); + + /* Program operation failed.*/ + err = FLASH_PROGRAM_FAILURE; + goto exit_error; + } + + /* Next page.*/ addr += chunk; pp += chunk; n -= chunk; } - devp->state = FLASH_READY; + /* Program operation succeeded.*/ + err = FLASH_NO_ERROR; + /* Common exit path for this function.*/ +exit_error: + devp->state = FLASH_READY; #if N25Q128_SHARED_SPI == TRUE spiReleaseBus(spip); #endif - - return FLASH_NO_ERROR; + return err; } static flash_error_t read(void *instance, flash_address_t addr, @@ -198,17 +244,16 @@ static flash_error_t read(void *instance, flash_address_t addr, #endif devp->state = FLASH_ACTIVE; + /* Read command.*/ spiSelect(spip); spi_send_cmd_addr(devp, N25Q128_CMD_READ, addr); spiReceive(spip, n, rp); spiUnselect(spip); devp->state = FLASH_READY; - #if N25Q128_SHARED_SPI == TRUE spiReleaseBus(spip); #endif - return FLASH_NO_ERROR; } diff --git a/os/ex/Micron/n25q128.h b/os/ex/Micron/n25q128.h index bdc500463..b86cfefc7 100644 --- a/os/ex/Micron/n25q128.h +++ b/os/ex/Micron/n25q128.h @@ -67,6 +67,24 @@ #define N25Q128_CMD_PROGRAM_OTP_ARRAY 0x42 /** @} */ +/** + * @name Status register bits + * @{ + */ +#define N25Q128_STS_BUSY 0x80U +#define N25Q128_STS_ERASE_SUSPEND 0x40U +#define N25Q128_STS_ERASE_ERROR 0x20U +#define N25Q128_STS_PROGRAM_ERROR 0x10U +#define N25Q128_STS_VPP_ERROR 0x08U +#define N25Q128_STS_PROGRAM_SUSPEND 0x04U +#define N25Q128_STS_PROTECTION_ERROR 0x02U +#define N25Q128_STS_RESERVED 0x01U +#define N25Q128_STS_ALL_ERRORS (N25Q128_STS_ERASE_ERROR | \ + N25Q128_STS_PROGRAM_ERROR | \ + N25Q128_STS_VPP_ERROR | \ + N25Q128_STS_PROTECTION_ERROR) +/** @} */ + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -84,6 +102,18 @@ #if !defined(N25Q128_SHARED_SPI) || defined(__DOXYGEN__) #define N25Q128_SHARED_SPI TRUE #endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the flash waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also when the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(N25Q128_NICE_WAITING) || defined(__DOXYGEN__) +#define N25Q128_NICE_WAITING TRUE +#endif /** @} */ /*===========================================================================*/ |