Skip to content

Commit c3fe366

Browse files
committed
add support for nucleo l4r5
Signed-off-by: Duc Tri Nguyen <[email protected]>
1 parent 2968023 commit c3fe366

File tree

7 files changed

+142
-4
lines changed

7 files changed

+142
-4
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

+105
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,31 @@ 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+
{
75+
RCC_PLLCFGR = (RCC_PLLCFGR_PLLM(pllm) << RCC_PLLCFGR_PLLM_SHIFT) |
76+
(plln << RCC_PLLCFGR_PLLN_SHIFT) |
77+
((pllp & 0x1Fu) << 27u) | /* NEWER PLLP */
78+
(source << RCC_PLLCFGR_PLLSRC_SHIFT) |
79+
(pllq << RCC_PLLCFGR_PLLQ_SHIFT) |
80+
(pllr << RCC_PLLCFGR_PLLR_SHIFT) | RCC_PLLCFGR_PLLREN;
81+
}
82+
5883
#else
5984
#error Unsupported libopencm3 board
6085
#endif
@@ -156,6 +181,69 @@ static void clock_setup(enum clock_mode clock) {
156181
# else
157182
# error Unsupported STM32F2 Board
158183
# endif
184+
#elif defined(NUCLEO_L4R5_BOARD)
185+
rcc_periph_clock_enable(RCC_PWR);
186+
rcc_periph_clock_enable(RCC_SYSCFG);
187+
pwr_set_vos_scale(PWR_SCALE1);
188+
/* The L4R5ZI chip also needs the R1MODE bit in PWR_CR5 register set, but
189+
OpenCM3 doesn't support this yet. But luckily the default value for the bit
190+
is 1. */
191+
switch (clock) {
192+
case CLOCK_BENCHMARK:
193+
/* Benchmark straight from the HSI16 without prescaling */
194+
rcc_osc_on(RCC_HSI16);
195+
rcc_wait_for_osc_ready(RCC_HSI16);
196+
rcc_ahb_frequency = 20000000;
197+
rcc_apb1_frequency = 20000000;
198+
rcc_apb2_frequency = 20000000;
199+
_clock_freq = 20000000;
200+
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
201+
rcc_set_ppre1(RCC_CFGR_PPRE_NODIV);
202+
rcc_set_ppre2(RCC_CFGR_PPRE_NODIV);
203+
rcc_osc_off(RCC_PLL);
204+
while(rcc_is_osc_ready(RCC_PLL));
205+
/* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 20MHz). */
206+
_rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 10, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV8);
207+
/* Enable PLL oscillator and wait for it to stabilize. */
208+
rcc_osc_on(RCC_PLL);
209+
flash_dcache_enable();
210+
flash_icache_enable();
211+
flash_set_ws(FLASH_ACR_LATENCY_0WS);
212+
flash_prefetch_enable();
213+
rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
214+
rcc_wait_for_sysclk_status(RCC_PLL);
215+
break;
216+
case CLOCK_FAST:
217+
default:
218+
rcc_osc_on(RCC_HSI16);
219+
rcc_wait_for_osc_ready(RCC_HSI16);
220+
rcc_ahb_frequency = 120000000;
221+
rcc_apb1_frequency = 120000000;
222+
rcc_apb2_frequency = 120000000;
223+
_clock_freq = 120000000;
224+
rcc_set_hpre(RCC_CFGR_HPRE_NODIV);
225+
rcc_set_ppre1(RCC_CFGR_PPRE_NODIV);
226+
rcc_set_ppre2(RCC_CFGR_PPRE_NODIV);
227+
rcc_osc_off(RCC_PLL);
228+
while(rcc_is_osc_ready(RCC_PLL));
229+
/* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 120MHz). */
230+
_rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 15, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV2);
231+
/* Enable PLL oscillator and wait for it to stabilize. */
232+
rcc_osc_on(RCC_PLL);
233+
rcc_wait_for_osc_ready(RCC_PLL);
234+
flash_dcache_enable();
235+
flash_icache_enable();
236+
flash_set_ws(0x05);
237+
flash_prefetch_enable();
238+
rcc_set_sysclk_source(RCC_CFGR_SW_PLL);
239+
rcc_wait_for_sysclk_status(RCC_PLL);
240+
break;
241+
}
242+
rcc_osc_on(RCC_HSI48); /* HSI48 must always be on for RNG */
243+
rcc_wait_for_osc_ready(RCC_HSI48);
244+
rcc_periph_clock_enable(RCC_RNG);
245+
rcc_set_clock48_source(RCC_CCIPR_CLK48SEL_HSI48);
246+
rng_enable();
159247
#else
160248
#error Unsupported platform
161249
#endif
@@ -171,6 +259,23 @@ void usart_setup() {
171259
#elif defined(NUCLEO_BOARD)
172260
rcc_periph_clock_enable(RCC_GPIOA);
173261
rcc_periph_clock_enable(RCC_USART2);
262+
#elif defined(NUCLEO_L4R5_BOARD)
263+
rcc_periph_clock_enable(RCC_GPIOG);
264+
rcc_periph_clock_enable(RCC_LPUART1);
265+
266+
PWR_CR2 |= PWR_CR2_IOSV;
267+
gpio_set_output_options(SERIAL_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, SERIAL_PINS);
268+
gpio_set_af(SERIAL_GPIO, GPIO_AF8, SERIAL_PINS);
269+
gpio_mode_setup(SERIAL_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, SERIAL_PINS);
270+
usart_set_baudrate(SERIAL_USART, SERIAL_BAUD);
271+
usart_set_databits(SERIAL_USART, 8);
272+
usart_set_stopbits(SERIAL_USART, USART_STOPBITS_1);
273+
usart_set_mode(SERIAL_USART, USART_MODE_TX_RX);
274+
usart_set_parity(SERIAL_USART, USART_PARITY_NONE);
275+
usart_set_flow_control(SERIAL_USART, USART_FLOWCONTROL_NONE);
276+
usart_disable_rx_interrupt(SERIAL_USART);
277+
usart_disable_tx_interrupt(SERIAL_USART);
278+
usart_enable(SERIAL_USART);
174279
#else
175280
#error Unsupported platform
176281
#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

libopencm3.nix

+10-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111

1212
stdenvNoCC.mkDerivation rec {
1313
pname = "libopencm3";
14-
version = "ec5aeba354ec273782e4441440fe9000b1c965e3";
14+
version = "228f28fa66b672535663aa9aa4d12ede8b1a8fc5";
1515
src = fetchFromGitHub {
1616
owner = "libopencm3";
1717
repo = pname;
18-
rev = "ec5aeba354ec273782e4441440fe9000b1c965e3";
19-
sha256 = "sha256-bgoMhOhBJZwPTa9gUH0vPSGZknDrb2mJZuFlCWNivYU=";
18+
rev = "228f28fa66b672535663aa9aa4d12ede8b1a8fc5";
19+
sha256 = "sha256-eqjOtvH+FwRaWqVSxUyK/gXtveEipLsyjd4jLzXbzbw=";
2020
};
2121
setupHook = writeText "setup-hook.sh" ''
2222
export OPENCM3_DIR="$1"
@@ -25,8 +25,15 @@ stdenvNoCC.mkDerivation rec {
2525
python311
2626
gcc-arm-embedded-13 # arm-gnu-toolchain-13.2.rel1
2727
];
28+
devicesPatch = writeText "devices-patch.txt" ''
29+
# Device otherwise missing from OpenCM3
30+
stm32l4r5zi stm32l4 ROM=2048K RAM=256K RAM3=384K
31+
'';
2832
postPatch = ''
2933
patchShebangs --build scripts/irq2nvic_h
34+
35+
# Apply the patch to devices.data
36+
cat ${devicesPatch} >> ld/devices.data
3037
'';
3138
dontConfigure = true;
3239
buildPhase = ''

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

+5
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,10 @@ 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+
},
160+
156161
}
157162
)
158163

0 commit comments

Comments
 (0)