diff --git a/hal/spi/spi_drv_stm32.c b/hal/spi/spi_drv_stm32.c index 125d4ac6..5139b517 100644 --- a/hal/spi/spi_drv_stm32.c +++ b/hal/spi/spi_drv_stm32.c @@ -248,7 +248,7 @@ int qspi_transfer( while (dsz > 0U) { if (fmode == 0) { - while ((QUADSPI_SR & QUADSPI_SR_FTF)); + while ((QUADSPI_SR & QUADSPI_SR_FTF) == 0); QUADSPI_DR = *dptr; } else { diff --git a/include/spi_drv.h b/include/spi_drv.h index 541c317a..d6e453e6 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -60,11 +60,11 @@ uint8_t spi_read(void); #ifdef QSPI_FLASH -enum QSPIMode { - QSPI_ADDR_MODE_SPI = 1, - QSPI_ADDR_MODE_DSPI = 2, - QSPI_ADDR_MODE_QSPI = 3, -}; + +/* these are used in macro logic, so must be defines */ +#define QSPI_ADDR_MODE_SPI 1 +#define QSPI_ADDR_MODE_DSPI 2 +#define QSPI_ADDR_MODE_QSPI 3 int qspi_transfer( const uint8_t cmd, uint32_t addr, uint32_t addrSz, diff --git a/src/qspi_flash.c b/src/qspi_flash.c index 9f3d7053..de9178be 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -32,7 +32,7 @@ #include "printf.h" #ifdef DEBUG_UART -#define DEBUG_QSPI +#define DEBUG_QSPI 1 #endif /* Flash Parameters: @@ -42,19 +42,19 @@ #define FLASH_DEVICE_SIZE (16 * 1024 * 1024) #endif #ifndef FLASH_PAGE_SIZE -#define FLASH_PAGE_SIZE 256 +#define FLASH_PAGE_SIZE SPI_FLASH_PAGE_SIZE #endif #ifndef FLASH_NUM_PAGES -#define FLASH_NUM_PAGES 0x10000 +#define FLASH_NUM_PAGES (FLASH_DEVICE_SIZE/FLASH_PAGE_SIZE) #endif #ifndef FLASH_SECTOR_SIZE -#define FLASH_SECTOR_SIZE WOLFBOOT_SECTOR_SIZE +#define FLASH_SECTOR_SIZE SPI_FLASH_SECTOR_SIZE #endif #define FLASH_NUM_SECTORS (FLASH_DEVICE_SIZE/FLASH_SECTOR_SIZE) /* QSPI Configuration */ #ifndef QSPI_ADDR_MODE -#define QSPI_ADDR_MODE QSPI_ADDR_MODE_QSPI +#define QSPI_ADDR_MODE QSPI_ADDR_MODE_SPI #endif #ifndef QSPI_ADDR_SZ #define QSPI_ADDR_SZ 3 @@ -70,6 +70,9 @@ /* Flash Commands */ #define WRITE_ENABLE_CMD 0x06U #define READ_SR_CMD 0x05U +#define READ_SR2_CMD 0x35U +#define WRITE_SR_CMD 0x01U +#define WRITE_SR2_CMD 0x31U #define WRITE_DISABLE_CMD 0x04U #define READ_ID_CMD 0x9FU @@ -81,14 +84,15 @@ #define FAST_READ_CMD 0x0BU #define DUAL_READ_CMD 0x3BU -#define QUAD_READ_CMD 0xEBU +#define QUAD_READ_CMD 0x6BU #define FAST_READ_4B_CMD 0x0CU #define DUAL_READ_4B_CMD 0x3CU #define QUAD_READ_4B_CMD 0x6CU #define PAGE_PROG_CMD 0x02U #define DUAL_PROG_CMD 0xA2U -#define QUAD_PROG_CMD 0x22U +#define QUAD_PROG_CMD 0x32U + #define PAGE_PROG_4B_CMD 0x12U #define DUAL_PROG_4B_CMD 0x12U #define QUAD_PROG_4B_CMD 0x34U @@ -101,8 +105,11 @@ #define FLASH_SR_WRITE_EN 0x02 /* 1=Write Enabled, 0=Write Disabled */ #define FLASH_SR_BUSY 0x01 /* 1=Busy, 0=Ready */ +#define FLASH_SR2_QE 0x02 /* 1=Quad Enable (QE) */ + +/* Read Command */ #if QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI && QSPI_ADDR_SZ == 4 -#define FLASH_READ_CMD QUAD_READ_4B_CMD +#define FLASH_READ_CMD QUAD_READ_4B_CMD #elif QSPI_ADDR_MODE == QSPI_ADDR_MODE_DSPI && QSPI_ADDR_SZ == 4 #define FLASH_READ_CMD DUAL_READ_4B_CMD #elif QSPI_ADDR_SZ == 4 @@ -115,6 +122,15 @@ #define FLASH_READ_CMD FAST_READ_CMD #endif +/* Write Command */ +#if QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI +#define FLASH_WRITE_CMD QUAD_PROG_CMD +#elif QSPI_ADDR_MODE == QSPI_ADDR_MODE_DSPI +#define FLASH_WRITE_CMD DUAL_PROG_CMD +#else +#define FLASH_WRITE_CMD PAGE_PROG_CMD +#endif + /* forward declarations */ static int qspi_wait_ready(void); @@ -135,8 +151,8 @@ static int qspi_flash_read_id(uint8_t* id, uint32_t idSz) QSPI_ADDR_MODE_SPI); qspi_status((uint8_t*)&status); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash: Ret %d: ID: %x, Cmd %x, status %x\n", - ret, *((uint32_t*)data), READ_ID_CMD, status); + wolfBoot_printf("Flash ID (ret %d): 0x%x, status %x\n", + ret, *((uint32_t*)data), status); #endif /* optionally return id data */ @@ -155,14 +171,14 @@ static int qspi_write_enable(void) ret = qspi_transfer(WRITE_ENABLE_CMD, 0, 0, NULL, 0, NULL, 0, 0, QSPI_ADDR_MODE_SPI); -#ifdef DEBUG_QSPI +#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 wolfBoot_printf("Write Enable: Ret %d\n", ret); #endif qspi_wait_ready(); ret = qspi_wait_we(); -#ifdef DEBUG_QSPI +#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 wolfBoot_printf("Write Enabled: %s\n", ret == 0 ? "yes" : "no"); #endif @@ -173,7 +189,7 @@ static int qspi_write_disable(void) { int ret = qspi_transfer(WRITE_DISABLE_CMD, 0, 0, NULL, 0, NULL, 0, 0, QSPI_ADDR_MODE_SPI); -#ifdef DEBUG_QSPI +#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 wolfBoot_printf("Write Disable: Ret %d\n", ret); #endif return ret; @@ -183,12 +199,19 @@ static int qspi_status(uint8_t* status) { int ret; uint8_t data[4]; /* size multiple of uint32_t */ +#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 + static uint8_t last_status = 0; +#endif memset(data, 0, sizeof(data)); ret = qspi_transfer(READ_SR_CMD, 0, 0, NULL, 0, data, 1, 0, QSPI_ADDR_MODE_SPI); -#ifdef DEBUG_QSPI - wolfBoot_printf("Status (ret %d): %02x\n", ret, data[0]); +#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 + if (status == NULL || last_status != data[0]) { + wolfBoot_printf("Status (ret %d): %02x -> %02x\n", + ret, last_status, data[0]); + } + last_status = data[0]; #endif if (ret == 0 && status) { *status = data[0]; @@ -236,6 +259,37 @@ static int qspi_wait_we(void) return -1; } +#if QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI +static int qspi_quad_enable(void) +{ + int ret; + uint8_t data[4]; /* size multiple of uint32_t */ + + ret = qspi_write_enable(); + if (ret == 0) { + memset(data, 0, sizeof(data)); + ret = qspi_transfer(READ_SR2_CMD, 0, 0, NULL, 0, data, 1, 0, + QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Status Reg 2: Ret %d, 0x%x\n", ret, data[0]); +#endif + if (ret == 0) { + if ((data[0] & FLASH_SR2_QE) == 0) { + data[0] |= FLASH_SR2_QE; + ret = qspi_transfer(WRITE_SR2_CMD, 0, 0, data, 1, NULL, 0, 0, + QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Setting Quad Enable: Ret %d, SR2 0x%x\n", + ret, data[0]); +#endif + } + } + qspi_write_disable(); + } + return ret; +} +#endif + #if QSPI_ADDR_SZ == 4 static int qspi_enter_4byte_addr(void) { @@ -279,6 +333,9 @@ uint16_t spi_flash_probe(void) spi_init(0,0); qspi_flash_read_id(NULL, 0); +#if QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI + qspi_quad_enable(); +#endif #if QSPI_ADDR_SZ == 4 qspi_enter_4byte_addr(); #endif @@ -289,6 +346,8 @@ uint16_t spi_flash_probe(void) return 0; } +/* Called for each sector from hal.h inline ext_flash_erase function + * Use SPI_FLASH_SECTOR_SIZE to adjust for QSPI sector size */ int spi_flash_sector_erase(uint32_t address) { int ret; @@ -301,7 +360,7 @@ int spi_flash_sector_erase(uint32_t address) NULL, 0, NULL, 0, 0, QSPI_ADDR_MODE_SPI); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Erase: Ret %d\n", ret); + wolfBoot_printf("Flash Erase: Ret %d, Address 0x%x\n", ret, address); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -315,12 +374,21 @@ int spi_flash_read(uint32_t address, void *data, int len) { int ret; + if (address > FLASH_DEVICE_SIZE) { +#ifdef DEBUG_QSPI + wolfBoot_printf("Flash Read: Invalid address (0x%x > 0x%x max)\n", + address, FLASH_DEVICE_SIZE); +#endif + return -1; + } + /* ------ Read Flash ------ */ ret = qspi_transfer(FLASH_READ_CMD, address, QSPI_ADDR_SZ, NULL, 0, data, len, QSPI_DUMMY_READ, QSPI_ADDR_MODE); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Read: Ret %d\r\n", ret); + wolfBoot_printf("Flash Read: Ret %d, Address 0x%x, Len %d, Cmd 0x%x\n", + ret, address, len, FLASH_READ_CMD); #endif return ret; @@ -329,7 +397,6 @@ int spi_flash_read(uint32_t address, void *data, int len) int spi_flash_write(uint32_t address, const void *data, int len) { int ret = 0; - uint8_t cmd[8]; /* size multiple of uint32_t */ uint32_t xferSz, page, pages, idx = 0; uintptr_t addr; @@ -345,11 +412,12 @@ int spi_flash_write(uint32_t address, const void *data, int len) addr = address + (page * FLASH_PAGE_SIZE); /* ------ Write Flash (page at a time) ------ */ - ret = qspi_transfer(PAGE_PROG_CMD, addr, QSPI_ADDR_SZ, + ret = qspi_transfer(FLASH_WRITE_CMD, addr, QSPI_ADDR_SZ, (const uint8_t*)(data + (page * FLASH_PAGE_SIZE)), xferSz, - NULL, 0, 0, QSPI_ADDR_MODE_SPI); + NULL, 0, 0, QSPI_ADDR_MODE); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Page %d Write: Ret %d\n", page, ret); + wolfBoot_printf("Flash Write: Ret %d, Address 0x%x, Len %d, Cmd 0x%x\n", + ret, addr, xferSz, FLASH_WRITE_CMD); #endif if (ret != 0) break; @@ -388,31 +456,30 @@ static int test_flash(void) uint8_t pageData[FLASH_PAGE_SIZE]; uint32_t wait = 0; - /* long wait */ - while (++wait < 1000000); - #ifndef TEST_FLASH_READONLY /* Erase sector */ - ret = ext_flash_erase(TEST_ADDRESS, WOLFBOOT_SECTOR_SIZE); - wolfBoot_printf("Erase Sector: Ret %d\n", ret); + ret = ext_flash_erase(TEST_ADDRESS, FLASH_SECTOR_SIZE); + wolfBoot_printf("Sector Erase: Ret %d\n", ret); - /* Write Pages */ + /* Write Page */ for (i=0; i 1 wolfBoot_printf("check[%3d] %02x\n", i, pageData[i]); + #endif if (pageData[i] != (i & 0xff)) { wolfBoot_printf("Check Data @ %d failed\n", i); return -1;