From a9526bab8f825f40b658c82054ee67de887ebcd5 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 30 Nov 2022 15:15:22 -0800 Subject: [PATCH] STM32 QSPI Flash support. Refactor SPI to allow different GPIO base/AF for each pin. Adds `DEBUG_UART` support for H7. --- Makefile | 2 +- config/examples/stm32h7.config | 2 + docs/Targets.md | 9 + hal/spi/spi_drv_nrf52.c | 21 +- hal/spi/spi_drv_nrf52.h | 4 +- hal/spi/spi_drv_stm32.c | 399 +++++++++++++++++++--------- hal/spi/spi_drv_stm32.h | 400 ++++++++++++++++++++-------- hal/spi/spi_drv_zynq.c | 6 +- hal/spi/spi_drv_zynq.h | 3 +- hal/stm32f4.c | 2 +- hal/stm32f7.c | 4 +- hal/stm32g0.c | 2 +- hal/stm32h7.c | 302 ++++++++++++++++++--- hal/stm32l0.c | 2 +- hal/stm32l4.c | 2 +- hal/stm32wb.c | 2 +- hal/zynq.c | 2 - include/hal.h | 13 +- include/spi_drv.h | 31 ++- include/spi_flash.h | 18 +- options.mk | 7 + src/image.c | 4 +- src/qspi_flash.c | 425 ++++++++++++++++++++++++++++++ src/spi_flash.c | 40 +-- test-app/Makefile | 9 + test-app/app_stm32f4.c | 2 +- test-app/app_stm32h7.c | 70 +++-- test-app/app_stm32l0.c | 146 +++++++++- tools/check_config/check_config.c | 4 +- tools/config.mk | 1 + 30 files changed, 1574 insertions(+), 360 deletions(-) create mode 100644 src/qspi_flash.c diff --git a/Makefile b/Makefile index 6004dc16..1d2e00d0 100644 --- a/Makefile +++ b/Makefile @@ -119,7 +119,7 @@ test-app/image.bin: wolfboot.elf $(Q)$(SIZE) test-app/image.elf standalone: - $(Q)$(MAKE) -C test-app TARGET=$(TARGET) EXT_FLASH=$(EXT_FLASH) SPI_FLASH=$(SPI_FLASH) ARCH=$(ARCH) \ + $(Q)$(MAKE) -C test-app TARGET=$(TARGET) EXT_FLASH=$(EXT_FLASH) SPI_FLASH=$(SPI_FLASH) QSPI_FLASH=$(QSPI_FLASH) ARCH=$(ARCH) \ NO_XIP=$(NO_XIP) V=$(V) RAM_CODE=$(RAM_CODE) WOLFBOOT_VERSION=$(WOLFBOOT_VERSION)\ MCUXPRESSO=$(MCUXPRESSO) MCUXPRESSO_CPU=$(MCUXPRESSO_CPU) MCUXPRESSO_DRIVERS=$(MCUXPRESSO_DRIVERS) \ MCUXPRESSO_CMSIS=$(MCUXPRESSO_CMSIS) NVM_FLASH_WRITEONCE=$(NVM_FLASH_WRITEONCE) \ diff --git a/config/examples/stm32h7.config b/config/examples/stm32h7.config index 5ce3d51c..09759f27 100644 --- a/config/examples/stm32h7.config +++ b/config/examples/stm32h7.config @@ -3,11 +3,13 @@ TARGET?=stm32h7 SIGN?=ECC256 HASH?=SHA256 DEBUG?=0 +DEBUG_UART?=0 VTOR?=1 CORTEX_M0?=0 NO_ASM?=0 EXT_FLASH?=0 SPI_FLASH?=0 +QSPI_FLASH?=0 ALLOW_DOWNGRADE?=0 NVM_FLASH_WRITEONCE?=0 WOLFBOOT_VERSION?=1 diff --git a/docs/Targets.md b/docs/Targets.md index 5803a8c7..78acbe8b 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -704,6 +704,8 @@ The STM32H7 build can be built using: make TARGET=stm32h7 SIGN=ECC256 ``` +The STM32H7 also supports using the QSPI for external flash. To enable use `QSPI_FLASH=1` in your configuration. The pins are defined in `hal/spi/spi_drv_stm32.h`. A built-in alternate pin configuration can be used with `QSPI_ALT_CONFIGURATION`. The flash and QSPI parameters are defined in `src/qspi_flash.c` and can be overrriden at build time. + ### STM32H7 Programming ST-Link Flash Tools: @@ -735,6 +737,13 @@ booting. ST-Link: `st-util -p 3333` +ST-Link: `ST-LINK_gdbserver -d -e -r 1 -p 3333` + +Mac OS: +``` +/Applications/STM32CubeIDE.app/Contents/Eclipse/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.macos64_2.0.300.202203231527/tools/bin/ST-LINK_gdbserver -d -cp /Applications/STM32CubeIDE.app/Contents/Eclipse/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.macos64_2.0.200.202202231230/tools/bin -e -r 1 -p 3333 +``` + 2. Start GDB Client from wolfBoot root: ```sh diff --git a/hal/spi/spi_drv_nrf52.c b/hal/spi/spi_drv_nrf52.c index d1524d6c..1f7df73f 100644 --- a/hal/spi/spi_drv_nrf52.c +++ b/hal/spi/spi_drv_nrf52.c @@ -50,27 +50,28 @@ #define SPI_FREQUENCY *((volatile uint32_t *)(SPI + 0x524)) #define SPI_CONFIG *((volatile uint32_t *)(SPI + 0x554)) -#define K125 0x02000000 -#define K250 0x04000000 -#define K500 0x08000000 -#define M1 0x10000000 -#define M2 0x20000000 -#define M4 0x40000000 -#define M8 0x80000000 +#define K125 0x02000000 +#define K250 0x04000000 +#define K500 0x08000000 +#define M1 0x10000000 +#define M2 0x20000000 +#define M4 0x40000000 +#define M8 0x80000000 -void RAMFUNCTION spi_cs_off(int pin) +void RAMFUNCTION spi_cs_off(uint32_t base, int pin) { GPIO_OUTSET = (1 << pin); while ((GPIO_OUT & (1 << pin)) == 0) ; + (void)base; } -void RAMFUNCTION spi_cs_on(int pin) +void RAMFUNCTION spi_cs_on(uint32_t base, int pin) { GPIO_OUTCLR = (1 << pin); while ((GPIO_OUT & (1 << pin)) != 0) ; - + (void)base; } uint8_t RAMFUNCTION spi_read(void) diff --git a/hal/spi/spi_drv_nrf52.h b/hal/spi/spi_drv_nrf52.h index 330585c7..8ba41f68 100644 --- a/hal/spi/spi_drv_nrf52.h +++ b/hal/spi/spi_drv_nrf52.h @@ -47,8 +47,8 @@ #endif -#define SPI_CS_FLASH SPI_CS_PIN - +#define SPI_CS_FLASH SPI_CS_PIN +#define SPI_CS_PIO_BASE GPIO_BASE #endif diff --git a/hal/spi/spi_drv_stm32.c b/hal/spi/spi_drv_stm32.c index b5c8d178..d8d493ec 100644 --- a/hal/spi/spi_drv_stm32.c +++ b/hal/spi/spi_drv_stm32.c @@ -6,7 +6,7 @@ * * Pinout: see spi_drv_stm32.h * - * Copyright (C) 2021 wolfSSL Inc. + * Copyright (C) 2022 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -25,146 +25,233 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include +#include #include "spi_drv.h" #include "spi_drv_stm32.h" -void RAMFUNCTION spi_cs_off(int pin) +#if defined(SPI_FLASH) || defined(QSPI_FLASH) + +void RAMFUNCTION stm_gpio_config(uint32_t base, uint32_t pin, uint32_t af, + uint32_t pull, uint32_t speed) { - SPI_PIO_CS_BSRR |= (1 << pin); - while(!(SPI_PIO_CS_ODR & (1 << pin))) + uint32_t reg; + uint32_t base_num = 0; + + /* Determine GPIO clock bit */ + if (base == GPIOA_BASE) + base_num = 0; + else if (base == GPIOB_BASE) + base_num = 1; +#ifdef GPIOC_BASE + else if (base == GPIOC_BASE) + base_num = 2; +#endif +#ifdef GPIOD_BASE + else if (base == GPIOD_BASE) + base_num = 3; +#endif +#ifdef GPIOE_BASE + else if (base == GPIOE_BASE) + base_num = 4; +#endif +#ifdef GPIOF_BASE + else if (base == GPIOF_BASE) + base_num = 5; +#endif +#ifdef GPIOG_BASE + else if (base == GPIOG_BASE) + base_num = 6; +#endif +#ifdef GPIOH_BASE + else if (base == GPIOH_BASE) + base_num = 7; +#endif +#ifdef GPIOI_BASE + else if (base == GPIOI_BASE) + base_num = 8; +#endif +#ifdef GPIOJ_BASE + else if (base == GPIOJ_BASE) + base_num = 9; +#endif +#ifdef GPIOK_BASE + else if (base == GPIOK_BASE) + base_num = 10; +#endif + + /* Enable GPIO clock */ + RCC_GPIO_CLOCK_ER |= (1 << base); + + /* Set Mode and Alternate Function */ + if (af == 0) { + /* mode = 0, af = 0 */ + SPI_PIO_MODE(base) &= ~(0x03 << (pin * 2)); + if (pin < 8) + SPI_PIO_AFL(base) &= ~(0xf << (pin * 4)); + else + SPI_PIO_AFH(base) &= ~(0xf << ((pin - 8) * 4)); + } + else { + /* mode = 2 (af) */ + reg = SPI_PIO_MODE(base) & ~(0x03 << (pin * 2)); + SPI_PIO_MODE(base) = reg | (2 << (pin * 2)); + + /* alternate mode */ + if (pin < 8) { + reg = SPI_PIO_AFL(base) & ~(0xf << (pin * 4)); + SPI_PIO_AFL(base) = reg | (af << (pin * 4)); + } + else { + reg = SPI_PIO_AFH(base) & ~(0xf << ((pin - 8) * 4)); + SPI_PIO_AFH(base) = reg | (af << ((pin - 8) * 4)); + } + } + + /* configure for pull 0=float, 1=pull up, 2=pull down */ + reg = SPI_PIO_PUPD(base) & ~(0x03 << (pin * 2)); + SPI_PIO_PUPD(base) = reg | (pull << (pin * 2)); + + /* configure output speed 0=low, 1=med, 2=high, 3=very high */ + reg = SPI_PIO_OSPD(base) & ~(0x03 << (pin * 2)); + SPI_PIO_OSPD(base) |= (speed << (pin * 2)); +} + +#ifdef SPI_FLASH +void RAMFUNCTION spi_cs_off(uint32_t base, int pin) +{ + SPI_PIO_BSRR(base) |= (1 << pin); + while (!(SPI_PIO_ODR(base) & (1 << pin))) ; } -void RAMFUNCTION spi_cs_on(int pin) +void RAMFUNCTION spi_cs_on(uint32_t base, int pin) { - SPI_PIO_CS_BSRR |= (1 << (pin + 16)); - while(SPI_PIO_CS_ODR & (1 << pin)) + SPI_PIO_BSRR(base) |= (1 << (pin + 16)); + while (SPI_PIO_ODR(base) & (1 << pin)) ; } +#endif /* SPI_FLASH */ -static void RAMFUNCTION spi_flash_pin_setup(void) +static void RAMFUNCTION stm_pins_setup(void) { - uint32_t reg; - RCC_GPIO_CLOCK_ER |= SPI_PIO_CS_CEN; - reg = SPI_PIO_CS_MODE & ~ (0x03 << (SPI_CS_FLASH * 2)); - SPI_PIO_CS_MODE = reg | (1 << (SPI_CS_FLASH * 2)); - reg = SPI_PIO_CS_PUPD & ~(0x03 << (SPI_CS_FLASH * 2)); - SPI_PIO_CS_PUPD = reg | (0x01 << (SPI_CS_FLASH * 2)); - reg = SPI_PIO_CS_OSPD & ~(0x03 << (SPI_CS_FLASH * 2)); - SPI_PIO_CS_OSPD |= (0x03 << (SPI_CS_FLASH * 2)); - spi_cs_off(SPI_CS_FLASH); -} - -static void spi_tpm2_pin_setup(void) -{ -#ifdef WOLFBOOT_TPM - uint32_t reg; - RCC_GPIO_CLOCK_ER |= SPI_PIO_CS_CEN; - reg = SPI_PIO_CS_MODE & ~ (0x03 << (SPI_CS_TPM * 2)); - SPI_PIO_CS_MODE = reg | (1 << (SPI_CS_TPM * 2)); - reg = SPI_PIO_CS_PUPD & ~(0x03 << (SPI_CS_TPM * 2)); - SPI_PIO_CS_PUPD = reg | (0x01 << (SPI_CS_TPM * 2)); - reg = SPI_PIO_CS_OSPD & ~(0x03 << (SPI_CS_TPM * 2)); - SPI_PIO_CS_OSPD |= (0x03 << (SPI_CS_TPM * 2)); - spi_cs_off(SPI_CS_TPM); +#ifdef SPI_FLASH + stm_gpio_config(SPI_CLOCK_PIO_BASE, SPI_CLOCK_PIN, SPI_CLOCK_PIN_AF, 2, 3); + stm_gpio_config(SPI_MOSI_PIO_BASE, SPI_MOSI_PIN, SPI_MOSI_PIN_AF, 2, 3); + stm_gpio_config(SPI_MISO_PIO_BASE, SPI_MISO_PIN, SPI_MISO_PIN_AF, 2, 3); +#endif +#ifdef QSPI_FLASH + stm_gpio_config(QSPI_CS_PIO_BASE, QSPI_CS_FLASH_PIN, QSPI_CS_FLASH_AF, 0, 0); + stm_gpio_config(QSPI_CLOCK_PIO_BASE, QSPI_CLOCK_PIN, QSPI_CLOCK_PIN_AF, 0, 0); + stm_gpio_config(QSPI_IO0_PIO_BASE, QSPI_IO0_PIN, QSPI_IO0_PIN_AF, 0, 0); + stm_gpio_config(QSPI_IO1_PIO_BASE, QSPI_IO1_PIN, QSPI_IO1_PIN_AF, 0, 0); + stm_gpio_config(QSPI_IO2_PIO_BASE, QSPI_IO2_PIN, QSPI_IO2_PIN_AF, 0, 0); + stm_gpio_config(QSPI_IO3_PIO_BASE, QSPI_IO3_PIN, QSPI_IO3_PIN_AF, 0, 0); #endif } -static void RAMFUNCTION spi1_pins_setup(void) +static void stm_pins_release(void) { - uint32_t reg; - RCC_GPIO_CLOCK_ER |= SPI_PIO_CEN; - /* Set mode = AF */ - reg = SPI_PIO_MODE & ~ (0x03 << (SPI1_CLOCK_PIN * 2)); - SPI_PIO_MODE = reg | (2 << (SPI1_CLOCK_PIN * 2)); - reg = SPI_PIO_MODE & ~ (0x03 << (SPI1_MOSI_PIN * 2)); - SPI_PIO_MODE = reg | (2 << (SPI1_MOSI_PIN * 2)); - reg = SPI_PIO_MODE & ~ (0x03 << (SPI1_MISO_PIN * 2)); - SPI_PIO_MODE = reg | (2 << (SPI1_MISO_PIN * 2)); - - /* Alternate function */ -#if SPI1_CLOCK_PIN < 8 - reg = SPI_PIO_AFL & ~(0xf << ((SPI1_CLOCK_PIN) * 4)); - SPI_PIO_AFL = reg | (SPI1_PIN_AF << ((SPI1_CLOCK_PIN) * 4)); -#else - reg = SPI_PIO_AFH & ~(0xf << ((SPI1_CLOCK_PIN - 8) * 4)); - SPI_PIO_AFH = reg | (SPI1_PIN_AF << ((SPI1_CLOCK_PIN - 8) * 4)); +#ifdef SPI_FLASH + stm_gpio_config(SPI_CLOCK_PIO_BASE, SPI_CLOCK_PIN, 0, 0, 0); + stm_gpio_config(SPI_MOSI_PIO_BASE, SPI_MOSI_PIN, 0, 0, 0); + stm_gpio_config(SPI_MISO_PIO_BASE, SPI_MISO_PIN, 0, 0, 0); #endif -#if SPI1_MOSI_PIN < 8 - reg = SPI_PIO_AFL & ~(0xf << ((SPI1_MOSI_PIN) * 4)); - SPI_PIO_AFL = reg | (SPI1_PIN_AF << ((SPI1_MOSI_PIN) * 4)); -#else - reg = SPI_PIO_AFH & ~(0xf << ((SPI1_MOSI_PIN-8) * 4)); - SPI_PIO_AFH = reg | (SPI1_PIN_AF << ((SPI1_MOSI_PIN - 8) * 4)); -#endif -#if SPI1_MISO_PIN < 8 - reg = SPI_PIO_AFL & ~(0xf << ((SPI1_MISO_PIN) * 4)); - SPI_PIO_AFL = reg | (SPI1_PIN_AF << ((SPI1_MISO_PIN) * 4)); -#else - reg = SPI_PIO_AFH & ~(0xf << ((SPI1_MISO_PIN-8) * 4)); - SPI_PIO_AFH = reg | (SPI1_PIN_AF << ((SPI1_MISO_PIN - 8) * 4)); -#endif - -#ifdef PLATFORM_stm32l0 - reg = SPI_PIO_PUPD & ~(0x03 << (SPI1_CLOCK_PIN * 2)); - SPI_PIO_PUPD = reg | (0x02 << (SPI1_CLOCK_PIN * 2)); - reg = SPI_PIO_PUPD & ~(0x03 << (SPI1_MOSI_PIN * 2)); - SPI_PIO_PUPD = reg | (0x02 << (SPI1_MOSI_PIN * 2)); - reg = SPI_PIO_PUPD & ~(0x03 << (SPI1_MISO_PIN * 2)); - SPI_PIO_PUPD = reg | (0x02 << (SPI1_MISO_PIN * 2)); - - reg = SPI_PIO_OSPD & ~(0x03 << (SPI1_CLOCK_PIN * 2)); - SPI_PIO_OSPD |= (0x03 << (SPI1_CLOCK_PIN * 2)); - reg = SPI_PIO_OSPD & ~(0x03 << (SPI1_MOSI_PIN * 2)); - SPI_PIO_OSPD |= (0x03 << (SPI1_MOSI_PIN * 2)); - reg = SPI_PIO_OSPD & ~(0x03 << (SPI1_MISO_PIN * 2)); - SPI_PIO_OSPD |= (0x03 << (SPI1_MISO_PIN * 2)); +#ifdef QSPI_FLASH + stm_gpio_config(QSPI_CS_PIO_BASE, QSPI_CS_FLASH_PIN, 0, 0, 0); + stm_gpio_config(QSPI_CLOCK_PIO_BASE, QSPI_CLOCK_PIN, 0, 0, 0); + stm_gpio_config(QSPI_IO0_PIO_BASE, QSPI_IO0_PIN, 0, 0, 0); + stm_gpio_config(QSPI_IO1_PIO_BASE, QSPI_IO1_PIN, 0, 0, 0); + stm_gpio_config(QSPI_IO2_PIO_BASE, QSPI_IO2_PIN, 0, 0, 0); + stm_gpio_config(QSPI_IO3_PIO_BASE, QSPI_IO3_PIN, 0, 0, 0); #endif } -static void spi_pins_release(void) +static void RAMFUNCTION spi_reset(void) { - uint32_t reg; - /* Set mode = 0 */ - SPI_PIO_MODE &= ~ (0x03 << (SPI1_CLOCK_PIN * 2)); - SPI_PIO_MODE &= ~ (0x03 << (SPI1_MOSI_PIN * 2)); - SPI_PIO_MODE &= ~ (0x03 << (SPI1_MISO_PIN * 2)); - - /* Alternate function clear */ -#if SPI1_CLOCK_PIN < 8 - SPI_PIO_AFL &= ~(0xf << ((SPI1_CLOCK_PIN) * 4)); -#else - SPI_PIO_AFH &= ~(0xf << ((SPI1_CLOCK_PIN - 8) * 4)); +#ifdef QSPI_FLASH + AHB3_CLOCK_RST |= RCC_AHB3ENR_QSPIEN; + AHB3_CLOCK_RST &= ~RCC_AHB3ENR_QSPIEN; #endif -#if SPI1_MOSI_PIN < 8 - SPI_PIO_AFL &= ~(0xf << ((SPI1_MOSI_PIN) * 4)); -#else - SPI_PIO_AFL &= ~(0xf << ((SPI1_MOSI_PIN - 8) * 4)); -#endif -#if SPI1_MISO_PIN < 8 - SPI_PIO_AFL &= ~(0xf << ((SPI1_MISO_PIN) * 4)); -#else - SPI_PIO_AFL &= ~(0xf << ((SPI1_MISO_PIN - 8) * 4)); -#endif - - /* Floating */ - SPI_PIO_PUPD &= ~ (0x03 << (SPI1_CLOCK_PIN * 2)); - SPI_PIO_PUPD &= ~ (0x03 << (SPI1_MOSI_PIN * 2)); - SPI_PIO_PUPD &= ~ (0x03 << (SPI1_MISO_PIN * 2)); - - /* Release CS */ - SPI_PIO_CS_MODE &= ~ (0x03 << (SPI_CS_FLASH * 2)); - SPI_PIO_CS_PUPD &= ~ (0x03 << (SPI_CS_FLASH * 2)); - -} - -static void RAMFUNCTION spi1_reset(void) -{ +#ifdef SPI_FLASH APB2_CLOCK_RST |= SPI1_APB2_CLOCK_ER_VAL; APB2_CLOCK_RST &= ~SPI1_APB2_CLOCK_ER_VAL; +#endif } +#ifdef QSPI_FLASH +int qspi_transfer( + const uint8_t cmd, uint32_t addr, uint32_t addrSz, + const uint8_t* txData, uint32_t txSz, + uint8_t* rxData, uint32_t rxSz, uint32_t dummySz, + uint32_t mode) +{ + uint32_t fmode = 0, amode = 0; + uint32_t adsz = 0, dsz = 0; + uint8_t* dptr = NULL; + + if (txData != NULL && txSz > 0) { + fmode = 0; /* indirect write */ + dsz = txSz; + dptr = (uint8_t*)txData; + } + else if (rxData != NULL && rxSz > 0) { + fmode = 1; /* indirect read */ + dsz = rxSz; + dptr = rxData; + } + else { + mode = 0; /* no data */ + } + + if (dsz > 0) { + QUADSPI_DLR = dsz-1; + } + + if (addrSz > 0) { + amode = 1; + adsz = addrSz-1; + } + + /* Configure QSPI: CCR register with all communications parameters */ + /* mode 1=1SPI, 2=2SPI, 3=4SPI */ + QUADSPI_CCR = ( + QUADSPI_CCR_FMODE(fmode) | /* Functional Mode */ + QUADSPI_CCR_IMODE(1) | /* Instruction Mode */ + QUADSPI_CCR_ADMODE(amode) | /* Address Mode */ + QUADSPI_CCR_ADSIZE(adsz) | /* Address Size */ + QUADSPI_CCR_ABMODE(0) | /* Alternate byte (none) */ + QUADSPI_CCR_DMODE(mode) | /* Data Mode */ + QUADSPI_CCR_DCYC(dummySz) | /* Dummy Cycles (between instruction and read) */ + cmd /* Instruction / Command byte */ + ); + + /* Set command address 4 or 3 byte */ + QUADSPI_AR = addr; + + while (dsz > 0U) { + if (fmode == 0) { + while ((QUADSPI_SR & QUADSPI_SR_FTF)); + QUADSPI_DR = *dptr; + } + else { + while ((QUADSPI_SR & (QUADSPI_SR_FTF | QUADSPI_SR_TCF)) == 0); + *dptr = QUADSPI_DR; + } + dsz--; + dptr++; + } + + /* wait for transfer complete */ + while ((QUADSPI_SR & QUADSPI_SR_TCF) == 0); + QUADSPI_FCR |= QUADSPI_SR_TCF; /* clear transfer complete */ + + return 0; +} +#endif /* QSPI_FLASH */ + + +#ifdef SPI_FLASH uint8_t RAMFUNCTION spi_read(void) { volatile uint32_t reg; @@ -186,32 +273,86 @@ void RAMFUNCTION spi_write(const char byte) reg = SPI1_SR; } while ((reg & SPI_SR_TX_EMPTY) == 0); } +#endif /* SPI_FLASH */ - +static int initialized = 0; void RAMFUNCTION spi_init(int polarity, int phase) { - static int initialized = 0; if (!initialized) { initialized++; - spi1_pins_setup(); - spi_flash_pin_setup(); - spi_tpm2_pin_setup(); - APB2_CLOCK_ER |= SPI1_APB2_CLOCK_ER_VAL; - spi1_reset(); -#ifdef PLATFORM_stm32l0 - SPI1_CR1 = SPI_CR1_MASTER | (polarity << 1) | (phase << 0); -#else - SPI1_CR1 = SPI_CR1_MASTER | (5 << 3) | (polarity << 1) | (phase << 0); + + stm_pins_setup(); + +#ifdef SPI_FLASH + stm_gpio_config(SPI_CS_PIO_BASE, SPI_CS_FLASH, SPI_CS_FLASH_AF, 1, 3); + spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH); #endif +#ifdef WOLFBOOT_TPM + stm_gpio_config(SPI_CS_TPM_PIO_BASE, SPI_CS_TPM, SPI_CS_TPM_AF, 1, 3); + spi_cs_off(SPI_CS_TPM_PIO_BASE, SPI_CS_TPM); +#endif + +#ifdef QSPI_FLASH + /* Enable QUADSPI clock on HCLK3 (240MHz max) */ + RCC_D1CCIPR &= ~RCC_D1CCIPR_QSPISEL_MASK; + RCC_D1CCIPR |= RCC_D1CCIPR_QSPISEL(0); + AHB3_CLOCK_EN |= RCC_AHB3ENR_QSPIEN; +#endif +#ifdef SPI_FLASH + APB2_CLOCK_ER |= SPI1_APB2_CLOCK_ER_VAL; +#endif + + spi_reset(); + +#ifdef QSPI_FLASH + /* Configure QSPI FIFO Threshold (1 byte) */ + QUADSPI_CR &= ~QUADSPI_CR_FTHRES_MASK; + QUADSPI_CR |= QUADSPI_CR_FTHRES(1); + + /* Wait till BUSY flag cleared */ + while (QUADSPI_SR & QUADSPI_SR_BUSY) {}; + + /* Configure QSPI Clock Prescaler (240/4=60 MHz), Flash ID 0, Dual Flash=0, Sample Shift=None */ + QUADSPI_CR &= ~(QUADSPI_CR_PRESCALER_MASK | QUADSPI_CR_FSEL | QUADSPI_CR_DFM | QUADSPI_CR_SSHIFT); + QUADSPI_CR = (QUADSPI_CR_PRESCALER(30)); + + /* Configure QSPI Flash Size (16MB), CS High Time (1 clock) and Clock Mode (0) */ + QUADSPI_DCR &= ~(QUADSPI_DCR_FSIZE_MASK | QUADSPI_DCR_CSHT_MASK | QUADSPI_DCR_CKMODE_3); + QUADSPI_DCR = (QUADSPI_DCR_FSIZE(22) | QUADSPI_DCR_CSHT(0) | QUADSPI_DCR_CKMODE_0); + + /* Enable the QSPI peripheral */ + QUADSPI_CR |= QUADSPI_CR_EN; +#endif /* QSPI_FLASH */ +#ifdef SPI_FLASH + /* Configure SPI1 for master mode */ +# ifdef PLATFORM_stm32l0 + SPI1_CR1 = SPI_CR1_MASTER | (polarity << 1) | (phase << 0); +# else + /* baud rate 5 (hclk/6) */ + SPI1_CR1 = SPI_CR1_MASTER | (5 << 3) | (polarity << 1) | (phase << 0); +# endif SPI1_CR2 |= SPI_CR2_SSOE; SPI1_CR1 |= SPI_CR1_SPI_EN; +#endif /* SPI_FLASH */ } } void RAMFUNCTION spi_release(void) { - spi1_reset(); - SPI1_CR2 &= ~SPI_CR2_SSOE; - SPI1_CR1 = 0; - spi_pins_release(); + if (initialized > 0) { + initialized--; + } + if (initialized == 0) { + spi_reset(); + #ifdef QSPI_FLASH + QUADSPI_CR &= ~QUADSPI_CR_EN; + #endif + #ifdef SPI_FLASH + SPI1_CR2 &= ~SPI_CR2_SSOE; + SPI1_CR1 = 0; + #endif + stm_pins_release(); + } } + +#endif /* SPI_FLASH || QSPI_FLASH */ diff --git a/hal/spi/spi_drv_stm32.h b/hal/spi/spi_drv_stm32.h index 732e2bf3..03030db6 100644 --- a/hal/spi/spi_drv_stm32.h +++ b/hal/spi/spi_drv_stm32.h @@ -17,17 +17,8 @@ #ifndef SPI_DRV_STM32_H_INCLUDED #define SPI_DRV_STM32_H_INCLUDED + #include -/** SPI settings **/ - -#define SPI1 (0x40013000)/* SPI1 base address */ -#define SPI1_APB2_CLOCK_ER_VAL (1 << 12) - -#define CEN_GPIOA (1 << 0) -#define CEN_GPIOB (1 << 1) -#define CEN_GPIOC (1 << 2) -#define CEN_GPIOD (1 << 3) -#define CEN_GPIOE (1 << 4) #ifdef PLATFORM_stm32f4 #define APB2_CLOCK_ER (*(volatile uint32_t *)(0x40023844)) @@ -38,18 +29,18 @@ #define GPIOC_BASE (0x40020800) #define GPIOD_BASE (0x40020C00) #define GPIOE_BASE (0x40021000) -#define SPI_GPIO GPIOB_BASE -#define SPI_CS_GPIO GPIOE_BASE -#define SPI_CS_FLASH 1 /* Flash CS connected to GPIOE1 */ -#define SPI_CS_TPM 0 /* TPM CS connected to GPIOE0 */ -#define SPI1_PIN_AF 5 /* Alternate function for SPI pins */ -#define SPI1_CLOCK_PIN 3 /* SPI_SCK: PB3 */ -#define SPI1_MISO_PIN 4 /* SPI_MISO PB4 */ -#define SPI1_MOSI_PIN 5 /* SPI_MOSI PB5 */ -#endif +#define SPI_GPIO GPIOB_BASE +#define SPI_CS_GPIO GPIOE_BASE +#define SPI_CS_FLASH 1 /* Flash CS connected to GPIOE1 */ +#define SPI_CS_TPM 0 /* TPM CS connected to GPIOE0 */ +#define SPI_PIN_AF 5 /* Alternate function for SPI pins */ +#define SPI_CLOCK_PIN 3 /* SPI_SCK: PB3 */ +#define SPI_MISO_PIN 4 /* SPI_MISO PB4 */ +#define SPI_MOSI_PIN 5 /* SPI_MOSI PB5 */ +#endif /* PLATFORM_stm32f4 */ + #ifdef PLATFORM_stm32u5 - #ifdef TZEN #define PERIPH_BASE (0x50000000UL) #else @@ -59,36 +50,34 @@ #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) #define AHB2PERIPH_BASE (PERIPH_BASE + 0x02020000UL) -#undef SPI1 -#define SPI1 (APB2PERIPH_BASE + 0x3000UL) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) -#define RCC_BASE (APB2PERIPH_BASE + 0x0C00UL) +#define RCC_BASE (APB2PERIPH_BASE + 0x0C00UL) #define APB2_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xA4)) #define APB2_CLOCK_RST (*(volatile uint32_t *)(RCC_BASE + 0x7C)) #define RCC_GPIO_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0x8C)) -#define GPIO_BASE (APB2PERIPH_BASE + 0x02020000UL) -#define GPIOA_BASE (GPIO_BASE + 0x00000UL) -#define GPIOB_BASE (GPIO_BASE + 0x00400UL) -#define GPIOC_BASE (GPIO_BASE + 0x00800UL) -#define GPIOD_BASE (GPIO_BASE + 0x00C00UL) -#define GPIOE_BASE (GPIO_BASE + 0x01000UL) -#define GPIOF_BASE (GPIO_BASE + 0x01400UL) -#define GPIOG_BASE (GPIO_BASE + 0x01800UL) -#define GPIOH_BASE (GPIO_BASE + 0x01C00UL) -#define GPIOI_BASE (GPIO_BASE + 0x02000UL) +#define GPIO_BASE (APB2PERIPH_BASE + 0x02020000UL) +#define GPIOA_BASE (GPIO_BASE + 0x00000UL) +#define GPIOB_BASE (GPIO_BASE + 0x00400UL) +#define GPIOC_BASE (GPIO_BASE + 0x00800UL) +#define GPIOD_BASE (GPIO_BASE + 0x00C00UL) +#define GPIOE_BASE (GPIO_BASE + 0x01000UL) +#define GPIOF_BASE (GPIO_BASE + 0x01400UL) +#define GPIOG_BASE (GPIO_BASE + 0x01800UL) +#define GPIOH_BASE (GPIO_BASE + 0x01C00UL) +#define GPIOI_BASE (GPIO_BASE + 0x02000UL) /* STMOD+ Port */ -#define SPI_GPIO GPIOE_BASE -#define SPI_CS_GPIO GPIOE_BASE -#define SPI_CS_FLASH 11 /* Flash CS connected to GPIOE11 */ -#define SPI_CS_TPM 10 /* TPM CS connected to GPIOE10 */ - -#define SPI1_PIN_AF 5 /* Alternate function for SPI pins */ -#define SPI1_CLOCK_PIN 13 /* SPI_SCK: PE13 */ -#define SPI1_MISO_PIN 14 /* SPI_MISO PE14 */ -#define SPI1_MOSI_PIN 15 /* SPI_MOSI PE15 */ +#define SPI_GPIO GPIOE_BASE +#define SPI_CS_GPIO GPIOE_BASE +#define SPI_CS_FLASH 11 /* Flash CS connected to GPIOE11 */ +#define SPI_CS_TPM 10 /* TPM CS connected to GPIOE10 */ +#define SPI_PIN_AF 5 /* Alternate function for SPI pins */ +#define SPI_CLOCK_PIN 13 /* SPI_SCK: PE13 */ +#define SPI_MISO_PIN 14 /* SPI_MISO PE14 */ +#define SPI_MOSI_PIN 15 /* SPI_MOSI PE15 */ #endif /* PLATFORM_stm32u5 */ @@ -102,15 +91,16 @@ #define GPIOD_BASE (0x48000C00) /* STM32WB55 NUCLEO: CN9: D13=SCK, D12=MISO, D11=MOSI, FLASHCS=D10, TPMCS=D9 */ -#define SPI_GPIO GPIOA_BASE -#define SPI_CS_GPIO GPIOA_BASE -#define SPI_CS_FLASH 4 /* Flash CS connected to GPIOA4 */ -#define SPI_CS_TPM 9 /* TPM CS connected to GPIOA9 */ -#define SPI1_PIN_AF 5 /* Alternate function for SPI pins */ -#define SPI1_CLOCK_PIN 5 /* SPI_SCK: PA5 */ -#define SPI1_MISO_PIN 6 /* SPI_MISO PA6 */ -#define SPI1_MOSI_PIN 7 /* SPI_MOSI PA7 */ -#endif +#define SPI_GPIO GPIOA_BASE +#define SPI_CS_GPIO GPIOA_BASE +#define SPI_CS_FLASH 4 /* Flash CS connected to GPIOA4 */ +#define SPI_CS_TPM 9 /* TPM CS connected to GPIOA9 */ +#define SPI_PIN_AF 5 /* Alternate function for SPI pins */ +#define SPI_CLOCK_PIN 5 /* SPI_SCK: PA5 */ +#define SPI_MISO_PIN 6 /* SPI_MISO PA6 */ +#define SPI_MOSI_PIN 7 /* SPI_MOSI PA7 */ +#endif /* PLATFORM_stm32wb */ + #ifdef PLATFORM_stm32l0 #define APB2_CLOCK_ER (*(volatile uint32_t *)(0x40021034)) @@ -120,55 +110,206 @@ #define GPIOB_BASE (0x50000400) #define SPI_CS_GPIO GPIOB_BASE -#define SPI1_PIN_AF 0 /* Alternate function for SPI pins */ +#define SPI_PIN_AF 0 /* Alternate function for SPI pins */ #ifndef SPI_ALT_CONFIGURATION - #define SPI_GPIO GPIOB_BASE - #define SPI_CS_FLASH 8 /* Flash CS connected to GPIOB8 */ - #define SPI1_CLOCK_PIN 3 /* SPI_SCK: PB3 */ - #define SPI1_MISO_PIN 4 /* SPI_MISO PB4 */ - #define SPI1_MOSI_PIN 5 /* SPI_MOSI PB5 */ + #define SPI_GPIO GPIOB_BASE + #define SPI_CS_FLASH 8 /* Flash CS connected to GPIOB8 */ + #define SPI_CLOCK_PIN 3 /* SPI_SCK: PB3 */ + #define SPI_MISO_PIN 4 /* SPI_MISO PB4 */ + #define SPI_MOSI_PIN 5 /* SPI_MOSI PB5 */ #else - #define SPI_GPIO GPIOA_BASE - #define SPI_CS_FLASH 6 /* Flash CS connected to GPIOB6 */ - #define SPI1_CLOCK_PIN 5 /* SPI_SCK: PA5 */ - #define SPI1_MISO_PIN 6 /* SPI_MISO PA6 */ - #define SPI1_MOSI_PIN 7 /* SPI_MOSI PA7 */ + #define SPI_GPIO GPIOA_BASE + #define SPI_CS_FLASH 6 /* Flash CS connected to GPIOB6 */ + #define SPI_CLOCK_PIN 5 /* SPI_SCK: PA5 */ + #define SPI_MISO_PIN 6 /* SPI_MISO PA6 */ + #define SPI_MOSI_PIN 7 /* SPI_MOSI PA7 */ #endif /* SPI_ALT_CONFIGURATION */ #endif /* PLATFORM_stm32l0 */ -#define SPI_PIO_BASE SPI_GPIO -#define SPI_CS_PIO_BASE SPI_CS_GPIO -#if (SPI_GPIO == GPIOA_BASE) -# define SPI_PIO_CEN CEN_GPIOA -#elif (SPI_GPIO == GPIOB_BASE) -# define SPI_PIO_CEN CEN_GPIOB -#elif (SPI_GPIO == GPIOC_BASE) -# define SPI_PIO_CEN CEN_GPIOC -#elif (SPI_GPIO == GPIOD_BASE) -# define SPI_PIO_CEN CEN_GPIOD -#elif (SPI_GPIO == GPIOE_BASE) -# define SPI_PIO_CEN CEN_GPIOE +#ifdef PLATFORM_stm32h7 + +#define RCC_BASE (0x58024400UL) +#define RCC_GPIO_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xE0)) /* RM0433 - 8.7.43 (RCC_AHB4ENR) */ +#define APB2_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xF0)) /* RM0433 - 8.7.47 */ +#define APB2_CLOCK_RST (*(volatile uint32_t *)(RCC_BASE + 0x98)) /* RM0433 - 8.7.35 */ + +#define GPIOA_BASE (0x58020000) +#define GPIOB_BASE (0x58020400) +#define GPIOC_BASE (0x58020800) +#define GPIOD_BASE (0x58020C00) +#define GPIOE_BASE (0x58021000) +#define GPIOF_BASE (0x58021400) +#define GPIOG_BASE (0x58021800) + + +/** QSPI **/ +/* Default Base (E) and AF (alternate function=10) for QSPI */ +#define QSPI_GPIO GPIOE_BASE +#define QSPI_PIN_AF 10 + +/* QSPI uses hclk3 (240MHz max) by default */ +#define RCC_D1CCIPR (*(volatile uint32_t *)(RCC_BASE + 0x4C)) /* RM0433 - 8.7.19 (RCC_D1CCIPR) */ +#define RCC_D1CCIPR_QSPISEL_MASK (0x3 << 4) +#define RCC_D1CCIPR_QSPISEL(sel) (((sel) & 0x3) << 4) /* 0=hclk3, 1=pll1_q_ck, 2=pll2_r_ck, 3=per_ck */ +#define AHB3_CLOCK_RST (*(volatile uint32_t *)(RCC_BASE + 0x7C)) /* RM0433 - 8.7.28 - RCC_AHB3RSTR */ +#define AHB3_CLOCK_EN (*(volatile uint32_t *)(RCC_BASE + 0xD4)) /* RM0433 - 8.7.40 - RCC_AHB3ENR */ +#define RCC_AHB3ENR_QSPIEN (1 << 14) + +/* QSPI CLK PB2 */ +#define QSPI_CLOCK_PIO_BASE GPIOB_BASE +#define QSPI_CLOCK_PIN 2 +#define QSPI_CLOCK_PIN_AF 9 + +/* nQSPI_CS PG6 (alt PB6) */ +#ifndef QSPI_ALT_CONFIGURATION +#define QSPI_CS_PIO_BASE GPIOG_BASE +#define QSPI_CS_FLASH_PIN 6 +#define QSPI_CS_FLASH_AF 10 +#else +#define QSPI_CS_PIO_BASE GPIOB_BASE +#define QSPI_CS_FLASH_PIN 6 +#define QSPI_CS_FLASH_AF 10 #endif -#if (SPI_CS_GPIO == GPIOA_BASE) -# define SPI_PIO_CS_CEN CEN_GPIOA -#elif (SPI_CS_GPIO == GPIOB_BASE) -# define SPI_PIO_CS_CEN CEN_GPIOB -#elif (SPI_CS_GPIO == GPIOC_BASE) -# define SPI_PIO_CS_CEN CEN_GPIOC -#elif (SPI_CS_GPIO == GPIOD_BASE) -# define SPI_PIO_CS_CEN CEN_GPIOD -#elif (SPI_CS_GPIO == GPIOE_BASE) -# define SPI_PIO_CS_CEN CEN_GPIOE +/* QSPI_IO0 (MOSI) - PD11 (alt PE7) */ +#ifndef QSPI_ALT_CONFIGURATION +#define QSPI_IO0_PIO_BASE GPIOD_BASE +#define QSPI_IO0_PIN 11 +#define QSPI_IO0_PIN_AF 9 +#else +#define QSPI_IO0_PIO_BASE GPIOE_BASE +#define QSPI_IO0_PIN 7 +#define QSPI_IO0_PIN_AF 10 #endif +/* QSPI_IO1 (MISO) - PD12 (alt PE8) */ +#ifndef QSPI_ALT_CONFIGURATION +#define QSPI_IO1_PIO_BASE GPIOD_BASE +#define QSPI_IO1_PIN 12 +#define QSPI_IO1_PIN_AF 9 +#else +#define QSPI_IO1_PIO_BASE GPIOE_BASE +#define QSPI_IO1_PIN 8 +#define QSPI_IO1_PIN_AF 10 +#endif -#define SPI1_CR1 (*(volatile uint32_t *)(SPI1)) -#define SPI1_CR2 (*(volatile uint32_t *)(SPI1 + 0x04)) -#define SPI1_SR (*(volatile uint32_t *)(SPI1 + 0x08)) -#define SPI1_DR (*(volatile uint32_t *)(SPI1 + 0x0c)) +/* QSPI_IO2 - PE2 (alt PE9) */ +#ifndef QSPI_ALT_CONFIGURATION +#define QSPI_IO2_PIO_BASE GPIOE_BASE +#define QSPI_IO2_PIN 2 +#define QSPI_IO2_PIN_AF 9 +#else +#define QSPI_IO2_PIO_BASE GPIOE_BASE +#define QSPI_IO2_PIN 9 +#define QSPI_IO2_PIN_AF 10 +#endif + +/* QSPI_IO3 - PD13 (alt PE10) */ +#ifndef QSPI_ALT_CONFIGURATION +#define QSPI_IO3_PIO_BASE GPIOD_BASE +#define QSPI_IO3_PIN 13 +#define QSPI_IO3_PIN_AF 9 +#else +#define QSPI_IO3_PIO_BASE GPIOE_BASE +#define QSPI_IO3_PIN 10 +#endif + +#endif /* PLATFORM_stm32h7 */ + + +/* Setup SPI PIO Bases */ +#ifndef SPI_CLOCK_PIO_BASE +#define SPI_CLOCK_PIO_BASE SPI_GPIO +#endif +#ifndef SPI_MISO_PIO_BASE +#define SPI_MISO_PIO_BASE SPI_GPIO +#endif +#ifndef SPI_MOSI_PIO_BASE +#define SPI_MOSI_PIO_BASE SPI_GPIO +#endif +#ifndef SPI_CS_PIO_BASE +#define SPI_CS_PIO_BASE SPI_CS_GPIO +#endif +#ifndef SPI_CS_TPM_PIO_BASE +#define SPI_CS_TPM_PIO_BASE SPI_CS_GPIO +#endif + +#ifdef QSPI_FLASH +#ifndef QSPI_CS_PIO_BASE +#define QSPI_CS_PIO_BASE QSPI_CS_GPIO +#endif +#ifndef QSPI_CLOCK_PIO_BASE +#define QSPI_CLOCK_PIO_BASE QSPI_GPIO +#endif +#ifndef QSPI_IO0_PIO_BASE +#define QSPI_IO0_PIO_BASE QSPI_GPIO +#endif +#ifndef QSPI_IO1_PIO_BASE +#define QSPI_IO1_PIO_BASE QSPI_GPIO +#endif +#ifndef QSPI_IO2_PIO_BASE +#define QSPI_IO2_PIO_BASE QSPI_GPIO +#endif +#ifndef QSPI_IO3_PIO_BASE +#define QSPI_IO3_PIO_BASE QSPI_GPIO +#endif +#endif + +/* Setup alternate functions */ +#ifndef SPI_CLOCK_PIN_AF +#define SPI_CLOCK_PIN_AF SPI_PIN_AF +#endif +#ifndef SPI_MISO_PIN_AF +#define SPI_MISO_PIN_AF SPI_PIN_AF +#endif +#ifndef SPI_MOSI_PIN_AF +#define SPI_MOSI_PIN_AF SPI_PIN_AF +#endif +#ifndef SPI_CS_FLASH_AF +#define SPI_CS_FLASH_AF SPI_PIN_AF +#endif +#ifndef SPI_CS_TPM_AF +#define SPI_CS_TPM_AF SPI_PIN_AF +#endif + +#ifdef QSPI_FLASH +#ifndef QSPI_CS_FLASH_AF +#define QSPI_CS_FLASH_AF QSPI_PIN_AF +#endif +#ifndef QSPI_CLOCK_PIN_AF +#define QSPI_CLOCK_PIN_AF QSPI_PIN_AF +#endif +#ifndef QSPI_IO0_PIN_AF +#define QSPI_IO0_PIN_AF QSPI_PIN_AF +#endif +#ifndef QSPI_IO1_PIN_AF +#define QSPI_IO1_PIN_AF QSPI_PIN_AF +#endif +#ifndef QSPI_IO2_PIN_AF +#define QSPI_IO2_PIN_AF QSPI_PIN_AF +#endif +#ifndef QSPI_IO3_PIN_AF +#define QSPI_IO3_PIN_AF QSPI_PIN_AF +#endif +#endif /* QSPI_FLASH */ + + +#define GPIO_MODE_AF (2) + + +/* SPI */ +#ifndef SPI1_BASE +#define SPI1_BASE (0x40013000) /* SPI1 base address */ +#endif + +#define SPI1_APB2_CLOCK_ER_VAL (1 << 12) + +#define SPI1_CR1 (*(volatile uint32_t *)(SPI1_BASE)) +#define SPI1_CR2 (*(volatile uint32_t *)(SPI1_BASE + 0x04)) +#define SPI1_SR (*(volatile uint32_t *)(SPI1_BASE + 0x08)) +#define SPI1_DR (*(volatile uint32_t *)(SPI1_BASE + 0x0c)) #define SPI_CR1_CLOCK_PHASE (1 << 0) #define SPI_CR1_CLOCK_POLARITY (1 << 1) @@ -184,26 +325,79 @@ #define SPI_CR1_BIDIOE (1 << 14) #define SPI_CR2_SSOE (1 << 2) - #define SPI_SR_RX_NOTEMPTY (1 << 0) #define SPI_SR_TX_EMPTY (1 << 1) #define SPI_SR_BUSY (1 << 7) +#define SPI_PIO_MODE(base) (*(volatile uint32_t *)(base + 0x00)) +#define SPI_PIO_AFL(base) (*(volatile uint32_t *)(base + 0x20)) +#define SPI_PIO_AFH(base) (*(volatile uint32_t *)(base + 0x24)) +#define SPI_PIO_OSPD(base) (*(volatile uint32_t *)(base + 0x08)) +#define SPI_PIO_PUPD(base) (*(volatile uint32_t *)(base + 0x0c)) +#define SPI_PIO_ODR(base) (*(volatile uint32_t *)(base + 0x14)) +#define SPI_PIO_BSRR(base) (*(volatile uint32_t *)(base + 0x18)) -#define SPI_PIO_MODE (*(volatile uint32_t *)(SPI_PIO_BASE + 0x00)) -#define SPI_PIO_AFL (*(volatile uint32_t *)(SPI_PIO_BASE + 0x20)) -#define SPI_PIO_AFH (*(volatile uint32_t *)(SPI_PIO_BASE + 0x24)) -#define SPI_PIO_OSPD (*(volatile uint32_t *)(SPI_PIO_BASE + 0x08)) -#define SPI_PIO_PUPD (*(volatile uint32_t *)(SPI_PIO_BASE + 0x0c)) -#define SPI_PIO_BSRR (*(volatile uint32_t *)(SPI_PIO_BASE + 0x18)) -#define SPI_PIO_CS_MODE (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x00)) -#define SPI_PIO_CS_AFL (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x20)) -#define SPI_PIO_CS_AFH (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x24)) -#define SPI_PIO_CS_OSPD (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x08)) -#define SPI_PIO_CS_PUPD (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x0c)) -#define SPI_PIO_CS_BSRR (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x18)) -#define SPI_PIO_CS_ODR (*(volatile uint32_t *)(SPI_CS_PIO_BASE + 0x14)) -#define GPIO_MODE_AF (2) +/* QUADSPI */ +#ifndef QUADSPI_BASE +#define QUADSPI_BASE 0x52005000UL +#endif +#define QUADSPI_CR (*(volatile uint32_t *)(QUADSPI_BASE + 0x00)) /* Control register */ +#define QUADSPI_DCR (*(volatile uint32_t *)(QUADSPI_BASE + 0x04)) /* Device Configuration register */ +#define QUADSPI_SR (*(volatile uint32_t *)(QUADSPI_BASE + 0x08)) /* Status register */ +#define QUADSPI_FCR (*(volatile uint32_t *)(QUADSPI_BASE + 0x0C)) /* Flag Clear register */ +#define QUADSPI_DLR (*(volatile uint32_t *)(QUADSPI_BASE + 0x10)) /* Data Length register */ +#define QUADSPI_CCR (*(volatile uint32_t *)(QUADSPI_BASE + 0x14)) /* Communication Configuration register */ +#define QUADSPI_AR (*(volatile uint32_t *)(QUADSPI_BASE + 0x18)) /* Address register */ +#define QUADSPI_ABR (*(volatile uint32_t *)(QUADSPI_BASE + 0x1C)) /* Alternate Bytes register */ +#define QUADSPI_DR (*(volatile uint8_t *)(QUADSPI_BASE + 0x23)) /* Data register */ +#define QUADSPI_PSMKR (*(volatile uint32_t *)(QUADSPI_BASE + 0x24)) /* Polling Status Mask register */ +#define QUADSPI_PSMAR (*(volatile uint32_t *)(QUADSPI_BASE + 0x28)) /* Polling Status Match register */ +#define QUADSPI_PIR (*(volatile uint32_t *)(QUADSPI_BASE + 0x2C)) /* Polling Interval register */ +#define QUADSPI_LPTR (*(volatile uint32_t *)(QUADSPI_BASE + 0x30)) /* Low Power Timeout register */ + +#define QUADSPI_CR_PRESCALER_MASK (0xFF << 24) +#define QUADSPI_CR_PRESCALER(pre) ((((pre)-1) & 0xFF) << 24) /* Clock prescaler: quadspi_ker_ck/pre+1 */ +#define QUADSPI_CR_FTHRES_MASK (0xF << 8) +#define QUADSPI_CR_FTHRES(thr) ((((thr)-1) & 0xF) << 8) /* FIFO threshold level */ +#define QUADSPI_CR_FSEL (0x1 << 7) /* 0=Flash 1 or 1=Flash 2 */ +#define QUADSPI_CR_DFM (0x1 << 6) /* Dual-flash mode */ +#define QUADSPI_CR_SSHIFT (0x1 << 4) /* Sample shift 1=1/2 cycle shift */ +#define QUADSPI_CR_ABORT (0x1 << 1) /* Abort request */ +#define QUADSPI_CR_EN (0x1 << 0) /* Enable the QUADSPI */ + +#define QUADSPI_CCR_DDRM (1 << 31) /* Double data rate mode */ +#define QUADSPI_CCR_DHHC (1 << 30) /* Delay the data output by 1/4 of the QUADSPI output clock cycle in DDR mode */ +#define QUADSPI_CCR_FRCM (1 << 29) /* Free running clock mode */ +#define QUADSPI_CCR_SIOO (1 << 28) /* Send instruction only once mode */ +#define QUADSPI_CCR_FMODE_MASK (0x3 << 26) +#define QUADSPI_CCR_FMODE(fmode) (((fmode) & 0x3) << 26) /* Functional Mode (0=indirect write, 1=indirect read, 2=auto poll, 3=mem mapped) */ +#define QUADSPI_CCR_DMODE_MASK (0x3 << 24) +#define QUADSPI_CCR_DMODE(dmode) (((dmode) & 0x3) << 24) /* Data mode (0=no data, 1=data on single line, 2=data on two lines, 3=data on four lines) */ +#define QUADSPI_CCR_DCYC_MASK (0x1F << 18) +#define QUADSPI_CCR_DCYC(dcyc) (((dcyc) & 0x1F) << 18) /* Number of dummy cycles */ +#define QUADSPI_CCR_ABSIZE_MASK (0x3 << 16) +#define QUADSPI_CCR_ABSIZE(absz) (((absz) & 0x3) << 16) /* Alternate bytes size */ +#define QUADSPI_CCR_ABMODE_MASK (0x3 << 14) +#define QUADSPI_CCR_ABMODE(abmode) (((abmode) & 0x3) << 14) /* Alternate bytes mode (0=no alt data, 1=alt on single line, 2=alt on two lines, 3=alt on four lines) */ +#define QUADSPI_CCR_ADSIZE_MASK (0x3 << 12) +#define QUADSPI_CCR_ADSIZE(sz) (((sz) & 0x3) << 12) /* Address bytes size (0=8-bit, 1=16-bit, 2=24-bit, 3=32-bit) */ +#define QUADSPI_CCR_ADMODE_MASK (0x3 << 10) +#define QUADSPI_CCR_ADMODE(admode) (((admode) & 0x3) << 10) /* Address mode (0=no addr, 1=addr on single line, 2=addr on two lines, 3=addr on four lines) */ +#define QUADSPI_CCR_IMODE_MASK (0x3 << 8) +#define QUADSPI_CCR_IMODE(imode) (((imode) & 0x3) << 8) /* Instruction mode (0=no instr, 1=instr on single line, 2=instr on two lines, 3=instr on four lines) */ +#define QUADSPI_CCR_INSTRUCTION_MASK (0xFF << 0) +#define QUADSPI_CCR_INSTRUCTION(ins) (((ins) & 0xFF) << 0) /* Instruction to be send to the external SPI device */ + +#define QUADSPI_DCR_FSIZE_MASK (0x1F << 16) +#define QUADSPI_DCR_FSIZE(fsz) (((fsz) & 0x1F) << 16) /* Flash memory size (2 ^ (fsize + 1)). Example 16MB is 22 */ +#define QUADSPI_DCR_CSHT_MASK (0x7 << 8) +#define QUADSPI_DCR_CSHT(csht) (((csht) & 0x7) << 8) /* Chip select high time - Number of clock cycles (+1) nCS to remain high between commands */ +#define QUADSPI_DCR_CKMODE_3 (1 << 0) /* Clock mode 3 - clk high while nCS released */ +#define QUADSPI_DCR_CKMODE_0 (0) /* Clock mode 0 - clk low while nCS released */ + +#define QUADSPI_SR_TCF (1 << 1) /* Transfer complete flag - set in indirect mode when the programmed number of data has been transferred */ +#define QUADSPI_SR_FTF (1 << 2) /* FIFO threshold flag */ +#define QUADSPI_SR_BUSY (1 << 5) /* Busy - operation is on going when set */ #endif /* !SPI_DRV_STM32_H_INCLUDED */ diff --git a/hal/spi/spi_drv_zynq.c b/hal/spi/spi_drv_zynq.c index ba35b0ec..442c05ca 100644 --- a/hal/spi/spi_drv_zynq.c +++ b/hal/spi/spi_drv_zynq.c @@ -31,13 +31,15 @@ #ifdef SPI_FLASH -void spi_cs_off(int pin) +void spi_cs_off(uint32_t base, int pin) { + (void)base; (void)pin; } -void spi_cs_on(int pin) +void spi_cs_on(uint32_t base, int pin) { + (void)base; (void)pin; } diff --git a/hal/spi/spi_drv_zynq.h b/hal/spi/spi_drv_zynq.h index ec53bb5f..c78e2093 100644 --- a/hal/spi/spi_drv_zynq.h +++ b/hal/spi/spi_drv_zynq.h @@ -19,6 +19,7 @@ #define SPI_DRV_ZYNQ_H_INCLUDED #include -#define SPI_CS_FLASH 0 +#define SPI_CS_FLASH 0 +#define SPI_CS_PIO_BASE 0UL #endif /* !SPI_DRV_ZYNQ_H_INCLUDED */ diff --git a/hal/stm32f4.c b/hal/stm32f4.c index f5f38b27..fcc11b5e 100644 --- a/hal/stm32f4.c +++ b/hal/stm32f4.c @@ -343,7 +343,7 @@ void hal_init(void) void hal_prepare_boot(void) { #ifdef SPI_FLASH - spi_release(); + spi_flash_release(); #endif clock_pll_off(); diff --git a/hal/stm32f7.c b/hal/stm32f7.c index f910610f..f16212eb 100644 --- a/hal/stm32f7.c +++ b/hal/stm32f7.c @@ -114,7 +114,7 @@ #define FLASH_OPTKEY2 (0x4C5D6E7F) -/* FLASH Geometry +/* FLASH Geometry * * per ST AN4826, two configurations are possible on STM32F7: * @@ -421,7 +421,7 @@ void hal_init(void) void RAMFUNCTION hal_prepare_boot(void) { #ifdef SPI_FLASH - spi_release(); + spi_flash_release(); #endif clock_pll_off(); diff --git a/hal/stm32g0.c b/hal/stm32g0.c index 67a38fd6..21246d86 100644 --- a/hal/stm32g0.c +++ b/hal/stm32g0.c @@ -331,7 +331,7 @@ static void RAMFUNCTION do_secure_boot(void) void RAMFUNCTION hal_prepare_boot(void) { #ifdef SPI_FLASH - spi_release(); + spi_flash_release(); #endif clock_pll_off(); #ifdef FLASH_SECURABLE_MEMORY_SUPPORT diff --git a/hal/stm32h7.c b/hal/stm32h7.c index 1f4d73c2..e398056b 100644 --- a/hal/stm32h7.c +++ b/hal/stm32h7.c @@ -30,7 +30,6 @@ /* STM32 H7 register configuration */ /*** RCC ***/ - #define RCC_BASE (0x58024400) /* RM0433 - Table 8 */ #define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00)) /* RM0433 - 7.7.2 */ #define RCC_PLLCKSELR (*(volatile uint32_t *)(RCC_BASE + 0x28)) /* RM0433 - 7.7.11 */ @@ -42,10 +41,15 @@ #define RCC_D2CFGR (*(volatile uint32_t *)(RCC_BASE + 0x1C)) /* RM0433 - 7.7.8 */ #define RCC_D3CFGR (*(volatile uint32_t *)(RCC_BASE + 0x20)) /* RM0433 - 7.7.9 */ -#define APB1_CLOCK_LER (*(volatile uint32_t *)(RCC_BASE + 0xE8)) /* RM0433 - 7.7.45 */ -#define APB1_CLOCK_HER (*(volatile uint32_t *)(RCC_BASE + 0xEC)) /* RM0433 - 7.7.46 */ -#define APB2_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xF0)) /* RM0433 - 7.7.47 */ +#define RCC_D2CCIP2R (*(volatile uint32_t *)(RCC_BASE + 0x54)) /* RM0433 - 8.7.21 */ +#define APB1_CLOCK_LRST (*(volatile uint32_t *)(RCC_BASE + 0x90)) /* RM0433 - 8.7.33 - RCC_APB1LRSTR */ + +#define AHB4_CLOCK_ENR (*(volatile uint32_t *)(RCC_BASE + 0xE0)) /* RM0433 - 8.7.43 */ +#define APB1_CLOCK_LER (*(volatile uint32_t *)(RCC_BASE + 0xE8)) /* RM0433 - 8.7.45 - RCC_APB1LENR */ +#define APB1_CLOCK_HER (*(volatile uint32_t *)(RCC_BASE + 0xEC)) /* RM0433 - 8.7.46 */ +#define APB2_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xF0)) /* RM0433 - 8.7.47 */ +#define AHB3_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0xD4)) /* RM0433 - 8.7.40 */ #define RCC_CR_PLL1RDY (1 << 25) #define RCC_CR_PLL1ON (1 << 24) @@ -72,6 +76,25 @@ #define RCC_PLLCKSELR_DIVM1_NONE 0x1 +/*** GPIO ***/ +#define GPIOA_BASE (0x58020000) +#define GPIOB_BASE (0x58020400) +#define GPIOC_BASE (0x58020800) +#define GPIOD_BASE (0x58020C00) +#define GPIOE_BASE (0x58021000) +#define GPIOF_BASE (0x58021400) +#define GPIOG_BASE (0x58021800) + +#define GPIO_MODE(base) (*(volatile uint32_t *)((base) + 0x00)) +#define GPIO_OTYPE(base) (*(volatile uint32_t *)((base) + 0x04)) +#define GPIO_OSPD(base) (*(volatile uint32_t *)((base) + 0x08)) +#define GPIO_PUPD(base) (*(volatile uint32_t *)((base) + 0x0c)) +#define GPIO_ODR(base) (*(volatile uint32_t *)((base) + 0x14)) +#define GPIO_BSRR(base) (*(volatile uint32_t *)((base) + 0x18)) +#define GPIO_AFRL(base) (*(volatile uint32_t *)((base) + 0x20)) +#define GPIO_AFRH(base) (*(volatile uint32_t *)((base) + 0x24)) + + /*** PWR ***/ #define PWR_BASE (0x58024800) /* RM0433 - Table 8 */ #define PWR_CSR1 (*(volatile uint32_t *)(PWR_BASE + 0x04)) /* RM0433 - 5.8.x */ @@ -95,6 +118,85 @@ #define RCC_PRESCALER_DIV_NONE 0 #define RCC_PRESCALER_DIV_2 8 + +/*** UART ***/ +#ifndef CLOCK_SPEED +#define CLOCK_SPEED 64000000UL /* 120MHz pclk1, 64MHz HSI */ +#endif +#ifndef BAUD_RATE +#define BAUD_RATE 115200 +#endif +#ifndef UART_PORT +#define UART_PORT 3 /* default to Nucleo VCOM port */ +#endif + +#if UART_PORT == 3 +/* USART3 Base address (connected to ST virtual com port on Nucleo board) */ +#define UART_BASE (0x40004800) +#define UART_GPIO_BASE GPIOD_BASE +#define UART_TX_PIN 8 /* PD8, USART Transmit pin */ +#define UART_RX_PIN 9 /* PD9, USART Receive pin */ +#else +/* USART2 Base address (chosen because of its pin layout on Nucleo board) */ +#define UART_BASE (0x40004400) +#define UART_GPIO_BASE GPIOD_BASE +#define UART_TX_PIN 5 /* PD5, USART Transmit pin */ +#define UART_RX_PIN 6 /* PD6, USART Receive pin */ +#endif + +#define UART_PIN_AF 7 /* AF stands for Alternate Function. USART TX/RX */ + +/* UART/USART: Defining register start addresses. */ +#define UART_CR1(base) (*(volatile uint32_t *)((base) + 0x00)) +#define UART_CR2(base) (*(volatile uint32_t *)((base) + 0x04)) +#define UART_CR3(base) (*(volatile uint32_t *)((base) + 0x08)) +#define UART_BRR(base) (*(volatile uint32_t *)((base) + 0x0C)) +#define UART_RQR(base) (*(volatile uint32_t *)((base) + 0x18)) +#define UART_ISR(base) (*(volatile uint32_t *)((base) + 0x1C)) +#define UART_ICR(base) (*(volatile uint32_t *)((base) + 0x20)) +#define UART_RDR(base) (*(volatile uint32_t *)((base) + 0x24)) +#define UART_TDR(base) (*(volatile uint32_t *)((base) + 0x28)) +#define UART_PRESC(base) (*(volatile uint32_t *)((base) + 0x2C)) + +/* UART/USART: Defining register bit placement for CR1 and ISR register for readability. */ +#define UART_CR1_UART_ENABLE (1 << 0) +#define UART_CR1_TX_ENABLE (1 << 3) +#define UART_CR1_RX_ENABLE (1 << 2) +#define UART_CR1_M1 (1 << 28) +#define UART_CR1_M0 (1 << 12) +#define UART_CR1_PARITY_ENABLED (1 << 10) +#define UART_CR1_PARITY_ODD (1 << 9) +#define UART_CR1_FIFOEN (1 << 29) +#define UART_CR1_OVER8 (1 << 15) + +#define UART_CR2_STOP_MASK (0x3 << 12) +#define UART_CR2_STOP(bits) (((bits) & 0x3) << 12) +#define USART_CR2_LINEN (1 << 14) +#define USART_CR2_CLKEN (1 << 11) + +#define USART_CR3_SCEN (1 << 5) +#define USART_CR3_HDSEL (1 << 3) +#define USART_CR3_IREN (1 << 1) + +#define UART_ISR_TX_FIFO_NOT_FULL (1 << 7) /* Transmit Data Empty (TXE) or TX FIFO Not Full (TXFNF) */ +#define UART_ISR_RX_FIFO_NOT_EMPTY (1 << 5) +#define UART_ISR_TRANSMISSION_COMPLETE (1 << 6) + +/* RCC: Defining register bit placement for APB1, APB2, AHB1 and AHB4 register for readability. */ +#define RCC_APB1_USART2_EN (1 << 17) +#define RCC_APB1_USART3_EN (1 << 18) +#define RCC_APB1_UART4_EN (1 << 19) +#define RCC_APB1_UART5_EN (1 << 20) +#define RCC_APB1_UART7_EN (1 << 30) +#define RCC_APB1_UART8_EN (1 << 31) +#define RCC_APB2_USART1_EN (1 << 4) +#define RCC_APB2_USART6_EN (1 << 5) + +#define RCC_AHB4_GPIOD_EN (1 << 3) + +/*** QSPI ***/ +/* See hal/spi/spi_drv_stm32.c */ + /*** FLASH ***/ #define SYSCFG_APB4_CLOCK_ER_VAL (1 << 0) /* RM0433 - 7.7.48 - RCC_APB4ENR - SYSCFGEN */ @@ -102,25 +204,25 @@ #define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00)) /* RM0433 - 3.9.1 - FLASH_ACR */ #define FLASH_OPTSR_CUR (*(volatile uint32_t *)(FLASH_BASE + 0x1C)) -/*bank 1 */ -#define FLASH_KEYR1 (*(volatile uint32_t *)(FLASH_BASE + 0x04)) /* RM0433 - 3.9.2 - FLASH_KEYR 1 */ -#define FLASH_SR1 (*(volatile uint32_t *)(FLASH_BASE + 0x10)) /* RM0433 - 3.9.5 - FLASH_SR 1 */ -#define FLASH_CR1 (*(volatile uint32_t *)(FLASH_BASE + 0x0C)) /* RM0433 - 3.9.4 - FLASH_CR 1 */ +/* Bank 1 */ +#define FLASH_KEYR1 (*(volatile uint32_t *)(FLASH_BASE + 0x04)) /* RM0433 - 3.9.2 - FLASH_KEYR 1 */ +#define FLASH_SR1 (*(volatile uint32_t *)(FLASH_BASE + 0x10)) /* RM0433 - 3.9.5 - FLASH_SR 1 */ +#define FLASH_CR1 (*(volatile uint32_t *)(FLASH_BASE + 0x0C)) /* RM0433 - 3.9.4 - FLASH_CR 1 */ -/*bank 2 */ -#define FLASH_KEYR2 (*(volatile uint32_t *)(FLASH_BASE + 0x104)) /* RM0433 - 3.9.24 - FLASH_KEYR 2 */ -#define FLASH_SR2 (*(volatile uint32_t *)(FLASH_BASE + 0x110)) /* RM0433 - 3.9.26 - FLASH_SR 2 */ -#define FLASH_CR2 (*(volatile uint32_t *)(FLASH_BASE + 0x10C)) /* RM0433 - 3.9.25 - FLASH_CR 2 */ +/* Bank 2 */ +#define FLASH_KEYR2 (*(volatile uint32_t *)(FLASH_BASE + 0x104)) /* RM0433 - 3.9.24 - FLASH_KEYR 2 */ +#define FLASH_SR2 (*(volatile uint32_t *)(FLASH_BASE + 0x110)) /* RM0433 - 3.9.26 - FLASH_SR 2 */ +#define FLASH_CR2 (*(volatile uint32_t *)(FLASH_BASE + 0x10C)) /* RM0433 - 3.9.25 - FLASH_CR 2 */ +/* Flash Configuration */ #define FLASHMEM_ADDRESS_SPACE (0x08000000UL) #define FLASH_PAGE_SIZE (0x20000) /* 128KB */ #define FLASH_BANK2_BASE (0x08100000UL) /*!< Base address of : (up to 1 MB) Flash Bank2 accessible over AXI */ #define FLASH_BANK2_BASE_REL (FLASH_BANK2_BASE - FLASHMEM_ADDRESS_SPACE) #define FLASH_TOP (0x081FFFFFUL) /*!< FLASH end address */ - /* Register values */ -#define FLASH_ACR_LATENCY_MASK (0x07) +#define FLASH_ACR_LATENCY_MASK (0x07) #define FLASH_SR_BSY (1 << 0) #define FLASH_SR_WBNE (1 << 1) #define FLASH_SR_QW (1 << 2) @@ -148,8 +250,8 @@ #define FLASH_CR_SNB_SHIFT 8 /* SNB bits 10:8 */ #define FLASH_CR_SNB_MASK 0x7 /* SNB bits 10:8 - 3 bits */ -#define FLASH_KEY1 (0x45670123) -#define FLASH_KEY2 (0xCDEF89AB) +#define FLASH_KEY1 (0x45670123) +#define FLASH_KEY2 (0xCDEF89AB) /* STM32H7: Due to ECC functionality, it is not possible to write partition/sector @@ -182,33 +284,37 @@ static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates) { uint32_t reg = FLASH_ACR; if ((reg & FLASH_ACR_LATENCY_MASK) != waitstates) - FLASH_ACR = (reg & ~FLASH_ACR_LATENCY_MASK) | waitstates; + FLASH_ACR = (reg & ~FLASH_ACR_LATENCY_MASK) | waitstates; } static RAMFUNCTION void flash_wait_last(void) { - while((FLASH_OPTSR_CUR & FLASH_OPTSR_CUR_BSY)) + while ((FLASH_OPTSR_CUR & FLASH_OPTSR_CUR_BSY)) ; } static RAMFUNCTION void flash_wait_complete(uint8_t bank) { - if (bank==0) - while ((FLASH_SR1 & FLASH_SR_QW) == FLASH_SR_QW); - if (bank==1) - while ((FLASH_SR2 & FLASH_SR_QW) == FLASH_SR_QW); + if (bank == 0) { + while ((FLASH_SR1 & FLASH_SR_QW) == FLASH_SR_QW); + } + else { + while ((FLASH_SR2 & FLASH_SR_QW) == FLASH_SR_QW); + } } static void RAMFUNCTION flash_clear_errors(uint8_t bank) { - if (bank==0) + if (bank == 0) { FLASH_SR1 |= (FLASH_SR_WRPERR | FLASH_SR_PGSERR | FLASH_SR_STRBERR | FLASH_SR_INCERR | FLASH_SR_OPERR | FLASH_SR_RDPERR | FLASH_SR_RDSERR | FLASH_SR_SNECCERR | FLASH_SR_DBECCERR); - if (bank==1) + } + else { FLASH_SR2 |= (FLASH_SR_WRPERR | FLASH_SR_PGSERR | FLASH_SR_STRBERR | FLASH_SR_INCERR | FLASH_SR_OPERR | FLASH_SR_RDPERR | FLASH_SR_RDSERR | FLASH_SR_SNECCERR | FLASH_SR_DBECCERR); + } } static void RAMFUNCTION flash_program_on(uint8_t bank) @@ -217,7 +323,8 @@ static void RAMFUNCTION flash_program_on(uint8_t bank) FLASH_CR1 |= FLASH_CR_PG; while ((FLASH_CR1 & FLASH_CR_PG) == 0) ; - } else { + } + else { FLASH_CR2 |= FLASH_CR_PG; while ((FLASH_CR2 & FLASH_CR_PG) == 0) ; @@ -228,7 +335,8 @@ static void RAMFUNCTION flash_program_off(uint8_t bank) { if (bank == 0) { FLASH_CR1 &= ~FLASH_CR_PG; - } else { + } + else { FLASH_CR2 &= ~FLASH_CR_PG; } } @@ -261,7 +369,8 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) dst[ii] = src[ii]; } i+=32; - } else { + } + else { int off = (address + i) - (((address + i) >> 5) << 5); uint32_t base_addr = (address + i) & (~0x1F); /* aligned to 256 bit */ dst = (uint32_t *)(base_addr); @@ -274,15 +383,17 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) return -1; hal_flash_erase(STM32H7_PART_BOOT_FLAGS_PAGE_ADDRESS, STM32H7_SECTOR_SIZE); - } else if (STM32H7_UPDATE_FLAGS_PAGE(address)) { + } + else if (STM32H7_UPDATE_FLAGS_PAGE(address)) { if (base_addr != STM32H7_PART_UPDATE_END - STM32H7_WORD_SIZE) return -1; hal_flash_erase(STM32H7_PART_UPDATE_FLAGS_PAGE_ADDRESS, STM32H7_SECTOR_SIZE); } /* Replace bytes in cache */ - while ((off < STM32H7_WORD_SIZE) && (i < len)) + while ((off < STM32H7_WORD_SIZE) && (i < len)) { vbytes[off++] = data[i++]; + } /* Actual write from cache to FLASH */ flash_wait_last(); @@ -350,8 +461,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) p < end_address; p += FLASH_PAGE_SIZE) { - if (p < FLASH_BANK2_BASE_REL) - { + if (p < FLASH_BANK2_BASE_REL) { uint32_t reg = FLASH_CR1 & (~((FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT) | FLASH_CR_PSIZE)); FLASH_CR1 = reg | @@ -361,8 +471,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) flash_wait_complete(1); } if ((p>= FLASH_BANK2_BASE_REL) && - (p <= (FLASH_TOP - FLASHMEM_ADDRESS_SPACE))) - { + (p <= (FLASH_TOP - FLASHMEM_ADDRESS_SPACE))) { uint32_t reg = FLASH_CR2 & (~((FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT) | FLASH_CR_PSIZE)); p-= (FLASH_BANK2_BASE); @@ -376,6 +485,108 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) return 0; } +#ifdef DEBUG_UART +static int uart_init(void) +{ + uint32_t reg; + + /* Set general UART clock source (all uarts but nr 1 and 6) */ + /* USART234578SEL bits 2:0 */ + RCC_D2CCIP2R &= ~(0x7 << 0); + RCC_D2CCIP2R |= (0x3 << 0); /* 000 = pclk1 (120MHz), 011 = hsi (64MHz) */ + +#if UART_PORT == 3 + /* Enable clock for USART_3 and reset */ + APB1_CLOCK_LER |= RCC_APB1_USART3_EN; + + APB1_CLOCK_LRST |= RCC_APB1_USART3_EN; + APB1_CLOCK_LRST &= ~RCC_APB1_USART3_EN; +#else + /* Enable clock for USART_2 and reset */ + APB1_CLOCK_LER |= RCC_APB1_USART2_EN; + + APB1_CLOCK_LRST |= RCC_APB1_USART2_EN; + APB1_CLOCK_LRST &= ~RCC_APB1_USART2_EN; +#endif + + /* Enable UART pins */ + AHB4_CLOCK_ENR |= RCC_AHB4_GPIOD_EN; + + /* Set mode = AF. The PORT D I/O pin is first reset and then set to AF + * (bit config 10:Alternate function mode) */ + reg = GPIO_MODE(UART_GPIO_BASE) & ~(0x03 << (UART_TX_PIN * 2)); + GPIO_MODE(UART_GPIO_BASE) = reg | (2 << (UART_TX_PIN * 2)); + reg = GPIO_MODE(UART_GPIO_BASE) & ~(0x03 << (UART_RX_PIN * 2)); + GPIO_MODE(UART_GPIO_BASE) = reg | (2 << (UART_RX_PIN * 2)); + + /* Alternate function. Use AFLR for pins 0-7 and AFHR for pins 8-15 */ +#if UART_TX_PIN < 8 + reg = GPIO_AFRL(UART_GPIO_BASE) & ~(0xf << ((UART_TX_PIN) * 4)); + GPIO_AFRL(UART_GPIO_BASE) = reg | (UART_PIN_AF << ((UART_TX_PIN) * 4)); +#else + reg = GPIO_AFRH(UART_GPIO_BASE) & ~(0xf << ((UART_TX_PIN - 8) * 4)); + GPIO_AFRH(UART_GPIO_BASE) = reg | (UART_PIN_AF << ((UART_TX_PIN - 8) * 4)); +#endif +#if UART_RX_PIN < 8 + reg = GPIO_AFRL(UART_GPIO_BASE) & ~(0xf << ((UART_RX_PIN)*4)); + GPIO_AFRL(UART_GPIO_BASE) = reg | (UART_PIN_AF << ((UART_RX_PIN)*4)); +#else + reg = GPIO_AFRH(UART_GPIO_BASE) & ~(0xf << ((UART_RX_PIN - 8) * 4)); + GPIO_AFRH(UART_GPIO_BASE) = reg | (UART_PIN_AF << ((UART_RX_PIN - 8) * 4)); +#endif + + /* Disable UART to enable settings to be written into the registers. */ + if (UART_CR1(UART_BASE) & UART_CR1_UART_ENABLE) { + UART_CR1(UART_BASE) &= ~UART_CR1_UART_ENABLE; + } + + /* Clock Prescaler */ + UART_PRESC(UART_BASE) = 0; /* no div (div=1) */ + + /* Configure clock (speed/bitrate). Requires UE = 0. */ + UART_BRR(UART_BASE) = (uint16_t)(CLOCK_SPEED / BAUD_RATE); + + /* Enable FIFO mode */ + UART_CR1(UART_BASE) |= UART_CR1_FIFOEN; + + /* Enable 16-bit oversampling */ + UART_CR1(UART_BASE) &= ~UART_CR1_OVER8; + + /* Configure the M bits (word length) */ + /* Word length is 8 bits by default (0=1 start, 8 data, 0 stop) */ + UART_CR1(UART_BASE) &= ~(UART_CR1_M0 | UART_CR1_M1); + + /* Configure stop bits (00: 1 stop bit / 10: 2 stop bits.) */ + UART_CR2(UART_BASE) &= ~UART_CR2_STOP_MASK; + UART_CR2(UART_BASE) |= UART_CR2_STOP(0); + + /* Configure parity bits, disabled */ + UART_CR1(UART_BASE) &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD); + + /* In asynchronous mode, the following bits must be kept cleared: + * - LINEN and CLKEN bits in the USART_CR2 register, + * - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ + UART_CR2(UART_BASE) &= ~(USART_CR2_LINEN | USART_CR2_CLKEN); + UART_CR3(UART_BASE) &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN); + + /* Turn on UART */ + UART_CR1(UART_BASE) |= (UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE | + UART_CR1_UART_ENABLE); + + return 0; +} + +void uart_write(const char* buf, unsigned int sz) +{ + uint32_t pos = 0; + while (sz-- > 0) { + while ((UART_ISR(UART_BASE) & UART_ISR_TX_FIFO_NOT_FULL) == 0); + + UART_TDR(UART_BASE) = buf[pos++]; + } +} +#endif /* DEBUG_UART */ + static void clock_pll_off(void) { uint32_t reg32; @@ -391,12 +602,12 @@ static void clock_pll_off(void) } /* This implementation will setup HSI RC 16 MHz as PLL Source Mux, PLLCLK - * as System Clock Source*/ + * as System Clock Source */ static void clock_pll_on(int powersave) { uint32_t reg32; uint32_t cpu_freq, plln, pllm, pllq, pllp, pllr, hpre, d1cpre, d1ppre; - uint32_t d2ppre1,d2ppre2, d3ppre , flash_waitstates; + uint32_t d2ppre1, d2ppre2, d3ppre, flash_waitstates; PWR_CR3 |= PWR_CR3_LDOEN; while ((PWR_CSR1 & PWR_CSR1_ACTVOSRDY) == 0) {}; @@ -415,12 +626,12 @@ static void clock_pll_on(int powersave) pllp = 2; pllq = 20; pllr = 2; - d1cpre = RCC_PRESCALER_DIV_NONE; - hpre = RCC_PRESCALER_DIV_2; - d1ppre = (RCC_PRESCALER_DIV_2 >>1 ); - d2ppre1 = (RCC_PRESCALER_DIV_2>>1); - d2ppre2 = (RCC_PRESCALER_DIV_2 >>1); - d3ppre = (RCC_PRESCALER_DIV_2 >>1); + d1cpre = RCC_PRESCALER_DIV_NONE; + hpre = RCC_PRESCALER_DIV_2; + d1ppre = (RCC_PRESCALER_DIV_2 >> 1); + d2ppre1 = (RCC_PRESCALER_DIV_2 >> 1); + d2ppre2 = (RCC_PRESCALER_DIV_2 >> 1); + d3ppre = (RCC_PRESCALER_DIV_2 >> 1); flash_waitstates = 4; flash_set_waitstates(flash_waitstates); @@ -534,8 +745,17 @@ void RAMFUNCTION hal_flash_dualbank_swap(void) void hal_init(void) { clock_pll_on(0); + +#ifdef DEBUG_UART + uart_init(); + uart_write("wolfBoot Init\n", 14); +#endif } + void hal_prepare_boot(void) { +#ifdef SPI_FLASH + spi_flash_release(); +#endif clock_pll_off(); } diff --git a/hal/stm32l0.c b/hal/stm32l0.c index b913abab..b31c6773 100644 --- a/hal/stm32l0.c +++ b/hal/stm32l0.c @@ -259,7 +259,7 @@ void hal_init(void) void hal_prepare_boot(void) { #ifdef SPI_FLASH - spi_release(); + spi_flash_release(); #endif hal_flash_lock(); if ((FLASH_PECR & FLASH_PECR_PELOCK) == 0) diff --git a/hal/stm32l4.c b/hal/stm32l4.c index ade46fbd..60956972 100644 --- a/hal/stm32l4.c +++ b/hal/stm32l4.c @@ -249,7 +249,7 @@ void hal_init(void) void hal_prepare_boot(void) { #ifdef SPI_FLASH - spi_release(); + spi_flash_release(); #endif clock_pll_off(); diff --git a/hal/stm32wb.c b/hal/stm32wb.c index 21db5e37..c7ad0db5 100644 --- a/hal/stm32wb.c +++ b/hal/stm32wb.c @@ -323,7 +323,7 @@ void hal_init(void) void hal_prepare_boot(void) { #ifdef SPI_FLASH - spi_release(); + spi_flash_release(); #endif clock_pll_off(); } diff --git a/hal/zynq.c b/hal/zynq.c index d2fdc595..9d60512f 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -1333,9 +1333,7 @@ static int test_flash(QspiDev_t* dev) { int ret; uint32_t i; -#ifndef USE_XQSPIPSU uint8_t pageData[FLASH_PAGE_SIZE]; -#endif #ifndef TEST_FLASH_READONLY /* Erase sector */ diff --git a/include/hal.h b/include/hal.h index 648a9c7f..c41349ef 100644 --- a/include/hal.h +++ b/include/hal.h @@ -66,7 +66,7 @@ void hal_prepare_boot(void); void *hal_get_dts_update_address(void); #endif -#ifndef SPI_FLASH +#if !defined(SPI_FLASH) && !defined(QSPI_FLASH) /* user supplied external flash interfaces */ int ext_flash_write(uintptr_t address, const uint8_t *data, int len); int ext_flash_read(uintptr_t address, uint8_t *data, int len); @@ -81,11 +81,16 @@ void hal_prepare_boot(void); #define ext_flash_write spi_flash_write static inline int ext_flash_erase(uintptr_t address, int len) { + int ret = 0; uint32_t end = address + len - 1; uint32_t p; - for (p = address; p <= end; p += SPI_FLASH_SECTOR_SIZE) - spi_flash_sector_erase(p); - return 0; + for (p = address; p <= end; p += SPI_FLASH_SECTOR_SIZE) { + ret = spi_flash_sector_erase(p); + if (ret != 0) { + break; + } + } + return ret; } #endif /* !SPI_FLASH */ diff --git a/include/spi_drv.h b/include/spi_drv.h index 7f0d11a0..541c317a 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -7,7 +7,7 @@ * implementing the spi_ calls below. * * - * Copyright (C) 2021 wolfSSL Inc. + * Copyright (C) 2022 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -32,9 +32,11 @@ #include #include "image.h" +#if defined(SPI_FLASH) || defined(QSPI_FLASH) + #if defined(PLATFORM_stm32f4) || defined(PLATFORM_stm32f7) || \ defined(PLATFORM_stm32wb) || defined(PLATFORM_stm32l0) || \ - defined(PLATFORM_stm32u5) + defined(PLATFORM_stm32u5) || defined(PLATFORM_stm32h7) #include "hal/spi/spi_drv_stm32.h" #endif @@ -47,9 +49,30 @@ #endif void spi_init(int polarity, int phase); +void spi_release(void); + +#ifdef SPI_FLASH +void spi_cs_on(uint32_t base, int pin); +void spi_cs_off(uint32_t base, int pin); void spi_write(const char byte); uint8_t spi_read(void); -void spi_cs_on(int pin); -void spi_cs_off(int pin); +#endif /* SPI_FLASH */ + + +#ifdef QSPI_FLASH +enum QSPIMode { + QSPI_ADDR_MODE_SPI = 1, + QSPI_ADDR_MODE_DSPI = 2, + QSPI_ADDR_MODE_QSPI = 3, +}; + +int qspi_transfer( + const uint8_t cmd, uint32_t addr, uint32_t addrSz, + const uint8_t* txData, uint32_t txSz, + uint8_t* rxData, uint32_t rxSz, uint32_t dummySz, + uint32_t mode); +#endif /* QSPI_FLASH */ + +#endif /* SPI_FLASH || QSPI_FLASH */ #endif /* !SPI_DRV_H_INCLUDED */ diff --git a/include/spi_flash.h b/include/spi_flash.h index 507c6063..e6fb27b0 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -6,7 +6,7 @@ * Compile with SPI_FLASH=1 * * - * Copyright (C) 2021 wolfSSL Inc. + * Copyright (C) 2022 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -28,24 +28,30 @@ #ifndef SPI_FLASH_DRI_H #define SPI_FLASH_DRI_H +#ifndef SPI_FLASH_SECTOR_SIZE #define SPI_FLASH_SECTOR_SIZE (4096) -#define SPI_FLASH_PAGE_SIZE (256) +#endif -#ifdef SPI_FLASH +#ifndef SPI_FLASH_PAGE_SIZE +#define SPI_FLASH_PAGE_SIZE (256) +#endif + +#if defined(SPI_FLASH) || defined(QSPI_FLASH) #include +/* returns (manuf << 8 | product) */ uint16_t spi_flash_probe(void); -void spi_release(void); +void spi_flash_release(void); -void spi_flash_sector_erase(uint32_t address); +int spi_flash_sector_erase(uint32_t address); int spi_flash_read(uint32_t address, void *data, int len); int spi_flash_write(uint32_t address, const void *data, int len); #else #define spi_flash_probe() do{}while(0) -#define spi_release() do{}while(0) +#define spi_flash_release() do{}while(0) #endif /* SPI_FLASH */ diff --git a/options.mk b/options.mk index dd37ffb5..bfb98a9a 100644 --- a/options.mk +++ b/options.mk @@ -303,6 +303,13 @@ ifeq ($(SPI_FLASH),1) WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(SPI_TARGET).o endif +ifeq ($(QSPI_FLASH),1) + EXT_FLASH=1 + CFLAGS+=-D"QSPI_FLASH=1" + OBJS+= src/qspi_flash.o + WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(SPI_TARGET).o +endif + ifeq ($(UART_FLASH),1) EXT_FLASH=1 endif diff --git a/src/image.c b/src/image.c index 0ff6015f..60a1ce1a 100644 --- a/src/image.c +++ b/src/image.c @@ -693,14 +693,14 @@ static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, (void)userCtx; (void)ctx; word16 i; - spi_cs_on(SPI_CS_TPM); + spi_cs_on(SPI_CS_TPM_PIO_BASE, SPI_CS_TPM); memset(rxBuf, 0, xferSz); for (i = 0; i < xferSz; i++) { spi_write(txBuf[i]); rxBuf[i] = spi_read(); } - spi_cs_off(SPI_CS_TPM); + spi_cs_off(SPI_CS_TPM_PIO_BASE, SPI_CS_TPM); /* printf("\r\nSPI TX: "); printbin(txBuf, xferSz); diff --git a/src/qspi_flash.c b/src/qspi_flash.c new file mode 100644 index 00000000..46f794f9 --- /dev/null +++ b/src/qspi_flash.c @@ -0,0 +1,425 @@ +/* qspi_flash.c + * + * Generic implementation of the read/write/erase + * functionalities, on top of the spi_drv.h HAL. + * + * + * Copyright (C) 2022 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include "spi_drv.h" +#include "spi_flash.h" + +#ifdef QSPI_FLASH + +#include "string.h" +#include "printf.h" + +#ifdef DEBUG_UART +#define DEBUG_QSPI +#endif + +/* Flash Parameters: + * Winbond W25Q128FV 128Mbit serial flash + */ +#ifndef FLASH_DEVICE_SIZE +#define FLASH_DEVICE_SIZE (16 * 1024 * 1024) +#endif +#ifndef FLASH_PAGE_SIZE +#define FLASH_PAGE_SIZE 256 +#endif +#ifndef FLASH_NUM_PAGES +#define FLASH_NUM_PAGES 0x10000 +#endif +#ifndef FLASH_SECTOR_SIZE +#define FLASH_SECTOR_SIZE WOLFBOOT_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 +#endif +#ifndef QSPI_ADDR_SZ +#define QSPI_ADDR_SZ 3 +#endif +#ifndef QSPI_DUMMY_READ +#define QSPI_DUMMY_READ (8) /* Number of dummy clock cycles for reads */ +#endif +#ifndef QSPI_FLASH_READY_TRIES +#define QSPI_FLASH_READY_TRIES 1000 +#endif + + +/* Flash Commands */ +#define WRITE_ENABLE_CMD 0x06U +#define READ_SR_CMD 0x05U +#define WRITE_DISABLE_CMD 0x04U +#define READ_ID_CMD 0x9FU + +#define ENTER_QSPI_MODE_CMD 0x38U +#define EXIT_QSPI_MODE_CMD 0xFFU + +#define ENTER_4B_ADDR_MODE_CMD 0xB7U +#define EXIT_4B_ADDR_MODE_CMD 0xE9U + +#define FAST_READ_CMD 0x0BU +#define DUAL_READ_CMD 0x3BU +#define QUAD_READ_CMD 0xEBU +#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 PAGE_PROG_4B_CMD 0x12U +#define DUAL_PROG_4B_CMD 0x12U +#define QUAD_PROG_4B_CMD 0x34U + +#define SEC_ERASE_CMD 0x20U /* 4KB */ +#define BLOCK_ERASE_CMD 0xD8U /* 64KB */ +#define RESET_ENABLE_CMD 0x66U +#define RESET_MEMORY_CMD 0x99U + +#define FLASH_SR_WRITE_EN 0x02 /* 1=Write Enabled, 0=Write Disabled */ +#define FLASH_SR_BUSY 0x01 /* 1=Busy, 0=Ready */ + +#if QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI && QSPI_ADDR_SZ == 4 +#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 +#define FLASH_READ_CMD FAST_READ_4B_CMD +#elif QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI +#define FLASH_READ_CMD QUAD_READ_CMD +#elif QSPI_ADDR_MODE == QSPI_ADDR_MODE_DSPI +#define FLASH_READ_CMD DUAL_READ_CMD +#else +#define FLASH_READ_CMD FAST_READ_CMD +#endif + + +/* forward declarations */ +static int qspi_wait_ready(void); +static int qspi_status(uint8_t* status); +static int qspi_wait_we(void); +#ifdef TEST_FLASH +static int test_flash(void); +#endif + +static int qspi_flash_read_id(uint8_t* id, uint32_t idSz) +{ + int ret; + uint8_t data[4]; /* size multiple of uint32_t */ + uint32_t status = 0; + + memset(data, 0, sizeof(data)); + ret = qspi_transfer(READ_ID_CMD, 0, 0, NULL, 0, data, 3, 0, + 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, FLASH_READ_CMD, status); +#endif + + /* optionally return id data */ + if (ret == 0 && id) { + if (idSz > sizeof(data)) + idSz = sizeof(data); + memcpy(id, data, idSz); + } + + return ret; +} + +static int qspi_write_enable(void) +{ + int ret; + + ret = qspi_transfer(WRITE_ENABLE_CMD, 0, 0, NULL, 0, NULL, 0, 0, + QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Write Enable: Ret %d\n", ret); +#endif + + qspi_wait_ready(); + + ret = qspi_wait_we(); +#ifdef DEBUG_QSPI + wolfBoot_printf("Write Enabled: %s\n", ret == 0 ? "yes" : "no"); +#endif + + return ret; +} + +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 + wolfBoot_printf("Write Disable: Ret %d\n", ret); +#endif + return ret; +} + +static int qspi_status(uint8_t* status) +{ + int ret; + uint8_t data[4]; /* size multiple of uint32_t */ + + 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]); +#endif + if (ret == 0 && status) { + *status = data[0]; + } + return ret; +} + +static int qspi_wait_ready(void) +{ + int ret; + uint32_t timeout; + uint8_t status = 0; + + timeout = 0; + while (++timeout < QSPI_FLASH_READY_TRIES) { + ret = qspi_status(&status); + if (ret == 0 && (status & FLASH_SR_BUSY) == 0) { + return ret; + } + } + +#ifdef DEBUG_QSPI + wolfBoot_printf("Flash Ready Timeout!\n"); +#endif + return -1; +} + +static int qspi_wait_we(void) +{ + int ret; + uint32_t timeout; + uint8_t status = 0; + + timeout = 0; + while (++timeout < QSPI_FLASH_READY_TRIES) { + ret = qspi_status(&status); + if (ret == 0 && (status & FLASH_SR_WRITE_EN)) { + return ret; + } + } + +#ifdef DEBUG_QSPI + wolfBoot_printf("Flash WE Timeout!\n"); +#endif + return -1; +} + +#if QSPI_ADDR_SZ == 4 +static int qspi_enter_4byte_addr(void) +{ + int ret = qspi_write_enable(); + if (ret == 0) { + ret = qspi_transfer(ENTER_4B_ADDR_MODE_CMD, 0, 0, + NULL, 0, NULL, 0, + 0, QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret); +#endif + if (ret == 0) { + ret = qspi_wait_ready(); /* Wait for not busy */ + } + qspi_write_disable(); + } + return ret; +} +static int qspi_exit_4byte_addr(void) +{ + int ret = qspi_write_enable(); + if (ret == 0) { + ret = qspi_transfer(EXIT_4B_ADDR_MODE_CMD, 0, 0, + NULL, 0, NULL, 0, + 0, QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret); +#endif + if (ret == 0) { + ret = qspi_wait_ready(); /* Wait for not busy */ + } + qspi_write_disable(); + } + return ret; +} +#endif + + +uint16_t spi_flash_probe(void) +{ + spi_init(0,0); + qspi_flash_read_id(NULL, 0); + +#if QSPI_ADDR_SZ == 4 + qspi_enter_4byte_addr(); +#endif + +#ifdef TEST_FLASH + test_flash(); +#endif + return 0; +} + +int spi_flash_sector_erase(uint32_t address) +{ + int ret; + uint32_t idx = 0; + + ret = qspi_write_enable(); + if (ret == 0) { + /* ------ Erase Flash ------ */ + ret = qspi_transfer(SEC_ERASE_CMD, address, QSPI_ADDR_SZ, + NULL, 0, NULL, 0, + 0, QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Flash Erase: Ret %d\n", ret); +#endif + if (ret == 0) { + ret = qspi_wait_ready(); /* Wait for not busy */ + } + qspi_write_disable(); + } + return ret; +} + +int spi_flash_read(uint32_t address, void *data, int len) +{ + int ret; + + /* ------ 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); +#endif + + return ret; +} + +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; + + /* write by page */ + pages = ((len + (FLASH_PAGE_SIZE-1)) / FLASH_PAGE_SIZE); + for (page = 0; page < pages; page++) { + ret = qspi_write_enable(); + if (ret == 0) { + xferSz = len; + if (xferSz > FLASH_PAGE_SIZE) + xferSz = FLASH_PAGE_SIZE; + + addr = address + (page * FLASH_PAGE_SIZE); + + /* ------ Write Flash (page at a time) ------ */ + ret = qspi_transfer(PAGE_PROG_CMD, addr, QSPI_ADDR_SZ, + (const uint8_t*)(data + (page * FLASH_PAGE_SIZE)), xferSz, + NULL, 0, 0, QSPI_ADDR_MODE_SPI); +#ifdef DEBUG_QSPI + wolfBoot_printf("Flash Page %d Write: Ret %d\n", page, ret); +#endif + if (ret != 0) + break; + + ret = qspi_wait_ready(); /* Wait for not busy */ + if (ret != 0) { + break; + } + qspi_write_disable(); + } + } + + return ret; +} + +void spi_flash_release(void) +{ +#if QSPI_ADDR_SZ == 4 + qspi_exit_4byte_addr(); +#endif + + spi_release(); +} + +#endif /* QSPI_FLASH */ + + + + +#ifdef TEST_FLASH +#define TEST_ADDRESS (2 * 1024 * 1024) /* 2MB */ +static int test_flash(void) +{ + int ret; + uint32_t i; + 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); + + /* Write Pages */ + for (i=0; i 0) { flash_write_enable(); - spi_cs_on(SPI_CS_FLASH); + spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH); spi_write(BYTE_WRITE); spi_read(); write_address(address); spi_write(buf[j]); spi_read(); - spi_cs_off(SPI_CS_FLASH); + spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH); wait_busy(); spi_flash_read(address, &verify, 1); if ((verify & ~(buf[j])) == 0) { @@ -174,7 +174,7 @@ uint16_t spi_flash_probe(void) int i; spi_init(0,0); wait_busy(); - spi_cs_on(SPI_CS_FLASH); + spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH); spi_write(MDID); b0 = spi_read(); @@ -183,36 +183,37 @@ uint16_t spi_flash_probe(void) manuf = spi_read(); spi_write(0xFF); product = spi_read(); - spi_cs_off(SPI_CS_FLASH); + spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH); if (manuf == 0xBF || manuf == 0xC2) chip_write_mode = SST_SINGLEBYTE; if (manuf == 0xEF) chip_write_mode = WB_WRITEPAGE; #ifndef READONLY - spi_cs_on(SPI_CS_FLASH); + spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH); spi_write(WRSR); spi_read(); spi_write(0x00); spi_read(); - spi_cs_off(SPI_CS_FLASH); + spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH); #endif return (uint16_t)(manuf << 8 | product); } -void RAMFUNCTION spi_flash_sector_erase(uint32_t address) +int RAMFUNCTION spi_flash_sector_erase(uint32_t address) { address &= (~(SPI_FLASH_SECTOR_SIZE - 1)); wait_busy(); flash_write_enable(); - spi_cs_on(SPI_CS_FLASH); + spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH); spi_write(SECTOR_ERASE); spi_read(); write_address(address); - spi_cs_off(SPI_CS_FLASH); + spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH); wait_busy(); + return 0; } int RAMFUNCTION spi_flash_read(uint32_t address, void *data, int len) @@ -220,7 +221,7 @@ int RAMFUNCTION spi_flash_read(uint32_t address, void *data, int len) uint8_t *buf = data; int i = 0; wait_busy(); - spi_cs_on(SPI_CS_FLASH); + spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH); spi_write(BYTE_READ); spi_read(); write_address(address); @@ -229,7 +230,7 @@ int RAMFUNCTION spi_flash_read(uint32_t address, void *data, int len) buf[i++] = spi_read(); len--; } - spi_cs_off(SPI_CS_FLASH); + spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH); return i; } @@ -242,4 +243,9 @@ int RAMFUNCTION spi_flash_write(uint32_t address, const void *data, int len) return -1; } +void spi_flash_release(void) +{ + spi_release(); +} + #endif /* SPI_FLASH */ diff --git a/test-app/Makefile b/test-app/Makefile index 72fa061e..ac0bf5ad 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -45,6 +45,10 @@ endif include ../arch.mk +ifeq ($(DEBUG_UART),1) + APP_OBJS+=../src/string.o +endif + ifeq ($(TZEN),1) APP_OBJS+=../hal/$(TARGET)_ns.o else @@ -136,6 +140,11 @@ ifeq ($(SPI_FLASH),1) APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o ../src/spi_flash.o endif +ifeq ($(QSPI_FLASH),1) + CFLAGS+=-D"QSPI_FLASH" + APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o ../src/qspi_flash.o +endif + ifeq ($(UART_FLASH),1) CFLAGS+=-D"UART_FLASH=1" APP_OBJS+= ../src/uart_flash.o ../hal/uart/uart_drv_$(UART_TARGET).o diff --git a/test-app/app_stm32f4.c b/test-app/app_stm32f4.c index 71e8d1fe..f111708e 100644 --- a/test-app/app_stm32f4.c +++ b/test-app/app_stm32f4.c @@ -305,7 +305,7 @@ void main(void) { /* Update complete */ spi_flash_probe(); wolfBoot_update_trigger(); - spi_release(); + spi_flash_release(); hal_flash_lock(); break; } diff --git a/test-app/app_stm32h7.c b/test-app/app_stm32h7.c index 8f040cba..87f0f47b 100644 --- a/test-app/app_stm32h7.c +++ b/test-app/app_stm32h7.c @@ -26,7 +26,8 @@ * | * The following application runs on the above mentioned board. | * It contains setup of LD1, LD2 and LD3. | - * As well as setup of UART serial communication using USART2 on pins PD5 (TX) and PD6 (RX). | + * USART serial communication defaults to using USART3 on pins PD8 (TX) and PD9 (RX) (VCOM Port). | + * To use USART2 set UART_PORT=2 to use pins PD5 (TX) and PD6 (RX). | * -------------------------------------------------------------------------------------------------------------------- */ @@ -86,6 +87,8 @@ #define GPIOB_AFH (*(volatile uint32_t *)(GPIOB_BASE + 0x24)) #define GPIOB_AHB4_CLOCK_ER (1 << 1) +#define GPIOD_BASE (0x58020C00) + /* GPIO GROUP E */ #define GPIOE_BASE 0x58021000 #define GPIOE_MODE (*(volatile uint32_t *)(GPIOE_BASE + 0x00)) @@ -97,14 +100,23 @@ /* UART SETUP */ /* ====================================================================== */ +#ifndef UART_PORT +#define UART_PORT 3 /* default to Nucleo VCOM port */ +#endif + +#if UART_PORT == 3 +/* USART3 Base address (connected to ST virtual com port on Nucleo board) */ +#define UART_BASE (0x40004800) +#define UART_TX_PIN 8 /* PD8, USART Transmit pin */ +#define UART_RX_PIN 9 /* PD9, USART Receive pin */ +#else /* USART2 Base address (chosen because of its pin layout on Nucleo board) */ #define UART_BASE (0x40004400) -#define RCC_BASE (0x58024400) -#define GPIOD_BASE (0x58020C00) - -#define UART_PIN_AF 7 /* AF stands for Alternate Function. For PD5/PD6 AF7 equals USART2 RX/TX. */ #define UART_TX_PIN 5 /* PD5, USART Transmit pin */ #define UART_RX_PIN 6 /* PD6, USART Receive pin */ +#endif + +#define UART_PIN_AF 7 /* AF stands for Alternate Function. USART TX/RX */ /* UART/USART: Defining register start addresses. */ #define UART_CR1 (*(volatile uint32_t *)(UART_BASE + 0x00)) @@ -116,6 +128,7 @@ #define UART_RQR (*(volatile uint32_t *)(UART_BASE + 0x18)) /* RCC: Defining register start addresses. */ +#define RCC_BASE (0x58024400) #define RCC_D2CCIP2R (*(volatile uint32_t *)(RCC_BASE + 0x54)) #define RCC_AHB1ENR (*(volatile uint32_t *)(RCC_BASE + 0xD8)) #define RCC_AHB4ENR (*(volatile uint32_t *)(RCC_BASE + 0xE0)) @@ -154,7 +167,9 @@ #define RCC_AHB4_GPIOD_EN (1 << 3) /* HSI Clock speed */ +#ifndef CLOCK_SPEED #define CLOCK_SPEED 64000000 +#endif /* Marking the update partition as ready to be swapped and executed. */ #define UPDATE_PARTITION_BASE (0x08060000) @@ -177,16 +192,13 @@ static void ld1_write(uint8_t led_status) { - if (led_status == 0) - { + if (led_status == 0) { SET_BIT(GPIOB_BSRR, (1 << (LD1_PIN + 16))); } - else if (led_status == 2) - { + else if (led_status == 2) { SET_BIT(GPIOB_BSRR, (1 << LD1_PIN)); } - else if (led_status == 1) - { + else if (led_status == 1) { uint32_t reg; uint32_t pin = LD1_PIN; SET_BIT(RCC_AHB4ENR, GPIOB_AHB4_CLOCK_ER); @@ -200,16 +212,13 @@ static void ld1_write(uint8_t led_status) static void ld2_write(uint8_t led_status) { - if (led_status == 0) - { + if (led_status == 0) { GPIOE_BSRR |= (1 << (LD2_PIN + 16)); } - else if (led_status == 2) - { + else if (led_status == 2) { SET_BIT(GPIOE_BSRR, (1 << LD2_PIN)); } - else if (led_status == 1) - { + else if (led_status == 1) { uint32_t reg; uint32_t pin = LD2_PIN; RCC_AHB4ENR |= GPIOE_AHB4_CLOCK_ER; @@ -259,14 +268,23 @@ int uart_setup(uint32_t bitrate) GPIOD_MODE = reg | (2 << (UART_RX_PIN * 2)); /* Alternate function. Use AFLR for pins 0-7 and AFHR for pins 8-15 */ +#if UART_TX_PIN >= 8 + reg = GPIOD_AFRH & ~(0xf << ((UART_TX_PIN & 0x07)*4)); + GPIOD_AFRH = reg | (UART_PIN_AF << ((UART_TX_PIN & 0x07)*4)); +#else reg = GPIOD_AFRL & ~(0xf << ((UART_TX_PIN)*4)); GPIOD_AFRL = reg | (UART_PIN_AF << ((UART_TX_PIN)*4)); +#endif +#if UART_RX_PIN >= 8 + reg = GPIOD_AFRH & ~(0xf << ((UART_RX_PIN & 0x07)*4)); + GPIOD_AFRH = reg | (UART_PIN_AF << ((UART_RX_PIN & 0x07)*4)); +#else reg = GPIOD_AFRL & ~(0xf << ((UART_RX_PIN)*4)); GPIOD_AFRL = reg | (UART_PIN_AF << ((UART_RX_PIN)*4)); +#endif /* Disable UART to enable settings to be written into the registers. */ - if (READ_BIT(UART_CR1, UART_CR1_UART_ENABLE) == 1) - { + if (READ_BIT(UART_CR1, UART_CR1_UART_ENABLE) == 1) { CLEAR_BIT(UART_CR1, UART_CR1_UART_ENABLE); } @@ -276,8 +294,13 @@ int uart_setup(uint32_t bitrate) SET_BIT(RCC_D2CCIP2R, (1 << 1)); CLEAR_BIT(RCC_D2CCIP2R, (1 << 2)); +#if UART_PORT == 3 + /* Enable clock for USART_3 */ + SET_BIT(RCC_APB1ENR, RCC_APB1_USART3_EN); +#else /* Enable clock for USART_2 */ SET_BIT(RCC_APB1ENR, RCC_APB1_USART2_EN); +#endif /* Enable FIFO mode */ SET_BIT(UART_CR1, (1 << 29)); @@ -313,9 +336,9 @@ int uart_setup(uint32_t bitrate) return -1; } -void uart_write(const char c) +static void uart_write(const char c) { - /* USART transmit data register(TDR), bit 0-8 contains the data character + /* USART transmit data register(TDR), bit 0-8 contains the data character * to be transmitted. * The register mus be written only when TXE/TXFNF = 1; * TXE : Set by hardware when the content of the USART_TDR register has @@ -334,8 +357,7 @@ void uart_write(const char c) void uart_print(const char *s) { int i = 0; - while (s[i]) - { + while (s[i]) { uart_write(s[i++]); } } @@ -352,7 +374,7 @@ void main(void) ld3_write(LED_INIT); /* LED Indicator of successful UART initialization. SUCCESS = ON, FAIL = OFF */ - if (uart_setup(9600) < 0) + if (uart_setup(115200) < 0) ld2_write(LED_OFF); else ld2_write(LED_INIT); diff --git a/test-app/app_stm32l0.c b/test-app/app_stm32l0.c index cbbd4246..c1eafdaa 100644 --- a/test-app/app_stm32l0.c +++ b/test-app/app_stm32l0.c @@ -1,4 +1,4 @@ -/* main.c +/* app_stm32l0.c * * Test bare-metal boot-led-on application * @@ -32,6 +32,143 @@ #ifdef PLATFORM_stm32l0 +#define UART2 (0x40004400) +#define UART2_CR1 (*(volatile uint32_t *)(UART2 + 0x00)) +#define UART2_CR2 (*(volatile uint32_t *)(UART2 + 0x04)) +#define UART2_CR3 (*(volatile uint32_t *)(UART2 + 0x08)) +#define UART2_BRR (*(volatile uint32_t *)(UART2 + 0x0c)) +#define UART2_ISR (*(volatile uint32_t *)(UART2 + 0x1c)) +#define UART2_ICR (*(volatile uint32_t *)(UART2 + 0x20)) +#define UART2_RDR (*(volatile uint32_t *)(UART2 + 0x24)) +#define UART2_TDR (*(volatile uint32_t *)(UART2 + 0x28)) + +#define UART_CR1_UART_ENABLE (1 << 0) +#define UART_CR1_SYMBOL_LEN (1 << 12) +#define UART_CR1_PARITY_ENABLED (1 << 10) +#define UART_CR1_OVER8 (1 << 15) +#define UART_CR1_PARITY_ODD (1 << 9) +#define UART_CR1_TX_ENABLE (1 << 3) +#define UART_CR1_RX_ENABLE (1 << 2) +#define UART_CR2_STOPBITS (3 << 12) +#define UART_CR2_LINEN (1 << 14) +#define UART_CR2_CLKEN (1 << 11) +#define UART_CR3_HDSEL (1 << 3) +#define UART_CR3_SCEN (1 << 5) +#define UART_CR3_IREN (1 << 1) +#define UART_ISR_TX_EMPTY (1 << 7) +#define UART_ISR_RX_NOTEMPTY (1 << 5) + +#define RCC_IOPENR (*(volatile uint32_t *)(0x4002102C)) +#define APB1_CLOCK_ER (*(volatile uint32_t *)(0x40021038)) +#define IOPAEN (1 << 0) +#define IOPCEN (1 << 2) + +#define UART2_APB1_CLOCK_ER_VAL (1 << 17) + +#define GPIOA_BASE 0x50000000 +#define GPIOA_MODE (*(volatile uint32_t *)(GPIOA_BASE + 0x00)) +#define GPIOA_OTYPE (*(volatile uint32_t *)(GPIOA_BASE + 0x04)) +#define GPIOA_OSPD (*(volatile uint32_t *)(GPIOA_BASE + 0x08)) +#define GPIOA_PUPD (*(volatile uint32_t *)(GPIOA_BASE + 0x0c)) +#define GPIOA_ODR (*(volatile uint32_t *)(GPIOA_BASE + 0x14)) +#define GPIOA_BSRR (*(volatile uint32_t *)(GPIOA_BASE + 0x18)) +#define GPIOA_AFL (*(volatile uint32_t *)(GPIOA_BASE + 0x20)) +#define GPIOA_AFH (*(volatile uint32_t *)(GPIOA_BASE + 0x24)) + +#define GPIO_MODE_AF (2) +#define UART2_PIN_AF 4 +#define UART2_RX_PIN 2 +#define UART2_TX_PIN 3 + +#ifndef CPU_FREQ +#define CPU_FREQ (24000000) +#endif + +#ifndef UART_FLASH + +static void uart2_pins_setup(void) +{ + uint32_t reg; + RCC_IOPENR |= IOPAEN; + /* Set mode = AF */ + reg = GPIOA_MODE & ~ (0x03 << (UART2_RX_PIN * 2)); + GPIOA_MODE = reg | (2 << (UART2_RX_PIN * 2)); + reg = GPIOA_MODE & ~ (0x03 << (UART2_TX_PIN * 2)); + GPIOA_MODE = reg | (2 << (UART2_TX_PIN * 2)); + + /* Alternate function: use low pins (2 and 3) */ + reg = GPIOA_AFL & ~(0xf << (UART2_TX_PIN * 4)); + GPIOA_AFL = reg | (UART2_PIN_AF << (UART2_TX_PIN * 4)); + reg = GPIOA_AFL & ~(0xf << (UART2_RX_PIN * 4)); + GPIOA_AFL = reg | (UART2_PIN_AF << (UART2_RX_PIN * 4)); + +} + +int uart_setup(uint32_t bitrate) +{ + uint32_t reg; + + /* Enable pins and configure for AF */ + uart2_pins_setup(); + + /* Turn on the device */ + APB1_CLOCK_ER |= UART2_APB1_CLOCK_ER_VAL; + + /* Enable 16-bit oversampling */ + UART2_CR1 &= (~UART_CR1_OVER8); + + /* Configure clock */ + UART2_BRR |= (uint16_t)(CPU_FREQ / bitrate); + + /* Configure data bits to 8 */ + UART2_CR1 &= ~UART_CR1_SYMBOL_LEN; + + /* Disable parity */ + UART2_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD); + + /* Set stop bits */ + UART2_CR2 = UART2_CR2 & ~UART_CR2_STOPBITS; + + /* Clear flags for async mode */ + UART2_CR2 &= ~(UART_CR2_LINEN | UART_CR2_CLKEN); + UART2_CR3 &= ~(UART_CR3_SCEN | UART_CR3_HDSEL | UART_CR3_IREN); + + /* Configure for RX+TX, turn on. */ + UART2_CR1 |= UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE | UART_CR1_UART_ENABLE; + + return 0; +} + +int uart_write(const uint8_t c) +{ + volatile uint32_t reg; + do { + reg = UART2_ISR; + } while ((reg & UART_ISR_TX_EMPTY) == 0); + UART2_TDR = c; + return 1; +} + +int uart_read(uint8_t *c, int len) +{ + volatile uint32_t reg; + int i = 0; + reg = UART2_ISR; + if (reg & UART_ISR_RX_NOTEMPTY) { + *c = (uint8_t)UART2_RDR; + return 1; + } + return 0; +} + +void uart_print(const char *s) +{ + int i = 0; + while (s[i]) { + uart_write(s[i++]); + } +} + /* Matches all keys: * - chacha (32 + 12) * - aes128 (16 + 16) @@ -41,9 +178,14 @@ char enc_key[] = "0123456789abcdef0123456789abcdef" "0123456789abcdef"; -void main(void) { +void main(void) +{ uint32_t version; volatile uint32_t i, j; + + uart_setup(115200); + uart_print("STM32L0 Test Application\n\r"); + #ifdef SPI_FLASH spi_flash_probe(); #endif diff --git a/tools/check_config/check_config.c b/tools/check_config/check_config.c index e20107f4..7a539536 100644 --- a/tools/check_config/check_config.c +++ b/tools/check_config/check_config.c @@ -57,9 +57,9 @@ void hal_prepare_boot(void) { } -void spi_flash_sector_erase(uint32_t address) +int spi_flash_sector_erase(uint32_t address) { - + return 0; } int spi_flash_read(uint32_t address, void *data, int len) { diff --git a/tools/config.mk b/tools/config.mk index b8f199f8..0f3edcee 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -19,6 +19,7 @@ ifeq ($(ARCH),) NO_ASM?=0 EXT_FLASH?=0 SPI_FLASH?=0 + QSPI_FLASH?=0 NO_XIP?=0 UART_FLASH?=0 ALLOW_DOWNGRADE?=0