48#ifndef EXT_FLASH_SPI_CONTROLLER
50#define EXT_FLASH_SPI_CONTROLLER 0xFF
52#define EXT_FLASH_SPI_PIN_SCK GPIO_HAL_PIN_UNKNOWN
53#define EXT_FLASH_SPI_PIN_MOSI GPIO_HAL_PIN_UNKNOWN
54#define EXT_FLASH_SPI_PIN_MISO GPIO_HAL_PIN_UNKNOWN
55#define EXT_FLASH_SPI_PIN_CS GPIO_HAL_PIN_UNKNOWN
57#define EXT_FLASH_DEVICE_ID 0xFF
58#define EXT_FLASH_MID 0xFF
60#define EXT_FLASH_PROGRAM_PAGE_SIZE 256
61#define EXT_FLASH_ERASE_SECTOR_SIZE 4096
66#define LOG_MODULE "ext-flash"
67#define LOG_LEVEL LOG_LEVEL_NONE
71#define BLS_CODE_PROGRAM 0x02
72#define BLS_CODE_READ 0x03
73#define BLS_CODE_READ_STATUS 0x05
74#define BLS_CODE_WRITE_ENABLE 0x06
75#define BLS_CODE_SECTOR_ERASE 0x20
76#define BLS_CODE_MDID 0x90
78#define BLS_CODE_PD 0xB9
79#define BLS_CODE_RPD 0xAB
83#define BLS_CODE_ERASE_4K 0x20
84#define BLS_CODE_ERASE_32K 0x52
85#define BLS_CODE_ERASE_64K 0xD8
86#define BLS_CODE_ERASE_ALL 0xC7
90#define BLS_STATUS_SRWD_BM 0x80
91#define BLS_STATUS_BP_BM 0x0C
92#define BLS_STATUS_WEL_BM 0x02
93#define BLS_STATUS_WIP_BM 0x01
95#define BLS_STATUS_BIT_BUSY 0x01
97#define VERIFY_PART_LOCKED -2
98#define VERIFY_PART_ERROR -1
99#define VERIFY_PART_POWERED_DOWN 0
100#define VERIFY_PART_OK 1
102static const spi_device_t flash_spi_configuration_default = {
103#if GPIO_HAL_PORT_PIN_NUMBERING
104 .port_spi_sck = EXT_FLASH_SPI_PORT_SCK,
105 .port_spi_miso = EXT_FLASH_SPI_PORT_MISO,
106 .port_spi_mosi = EXT_FLASH_SPI_PORT_MOSI,
107 .port_spi_cs = EXT_FLASH_SPI_PORT_CS,
109 .spi_controller = EXT_FLASH_SPI_CONTROLLER,
110 .pin_spi_sck = EXT_FLASH_SPI_PIN_SCK,
111 .pin_spi_miso = EXT_FLASH_SPI_PIN_MISO,
112 .pin_spi_mosi = EXT_FLASH_SPI_PIN_MOSI,
113 .pin_spi_cs = EXT_FLASH_SPI_PIN_CS,
114 .spi_bit_rate = 4000000,
126 return &flash_spi_configuration_default;
137 if(
spi_select(flash_spi_configuration) == SPI_DEV_STATUS_OK) {
166 ret =
spi_write(flash_spi_configuration, wbuf,
sizeof(wbuf));
168 if(ret != SPI_DEV_STATUS_OK) {
180 ret =
spi_read(flash_spi_configuration, &buf,
sizeof(buf));
182 if(ret != SPI_DEV_STATUS_OK) {
208 uint8_t rbuf[2] = { 0, 0 };
212 return VERIFY_PART_LOCKED;
215 if(
spi_write(flash_spi_configuration, wbuf,
sizeof(wbuf)) != SPI_DEV_STATUS_OK) {
217 return VERIFY_PART_ERROR;
220 ret =
spi_read(flash_spi_configuration, rbuf,
sizeof(rbuf));
222 if(ret != SPI_DEV_STATUS_OK) {
223 return VERIFY_PART_ERROR;
226 LOG_DBG(
"Verify: %02x %02x\n", rbuf[0], rbuf[1]);
228 if(rbuf[0] != EXT_FLASH_MID || rbuf[1] != EXT_FLASH_DEVICE_ID) {
229 return VERIFY_PART_POWERED_DOWN;
231 return VERIFY_PART_OK;
245 if(
wait_ready(flash_spi_configuration) ==
false) {
255 if(
spi_write_byte(flash_spi_configuration, cmd) != SPI_DEV_STATUS_OK) {
263 if(
verify_part(flash_spi_configuration) == VERIFY_PART_POWERED_DOWN) {
290 success = (
spi_write(flash_spi_configuration, &cmd,
sizeof(cmd)) == SPI_DEV_STATUS_OK);
293 success =
wait_ready(flash_spi_configuration) ==
true ? true :
false;
315 ret = (
spi_write(flash_spi_configuration, wbuf,
sizeof(wbuf)) == SPI_DEV_STATUS_OK);
336 if(
spi_acquire(flash_spi_configuration) != SPI_DEV_STATUS_OK) {
345 if(
verify_part(flash_spi_configuration) == VERIFY_PART_OK) {
366 if(
spi_release(flash_spi_configuration) != SPI_DEV_STATUS_OK) {
384 if(
wait_ready(flash_spi_configuration) ==
false) {
393 wbuf[1] = (offset >> 16) & 0xff;
394 wbuf[2] = (offset >> 8) & 0xff;
395 wbuf[3] = offset & 0xff;
401 if(
spi_write(flash_spi_configuration, wbuf,
sizeof(wbuf)) != SPI_DEV_STATUS_OK) {
407 ret = (
spi_read(flash_spi_configuration, buf, length) == SPI_DEV_STATUS_OK);
426 if(
wait_ready(flash_spi_configuration) ==
false) {
434 ilen = EXT_FLASH_PROGRAM_PAGE_SIZE - (offset % EXT_FLASH_PROGRAM_PAGE_SIZE);
440 wbuf[1] = (offset >> 16) & 0xff;
441 wbuf[2] = (offset >> 8) & 0xff;
442 wbuf[3] = offset & 0xff;
456 if(
spi_write(flash_spi_configuration, wbuf,
sizeof(wbuf)) != SPI_DEV_STATUS_OK) {
462 if(
spi_write(flash_spi_configuration, buf, ilen) != SPI_DEV_STATUS_OK) {
483 uint32_t i, numsectors;
484 uint32_t endoffset = offset + length - 1;
490 offset = (offset / EXT_FLASH_ERASE_SECTOR_SIZE) * EXT_FLASH_ERASE_SECTOR_SIZE;
491 numsectors = (endoffset - offset + EXT_FLASH_ERASE_SECTOR_SIZE - 1) / EXT_FLASH_ERASE_SECTOR_SIZE;
495 for(i = 0; i < numsectors; i++) {
497 if(
wait_ready(flash_spi_configuration) ==
false) {
505 wbuf[1] = (offset >> 16) & 0xff;
506 wbuf[2] = (offset >> 8) & 0xff;
507 wbuf[3] = offset & 0xff;
513 if(
spi_write(flash_spi_configuration, wbuf,
sizeof(wbuf)) != SPI_DEV_STATUS_OK) {
520 offset += EXT_FLASH_ERASE_SECTOR_SIZE;
537 LOG_INFO(
"Flash init successful\n");
Header file for the external SPI flash API.
Header file for the GPIO HAL.
static bool write_enable(const spi_device_t *flash_spi_configuration)
Enable write.
bool ext_flash_read(const spi_device_t *conf, uint32_t offset, uint32_t length, uint8_t *buf)
Read storage content.
static const spi_device_t * get_spi_conf(const spi_device_t *conf)
Get spi configuration, return default configuration if NULL.
bool ext_flash_close(const spi_device_t *conf)
Close the storage driver.
static uint8_t verify_part(const spi_device_t *flash_spi_configuration)
Verify the flash part.
static bool power_down(const spi_device_t *flash_spi_configuration)
Put the device in power save mode.
#define BLS_CODE_RPD
Release Power-Down.
#define BLS_CODE_MDID
Manufacturer Device ID.
bool ext_flash_init(const spi_device_t *conf)
Initialise the external flash.
bool ext_flash_open(const spi_device_t *conf)
Initialize storage driver.
#define BLS_CODE_SECTOR_ERASE
Sector Erase.
static void deselect(const spi_device_t *flash_spi_configuration)
Set external flash CSN line.
#define BLS_STATUS_BIT_BUSY
Busy bit of the status register.
static bool wait_ready(const spi_device_t *flash_spi_configuration)
Wait till previous erase/program operation completes.
#define BLS_CODE_READ_STATUS
Read Status Register.
#define BLS_CODE_READ
Read Data.
bool ext_flash_write(const spi_device_t *conf, uint32_t offset, uint32_t length, const uint8_t *buf)
Write to storage sectors.
#define BLS_CODE_PD
Power down.
static bool power_standby(const spi_device_t *flash_spi_configuration)
Take device out of power save mode and prepare it for normal operation.
#define BLS_CODE_WRITE_ENABLE
Write Enable.
static bool select_on_bus(const spi_device_t *flash_spi_configuration)
Clear external flash CSN line.
#define BLS_CODE_PROGRAM
Page Program.
bool ext_flash_erase(const spi_device_t *conf, uint32_t offset, uint32_t length)
Erase storage sectors corresponding to the range.
#define GPIO_HAL_PIN_UNKNOWN
Unknown GPIO.
spi_status_t spi_release(const spi_device_t *dev)
Closes and then unlocks an SPI controller.
spi_status_t spi_read(const spi_device_t *dev, uint8_t *buf, int size)
Reads a buffer from an SPI device.
spi_status_t spi_deselect(const spi_device_t *dev)
Deselects the SPI peripheral.
spi_status_t spi_acquire(const spi_device_t *dev)
Locks and then opens an SPI controller.
spi_status_t spi_write_byte(const spi_device_t *dev, uint8_t data)
Writes a single byte to an SPI device.
spi_status_t spi_write(const spi_device_t *dev, const uint8_t *data, int size)
Writes a buffer to an SPI device.
spi_status_t spi_select(const spi_device_t *dev)
Selects the SPI peripheral.
Header file for the logging system.
Header file for the SPI HAL.
SPI Device Configuration.