STM32 QSPI Flash support. Refactor SPI to allow different GPIO base/AF for each pin. Adds `DEBUG_UART` support for H7.

pull/264/head
David Garske 2022-11-30 15:15:22 -08:00 committed by Daniele Lacamera
parent ac6f5207c7
commit a9526bab8f
30 changed files with 1574 additions and 360 deletions

View File

@ -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) \

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <stdint.h>
#include <stddef.h>
#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 */

View File

@ -17,17 +17,8 @@
#ifndef SPI_DRV_STM32_H_INCLUDED
#define SPI_DRV_STM32_H_INCLUDED
#include <stdint.h>
/** 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 */

View File

@ -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;
}

View File

@ -19,6 +19,7 @@
#define SPI_DRV_ZYNQ_H_INCLUDED
#include <stdint.h>
#define SPI_CS_FLASH 0
#define SPI_CS_FLASH 0
#define SPI_CS_PIO_BASE 0UL
#endif /* !SPI_DRV_ZYNQ_H_INCLUDED */

View File

@ -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();

View File

@ -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();

View File

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

View File

@ -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();
}

View File

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

View File

@ -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();

View File

@ -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();
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 <stdint.h>
#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 */

View File

@ -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 <stdint.h>
/* 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 */

View File

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

View File

@ -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);

425
src/qspi_flash.c 100644
View File

@ -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<sizeof(pageData); i++) {
pageData[i] = (i & 0xff);
}
ret = ext_flash_write(TEST_ADDRESS, pageData, sizeof(pageData));
wolfBoot_printf("Write Page: 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("Checking...\n");
/* Check data */
for (i=0; i<sizeof(pageData); i++) {
wolfBoot_printf("check[%3d] %02x\n", i, pageData[i]);
if (pageData[i] != (i & 0xff)) {
wolfBoot_printf("Check Data @ %d failed\n", i);
return -1;
}
}
wolfBoot_printf("Flash Test Passed\n");
return ret;
}
#endif /* TEST_FLASH */

View File

@ -68,21 +68,21 @@ static void RAMFUNCTION write_address(uint32_t address)
static uint8_t RAMFUNCTION read_status(void)
{
uint8_t status;
spi_cs_on(SPI_CS_FLASH);
spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH);
spi_write(RDSR);
spi_read();
spi_write(0xFF);
status = spi_read();
spi_cs_off(SPI_CS_FLASH);
spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH);
return status;
}
static void RAMFUNCTION spi_cmd(uint8_t cmd)
{
spi_cs_on(SPI_CS_FLASH);
spi_cs_on(SPI_CS_PIO_BASE, SPI_CS_FLASH);
spi_write(cmd);
spi_read();
spi_cs_off(SPI_CS_FLASH);
spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH);
}
static void RAMFUNCTION flash_write_enable(void)
@ -118,7 +118,7 @@ static int RAMFUNCTION spi_flash_write_page(uint32_t address, const void *data,
flash_write_enable();
wait_busy();
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);
@ -128,7 +128,7 @@ static int RAMFUNCTION spi_flash_write_page(uint32_t address, const void *data,
spi_read();
len--;
} while ((address & (SPI_FLASH_PAGE_SIZE - 1)) != 0);
spi_cs_off(SPI_CS_FLASH);
spi_cs_off(SPI_CS_PIO_BASE, SPI_CS_FLASH);
}
wait_busy();
return 0;
@ -145,13 +145,13 @@ static int RAMFUNCTION spi_flash_write_sb(uint32_t address, const void *data, in
return -1;
while (len > 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 */

View File

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

View File

@ -305,7 +305,7 @@ void main(void) {
/* Update complete */
spi_flash_probe();
wolfBoot_update_trigger();
spi_release();
spi_flash_release();
hal_flash_lock();
break;
}

View File

@ -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);

View File

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

View File

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

View File

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