diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-05-10 12:42:21 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-05-10 12:42:21 +0000 |
commit | 7d7a7482c184ff44780f7504d48b86fb24b3fb53 (patch) | |
tree | 41bec205c121380413432b4caffdeaa83e580ccf /os | |
parent | 0deff4750e9aa70a01c5c7db6aeb3f32024df352 (diff) | |
download | ChibiOS-7d7a7482c184ff44780f7504d48b86fb24b3fb53.tar.gz ChibiOS-7d7a7482c184ff44780f7504d48b86fb24b3fb53.tar.bz2 ChibiOS-7d7a7482c184ff44780f7504d48b86fb24b3fb53.zip |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9456 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r-- | os/ex/Micron/n25q128.c | 201 | ||||
-rw-r--r-- | os/ex/Micron/n25q128.h | 7 | ||||
-rw-r--r-- | os/hal/lib/peripherals/flash/hal_flash.h | 43 |
3 files changed, 117 insertions, 134 deletions
diff --git a/os/ex/Micron/n25q128.c b/os/ex/Micron/n25q128.c index b6a00170a..9031ddd3a 100644 --- a/os/ex/Micron/n25q128.c +++ b/os/ex/Micron/n25q128.c @@ -35,7 +35,14 @@ #define PAGE_SIZE 256U #define PAGE_MASK (PAGE_SIZE - 1U) -#define SECTOR_SIZE 4096U + +#if N25Q128_USE_SUB_SECTORS == TRUE +#define SECTOR_SIZE 0x00001000U +#define CMD_SECTOR_ERASE N25Q128_CMD_SUBSECTOR_ERASE +#else +#define SECTOR_SIZE 0x00010000U +#define CMD_SECTOR_ERASE N25Q128_CMD_SECTOR_ERASE +#endif /*===========================================================================*/ /* Driver exported variables. */ @@ -47,12 +54,8 @@ static const flash_descriptor_t *get_descriptor(void *instance); static flash_error_t erase_all(void *instance); -static flash_error_t erase_sectors(void *instance, - flash_sector_t sector, - flash_sector_t n); -static flash_error_t verify_erase(void *instance, - flash_sector_t sector, - flash_sector_t n); +static flash_error_t erase_sector(void *instance, flash_sector_t sector); +static flash_error_t verify_erase(void *instance, flash_sector_t sector); static flash_error_t program(void *instance, flash_address_t addr, const uint8_t *pp, size_t n); static flash_error_t read(void *instance, flash_address_t addr, @@ -62,25 +65,46 @@ static flash_error_t read(void *instance, flash_address_t addr, * @brief Virtual methods table. */ static const struct N25Q128DriverVMT n25q128_vmt = { - get_descriptor, erase_all, erase_sectors, verify_erase, program, read + get_descriptor, erase_all, erase_sector, verify_erase, program, read }; /** * @brief N25Q128 descriptor. */ static flash_descriptor_t descriptor = { - .attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE, - .page_size = 256, - .sectors_count = 4096, + .attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE | + FLASH_ATTR_SUSPEND_ERASE_CAPABLE, + .page_size = 256U, +#if N25Q128_USE_SUB_SECTORS == TRUE + .sectors_count = 4096U, +#else + .sectors_count = 256U, +#endif .sectors = NULL, .sectors_size = SECTOR_SIZE, - .address = 0 + .address = 0U }; /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +#if N25Q128_SHARED_SPI == TRUE +void flash_bus_acquire(N25Q128Driver *devp) { + + spiAcquireBus(devp->config->spip); + spiStart(devp->config->spip, devp->config->spicfg); +} + +void flash_bus_release(N25Q128Driver *devp) { + + spiReleaseBus(devp->config->spip); +} +#else +#define flash_bus_acquire(devp) +#define flash_bus_release(devp) +#endif + static void flash_send_cmd_addr(N25Q128Driver *devp, uint8_t cmd, flash_address_t addr) { @@ -146,11 +170,8 @@ static flash_error_t erase_all(void *instance) { osalDbgCheck(instance != NULL); osalDbgAssert(devp->state == FLASH_READY, "invalid state"); -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); - spiStart(spip, devp->config->spicfg); -#endif - devp->state = FLASH_ACTIVE; + flash_bus_acquire(devp); + devp->state = FLASH_ERASING; /* Enabling write operation.*/ spiSelect(spip); @@ -168,120 +189,87 @@ static flash_error_t erase_all(void *instance) { err = flash_poll_status(devp); devp->state = FLASH_READY; -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif + flash_bus_release(devp); return err; } -static flash_error_t erase_sectors(void *instance, - flash_sector_t sector, - flash_sector_t n) { +static flash_error_t erase_sector(void *instance, flash_sector_t sector) { N25Q128Driver *devp = (N25Q128Driver *)instance; SPIDriver *spip = devp->config->spip; flash_address_t addr = (flash_address_t)(sector * SECTOR_SIZE); - - osalDbgCheck((instance != NULL) && (n > 0U)); - osalDbgCheck(sector + n <= descriptor.sectors_count); - osalDbgAssert(devp->state == FLASH_READY, "invalid state"); - -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); - spiStart(spip, devp->config->spicfg); -#endif - devp->state = FLASH_ACTIVE; flash_error_t err; - /* Sub-sectors erased one by one, a possible optimization could be to - erase whole sectors where possible.*/ - while (n > 0) { + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < descriptor.sectors_count); + osalDbgAssert(devp->state == FLASH_READY, "invalid state"); - /* Enabling write operation.*/ - spiSelect(spip); - flash_send_cmd(devp, N25Q128_CMD_WRITE_ENABLE); - spiUnselect(spip); - (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ + flash_bus_acquire(devp); + devp->state = FLASH_ERASING; - /* Sub-sector erase command.*/ - spiSelect(spip); - flash_send_cmd_addr(devp, N25Q128_CMD_SUBSECTOR_ERASE, addr); - spiUnselect(spip); + /* Enabling write operation.*/ + spiSelect(spip); + flash_send_cmd(devp, N25Q128_CMD_WRITE_ENABLE); + spiUnselect(spip); + (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ - /* Wait for status and check errors.*/ - (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ - err = flash_poll_status(devp); - if (err != FLASH_NO_ERROR) { - break; - } + /* Sector erase command.*/ + spiSelect(spip); + flash_send_cmd_addr(devp, CMD_SECTOR_ERASE, addr); + spiUnselect(spip); - n--; - addr += SECTOR_SIZE; - } + /* Wait for status and check errors.*/ + (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ + err = flash_poll_status(devp); devp->state = FLASH_READY; -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif + flash_bus_release(devp); return err; } -static flash_error_t verify_erase(void *instance, - flash_sector_t sector, - flash_sector_t n) { +static flash_error_t verify_erase(void *instance, flash_sector_t sector) { N25Q128Driver *devp = (N25Q128Driver *)instance; SPIDriver *spip = devp->config->spip; - flash_error_t err; + unsigned i; - osalDbgCheck((instance != NULL) && (n > 0U)); - osalDbgCheck(sector + n <= descriptor.sectors_count); + osalDbgCheck(instance != NULL); + osalDbgCheck(sector < descriptor.sectors_count); osalDbgAssert(devp->state == FLASH_READY, "invalid state"); -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); - spiStart(spip, devp->config->spicfg); -#endif - devp->state = FLASH_ACTIVE; + flash_bus_acquire(devp); + devp->state = FLASH_READING; /* Read command.*/ spiSelect(spip); flash_send_cmd_addr(devp, N25Q128_CMD_READ, (size_t)(sector * SECTOR_SIZE)); - n *= SECTOR_SIZE; - while (--n) { + for (i = SECTOR_SIZE; i > 0U; i--) { if (spiPolledExchange(spip, 0xFF) != 0xFF) { - err = FLASH_VERIFY_FAILURE; - goto skip; + flash_bus_release(devp); + return FLASH_VERIFY_FAILURE; } } spiUnselect(spip); - err = FLASH_NO_ERROR; -skip: devp->state = FLASH_READY; -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif - return err; + flash_bus_release(devp); + return FLASH_NO_ERROR; } 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; osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U)); osalDbgCheck((size_t)addr + n <= (size_t)descriptor.sectors_count * (size_t)descriptor.sectors_size); osalDbgAssert(devp->state == FLASH_READY, "invalid state"); -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); - spiStart(spip, devp->config->spicfg); -#endif - devp->state = FLASH_ACTIVE; + flash_bus_acquire(devp); + devp->state = FLASH_WRITING; /* Data is programmed page by page.*/ while (n > 0U) { + flash_error_t err; /* Data size that can be written in a single program page operation.*/ size_t chunk = (size_t)(((addr | PAGE_MASK) + 1U) - addr); @@ -305,7 +293,8 @@ static flash_error_t program(void *instance, flash_address_t addr, (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/ err = flash_poll_status(devp); if (err != FLASH_NO_ERROR) { - break; + flash_bus_release(devp); + return err; } /* Next page.*/ @@ -315,10 +304,8 @@ static flash_error_t program(void *instance, flash_address_t addr, } devp->state = FLASH_READY; -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif - return err; + flash_bus_release(devp); + return FLASH_NO_ERROR; } static flash_error_t read(void *instance, flash_address_t addr, @@ -331,11 +318,8 @@ static flash_error_t read(void *instance, flash_address_t addr, (size_t)descriptor.sectors_size); osalDbgAssert(devp->state == FLASH_READY, "invalid state"); -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); - spiStart(spip, devp->config->spicfg); -#endif - devp->state = FLASH_ACTIVE; + flash_bus_acquire(devp); + devp->state = FLASH_READING; /* Read command.*/ spiSelect(spip); @@ -344,9 +328,7 @@ static flash_error_t read(void *instance, flash_address_t addr, spiUnselect(spip); devp->state = FLASH_READY; -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif + flash_bus_release(devp); return FLASH_NO_ERROR; } @@ -387,7 +369,7 @@ void n25q128Start(N25Q128Driver *devp, const N25Q128Config *config) { SPIDriver *spip = config->spip; devp->config = config; - spiStart(devp->config->spip, devp->config->spicfg); + flash_bus_acquire(devp); /* Reset Enable command.*/ spiSelect(spip); @@ -400,7 +382,9 @@ void n25q128Start(N25Q128Driver *devp, const N25Q128Config *config) { spiSelect(spip); flash_send_cmd(devp, N25Q128_CMD_RESET_MEMORY); spiUnselect(spip); + devp->state = FLASH_READY; + flash_bus_release(devp); } } @@ -418,17 +402,13 @@ void n25q128Stop(N25Q128Driver *devp) { osalDbgAssert(devp->state != FLASH_UNINIT, "invalid state"); if (devp->state != FLASH_STOP) { -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); -#endif + flash_bus_acquire(devp); spiStop(spip); + devp->config = NULL; devp->state = FLASH_STOP; - -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif + flash_bus_release(devp); } } @@ -447,11 +427,8 @@ void n25q128ReadId(N25Q128Driver *devp, uint8_t *rp, size_t n) { osalDbgCheck((devp != NULL) && (rp != NULL) && (n > 0U) && (n <= 17U)); osalDbgAssert(devp->state == FLASH_READY, "invalid state"); -#if N25Q128_SHARED_SPI == TRUE - spiAcquireBus(spip); - spiStart(spip, devp->config->spicfg); -#endif - devp->state = FLASH_ACTIVE; + flash_bus_acquire(devp); + devp->state = FLASH_READING; /* Read Id command.*/ spiSelect(spip); @@ -460,9 +437,7 @@ void n25q128ReadId(N25Q128Driver *devp, uint8_t *rp, size_t n) { spiUnselect(spip); devp->state = FLASH_READY; -#if N25Q128_SHARED_SPI == TRUE - spiReleaseBus(spip); -#endif + flash_bus_release(devp); } /** @} */ diff --git a/os/ex/Micron/n25q128.h b/os/ex/Micron/n25q128.h index 9ae12f1bd..683d66bb0 100644 --- a/os/ex/Micron/n25q128.h +++ b/os/ex/Micron/n25q128.h @@ -114,6 +114,13 @@ #if !defined(N25Q128_NICE_WAITING) || defined(__DOXYGEN__) #define N25Q128_NICE_WAITING TRUE #endif + +/** + * @brief Uses 4kB sub-sectors rather than 64kB sectors. + */ +#if !defined(N25Q128_USE_SUB_SECTORS) || defined(__DOXYGEN__) +#define N25Q128_USE_SUB_SECTORS FALSE +#endif /** @} */ /*===========================================================================*/ diff --git a/os/hal/lib/peripherals/flash/hal_flash.h b/os/hal/lib/peripherals/flash/hal_flash.h index 722326607..b62f73d66 100644 --- a/os/hal/lib/peripherals/flash/hal_flash.h +++ b/os/hal/lib/peripherals/flash/hal_flash.h @@ -33,10 +33,11 @@ * @name Flash attributes
* @{
*/
-#define FLASH_ATTR_ERASED_IS_ONE 0x00000001
-#define FLASH_ATTR_MEMORY_MAPPED 0x00000002
-#define FLASH_ATTR_REWRITABLE 0x00000004
-#define FLASH_ATTR_READ_ECC_CAPABLE 0x00000008
+#define FLASH_ATTR_ERASED_IS_ONE 0x00000001
+#define FLASH_ATTR_MEMORY_MAPPED 0x00000002
+#define FLASH_ATTR_REWRITABLE 0x00000004
+#define FLASH_ATTR_READ_ECC_CAPABLE 0x00000008
+#define FLASH_ATTR_SUSPEND_ERASE_CAPABLE 0x00000010
/** @} */
/*===========================================================================*/
@@ -58,7 +59,10 @@ typedef enum { FLASH_UNINIT = 0,
FLASH_STOP = 1,
FLASH_READY = 2,
- FLASH_ACTIVE = 3
+ FLASH_READING = 3,
+ FLASH_WRITING = 4,
+ FLASH_ERASING = 5,
+ FLASH_SUSPENDED = 6
} flash_state_t;
/**
@@ -70,7 +74,8 @@ typedef enum { FLASH_PROGRAM_FAILURE = 2, /* Program operation failed. */
FLASH_ERASE_FAILURE = 3, /* Erase operation failed. */
FLASH_VERIFY_FAILURE = 4, /* Verify operation failed. */
- FLASH_HW_FAILURE = 5 /* Controller or communication error. */
+ FLASH_BUSY = 5, /* Attempt to access a sector being erased. */
+ FLASH_HW_FAILURE = 6 /* Controller or communication error. */
} flash_error_t;
/**
@@ -142,13 +147,11 @@ typedef struct { /* Erase whole flash device.*/ \
flash_error_t (*erase_all)(void *instance); \
/* Erase single sector.*/ \
- flash_error_t (*erase_sectors)(void *instance, \
- flash_sector_t sector, \
- flash_sector_t n); \
+ flash_error_t (*erase_sector)(void *instance, \
+ flash_sector_t sector); \
/* Erase single sector.*/ \
flash_error_t (*verify_erase)(void *instance, \
- flash_sector_t sector, \
- flash_sector_t n); \
+ flash_sector_t sector); \
/* Write operation.*/ \
flash_error_t (*program)(void *instance, flash_address_t addr, \
const uint8_t *pp, size_t n); \
@@ -219,30 +222,28 @@ typedef struct { (ip)->vmt_baseflash->erase_all(ip)
/**
- * @brief Erase operation on a series of contiguous sectors.
+ * @brief Erase operation on a sector.
*
* @param[in] ip pointer to a @p BaseFlash or derived class
- * @param[in] secotr first sector to be erased
- * @param[in] n number of sectors to be erased
+ * @param[in] sector sector to be erased
* @return An error code.
*
* @api
*/
-#define flashEraseSectors(ip, sector, n) \
- (ip)->vmt_baseflash->erase_sectors(ip, sector, n)
+#define flashEraseSector(ip, sector) \
+ (ip)->vmt_baseflash->erase_sector(ip, sector)
/**
- * @brief Returns the erase state of a series of contiguous sectors.
+ * @brief Returns the erase state of a sector.
*
* @param[in] ip pointer to a @p BaseFlash or derived class
- * @param[in] secotr first sector to be erased
- * @param[in] n number of sectors to be erased
+ * @param[in] sector sector to be verified
* @return An error code.
*
* @api
*/
-#define flashVerifyErase(ip, sector, n) \
- (ip)->vmt_baseflash->verify_erase(ip, sector, n)
+#define flashVerifyErase(ip, sector) \
+ (ip)->vmt_baseflash->verify_erase(ip, sector)
/**
* @brief Write operation.
|