Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Nucleo l4r5 #55

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions hal/devices.data
Original file line number Diff line number Diff line change
Expand Up @@ -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
104 changes: 104 additions & 0 deletions hal/hal-opencm3.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ const struct rcc_clock_scale benchmarkclock = {
#define SERIAL_PINS (GPIO8 | GPIO9)
#define STM32

#elif defined(STM32L4R5ZI)
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/flash.h>
#include <libopencm3/stm32/rng.h>
#include <libopencm3/stm32/pwr.h>

#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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
11 changes: 11 additions & 0 deletions hal/nucleo_l4r5.cfg
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions mk/nucleo-l4r5zi.mk
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions scripts/tests
Original file line number Diff line number Diff line change
Expand Up @@ -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("_", "-")
Expand Down Expand Up @@ -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",
},
}
)

Expand Down