mirror of https://github.com/wolfSSL/wolfBoot.git
Add uart driver for stm32u5
parent
4efc00a806
commit
6b8702dd63
|
|
@ -24,6 +24,7 @@
|
|||
#include <string.h>
|
||||
#include "hal/stm32u5.h"
|
||||
#include "hal.h"
|
||||
#include "uart_drv.h"
|
||||
|
||||
|
||||
static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates)
|
||||
|
|
@ -33,7 +34,7 @@ static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates)
|
|||
FLASH_ACR = (reg & ~FLASH_ACR_LATENCY_MASK) | waitstates;
|
||||
}
|
||||
|
||||
static RAMFUNCTION void flash_wait_complete(uint8_t bank)
|
||||
void RAMFUNCTION hal_flash_wait_complete(uint8_t bank)
|
||||
{
|
||||
while ((FLASH_NS_SR & (FLASH_SR_BSY | FLASH_SR_WDW)) != 0)
|
||||
;
|
||||
|
|
@ -44,7 +45,7 @@ static RAMFUNCTION void flash_wait_complete(uint8_t bank)
|
|||
|
||||
}
|
||||
|
||||
static void RAMFUNCTION flash_clear_errors(uint8_t bank)
|
||||
void RAMFUNCTION hal_flash_clear_errors(uint8_t bank)
|
||||
{
|
||||
|
||||
FLASH_NS_SR |= (FLASH_SR_OPERR | FLASH_SR_PROGERR | FLASH_SR_WRPERR |
|
||||
|
|
@ -68,7 +69,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
|||
uint32_t qword[4];
|
||||
volatile uint32_t *sr, *cr;
|
||||
|
||||
flash_clear_errors(0);
|
||||
hal_flash_clear_errors(0);
|
||||
src = (uint32_t*)data;
|
||||
dst = (uint32_t*)address;
|
||||
|
||||
|
|
@ -105,7 +106,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
|||
ISB();
|
||||
dst[(i >> 2) + 3] = qword[3];
|
||||
ISB();
|
||||
flash_wait_complete(0);
|
||||
hal_flash_wait_complete(0);
|
||||
if ((*sr & FLASH_SR_EOP) != 0)
|
||||
*sr |= FLASH_SR_EOP;
|
||||
*cr &= ~FLASH_CR_PG;
|
||||
|
|
@ -117,7 +118,7 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
|||
|
||||
void RAMFUNCTION hal_flash_unlock(void)
|
||||
{
|
||||
flash_wait_complete(0);
|
||||
hal_flash_wait_complete(0);
|
||||
#if (TZ_SECURE())
|
||||
if ((FLASH_CR & FLASH_CR_LOCK) != 0) {
|
||||
FLASH_KEYR = FLASH_KEY1;
|
||||
|
|
@ -140,7 +141,7 @@ void RAMFUNCTION hal_flash_unlock(void)
|
|||
|
||||
void RAMFUNCTION hal_flash_lock(void)
|
||||
{
|
||||
flash_wait_complete(0);
|
||||
hal_flash_wait_complete(0);
|
||||
#if (TZ_SECURE())
|
||||
if ((FLASH_CR & FLASH_CR_LOCK) == 0)
|
||||
FLASH_CR |= FLASH_CR_LOCK;
|
||||
|
|
@ -151,7 +152,7 @@ void RAMFUNCTION hal_flash_lock(void)
|
|||
|
||||
void RAMFUNCTION hal_flash_opt_unlock(void)
|
||||
{
|
||||
flash_wait_complete(0);
|
||||
hal_flash_wait_complete(0);
|
||||
|
||||
if ((FLASH_NS_CR & FLASH_CR_OPTLOCK) != 0) {
|
||||
FLASH_NS_OPTKEYR = FLASH_OPTKEY1;
|
||||
|
|
@ -167,7 +168,7 @@ void RAMFUNCTION hal_flash_opt_lock(void)
|
|||
{
|
||||
|
||||
FLASH_NS_CR |= FLASH_CR_OPTSTRT;
|
||||
flash_wait_complete(0);
|
||||
hal_flash_wait_complete(0);
|
||||
FLASH_NS_CR |= FLASH_CR_OBL_LAUNCH;
|
||||
if ((FLASH_NS_CR & FLASH_CR_OPTLOCK) == 0)
|
||||
FLASH_NS_CR |= FLASH_CR_OPTLOCK;
|
||||
|
|
@ -179,7 +180,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
|
|||
uint32_t p;
|
||||
volatile uint32_t *cr = &FLASH_NS_CR;
|
||||
|
||||
flash_clear_errors(0);
|
||||
hal_flash_clear_errors(0);
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -219,7 +220,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
|
|||
*cr = reg;
|
||||
DMB();
|
||||
*cr |= FLASH_CR_STRT;
|
||||
flash_wait_complete(0);
|
||||
hal_flash_wait_complete(0);
|
||||
}
|
||||
/* If the erase operation is completed, disable the associated bits */
|
||||
*cr &= ~FLASH_CR_PER ;
|
||||
|
|
@ -500,6 +501,8 @@ static void led_unsecure()
|
|||
#define TZSC1_BASE 0x50032400u
|
||||
#define TZSC_SECCFGR1 (*(volatile uint32_t *)(TZSC1_BASE + 0x10u))
|
||||
#define TZSC_SECCFGR1_USART3SEC (1u << 10)
|
||||
#define TZSC_SECCFGR2 (*(volatile uint32_t *)(TZSC1_BASE + 0x14u))
|
||||
#define TZSC_SECCFGR2_USART1SEC (1u << 3)
|
||||
|
||||
static void periph_unsecure(void)
|
||||
{
|
||||
|
|
@ -522,6 +525,24 @@ static void periph_unsecure(void)
|
|||
DMB();
|
||||
TZSC_SECCFGR1 = reg;
|
||||
}
|
||||
|
||||
/* Enable clock for GPIO A (USART1 pins PA9/PA10) */
|
||||
RCC_AHB2ENR1_CLOCK_ER |= GPIOA_AHB2ENR1_CLOCK_ER;
|
||||
|
||||
/* Enable clock for USART1 */
|
||||
RCC_APB2ENR |= UART1_APB2_CLOCK_ER_VAL;
|
||||
|
||||
/* Unsecure USART1 pins (PA9 TX, PA10 RX) */
|
||||
GPIOA_SECCFGR &= ~(1u << UART1_TX_PIN);
|
||||
GPIOA_SECCFGR &= ~(1u << UART1_RX_PIN);
|
||||
|
||||
/* Unsecure USART1 peripheral in GTZC TZSC */
|
||||
reg = TZSC_SECCFGR2;
|
||||
if (reg & TZSC_SECCFGR2_USART1SEC) {
|
||||
reg &= ~TZSC_SECCFGR2_USART1SEC;
|
||||
DMB();
|
||||
TZSC_SECCFGR2 = reg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -554,6 +575,12 @@ void hal_init(void)
|
|||
fork_bootloader();
|
||||
#endif
|
||||
clock_pll_on(0);
|
||||
|
||||
#ifdef DEBUG_UART
|
||||
uart_init(115200, 8, 'N', 1);
|
||||
uart_write("wolfBoot Init\n", 14);
|
||||
#endif
|
||||
|
||||
#if TZ_SECURE()
|
||||
hal_tz_sau_init();
|
||||
hal_gtzc_init();
|
||||
|
|
|
|||
|
|
@ -277,6 +277,68 @@
|
|||
|
||||
#define RCC_AHB2_CLOCK_ER RCC_AHB2ENR1_CLOCK_ER
|
||||
|
||||
/* UART */
|
||||
#if (TZ_SECURE())
|
||||
#define UART1 (0x50013800) /* USART1 - RM0456 - Table 4 */
|
||||
#define GPIOA_BASE (0x52020000)
|
||||
#else
|
||||
#define UART1 (0x40013800) /* USART1 - RM0456 - Table 4 */
|
||||
#define GPIOA_BASE (0x42020000)
|
||||
#endif
|
||||
|
||||
#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_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_PRE(base) (*(volatile uint32_t *)((base) + 0x2C))
|
||||
|
||||
#define UART_CR1_UART_ENABLE (1 << 0)
|
||||
#define UART_CR1_OVER8 (1 << 15)
|
||||
#define UART_CR1_SYMBOL_LEN (1 << 12)
|
||||
#define UART_CR1_PARITY_ENABLED (1 << 10)
|
||||
#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_TX_COMPLETE (1 << 6)
|
||||
#define UART_ISR_RX_NOTEMPTY (1 << 5)
|
||||
#define UART_EPE (1 << 0) /* Parity error */
|
||||
#define UART_EFE (1 << 1) /* Framing error */
|
||||
#define UART_ENE (1 << 2) /* Noise error */
|
||||
#define UART_ORE (1 << 3) /* Overrun error */
|
||||
|
||||
#define UART1_APB2_CLOCK_ER_VAL (1 << 14) /* RM0456 - RCC_APB2ENR - USART1EN */
|
||||
#define RCC_APB2ENR (*(volatile uint32_t *)(RCC_BASE + 0xA4)) /* RM0456 - Table 108 */
|
||||
|
||||
#define RCC_CCIPR1 (*(volatile uint32_t *)(RCC_BASE + 0xE0)) /* RM0456 - 11.8.46 */
|
||||
#define RCC_CCIPR1_USART1SEL_SHIFT (0)
|
||||
#define RCC_CCIPR1_USART1SEL_MASK (0x3)
|
||||
#define RCC_CCIPR1_USART1SEL_HSI16 (0x2)
|
||||
|
||||
#define HSI16_FREQ (16000000)
|
||||
|
||||
/* USART1 pin configuration: PA9 (TX) / PA10 (RX), AF7.
|
||||
* Connected to the ST-LINK VCP on Nucleo-U575ZI-Q. */
|
||||
#define UART1_PIN_AF 7
|
||||
#define UART1_TX_PIN 9
|
||||
#define UART1_RX_PIN 10
|
||||
|
||||
#define GPIOA_AHB2ENR1_CLOCK_ER (1 << 0)
|
||||
#define GPIOA_MODE (*(volatile uint32_t *)(GPIOA_BASE + 0x00))
|
||||
#define GPIOA_AFL (*(volatile uint32_t *)(GPIOA_BASE + 0x20))
|
||||
#define GPIOA_AFH (*(volatile uint32_t *)(GPIOA_BASE + 0x24))
|
||||
#define GPIOA_SECCFGR (*(volatile uint32_t *)(GPIOA_BASE + 0x30))
|
||||
|
||||
/* Reset */
|
||||
#define OPTR_SWAP_BANK (1 << 20)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
/* uart_drv_stm32u5.c
|
||||
*
|
||||
* Driver for the back-end of the UART_FLASH module.
|
||||
*
|
||||
* Example implementation for stm32U5
|
||||
* using USART1 (PA9/PA10, ST-LINK VCP on B-U585I-IOT02A).
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2026 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 3 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
|
||||
*/
|
||||
|
||||
#ifdef TARGET_stm32u5
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hal/stm32u5.h"
|
||||
|
||||
static void uart_pins_setup(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
RCC_AHB2ENR1_CLOCK_ER |= GPIOA_AHB2ENR1_CLOCK_ER;
|
||||
/* Set mode = AF */
|
||||
reg = GPIOA_MODE & ~(0x03 << (UART1_RX_PIN * 2));
|
||||
GPIOA_MODE = reg | (2 << (UART1_RX_PIN * 2));
|
||||
reg = GPIOA_MODE & ~(0x03 << (UART1_TX_PIN * 2));
|
||||
GPIOA_MODE = reg | (2 << (UART1_TX_PIN * 2));
|
||||
|
||||
/* Alternate function: use hi pins (9 and 10) */
|
||||
reg = GPIOA_AFH & ~(0xf << ((UART1_TX_PIN - 8) * 4));
|
||||
GPIOA_AFH = reg | (UART1_PIN_AF << ((UART1_TX_PIN - 8) * 4));
|
||||
reg = GPIOA_AFH & ~(0xf << ((UART1_RX_PIN - 8) * 4));
|
||||
GPIOA_AFH = reg | (UART1_PIN_AF << ((UART1_RX_PIN - 8) * 4));
|
||||
}
|
||||
|
||||
static void uart_clear_errors(uint32_t base)
|
||||
{
|
||||
UART_ICR(base) = UART_ISR(base) & (UART_ENE | UART_EPE | UART_ORE | UART_EFE);
|
||||
}
|
||||
|
||||
int uart_tx(const uint8_t c)
|
||||
{
|
||||
volatile uint32_t reg;
|
||||
do {
|
||||
reg = UART_ISR(UART1);
|
||||
if (reg & (UART_ENE | UART_EPE | UART_ORE | UART_EFE))
|
||||
uart_clear_errors(UART1);
|
||||
} while ((reg & UART_ISR_TX_EMPTY) == 0);
|
||||
UART_TDR(UART1) = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uart_rx(uint8_t *c)
|
||||
{
|
||||
volatile uint32_t reg;
|
||||
reg = UART_ISR(UART1);
|
||||
if (reg & (UART_ENE | UART_EPE | UART_ORE | UART_EFE))
|
||||
uart_clear_errors(UART1);
|
||||
if (reg & UART_ISR_RX_NOTEMPTY) {
|
||||
*c = (uint8_t)UART_RDR(UART1);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_init(uint32_t bitrate, uint8_t data, char parity, uint8_t stop)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Enable USART1 peripheral clock */
|
||||
RCC_APB2ENR |= UART1_APB2_CLOCK_ER_VAL;
|
||||
|
||||
/* If the UART is already running (e.g. left enabled by the secure
|
||||
* bootloader), let the last frame finish shifting out before
|
||||
* reconfiguring, or the character is cut mid-frame */
|
||||
if (UART_CR1(UART1) & UART_CR1_UART_ENABLE) {
|
||||
while ((UART_ISR(UART1) & UART_ISR_TX_COMPLETE) == 0) {};
|
||||
}
|
||||
|
||||
uart_pins_setup();
|
||||
|
||||
/* Use HSI16 as USART1 kernel clock, so the baud rate does not
|
||||
* depend on the current SYSCLK/PLL configuration */
|
||||
RCC_CR |= RCC_CR_HSION;
|
||||
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
|
||||
reg = RCC_CCIPR1 & (~(RCC_CCIPR1_USART1SEL_MASK << RCC_CCIPR1_USART1SEL_SHIFT));
|
||||
RCC_CCIPR1 = reg | (RCC_CCIPR1_USART1SEL_HSI16 << RCC_CCIPR1_USART1SEL_SHIFT);
|
||||
|
||||
/* Disable UART to configure BRR (only writable while disabled) */
|
||||
UART_CR1(UART1) &= ~UART_CR1_UART_ENABLE;
|
||||
|
||||
/* Enable 16-bit oversampling */
|
||||
UART_CR1(UART1) &= ~UART_CR1_OVER8;
|
||||
|
||||
/* Configure baud rate */
|
||||
UART_BRR(UART1) = (uint16_t)(HSI16_FREQ / bitrate);
|
||||
|
||||
/* Configure data bits */
|
||||
if (data == 8)
|
||||
UART_CR1(UART1) &= ~UART_CR1_SYMBOL_LEN;
|
||||
else
|
||||
UART_CR1(UART1) |= UART_CR1_SYMBOL_LEN;
|
||||
|
||||
/* Configure parity */
|
||||
switch (parity) {
|
||||
case 'O':
|
||||
UART_CR1(UART1) |= UART_CR1_PARITY_ODD;
|
||||
/* fall through to enable parity */
|
||||
/* FALL THROUGH */
|
||||
case 'E':
|
||||
UART_CR1(UART1) |= UART_CR1_PARITY_ENABLED;
|
||||
break;
|
||||
default:
|
||||
UART_CR1(UART1) &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD);
|
||||
}
|
||||
/* Set stop bits */
|
||||
reg = UART_CR2(UART1) & ~UART_CR2_STOPBITS;
|
||||
if (stop > 1)
|
||||
UART_CR2(UART1) = reg | (2 << 12);
|
||||
else
|
||||
UART_CR2(UART1) = reg;
|
||||
|
||||
/* Clear flags for async mode */
|
||||
UART_CR2(UART1) &= ~(UART_CR2_LINEN | UART_CR2_CLKEN);
|
||||
UART_CR3(UART1) &= ~(UART_CR3_SCEN | UART_CR3_HDSEL | UART_CR3_IREN);
|
||||
|
||||
/* Configure for RX+TX, turn on. */
|
||||
UART_CR1(UART1) |= UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE | UART_CR1_UART_ENABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UART
|
||||
void uart_write(const char *buf, unsigned int len)
|
||||
{
|
||||
while (len--) {
|
||||
uart_tx(*buf);
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TARGET_stm32u5 */
|
||||
|
|
@ -654,6 +654,9 @@ ifeq ($(TARGET),stm32u5)
|
|||
endif
|
||||
CFLAGS+=-mcpu=cortex-m33
|
||||
LDFLAGS+=-mcpu=cortex-m33
|
||||
ifeq ($(DEBUG_UART),1)
|
||||
APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET)_ns.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),stm32u3)
|
||||
|
|
@ -1382,6 +1385,9 @@ delta-extra-data: image.bin
|
|||
../hal/spi/spi_drv_$(SPI_TARGET)_ns.o: ../hal/spi/spi_drv_$(SPI_TARGET).c FORCE
|
||||
$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/spi/spi_drv_$(SPI_TARGET).c -DNONSECURE_APP
|
||||
|
||||
../hal/uart/uart_drv_$(UART_TARGET)_ns.o: ../hal/uart/uart_drv_$(UART_TARGET).c FORCE
|
||||
$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/uart/uart_drv_$(UART_TARGET).c -DNONSECURE_APP
|
||||
|
||||
board_$(BOARD).o: ../hal/boards/$(BOARD)/board.c
|
||||
@echo "\t[CC-$(ARCH)] $@"
|
||||
$(Q)$(CC) $(CFLAGS) -DDEBUG_UART -c $(OUTPUT_FLAG) $@ $<
|
||||
|
|
|
|||
Loading…
Reference in New Issue