From b4b6ab1bdfadfce01952a038309a87419886ca68 Mon Sep 17 00:00:00 2001 From: "Xenofon (Fontas) Fafoutis" Date: Wed, 4 Apr 2018 11:08:18 +0100 Subject: [PATCH] improvements in ext-flash driver --- os/dev/ext-flash.c | 167 +++++++++++++++++++++++++-------------------- os/dev/ext-flash.h | 22 +++--- 2 files changed, 105 insertions(+), 84 deletions(-) diff --git a/os/dev/ext-flash.c b/os/dev/ext-flash.c index 7a0e6735b..2d84cbdd7 100644 --- a/os/dev/ext-flash.c +++ b/os/dev/ext-flash.c @@ -109,13 +109,22 @@ static spi_device_t flash_spi_configuration_default = { .spi_pha = 0, .spi_pol = 0 }; - -static spi_device_t *flash_spi_configuration; +/*---------------------------------------------------------------------------*/ +/** + * Get spi configuration, return default configuration if NULL + */ +static spi_device_t* +get_spi_conf(spi_device_t *conf) { + if(conf == NULL) { + return &flash_spi_configuration_default; + } + return conf; +}/*---------------------------------------------------------------------------*/ /** * Clear external flash CSN line */ static bool -select_on_bus(void) +select_on_bus(spi_device_t *flash_spi_configuration) { if(spi_select(flash_spi_configuration) == SPI_DEV_STATUS_OK) { return true; @@ -127,7 +136,7 @@ select_on_bus(void) * Set external flash CSN line */ static void -deselect(void) +deselect(spi_device_t *flash_spi_configuration) { spi_deselect(flash_spi_configuration); } @@ -137,19 +146,19 @@ deselect(void) * \return True when successful. */ static bool -wait_ready(void) +wait_ready(spi_device_t *flash_spi_configuration) { bool ret; const uint8_t wbuf[1] = { BLS_CODE_READ_STATUS }; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } ret = spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)); if(ret != SPI_DEV_STATUS_OK) { - deselect(); + deselect(flash_spi_configuration); return false; } @@ -164,7 +173,7 @@ wait_ready(void) if(ret != SPI_DEV_STATUS_OK) { /* Error */ - deselect(); + deselect(flash_spi_configuration); return false; } @@ -173,7 +182,7 @@ wait_ready(void) break; } } - deselect(); + deselect(flash_spi_configuration); return true; } /*---------------------------------------------------------------------------*/ @@ -185,23 +194,23 @@ wait_ready(void) * was powered down */ static uint8_t -verify_part(void) +verify_part(spi_device_t *flash_spi_configuration) { const uint8_t wbuf[] = { BLS_CODE_MDID, 0xFF, 0xFF, 0x00 }; uint8_t rbuf[2] = { 0, 0 }; bool ret; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return VERIFY_PART_LOCKED; } if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { - deselect(); + deselect(flash_spi_configuration); return VERIFY_PART_ERROR; } ret = spi_read(flash_spi_configuration, rbuf, sizeof(rbuf)); - deselect(); + deselect(flash_spi_configuration); if(ret != SPI_DEV_STATUS_OK) { return VERIFY_PART_ERROR; } @@ -219,31 +228,31 @@ verify_part(void) * the status register is accessible. */ static bool -power_down(void) +power_down(spi_device_t *flash_spi_configuration) { uint8_t cmd; uint8_t i; /* First, wait for the device to be ready */ - if(wait_ready() == false) { + if(wait_ready(flash_spi_configuration) == false) { /* Entering here will leave the device in standby instead of powerdown */ return false; } cmd = BLS_CODE_PD; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } if(spi_write_byte(flash_spi_configuration, cmd) != SPI_DEV_STATUS_OK) { - deselect(); + deselect(flash_spi_configuration); return false; } - deselect(); + deselect(flash_spi_configuration); i = 0; while(i < 10) { - if(verify_part() == VERIFY_PART_POWERED_DOWN) { + if(verify_part(flash_spi_configuration) == VERIFY_PART_POWERED_DOWN) { /* Device is powered down */ return true; } @@ -251,7 +260,7 @@ power_down(void) } /* Should not be required */ - deselect(); + deselect(flash_spi_configuration); return false; } /*---------------------------------------------------------------------------*/ @@ -260,23 +269,23 @@ power_down(void) * \return True if the command was written successfully */ static bool -power_standby(void) +power_standby(spi_device_t *flash_spi_configuration) { uint8_t cmd; bool success; cmd = BLS_CODE_RPD; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } success = (spi_write(flash_spi_configuration, &cmd, sizeof(cmd)) == SPI_DEV_STATUS_OK); if(success) { - success = wait_ready() == true ? true : false; + success = wait_ready(flash_spi_configuration) == true ? true : false; } - deselect(); + deselect(flash_spi_configuration); return success; } @@ -286,17 +295,17 @@ power_standby(void) * \return True when successful. */ static bool -write_enable(void) +write_enable(spi_device_t *flash_spi_configuration) { bool ret; const uint8_t wbuf[] = { BLS_CODE_WRITE_ENABLE }; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } ret = (spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) == SPI_DEV_STATUS_OK); - deselect(); + deselect(flash_spi_configuration); if(ret == false) { return false; @@ -305,8 +314,12 @@ write_enable(void) } /*---------------------------------------------------------------------------*/ bool -ext_flash_open() +ext_flash_open(spi_device_t *conf) { + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); + /* Check if platform has ext-flash */ if(flash_spi_configuration->pin_spi_sck == 255) { return false; @@ -316,37 +329,51 @@ ext_flash_open() return false; } /* Default output to clear chip select */ - deselect(); + deselect(flash_spi_configuration); /* Put the part is standby mode */ - power_standby(); + power_standby(flash_spi_configuration); - return verify_part() == VERIFY_PART_OK ? true : false; + if (verify_part(flash_spi_configuration) == VERIFY_PART_OK) { + return true; + } + + /* Failed to verify */ + spi_release(flash_spi_configuration); + return false; } /*---------------------------------------------------------------------------*/ bool -ext_flash_close() +ext_flash_close(spi_device_t *conf) { - /* Put the part in low power mode */ - if(power_down() == false) { - return false; - } + bool ret; + spi_device_t *flash_spi_configuration; + flash_spi_configuration = get_spi_conf(conf); + + /* Put the part in low power mode */ + ret = power_down(flash_spi_configuration); + + /* SPI is released no matter if power_down() succeeds or fails */ if(spi_release(flash_spi_configuration) != SPI_DEV_STATUS_OK) { return false; } - return true; + return ret; } /*---------------------------------------------------------------------------*/ bool -ext_flash_read(uint32_t offset, uint32_t length, uint8_t *buf) +ext_flash_read(spi_device_t *conf, uint32_t offset, uint32_t length, uint8_t *buf) { uint8_t wbuf[4]; bool ret; + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); + /* Wait till previous erase/program operation completes */ - if(wait_ready() == false) { + if(wait_ready(flash_spi_configuration) == false) { return false; } @@ -359,36 +386,40 @@ ext_flash_read(uint32_t offset, uint32_t length, uint8_t *buf) wbuf[2] = (offset >> 8) & 0xff; wbuf[3] = offset & 0xff; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } ret = (spi_read(flash_spi_configuration, buf, length) == SPI_DEV_STATUS_OK); - deselect(); + deselect(flash_spi_configuration); return ret; } /*---------------------------------------------------------------------------*/ bool -ext_flash_write(uint32_t offset, uint32_t length, const uint8_t *buf) +ext_flash_write(spi_device_t *conf, uint32_t offset, uint32_t length, const uint8_t *buf) { uint8_t wbuf[4]; uint32_t ilen; /* interim length per instruction */ + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); + while(length > 0) { /* Wait till previous erase/program operation completes */ - if(wait_ready() == false) { + if(wait_ready(flash_spi_configuration) == false) { return false; } - if(write_enable() == false) { + if(write_enable(flash_spi_configuration) == false) { return false; } @@ -410,30 +441,30 @@ ext_flash_write(uint32_t offset, uint32_t length, const uint8_t *buf) * is not imposed here since above instructions * should be enough to delay * as much. */ - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } if(spi_write(flash_spi_configuration, buf, ilen) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } buf += ilen; - deselect(); + deselect(flash_spi_configuration); } return true; } /*---------------------------------------------------------------------------*/ bool -ext_flash_erase(uint32_t offset, uint32_t length) +ext_flash_erase(spi_device_t *conf, uint32_t offset, uint32_t length) { /* * Note that Block erase might be more efficient when the floor map @@ -443,6 +474,10 @@ ext_flash_erase(uint32_t offset, uint32_t length) uint8_t wbuf[4]; uint32_t i, numsectors; uint32_t endoffset = offset + length - 1; + + spi_device_t *flash_spi_configuration; + + flash_spi_configuration = get_spi_conf(conf); offset = (offset / EXT_FLASH_ERASE_SECTOR_SIZE) * EXT_FLASH_ERASE_SECTOR_SIZE; numsectors = (endoffset - offset + EXT_FLASH_ERASE_SECTOR_SIZE - 1) / EXT_FLASH_ERASE_SECTOR_SIZE; @@ -451,11 +486,11 @@ ext_flash_erase(uint32_t offset, uint32_t length) for(i = 0; i < numsectors; i++) { /* Wait till previous erase/program operation completes */ - if(wait_ready() == false) { + if(wait_ready(flash_spi_configuration) == false) { return false; } - if(write_enable() == false) { + if(write_enable(flash_spi_configuration) == false) { return false; } @@ -463,16 +498,16 @@ ext_flash_erase(uint32_t offset, uint32_t length) wbuf[2] = (offset >> 8) & 0xff; wbuf[3] = offset & 0xff; - if(select_on_bus() == false) { + if(select_on_bus(flash_spi_configuration) == false) { return false; } if(spi_write(flash_spi_configuration, wbuf, sizeof(wbuf)) != SPI_DEV_STATUS_OK) { /* failure */ - deselect(); + deselect(flash_spi_configuration); return false; } - deselect(); + deselect(flash_spi_configuration); offset += EXT_FLASH_ERASE_SECTOR_SIZE; } @@ -481,33 +516,19 @@ ext_flash_erase(uint32_t offset, uint32_t length) } /*---------------------------------------------------------------------------*/ bool -ext_flash_test(void) +ext_flash_init(spi_device_t *conf) { - flash_spi_configuration = &flash_spi_configuration_default; - - if(ext_flash_open() == false) { + if(ext_flash_open(conf) == false) { return false; } - if(ext_flash_close() == false) { + if(ext_flash_close(conf) == false) { return false; } - LOG_INFO("Flash test successful\n"); + LOG_INFO("Flash init successful\n"); return true; } /*---------------------------------------------------------------------------*/ -bool -ext_flash_init(spi_device_t *conf) -{ - if(conf == NULL) { - flash_spi_configuration = &flash_spi_configuration_default; - } else { - flash_spi_configuration = conf; - } - - return ext_flash_test(); -} -/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/os/dev/ext-flash.h b/os/dev/ext-flash.h index 14017ab46..8012ee6dd 100644 --- a/os/dev/ext-flash.h +++ b/os/dev/ext-flash.h @@ -49,19 +49,22 @@ /*---------------------------------------------------------------------------*/ /** * \brief Initialize storage driver. + * \param SPI bus configuration struct. NULL for default. * \return True when successful. */ -bool ext_flash_open(void); +bool ext_flash_open(spi_device_t *conf); /** * \brief Close the storage driver + * \param SPI bus configuration struct. NULL for default. * * This call will put the device in its lower power mode (power down). */ -bool ext_flash_close(void); +bool ext_flash_close(spi_device_t *conf); /** * \brief Read storage content + * \param SPI bus configuration struct. NULL for default. * \param offset Address to read from * \param length Number of bytes to read * \param buf Buffer where to store the read bytes @@ -69,10 +72,11 @@ bool ext_flash_close(void); * * buf must be allocated by the caller */ -bool ext_flash_read(uint32_t offset, uint32_t length, uint8_t *buf); +bool ext_flash_read(spi_device_t *conf, uint32_t offset, uint32_t length, uint8_t *buf); /** * \brief Erase storage sectors corresponding to the range. + * \param SPI bus configuration struct. NULL for default. * \param offset Address to start erasing * \param length Number of bytes to erase * \return True when successful. @@ -80,26 +84,22 @@ bool ext_flash_read(uint32_t offset, uint32_t length, uint8_t *buf); * The erase operation will be sector-wise, therefore a call to this function * will generally start the erase procedure at an address lower than offset */ -bool ext_flash_erase(uint32_t offset, uint32_t length); +bool ext_flash_erase(spi_device_t *conf, uint32_t offset, uint32_t length); /** * \brief Write to storage sectors. + * \param SPI bus configuration struct. NULL for default. * \param offset Address to write to * \param length Number of bytes to write * \param buf Buffer holding the bytes to be written * * \return True when successful. */ -bool ext_flash_write(uint32_t offset, uint32_t length, const uint8_t *buf); - -/** - * \brief Test the flash (power on self-test) - * \return True when successful. - */ -bool ext_flash_test(void); +bool ext_flash_write(spi_device_t *conf, uint32_t offset, uint32_t length, const uint8_t *buf); /** * \brief Initialise the external flash + * \param SPI bus configuration struct. NULL for default. * * This function will explicitly put the part in its lowest power mode * (power-down).