aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/ex/Micron/n25q128.c201
-rw-r--r--os/ex/Micron/n25q128.h7
-rw-r--r--os/hal/lib/peripherals/flash/hal_flash.h43
-rw-r--r--testhal/STM32/STM32F3xx/SPI-N25Q128/main.c4
4 files changed, 119 insertions, 136 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.
diff --git a/testhal/STM32/STM32F3xx/SPI-N25Q128/main.c b/testhal/STM32/STM32F3xx/SPI-N25Q128/main.c
index c8ca4aaa4..41c8541e2 100644
--- a/testhal/STM32/STM32F3xx/SPI-N25Q128/main.c
+++ b/testhal/STM32/STM32F3xx/SPI-N25Q128/main.c
@@ -129,10 +129,10 @@ int main(void) {
err = flashRead(&flash, 0, buffer, 128);
if (err != FLASH_NO_ERROR)
chSysHalt("read error");
- err = flashEraseSectors(&flash, 0, 1);
+ err = flashEraseSector(&flash, 0);
if (err != FLASH_NO_ERROR)
chSysHalt("erase error");
- err = flashVerifyErase(&flash, 0, 1);
+ err = flashVerifyErase(&flash, 0);
if (err != FLASH_NO_ERROR)
chSysHalt("verify erase error");
err = flashRead(&flash, 0, buffer, 128);