From ceb256ed74e5f8cb5bf32f8268b2bd70f8850c1b Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 8 May 2016 13:12:28 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9451 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ex/Micron/n25q128.c | 109 +++++++++++++++++++++++++------ os/hal/lib/peripherals/flash/hal_flash.h | 18 +++-- 2 files changed, 98 insertions(+), 29 deletions(-) (limited to 'os') 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. -- cgit v1.2.3