Skip to content

boards: Added board nucleo_u545re_q#4803

Open
FarhadGUL06 wants to merge 109 commits into
tock:masterfrom
OxidosAutomotive:board_nucleo_u545re_q
Open

boards: Added board nucleo_u545re_q#4803
FarhadGUL06 wants to merge 109 commits into
tock:masterfrom
OxidosAutomotive:board_nucleo_u545re_q

Conversation

@FarhadGUL06
Copy link
Copy Markdown

Pull Request Overview

This pull request adds support for the Nucleo-U545RE-Q board (STM32U545) to Tock OS. It introduces a new stm32u5xx chip crate designed for the ultra-low-power STM32U5 series, with a specific focus on Secure Mode operation and TrustZone compatibility.

Features implemented:

  • New Chip Crate (stm32u5xx): implementation of core peripherals (RCC, GPIO, EXTI, TIM, USART).
  • Async USART with DMA: Serial driver using GPDMA engine for background transmission (TX) and IRQs for reliable, low-latency reception (RX) via a 32-byte circular FIFO.
  • GPIO & EXTI: Fully asynchronous interrupt handling for board buttons and LED.
  • Alarm HIL: Implemented TIM2 as the timekeeper for both kernel and apps.
  • Multi-Process Support: Configured for up to 4 simultaneous userspace applications with 64KB+ of sandbox RAM. (Note: Currently tested with 1 app; further multi-app verification is pending tockloader integration).

Testing Strategy

This pull request was tested on a physical Nucleo-U545RE-Q hardware target.

  • Deployment: Deployment was performed using probe-rs and openocd.
  • Functionality:
    -- Verified kernel boot and console output at 115200 baud via USART1.
    -- Verified that the User Button (PC13) triggers asynchronous interrupts to toggle the User LED (PA5).
    -- Verified userspace delay_ms functionality using the TIM2-backed Alarm HIL.
    -- Validated the GPDMA1 configuration (Request ID 25) for stable background printing.

TODO or Help Wanted

This pull request still needs:

  • Tockloader Support: Investigating why the OpenOCD stm32u5x target configuration fails to identify the board automatically in WSL environments.
  • Multi-App Validation: Once tockloader is functional, perform stress tests with multiple concurrent processes to verify the 64KB sandbox allocation.
  • Extended Peripheral Support: Add more peripherals.

Documentation Updated

  • No updates required (Follows existing Tock architectural patterns).

Formatting

  • Ran make prepush.
  • Ran cargo fmt.

AI Use

  • The PR description details my use of AI in the production of the code in this PR. This port was developed with the assistance of an AI engineering agent (Gemini CLI). All generated code, register offsets, and memory maps were manually verified against the STM32U545 Reference Manual and validated on live hardware.

@github-actions github-actions Bot added the stm32 label Apr 22, 2026
Copy link
Copy Markdown
Contributor

@bradjc bradjc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good, just a couple notes about unsafe.

I'm not sure if it is now, but we really should start using tockloader local-board (if necessary) rather than make/objcopy manual fix ups. Using objcopy makes it nearly impossible to run more than one app. Ideally tockloader just works, but the local-board mechanism is basically just as seemless if there isn't a good way to do partial writes to a chip.

Comment thread boards/nucleo_u545re_q/Cargo.toml Outdated
Comment thread boards/nucleo_u545re_q/README.md Outdated
Comment on lines +45 to +50
## Flashing Notes

This board is flashed using **`probe-rs`** or **`openocd`**. Due to the specific
memory layout and metadata sections of the STM32U5, the Makefile surgically
extracts executable sections (stripping metadata like `.ARM.attributes`) before
flashing to prevent errors when writing to protected system memory addresses.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the binary file the make system builds not suitable? I would prefer to avoid have custom elf/obcopy logic per-board if we can avoid it. That would seem to suggest the linker script is wrong for this board if it is required, and perhaps we should fix the issue with the linker script so we can document exactly what the requirements are.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FarhadGUL06 do we have this problem on other boards? Those sections should not be loaded to the board, but I agree with @bradjc that we should rely on the ELF file and not do objcopy.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made some changes to tockloader and modified the current Makefile to be similar to the one for the nucleo_f429zi. I also tested installing two apps: a modified version of blink (which blinks the LED every 2 seconds but also toggles the LED when the user button is pressed) and c_hello.

Running "make flash" flashes only the kernel, and "tockloader install --openocd --board nucleo_u545re_q" loads the application from the current folder to the board. An application can also be loaded using "make program" (as explained in the README). Both applications work and can be seen as loaded by using "tockloader list --openocd --board nucleo_u545re_q".

Comment thread chips/stm32u5xx/src/exti.rs Outdated
Comment thread chips/stm32u5xx/src/gpio.rs Outdated
Comment thread chips/stm32u5xx/src/tim.rs Outdated
Comment thread chips/stm32u5xx/src/usart.rs
Comment thread chips/stm32u5xx/src/usart.rs Outdated
Comment thread chips/stm32u545/Cargo.toml Outdated
Comment thread chips/stm32u5xx/src/gpio.rs Outdated
Comment thread chips/stm32u5xx/src/exti.rs Outdated
Comment thread chips/stm32u5xx/src/gpio.rs Outdated
@alexandruradovici
Copy link
Copy Markdown
Contributor

Looks pretty good, just a couple notes about unsafe.

I'm not sure if it is now, but we really should start using tockloader local-board (if necessary) rather than make/objcopy manual fix ups. Using objcopy makes it nearly impossible to run more than one app. Ideally tockloader just works, but the local-board mechanism is basically just as seemless if there isn't a good way to do partial writes to a chip.

I think the flash layout should allow us to use tockloader, meaning it is split in pages of the same size. The manual's section 7.3.1 at page 292 says the flash is spilt up in two banks and has pages of 8KB and that the flash supports read-while-write. We would be able to use directly tockloader as long as we align the kernel and the apps to the 8K page size. I see three possible solutions:

  1. align the kernel and each app to the page size
  2. align the kernel to the page size and rewrite all apps always (tockloader has on option for this) while aligning all apps to the page size
  3. use the local-board and flash the whole flash to the board every time

if read-while-write does not work, we can flash the kernel to bank 0 and the apps to bank 1.

Comment thread chips/stm32u5xx/src/chip.rs Outdated
Comment thread chips/stm32u5xx/src/usart.rs
Comment thread chips/stm32u5xx/src/chip.rs
@FarhadGUL06 FarhadGUL06 requested a review from bradjc April 30, 2026 10:32
}
}

pub fn match_channel(&self, channel: ChannelId) -> Option<usize> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest implementing From<DmaChannel> for usize and that will allow the use of dam_channel.into().

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can delete this function and just use into.

Comment thread chips/stm32u5xx/src/dma.rs Outdated
Comment thread chips/stm32u5xx/src/dma.rs Outdated
Copy link
Copy Markdown
Contributor

@alexandruradovici alexandruradovici left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the tock-registers register fields for all the peripherals.

Copy link
Copy Markdown
Contributor

@alexandruradovici alexandruradovici left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the tock-registers register fields for all the peripherals.

@FarhadGUL06
Copy link
Copy Markdown
Author

Hi, @bradjc ! Could you please take a look at my latest commits when you have a moment? Thanks!

Comment thread chips/stm32u545/Cargo.toml Outdated
Comment thread chips/stm32u5xx/Cargo.toml Outdated
Comment thread boards/nucleo_u545re_q/src/main.rs Outdated
if let (Some(tx), Some(rx)) = (usart1_channel_tx, usart1_channel_rx) {
stm32u545::usart::Usart::set_dma(usart1, dma1, tx, rx);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be moved to Stm32u5xxPeripherals::configure() (or some suitable name)?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved all chip wiring to init function from Stm32u5xxDefaultPeripherals

Comment thread chips/stm32u5xx/src/lib.rs Outdated
Comment on lines +58 to +66
pub struct Stm32u5xxPeripherals<'a> {
pub rcc: rcc::Rcc,
pub exti: &'a exti::Exti<'a>,
pub dma1: &'a dma::Dma,
pub gpio_a: gpio::Port<'a>,
pub gpio_c: gpio::Port<'a>,
pub usart1: &'a usart::Usart<'a>,
pub tim2: tim::Tim2<'a>,
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why there is this peripherals and the default peripherals.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stm32u5xxDefaultPeripherals was indeed created to implement InterruptService and Stm32u5xxPeripherals for the board but i see the point and i will combine those.

@bradjc
Copy link
Copy Markdown
Contributor

bradjc commented May 8, 2026

I really thought I commented this already, but I think we need to include DmaSlice (https://github.com/tock/tock/blob/master/chips/nrf52/src/uart.rs#L166) and PanicWriter (https://github.com/tock/tock/blob/master/chips/nrf52/src/uart.rs#L802) in this PR. It is a bit of bad timing, but otherwise we keep making it more difficult to get to correct/sound chips.

@FarhadGUL06 FarhadGUL06 force-pushed the board_nucleo_u545re_q branch from 3042c2c to f64e7b7 Compare May 10, 2026 09:56
@FarhadGUL06 FarhadGUL06 requested a review from bradjc May 10, 2026 09:56
@FarhadGUL06
Copy link
Copy Markdown
Author

Hi @bradjc !
I combined Stm32u5xxPeripherals and Stm32u5xxDefaultPeripherals and implemented DmaSlice.

Comment thread boards/nucleo_u545re_q/src/main.rs Outdated
Comment on lines +167 to +173
let _ = periphs.usart1.configure(kernel::hil::uart::Parameters {
baud_rate: 115200,
stop_bits: kernel::hil::uart::StopBits::One,
parity: kernel::hil::uart::Parity::None,
hw_flow_control: false,
width: kernel::hil::uart::Width::Eight,
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread boards/nucleo_u545re_q/src/io.rs Outdated
Comment on lines +12 to +35
/// Writer is used by kernel::debug to print messages to the serial port.
pub struct Writer {}

/// Global static for debug writer
#[no_mangle]
pub static mut WRITER: Writer = Writer {};

impl Write for Writer {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.write(s.as_bytes());
Ok(())
}
}

impl IoWrite for Writer {
fn write(&mut self, buf: &[u8]) -> usize {
let uart = stm32u545::usart::Usart::new(stm32u545::usart::USART1_BASE);

for &c in buf {
uart.transmit_byte(c);
}
buf.len()
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Writer is used by kernel::debug to print messages to the serial port.
pub struct Writer {}
/// Global static for debug writer
#[no_mangle]
pub static mut WRITER: Writer = Writer {};
impl Write for Writer {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.write(s.as_bytes());
Ok(())
}
}
impl IoWrite for Writer {
fn write(&mut self, buf: &[u8]) -> usize {
let uart = stm32u545::usart::Usart::new(stm32u545::usart::USART1_BASE);
for &c in buf {
uart.transmit_byte(c);
}
buf.len()
}
}

@FarhadGUL06
Copy link
Copy Markdown
Author

Hi @bradjc ! I've made the final changes you requested. Is there anything else that needs to be changed? If there are any more changes to be made, could you let me know all of them for the current version? I'd like us to get this up and running as soon as possible. Thanks!

@FarhadGUL06 FarhadGUL06 requested a review from bradjc May 11, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants