From 4fd5d759ff68da2dac83e8314bd838f5486108f4 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 5 Sep 2024 16:00:24 -0700 Subject: [PATCH] Improved external QSPI and internal Flash tests and logging. --- hal/nrf5340.c | 80 +++++++++++++++++++++++++++++++++++++-- hal/nrf5340.h | 24 +++++++----- hal/spi/spi_drv_nrf5340.c | 4 ++ src/qspi_flash.c | 40 +++++++++++--------- 4 files changed, 117 insertions(+), 31 deletions(-) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index c5ae46416..c4110c735 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -25,8 +25,13 @@ #include "image.h" #include "string.h" +#include "printf.h" #include "nrf5340.h" +#ifdef TEST_FLASH +static int test_flash(void); +#endif + #ifdef DEBUG_UART #ifndef UART_SEL @@ -97,6 +102,7 @@ void uart_write(const char* buf, unsigned int sz) } #endif /* DEBUG_UART */ +/* Non-volatile memory controller - base address is 0x0 */ static void RAMFUNCTION flash_wait_complete(void) { while (NVMC_READY == 0) @@ -107,13 +113,17 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) { int i = 0; uint32_t *src, *dst; - +#ifdef DEBUG_FLASH + wolfBoot_printf("Internal Flash Write: addr 0x%x, len %d\n", address, len); +#endif while (i < len) { if ((len - i > 3) && ((((address + i) & 0x03) == 0) && ((((uint32_t)data) + i) & 0x03) == 0)) { src = (uint32_t *)data; dst = (uint32_t *)address; + /* set both secure and non-secure registers */ NVMC_CONFIG = NVMC_CONFIG_WEN; + NVMC_CONFIGNS = NVMC_CONFIG_WEN; flash_wait_complete(); dst[i >> 2] = src[i >> 2]; flash_wait_complete(); @@ -125,7 +135,9 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) dst = (uint32_t *)(address - off); val = dst[i >> 2]; vbytes[off] = data[i]; + /* set both secure and non-secure registers */ NVMC_CONFIG = NVMC_CONFIG_WEN; + NVMC_CONFIGNS = NVMC_CONFIG_WEN; flash_wait_complete(); dst[i >> 2] = val; flash_wait_complete(); @@ -139,10 +151,15 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { uint32_t end = address + len - 1; uint32_t p; +#ifdef DEBUG_FLASH + wolfBoot_printf("Internal Flash Erase: addr 0x%x, len %d\n", address, len); +#endif for (p = address; p <= end; p += FLASH_PAGE_SIZE) { + /* set both secure and non-secure registers */ NVMC_CONFIG = NVMC_CONFIG_EEN; + NVMC_CONFIGNS = NVMC_CONFIG_EEN; flash_wait_complete(); - NVMC_ERASEPAGE = p; + *(volatile uint32_t *)p = 0xFFFFFFFF; flash_wait_complete(); } return 0; @@ -182,13 +199,68 @@ void hal_init(void) uart_init(); uart_write("wolfBoot HAL Init\n", 18); #endif + +#ifdef TEST_FLASH + if (test_flash() != 0) { + wolfBoot_printf("Internal flash Test Failed!\n"); + } +#endif } void hal_prepare_boot(void) { -#if 0 - CLOCK_HFCLKSTOP = 1; + +} + +/* Test for internal flash erase/write */ +/* Use TEST_EXT_FLASH to test external QSPI flash (see qspi_flash.c) */ +#ifdef TEST_FLASH + +#ifndef TEST_ADDRESS +#define TEST_ADDRESS (0xFA000UL) #endif + +/* #define TEST_FLASH_READONLY */ + +static int test_flash(void) +{ + int ret = 0; + uint32_t i, len; + uint8_t* pagePtr = (uint8_t*)TEST_ADDRESS; + static uint8_t pageData[WOLFBOOT_SECTOR_SIZE]; + + wolfBoot_printf("Internal flash test at 0x%x\n", TEST_ADDRESS); + + /* Setup test data */ + for (i=0; i 1 - wolfBoot_printf("Write Enable: Ret %d\n", ret); + wolfBoot_printf("QSPI Write Enable: Ret %d\n", ret); #endif /* wait until write enabled and not busy */ @@ -191,13 +191,13 @@ static int qspi_write_enable(void) } if (timeout >= QSPI_FLASH_READY_TRIES) { #ifdef DEBUG_QSPI - wolfBoot_printf("Flash WE Timeout!\n"); + wolfBoot_printf("QSPI Flash WE Timeout!\n"); #endif return -1; /* timeout */ } #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 - wolfBoot_printf("Write Enabled: %s\n", + wolfBoot_printf("QSPI Write Enabled: %s\n", (status & FLASH_SR_WRITE_EN) ? "yes" : "no"); #endif @@ -208,7 +208,7 @@ static int qspi_write_disable(void) { int ret = qspi_command_simple(QSPI_MODE_WRITE, WRITE_DISABLE_CMD, NULL, 0); #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 - wolfBoot_printf("Write Disable: Ret %d\n", ret); + wolfBoot_printf("QSPI Write Disable: Ret %d\n", ret); #endif return ret; } @@ -225,7 +225,7 @@ static int qspi_status(uint8_t* status) ret = qspi_command_simple(QSPI_MODE_READ, READ_SR_CMD, data, 1); #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 if (status == NULL || last_status != data[0]) { - wolfBoot_printf("Status (ret %d): %02x -> %02x\n", + wolfBoot_printf("QSPI Status (ret %d): %02x -> %02x\n", ret, last_status, data[0]); } last_status = data[0]; @@ -251,7 +251,7 @@ static int qspi_wait_ready(void) } #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Ready Timeout!\n"); + wolfBoot_printf("QSPI Flash Ready Timeout!\n"); #endif return -1; } @@ -304,7 +304,7 @@ static int qspi_enter_4byte_addr(void) if (ret == 0) { ret = qspi_command_simple(QSPI_MODE_WRITE, ENTER_4B_ADDR_MODE_CMD, NULL, 0); #ifdef DEBUG_QSPI - wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret); + wolfBoot_printf("QSPI: Enter 4-byte address mode: Ret %d\n", ret); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -319,7 +319,7 @@ static int qspi_exit_4byte_addr(void) if (ret == 0) { ret = qspi_command_simple(QSPI_MODE_WRITE, EXIT_4B_ADDR_MODE_CMD, NULL, 0); #ifdef DEBUG_QSPI - wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret); + wolfBoot_printf("QSPI: Enter 4-byte address mode: Ret %d\n", ret); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -344,7 +344,9 @@ uint16_t spi_flash_probe(void) #endif #ifdef TEST_EXT_FLASH - test_ext_flash(); + if (test_ext_flash() < 0) { + wolfBoot_printf("QSPI flash test failed!\n"); + } #endif return 0; } @@ -366,7 +368,7 @@ int spi_flash_sector_erase(uint32_t address) NULL, 0, QSPI_DATA_MODE_NONE /* Data */ ); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Erase: Ret %d, Address 0x%x\n", ret, address); + wolfBoot_printf("QSPI Flash Erase: Ret %d, Address 0x%x\n", ret, address); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -391,7 +393,7 @@ int spi_flash_read(uint32_t address, void *data, int len) if (address > FLASH_DEVICE_SIZE) { #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Read: Invalid address (0x%x > 0x%x max)\n", + wolfBoot_printf("QSPI Flash Read: Invalid address (0x%x > 0x%x max)\n", address, FLASH_DEVICE_SIZE); #endif return -1; @@ -406,7 +408,7 @@ int spi_flash_read(uint32_t address, void *data, int len) ); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Read: Ret %d, Address 0x%x, Len %d, Cmd 0x%x\n", + wolfBoot_printf("QSPI Flash Read: Ret %d, Address 0x%x, Len %d, Cmd 0x%x\n", ret, address, len, FLASH_READ_CMD); #endif @@ -440,7 +442,7 @@ int spi_flash_write(uint32_t address, const void *data, int len) xferSz, QSPI_DATA_MODE /* Data */ ); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Write: Ret %d, Addr 0x%x, Len %d, Cmd 0x%x\n", + wolfBoot_printf("QSPI Flash Write: Ret %d, Addr 0x%x, Len %d, Cmd 0x%x\n", ret, addr, xferSz, FLASH_WRITE_CMD); #endif if (ret != 0) @@ -469,11 +471,12 @@ void spi_flash_release(void) #endif /* QSPI_FLASH || OCTOSPI_FLASH */ +/* Test for external QSPI flash */ #ifdef TEST_EXT_FLASH #ifndef TEST_EXT_ADDRESS /* Start Address for test - 2MB */ - #define TEST_EXT_ADDRESS (2 * 1024 * 1024) + #define TEST_EXT_ADDRESS (2UL * 1024UL * 1024UL) #endif static int test_ext_flash(void) @@ -483,6 +486,8 @@ static int test_ext_flash(void) uint8_t pageData[FLASH_PAGE_SIZE]; uint32_t wait = 0; + wolfBoot_printf("QSPI Flash Test at 0x%x\n", TEST_EXT_ADDRESS); + #ifndef TEST_FLASH_READONLY /* Erase sector */ ret = ext_flash_erase(TEST_EXT_ADDRESS, FLASH_SECTOR_SIZE); @@ -501,7 +506,6 @@ static int test_ext_flash(void) ret = ext_flash_read(TEST_EXT_ADDRESS, pageData, sizeof(pageData)); wolfBoot_printf("Page Read: Ret %d\n", ret); - wolfBoot_printf("Checking...\n"); /* Check data */ for (i=0; i 1 @@ -509,11 +513,11 @@ static int test_ext_flash(void) #endif if (pageData[i] != (i & 0xff)) { wolfBoot_printf("Check Data @ %d failed\n", i); - return -1; + return -i; } } - wolfBoot_printf("Flash Test Passed\n"); + wolfBoot_printf("QSPI Flash Test Passed\n"); return ret; } #endif /* TEST_EXT_FLASH */