aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2016-05-08 13:12:28 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2016-05-08 13:12:28 +0000
commitceb256ed74e5f8cb5bf32f8268b2bd70f8850c1b (patch)
tree6d5dba6fbbf96e2276e4735bc217e2ea9d92ce31 /os
parenta4e52c4687af0945077aed7203be852fcdf8bd9b (diff)
downloadChibiOS-ceb256ed74e5f8cb5bf32f8268b2bd70f8850c1b.tar.gz
ChibiOS-ceb256ed74e5f8cb5bf32f8268b2bd70f8850c1b.tar.bz2
ChibiOS-ceb256ed74e5f8cb5bf32f8268b2bd70f8850c1b.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9451 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/ex/Micron/n25q128.c109
-rw-r--r--os/hal/lib/peripherals/flash/hal_flash.h18
2 files changed, 98 insertions, 29 deletions
diff --git a/os/ex/Micron/n25q128.c b/os/ex/Micron/n25q128.c
index 4a2c7f93b..c152ee58d 100644
--- a/os/ex/Micron/n25q128.c
+++ b/os/ex/Micron/n25q128.c
@@ -35,6 +35,7 @@
#define PAGE_SIZE 256U
#define PAGE_MASK (PAGE_SIZE - 1U)
+#define SECTOR_SIZE 4096U
/*===========================================================================*/
/* Driver exported variables. */
@@ -44,7 +45,7 @@
/* Driver local variables and types. */
/*===========================================================================*/
-static const flash_descriptor_t *get_attributes(void *instance);
+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,
@@ -61,7 +62,7 @@ static flash_error_t read(void *instance, flash_address_t addr,
* @brief Virtual methods table.
*/
static const struct N25Q128DriverVMT n25q128_vmt = {
- get_attributes, erase_all, erase_sectors, are_sectors_erased,
+ get_descriptor, erase_all, erase_sectors, are_sectors_erased,
program, read
};
@@ -73,7 +74,7 @@ static flash_descriptor_t descriptor = {
.page_size = 256,
.sectors_count = 4096,
.sectors = NULL,
- .sectors_size = 4096,
+ .sectors_size = SECTOR_SIZE,
.address = 0
};
@@ -129,9 +130,10 @@ static flash_error_t flash_poll_status(N25Q128Driver *devp) {
return FLASH_NO_ERROR;
}
-static const flash_descriptor_t *get_attributes(void *instance) {
+static const flash_descriptor_t *get_descriptor(void *instance) {
N25Q128Driver *devp = (N25Q128Driver *)instance;
+ osalDbgCheck(instance != NULL);
osalDbgAssert(devp->state == FLASH_READY, "invalid state");
return &descriptor;
@@ -140,12 +142,37 @@ static const flash_descriptor_t *get_attributes(void *instance) {
static flash_error_t erase_all(void *instance) {
N25Q128Driver *devp = (N25Q128Driver *)instance;
SPIDriver *spip = devp->config->spip;
+ flash_error_t err;
+ osalDbgCheck(instance != NULL);
osalDbgAssert(devp->state == FLASH_READY, "invalid state");
- (void)instance;
+#if N25Q128_SHARED_SPI == TRUE
+ spiAcquireBus(spip);
+ spiStart(spip, devp->config->spicfg);
+#endif
+ devp->state = FLASH_ACTIVE;
- return FLASH_NO_ERROR;
+ /* Enabling write operation.*/
+ spiSelect(spip);
+ flash_send_cmd(devp, N25Q128_CMD_WRITE_ENABLE);
+ spiUnselect(spip);
+ (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/
+
+ /* Bulk erase command.*/
+ spiSelect(spip);
+ flash_send_cmd(devp, N25Q128_CMD_BULK_ERASE);
+ spiUnselect(spip);
+
+ /* 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
+ return err;
}
static flash_error_t erase_sectors(void *instance,
@@ -153,14 +180,51 @@ static flash_error_t erase_sectors(void *instance,
flash_sector_t n) {
N25Q128Driver *devp = (N25Q128Driver *)instance;
SPIDriver *spip = devp->config->spip;
+ flash_address_t addr = (flash_address_t)(sector * SECTOR_SIZE);
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector + n <= descriptor.sectors_count);
osalDbgAssert(devp->state == FLASH_READY, "invalid state");
- (void)instance;
- (void)sector;
- (void)n;
+#if N25Q128_SHARED_SPI == TRUE
+ spiAcquireBus(spip);
+ spiStart(spip, devp->config->spicfg);
+#endif
+ devp->state = FLASH_ACTIVE;
+ flash_error_t err;
- return FLASH_NO_ERROR;
+ /* Sub-sectors erased one by one, a possible optimization could be to
+ erase whole sectors where possible.*/
+ while (n > 0) {
+
+ /* Enabling write operation.*/
+ spiSelect(spip);
+ flash_send_cmd(devp, N25Q128_CMD_WRITE_ENABLE);
+ spiUnselect(spip);
+ (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/
+
+
+ /* Sub-sector erase command.*/
+ spiSelect(spip);
+ flash_send_cmd_addr(devp, N25Q128_CMD_SUBSECTOR_ERASE, addr);
+ spiUnselect(spip);
+
+ /* Wait for status and check errors.*/
+ (void) spiPolledExchange(spip, 0xFF); /* One frame delay.*/
+ err = flash_poll_status(devp);
+ if (err != FLASH_NO_ERROR) {
+ break;
+ }
+
+ n--;
+ addr += SECTOR_SIZE;
+ }
+
+ devp->state = FLASH_READY;
+#if N25Q128_SHARED_SPI == TRUE
+ spiReleaseBus(spip);
+#endif
+ return err;
}
static flash_error_t are_sectors_erased(void *instance,
@@ -169,11 +233,11 @@ static flash_error_t are_sectors_erased(void *instance,
N25Q128Driver *devp = (N25Q128Driver *)instance;
SPIDriver *spip = devp->config->spip;
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector + n <= descriptor.sectors_count);
osalDbgAssert(devp->state == FLASH_READY, "invalid state");
- (void)instance;
- (void)sector;
- (void)n;
+ (void)spip;
return FLASH_NO_ERROR;
}
@@ -184,6 +248,9 @@ static flash_error_t program(void *instance, flash_address_t addr,
SPIDriver *spip = devp->config->spip;
flash_error_t err;
+ osalDbgCheck((instance != NULL) && (pp != NULL));
+ 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
@@ -212,9 +279,9 @@ static flash_error_t program(void *instance, flash_address_t addr,
flash_send_cmd_addr(devp, N25Q128_CMD_PAGE_PROGRAM, addr);
spiSend(spip, chunk, pp);
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;
@@ -239,6 +306,9 @@ static flash_error_t read(void *instance, flash_address_t addr,
N25Q128Driver *devp = (N25Q128Driver *)instance;
SPIDriver *spip = devp->config->spip;
+ osalDbgCheck((instance != NULL) && (rp != NULL));
+ 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
@@ -273,6 +343,8 @@ static flash_error_t read(void *instance, flash_address_t addr,
*/
void n15q128ObjectInit(N25Q128Driver *devp) {
+ osalDbgCheck(devp != NULL);
+
devp->vmt_baseflash = &n25q128_vmt;
devp->state = FLASH_STOP;
devp->config = NULL;
@@ -288,12 +360,11 @@ void n15q128ObjectInit(N25Q128Driver *devp) {
*/
void n15q128Start(N25Q128Driver *devp, const N25Q128Config *config) {
- (void)config;
-
+ osalDbgCheck((devp != NULL) && (config != NULL));
osalDbgAssert(devp->state != FLASH_UNINIT, "invalid state");
if (devp->state == FLASH_STOP) {
-#if N25Q128_SHARED_SPI == TRUE
+#if N25Q128_SHARED_SPI == FALSE
spiStart(devp->config->spip, devp->config->spicfg);
#endif
devp->state = FLASH_READY;
@@ -310,6 +381,7 @@ void n15q128Start(N25Q128Driver *devp, const N25Q128Config *config) {
void n15q128Stop(N25Q128Driver *devp) {
SPIDriver *spip = devp->config->spip;
+ osalDbgCheck(devp != NULL);
osalDbgAssert(devp->state != FLASH_UNINIT, "invalid state");
if (devp->state != FLASH_STOP) {
@@ -318,12 +390,11 @@ void n15q128Stop(N25Q128Driver *devp) {
#endif
spiStop(spip);
+ devp->state = FLASH_STOP;
#if N25Q128_SHARED_SPI == TRUE
spiReleaseBus(spip);
#endif
-
- devp->state = FLASH_STOP;
}
}
diff --git a/os/hal/lib/peripherals/flash/hal_flash.h b/os/hal/lib/peripherals/flash/hal_flash.h
index c3559a732..b3c47b377 100644
--- a/os/hal/lib/peripherals/flash/hal_flash.h
+++ b/os/hal/lib/peripherals/flash/hal_flash.h
@@ -66,13 +66,11 @@ typedef enum {
*/
typedef enum {
FLASH_NO_ERROR = 0, /* No error. */
- FLASH_PARAMETER_ERROR = 1, /* Error in a function parameter. */
- FLASH_ADDRESS_ERROR = 2, /* Operation overlaps invalid addresses. */
- FLASH_ECC_ERROR = 3, /* ECC error during read operation. */
- FLASH_PROGRAM_FAILURE = 4, /* Program operation failed. */
- FLASH_ERASE_FAILURE = 5, /* Erase operation failed. */
- FLASH_VERIFY_FAILURE = 6, /* Verify operation failed. */
- FLASH_HW_FAILURE = 7 /* Controller or communication error. */
+ FLASH_ECC_ERROR = 1, /* ECC error during read operation. */
+ 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_error_t;
/**
@@ -140,7 +138,7 @@ typedef struct {
*/
#define _base_flash_methods_alone \
/* Get flash device attributes.*/ \
- const flash_descriptor_t * (*get_attributes)(void *instance); \
+ const flash_descriptor_t * (*get_descriptor)(void *instance); \
/* Erase whole flash device.*/ \
flash_error_t (*erase_all)(void *instance); \
/* Erase single sector.*/ \
@@ -206,8 +204,8 @@ typedef struct {
*
* @api
*/
-#define flashGetType(ip) \
- (ip)->vmt_baseflash->get_attributes(ip)
+#define flashGetDescriptor(ip) \
+ (ip)->vmt_baseflash->get_descriptor(ip)
/**
* @brief Whole device erase operation.