diff --git a/flake.nix b/flake.nix index 0005eab..568afeb 100644 --- a/flake.nix +++ b/flake.nix @@ -51,7 +51,7 @@ arm-pkgs = builtins.attrValues { libopencm3 = pkgs.callPackage ./libopencm3.nix { - targets = [ "stm32/f2" "stm32/f4" "stm32/f7" ]; + targets = [ "stm32/f2" "stm32/f4" "stm32/f7" "stm32/l4" ]; }; mbed-os = pkgs.callPackage ./mbed-os.nix { diff --git a/hal/devices.data b/hal/devices.data index b051f2f..301a150 100644 --- a/hal/devices.data +++ b/hal/devices.data @@ -3,3 +3,7 @@ stm32f407vg stm32f4 ROM=1024K RAM=128K stm32f4 END ROM_OFF=0x08000000 RAM_OFF=0x20000000 CPU=cortex-m4 FPU=hard-fpv4-sp-d16 stm32f767zi stm32f7 ROM=2048K RAM=384K stm32f7 END ROM_OFF=0x08000000 RAM_OFF=0x20010000 CPU=cortex-m7 FPU=hard-fpv5-sp-d16 + +# Device otherwise missing from OpenCM3 +stm32l4r5zi stm32l4 ROM=2048K RAM=256K RAM3=384K +stm32l4 END ROM_OFF=0x08000000 RAM_OFF=0x20000000 RAM2_OFF=0x10000000 RAM3_OFF=0x20040000 CPU=cortex-m4 FPU=hard-fpv4-sp-d16 diff --git a/hal/hal-opencm3.c b/hal/hal-opencm3.c index bdc92eb..c908249 100644 --- a/hal/hal-opencm3.c +++ b/hal/hal-opencm3.c @@ -55,6 +55,30 @@ const struct rcc_clock_scale benchmarkclock = { #define SERIAL_PINS (GPIO8 | GPIO9) #define STM32 +#elif defined(STM32L4R5ZI) +#include +#include +#include +#include +#include +#include + +#define SERIAL_GPIO GPIOG +#define SERIAL_USART LPUART1 +#define SERIAL_PINS (GPIO8 | GPIO7) +#define NUCLEO_L4R5_BOARD + +/* Patched function for newer PLL not yet supported by opencm3 */ +void _rcc_set_main_pll(uint32_t source, uint32_t pllm, uint32_t plln, uint32_t pllp, + uint32_t pllq, uint32_t pllr) { + RCC_PLLCFGR = (RCC_PLLCFGR_PLLM(pllm) << RCC_PLLCFGR_PLLM_SHIFT) | + (plln << RCC_PLLCFGR_PLLN_SHIFT) | + ((pllp & 0x1Fu) << 27u) | /* NEWER PLLP */ + (source << RCC_PLLCFGR_PLLSRC_SHIFT) | + (pllq << RCC_PLLCFGR_PLLQ_SHIFT) | + (pllr << RCC_PLLCFGR_PLLR_SHIFT) | RCC_PLLCFGR_PLLREN; +} + #else #error Unsupported libopencm3 board #endif @@ -156,6 +180,69 @@ static void clock_setup(enum clock_mode clock) { # else # error Unsupported STM32F2 Board # endif + #elif defined(NUCLEO_L4R5_BOARD) + rcc_periph_clock_enable(RCC_PWR); + rcc_periph_clock_enable(RCC_SYSCFG); + pwr_set_vos_scale(PWR_SCALE1); + /* The L4R5ZI chip also needs the R1MODE bit in PWR_CR5 register set, but + OpenCM3 doesn't support this yet. But luckily the default value for the bit + is 1. */ + switch (clock) { + case CLOCK_BENCHMARK: + /* Benchmark straight from the HSI16 without prescaling */ + rcc_osc_on(RCC_HSI16); + rcc_wait_for_osc_ready(RCC_HSI16); + rcc_ahb_frequency = 20000000; + rcc_apb1_frequency = 20000000; + rcc_apb2_frequency = 20000000; + _clock_freq = 20000000; + rcc_set_hpre(RCC_CFGR_HPRE_NODIV); + rcc_set_ppre1(RCC_CFGR_PPRE_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE_NODIV); + rcc_osc_off(RCC_PLL); + while (rcc_is_osc_ready(RCC_PLL)); + /* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 20MHz). */ + _rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 10, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV8); + /* Enable PLL oscillator and wait for it to stabilize. */ + rcc_osc_on(RCC_PLL); + flash_dcache_enable(); + flash_icache_enable(); + flash_set_ws(FLASH_ACR_LATENCY_0WS); + flash_prefetch_enable(); + rcc_set_sysclk_source(RCC_CFGR_SW_PLL); + rcc_wait_for_sysclk_status(RCC_PLL); + break; + case CLOCK_FAST: + default: + rcc_osc_on(RCC_HSI16); + rcc_wait_for_osc_ready(RCC_HSI16); + rcc_ahb_frequency = 120000000; + rcc_apb1_frequency = 120000000; + rcc_apb2_frequency = 120000000; + _clock_freq = 120000000; + rcc_set_hpre(RCC_CFGR_HPRE_NODIV); + rcc_set_ppre1(RCC_CFGR_PPRE_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE_NODIV); + rcc_osc_off(RCC_PLL); + while (rcc_is_osc_ready(RCC_PLL)); + /* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 120MHz). */ + _rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 15, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV2); + /* Enable PLL oscillator and wait for it to stabilize. */ + rcc_osc_on(RCC_PLL); + rcc_wait_for_osc_ready(RCC_PLL); + flash_dcache_enable(); + flash_icache_enable(); + flash_set_ws(0x05); + flash_prefetch_enable(); + rcc_set_sysclk_source(RCC_CFGR_SW_PLL); + rcc_wait_for_sysclk_status(RCC_PLL); + break; + } + rcc_osc_on(RCC_HSI48); /* HSI48 must always be on for RNG */ + rcc_wait_for_osc_ready(RCC_HSI48); + rcc_periph_clock_enable(RCC_RNG); + rcc_set_clock48_source(RCC_CCIPR_CLK48SEL_HSI48); + rng_enable(); #else #error Unsupported platform #endif @@ -171,6 +258,23 @@ void usart_setup() { #elif defined(NUCLEO_BOARD) rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_USART2); + #elif defined(NUCLEO_L4R5_BOARD) + rcc_periph_clock_enable(RCC_GPIOG); + rcc_periph_clock_enable(RCC_LPUART1); + + PWR_CR2 |= PWR_CR2_IOSV; + gpio_set_output_options(SERIAL_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, SERIAL_PINS); + gpio_set_af(SERIAL_GPIO, GPIO_AF8, SERIAL_PINS); + gpio_mode_setup(SERIAL_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, SERIAL_PINS); + usart_set_baudrate(SERIAL_USART, SERIAL_BAUD); + usart_set_databits(SERIAL_USART, 8); + usart_set_stopbits(SERIAL_USART, USART_STOPBITS_1); + usart_set_mode(SERIAL_USART, USART_MODE_TX_RX); + usart_set_parity(SERIAL_USART, USART_PARITY_NONE); + usart_set_flow_control(SERIAL_USART, USART_FLOWCONTROL_NONE); + usart_disable_rx_interrupt(SERIAL_USART); + usart_disable_tx_interrupt(SERIAL_USART); + usart_enable(SERIAL_USART); #else #error Unsupported platform #endif diff --git a/hal/nucleo_l4r5.cfg b/hal/nucleo_l4r5.cfg new file mode 100644 index 0000000..be4fffd --- /dev/null +++ b/hal/nucleo_l4r5.cfg @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 + +# This is for STM32L4R5 Nucleo Dev Boards. +source [find interface/stlink-dap.cfg] + +transport select dapdirect_swd + +source [find target/stm32l4x.cfg] + +# use hardware reset (srst seems to be problematic) +reset_config trst_only diff --git a/mk/nucleo-l4r5zi.mk b/mk/nucleo-l4r5zi.mk new file mode 100644 index 0000000..6202d7c --- /dev/null +++ b/mk/nucleo-l4r5zi.mk @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 +DEVICE=stm32l4r5zi +OPENCM3_TARGET=lib/stm32/l4 +override DEVICES_DATA := hal/devices.data + +include mk/opencm3.mk diff --git a/scripts/tests b/scripts/tests index cb84e52..38d9fd3 100755 --- a/scripts/tests +++ b/scripts/tests @@ -116,6 +116,7 @@ class PLATFORM(Enum): MPS2_AN500 = 4 NUCLEO_F207ZG = 5 MPS2_AN385 = 6 + NUCLEO_L4R5ZI = 7 def __str__(self): return self.name.lower().replace("_", "-") @@ -153,6 +154,9 @@ platform_map = RecursiveNamespace( f"{PLATFORM.MPS2_AN386}": {}, f"{PLATFORM.MPS2_AN385}": {}, f"{PLATFORM.MPS2_AN500}": {}, + f"{PLATFORM.NUCLEO_L4R5ZI}": { + "openocd_cfg": f"{ROOT}/hal/nucleo_l4r5.cfg", + }, } )