Skip to content

Commit ee07cad

Browse files
committed
Add support for nucleo l4r5
Signed-off-by: Duc Tri Nguyen <[email protected]> format Signed-off-by: Duc Tri Nguyen <[email protected]> revert the changes to libopencm3
1 parent 2968023 commit ee07cad

File tree

6 files changed

+130
-1
lines changed

6 files changed

+130
-1
lines changed

flake.nix

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
arm-pkgs = builtins.attrValues {
5353
libopencm3 = pkgs.callPackage ./libopencm3.nix {
54-
targets = [ "stm32/f2" "stm32/f4" "stm32/f7" ];
54+
targets = [ "stm32/f2" "stm32/f4" "stm32/f7" "stm32/l4" ];
5555
};
5656

5757
mbed-os = pkgs.callPackage ./mbed-os.nix {

hal/devices.data

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ stm32f407vg stm32f4 ROM=1024K RAM=128K
33
stm32f4 END ROM_OFF=0x08000000 RAM_OFF=0x20000000 CPU=cortex-m4 FPU=hard-fpv4-sp-d16
44
stm32f767zi stm32f7 ROM=2048K RAM=384K
55
stm32f7 END ROM_OFF=0x08000000 RAM_OFF=0x20010000 CPU=cortex-m7 FPU=hard-fpv5-sp-d16
6+
7+
# Device otherwise missing from OpenCM3
8+
stm32l4r5zi stm32l4 ROM=2048K RAM=256K RAM3=384K
9+
stm32l4 END ROM_OFF=0x08000000 RAM_OFF=0x20000000 RAM2_OFF=0x10000000 RAM3_OFF=0x20040000 CPU=cortex-m4 FPU=hard-fpv4-sp-d16

hal/hal-opencm3.c

+104
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ const struct rcc_clock_scale benchmarkclock = {
5555
#define SERIAL_PINS (GPIO8 | GPIO9)
5656
#define STM32
5757

58+
#elif defined(STM32L4R5ZI)
59+
#include <libopencm3/stm32/rcc.h>
60+
#include <libopencm3/stm32/gpio.h>
61+
#include <libopencm3/stm32/usart.h>
62+
#include <libopencm3/stm32/flash.h>
63+
#include <libopencm3/stm32/rng.h>
64+
#include <libopencm3/stm32/pwr.h>
65+
66+
#define SERIAL_GPIO GPIOG
67+
#define SERIAL_USART LPUART1
68+
#define SERIAL_PINS (GPIO8 | GPIO7)
69+
#define NUCLEO_L4R5_BOARD
70+
71+
/* Patched function for newer PLL not yet supported by opencm3 */
72+
void _rcc_set_main_pll(uint32_t source, uint32_t pllm, uint32_t plln, uint32_t pllp,
73+
uint32_t pllq, uint32_t pllr) {
74+
RCC_PLLCFGR = (RCC_PLLCFGR_PLLM(pllm) << RCC_PLLCFGR_PLLM_SHIFT) |
75+
(plln << RCC_PLLCFGR_PLLN_SHIFT) |
76+
((pllp & 0x1Fu) << 27u) | /* NEWER PLLP */
77+
(source << RCC_PLLCFGR_PLLSRC_SHIFT) |
78+
(pllq << RCC_PLLCFGR_PLLQ_SHIFT) |
79+
(pllr << RCC_PLLCFGR_PLLR_SHIFT) | RCC_PLLCFGR_PLLREN;
80+
}
81+
5882
#else
5983
#error Unsupported libopencm3 board
6084
#endif
@@ -156,6 +180,69 @@ static void clock_setup(enum clock_mode clock) {
156180
# else
157181
# error Unsupported STM32F2 Board
158182
# endif
183+
#elif defined(NUCLEO_L4R5_BOARD)
184+
rcc_periph_clock_enable(RCC_PWR);
185+
rcc_periph_clock_enable(RCC_SYSCFG);
186+
pwr_set_vos_scale(PWR_SCALE1);
187+
/* The L4R5ZI chip also needs the R1MODE bit in PWR_CR5 register set, but
188+
OpenCM3 doesn't support this yet. But luckily the default value for the bit
189+
is 1. */
190+
switch (clock) {
191+
case CLOCK_BENCHMARK:
192+
/* Benchmark straight from the HSI16 without prescaling */
193+
rcc_osc_on(RCC_HSI16);
194+
rcc_wait_for_osc_ready(RCC_HSI16);
195+
rcc_ahb_frequency = 20000000;
196+
rcc_apb1_frequency = 20000000;
197+
rcc_apb2_frequency = 20000000;
198+
_clock_freq = 20000000;
199+
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
200+
rcc_set_ppre1(RCC_CFGR_PPRE_NODIV);
201+
rcc_set_ppre2(RCC_CFGR_PPRE_NODIV);
202+
rcc_osc_off(RCC_PLL);
203+
while (rcc_is_osc_ready(RCC_PLL));
204+
/* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 20MHz). */
205+
_rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 10, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV8);
206+
/* Enable PLL oscillator and wait for it to stabilize. */
207+
rcc_osc_on(RCC_PLL);
208+
flash_dcache_enable();
209+
flash_icache_enable();
210+
flash_set_ws(FLASH_ACR_LATENCY_0WS);
211+
flash_prefetch_enable();
212+
rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
213+
rcc_wait_for_sysclk_status(RCC_PLL);
214+
break;
215+
case CLOCK_FAST:
216+
default:
217+
rcc_osc_on(RCC_HSI16);
218+
rcc_wait_for_osc_ready(RCC_HSI16);
219+
rcc_ahb_frequency = 120000000;
220+
rcc_apb1_frequency = 120000000;
221+
rcc_apb2_frequency = 120000000;
222+
_clock_freq = 120000000;
223+
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
224+
rcc_set_ppre1(RCC_CFGR_PPRE_NODIV);
225+
rcc_set_ppre2(RCC_CFGR_PPRE_NODIV);
226+
rcc_osc_off(RCC_PLL);
227+
while (rcc_is_osc_ready(RCC_PLL));
228+
/* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 120MHz). */
229+
_rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 15, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV2);
230+
/* Enable PLL oscillator and wait for it to stabilize. */
231+
rcc_osc_on(RCC_PLL);
232+
rcc_wait_for_osc_ready(RCC_PLL);
233+
flash_dcache_enable();
234+
flash_icache_enable();
235+
flash_set_ws(0x05);
236+
flash_prefetch_enable();
237+
rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
238+
rcc_wait_for_sysclk_status(RCC_PLL);
239+
break;
240+
}
241+
rcc_osc_on(RCC_HSI48); /* HSI48 must always be on for RNG */
242+
rcc_wait_for_osc_ready(RCC_HSI48);
243+
rcc_periph_clock_enable(RCC_RNG);
244+
rcc_set_clock48_source(RCC_CCIPR_CLK48SEL_HSI48);
245+
rng_enable();
159246
#else
160247
#error Unsupported platform
161248
#endif
@@ -171,6 +258,23 @@ void usart_setup() {
171258
#elif defined(NUCLEO_BOARD)
172259
rcc_periph_clock_enable(RCC_GPIOA);
173260
rcc_periph_clock_enable(RCC_USART2);
261+
#elif defined(NUCLEO_L4R5_BOARD)
262+
rcc_periph_clock_enable(RCC_GPIOG);
263+
rcc_periph_clock_enable(RCC_LPUART1);
264+
265+
PWR_CR2 |= PWR_CR2_IOSV;
266+
gpio_set_output_options(SERIAL_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, SERIAL_PINS);
267+
gpio_set_af(SERIAL_GPIO, GPIO_AF8, SERIAL_PINS);
268+
gpio_mode_setup(SERIAL_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, SERIAL_PINS);
269+
usart_set_baudrate(SERIAL_USART, SERIAL_BAUD);
270+
usart_set_databits(SERIAL_USART, 8);
271+
usart_set_stopbits(SERIAL_USART, USART_STOPBITS_1);
272+
usart_set_mode(SERIAL_USART, USART_MODE_TX_RX);
273+
usart_set_parity(SERIAL_USART, USART_PARITY_NONE);
274+
usart_set_flow_control(SERIAL_USART, USART_FLOWCONTROL_NONE);
275+
usart_disable_rx_interrupt(SERIAL_USART);
276+
usart_disable_tx_interrupt(SERIAL_USART);
277+
usart_enable(SERIAL_USART);
174278
#else
175279
#error Unsupported platform
176280
#endif

hal/nucleo_l4r5.cfg

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# SPDX-License-Identifier: Apache-2.0 or CC0-1.0
2+
3+
# This is for STM32L4R5 Nucleo Dev Boards.
4+
source [find interface/stlink-dap.cfg]
5+
6+
transport select dapdirect_swd
7+
8+
source [find target/stm32l4x.cfg]
9+
10+
# use hardware reset (srst seems to be problematic)
11+
reset_config trst_only

mk/nucleo-l4r5zi.mk

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-License-Identifier: Apache-2.0 or CC0-1.0
2+
DEVICE=stm32l4r5zi
3+
OPENCM3_TARGET=lib/stm32/l4
4+
override DEVICES_DATA := hal/devices.data
5+
6+
include mk/opencm3.mk

scripts/tests

+4
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class PLATFORM(Enum):
116116
MPS2_AN500 = 4
117117
NUCLEO_F207ZG = 5
118118
MPS2_AN385 = 6
119+
NUCLEO_L4R5ZI = 7
119120

120121
def __str__(self):
121122
return self.name.lower().replace("_", "-")
@@ -153,6 +154,9 @@ platform_map = RecursiveNamespace(
153154
f"{PLATFORM.MPS2_AN386}": {},
154155
f"{PLATFORM.MPS2_AN385}": {},
155156
f"{PLATFORM.MPS2_AN500}": {},
157+
f"{PLATFORM.NUCLEO_L4R5ZI}": {
158+
"openocd_cfg": f"{ROOT}/hal/nucleo_l4r5.cfg",
159+
},
156160
}
157161
)
158162

0 commit comments

Comments
 (0)