QSPI Flash tests passing in single SPI mode (working on Quad mode).

```
wolfBoot Init
Flash ID (ret 0): 0x1870EF, status 0
Erase Sector: Ret 0
Flash Write: Ret 0, Address 0x200000, Page 0, Len 256
Write Page: Ret 0
Flash Read: Ret 0, Address 0x200000, Len 256, Cmd 0xB
Read Page: Ret 0
Checking...
Flash Test Passed
```
pull/264/head
David Garske 2022-12-20 16:28:56 -08:00
parent 26bed3e893
commit 5331f5ee23
3 changed files with 102 additions and 35 deletions

View File

@ -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 {

View File

@ -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,

View File

@ -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<sizeof(pageData); i++) {
pageData[i] = (i & 0xff);
}
ret = ext_flash_write(TEST_ADDRESS, pageData, sizeof(pageData));
wolfBoot_printf("Write Page: Ret %d\n", ret);
wolfBoot_printf("Page Write: Ret %d\n", ret);
#endif /* !TEST_FLASH_READONLY */
/* Read page */
memset(pageData, 0, sizeof(pageData));
ret = ext_flash_read(TEST_ADDRESS, pageData, sizeof(pageData));
wolfBoot_printf("Read Page: Ret %d\n", ret);
wolfBoot_printf("Page Read: Ret %d\n", ret);
wolfBoot_printf("Checking...\n");
/* Check data */
for (i=0; i<sizeof(pageData); i++) {
#if defined(DEBUG_QSPI) && DEBUG_QSPI > 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;