From 2df656a2aa07a92d868a83a306f86d23ce82578c Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 25 Jul 2025 16:48:34 +0200 Subject: [PATCH 01/11] dt-rust.yaml: add nRF54L flash controller RRAM controller is used on the nRF54L series. Signed-off-by: Marcin Szymczyk --- dt-rust.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/dt-rust.yaml b/dt-rust.yaml index 01c747a..d083c3a 100644 --- a/dt-rust.yaml +++ b/dt-rust.yaml @@ -35,6 +35,7 @@ names: - "nordic,nrf52-flash-controller" - "nordic,nrf51-flash-controller" + - "nordic,rram-controller" - "raspberrypi,pico-flash-controller" - "zephyr,sim-flash" - "st,stm32-flash-controller" From 1e3c9d3044220a7f541aa559ca0f81ebd52fe6ca Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 13:10:03 +0200 Subject: [PATCH 02/11] samples: async-philosopers: add missing space Space was missing before board name. Signed-off-by: Marcin Szymczyk --- samples/async-philosophers/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/async-philosophers/src/lib.rs b/samples/async-philosophers/src/lib.rs index 0cf4b3b..a8cf1f1 100644 --- a/samples/async-philosophers/src/lib.rs +++ b/samples/async-philosophers/src/lib.rs @@ -26,7 +26,10 @@ const NUM_PHIL: usize = 6; #[no_mangle] extern "C" fn rust_main() { - printkln!("Async dining philosophers{}", zephyr::kconfig::CONFIG_BOARD); + printkln!( + "Async dining philosophers {}", + zephyr::kconfig::CONFIG_BOARD + ); printkln!("Time tick: {}", zephyr::time::SYS_FREQUENCY); let executor = EXECUTOR.init(Executor::new()); From f29fe19cf5245f2fba0707b0d5089d017dfdbd4f Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 13:13:47 +0200 Subject: [PATCH 03/11] samples: add support for nrf54l15dk/nrf54l15/cpuapp Tested manually, all tests are passing. Signed-off-by: Marcin Szymczyk --- samples/async-philosophers/sample.yaml | 1 + samples/bench/sample.yaml | 1 + samples/blinky/sample.yaml | 1 + samples/embassy/sample.yaml | 1 + samples/hello_world/sample.yaml | 1 + samples/philosophers/sample.yaml | 1 + 6 files changed, 6 insertions(+) diff --git a/samples/async-philosophers/sample.yaml b/samples/async-philosophers/sample.yaml index 1b96018..d72fcdc 100644 --- a/samples/async-philosophers/sample.yaml +++ b/samples/async-philosophers/sample.yaml @@ -15,6 +15,7 @@ common: - qemu_riscv32 - qemu_riscv64 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp tests: sample.rust.work-philosopher: tags: introduction diff --git a/samples/bench/sample.yaml b/samples/bench/sample.yaml index 0d8e5c1..87832aa 100644 --- a/samples/bench/sample.yaml +++ b/samples/bench/sample.yaml @@ -16,6 +16,7 @@ common: - qemu_riscv32 - qemu_riscv64 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp tests: sample.rust/bench.plain: tags: benchmark diff --git a/samples/blinky/sample.yaml b/samples/blinky/sample.yaml index 169fa5e..7e1ea70 100644 --- a/samples/blinky/sample.yaml +++ b/samples/blinky/sample.yaml @@ -9,6 +9,7 @@ common: - qemu_riscv32 - qemu_riscv64 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp tests: sample.rust.basic.blinky: tags: diff --git a/samples/embassy/sample.yaml b/samples/embassy/sample.yaml index c4a24cf..b4f76c9 100644 --- a/samples/embassy/sample.yaml +++ b/samples/embassy/sample.yaml @@ -15,6 +15,7 @@ common: - qemu_riscv32 - qemu_riscv64 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp tests: sample.rust.embassyhello: tags: introduction diff --git a/samples/hello_world/sample.yaml b/samples/hello_world/sample.yaml index 48d2a38..990ab13 100644 --- a/samples/hello_world/sample.yaml +++ b/samples/hello_world/sample.yaml @@ -15,6 +15,7 @@ common: - qemu_riscv32 - qemu_riscv64 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp tests: sample.rust.helloworld: tags: introduction diff --git a/samples/philosophers/sample.yaml b/samples/philosophers/sample.yaml index 8738850..75feb3a 100644 --- a/samples/philosophers/sample.yaml +++ b/samples/philosophers/sample.yaml @@ -17,6 +17,7 @@ common: - qemu_riscv32 - qemu_riscv64 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp tests: sample.rust.philosopher.semaphore: tags: introduction From 43eb608bb10d9f3be0926e165142fcf2e33e7e92 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 13:15:35 +0200 Subject: [PATCH 04/11] gitignore: skip `build` dirs Ignore the build directory. Signed-off-by: Marcin Szymczyk --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 85873b5..1674601 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Normal west builds will place the Rust target directory under the build directory. However, # sometimes IDEs and such will litter these target directories as well. +build*/ target/ # None of this code is an application, so don't capture any of the dependencies in the lock file. From 6079b4cfa8a3346150eea0280c41f365992fc8c6 Mon Sep 17 00:00:00 2001 From: Slava Krauchanka Date: Fri, 13 Jun 2025 21:16:58 +0200 Subject: [PATCH 05/11] added support for more granular RISCV32/64 ISA extensions --- CMakeLists.txt | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75ece41..961b7f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,10 +42,47 @@ function(_rust_map_target) elseif(CONFIG_RISCV) if(CONFIG_RISCV_ISA_RV64I) # TODO: Should fail if the extensions don't match. - set(RUST_TARGET "riscv64imac-unknown-none-elf" PARENT_SCOPE) + # We have multiple choices, try to pick the best. + # Note that Rust currently only supports "riscv64gc" and "riscv64imac" targets! + set(RUST_TARGET "riscv64") + if(CONFIG_RISCV_ISA_EXT_G) + set(RUST_TARGET "${RUST_TARGET}g") + else() + set(RUST_TARGET "${RUST_TARGET}i") + if(CONFIG_RISCV_ISA_EXT_M) + set(RUST_TARGET "${RUST_TARGET}m") + endif() + if(CONFIG_RISCV_ISA_EXT_A) + set(RUST_TARGET "${RUST_TARGET}a") + endif() + if(CONFIG_RISCV_ISA_EXT_F) + set(RUST_TARGET "${RUST_TARGET}f") + endif() + if(CONFIG_RISCV_ISA_EXT_D) + set(RUST_TARGET "${RUST_TARGET}d") + endif() + endif() + if(CONFIG_RISCV_ISA_EXT_C) + set(RUST_TARGET "${RUST_TARGET}c") + endif() + set(RUST_TARGET "${RUST_TARGET}-unknown-none-elf" PARENT_SCOPE) elseif(CONFIG_RISCV_ISA_RV32I) - # TODO: We have multiple choices, try to pick the best. - set(RUST_TARGET "riscv32i-unknown-none-elf" PARENT_SCOPE) + # We have multiple choices, try to pick the best. + # Note that Rust currently only supports subsets of "riscv32imafc" targets! + set(RUST_TARGET "riscv32i") + if(CONFIG_RISCV_ISA_EXT_M) + set(RUST_TARGET "${RUST_TARGET}m") + endif() + if(CONFIG_RISCV_ISA_EXT_A) + set(RUST_TARGET "${RUST_TARGET}a") + endif() + if(CONFIG_RISCV_ISA_EXT_F) + set(RUST_TARGET "${RUST_TARGET}f") + endif() + if(CONFIG_RISCV_ISA_EXT_C) + set(RUST_TARGET "${RUST_TARGET}c") + endif() + set(RUST_TARGET "${RUST_TARGET}-unknown-none-elf" PARENT_SCOPE) else() message(FATAL_ERROR "Rust: Unsupported riscv ISA") endif() From 4d6648497c085ed142ab72491a4fab7603e54ce0 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 14:29:23 +0200 Subject: [PATCH 06/11] cmake: add support for RV32E targets Tier 3 no-std targets that require building core and alloc from source. Signed-off-by: Marcin Szymczyk --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 961b7f5..a80b266 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,10 +66,14 @@ function(_rust_map_target) set(RUST_TARGET "${RUST_TARGET}c") endif() set(RUST_TARGET "${RUST_TARGET}-unknown-none-elf" PARENT_SCOPE) - elseif(CONFIG_RISCV_ISA_RV32I) + elseif(CONFIG_RISCV_ISA_RV32I OR CONFIG_RISCV_ISA_RV32E) # We have multiple choices, try to pick the best. # Note that Rust currently only supports subsets of "riscv32imafc" targets! - set(RUST_TARGET "riscv32i") + if(CONFIG_RISCV_ISA_RV32I) + set(RUST_TARGET "riscv32i") + else() + set(RUST_TARGET "riscv32e") + endif() if(CONFIG_RISCV_ISA_EXT_M) set(RUST_TARGET "${RUST_TARGET}m") endif() From 520c9a12944cd69578579ab6059a2cd8a10570bf Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 14:44:01 +0200 Subject: [PATCH 07/11] samples: replace BOARD with BOARD_TARGET BOARD_TARGET is more specific about which core runs the sample. Signed-off-by: Marcin Szymczyk --- samples/async-philosophers/src/lib.rs | 2 +- samples/embassy/src/lib.rs | 2 +- samples/hello_world/src/lib.rs | 2 +- samples/philosophers/src/lib.rs | 5 ++++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/samples/async-philosophers/src/lib.rs b/samples/async-philosophers/src/lib.rs index a8cf1f1..dbc4e8b 100644 --- a/samples/async-philosophers/src/lib.rs +++ b/samples/async-philosophers/src/lib.rs @@ -28,7 +28,7 @@ const NUM_PHIL: usize = 6; extern "C" fn rust_main() { printkln!( "Async dining philosophers {}", - zephyr::kconfig::CONFIG_BOARD + zephyr::kconfig::CONFIG_BOARD_TARGET ); printkln!("Time tick: {}", zephyr::time::SYS_FREQUENCY); diff --git a/samples/embassy/src/lib.rs b/samples/embassy/src/lib.rs index 8bfd14b..e814581 100644 --- a/samples/embassy/src/lib.rs +++ b/samples/embassy/src/lib.rs @@ -59,7 +59,7 @@ extern "C" fn rust_main() { info!( "Starting Embassy executor on {}", - zephyr::kconfig::CONFIG_BOARD + zephyr::kconfig::CONFIG_BOARD_TARGET ); let executor = EXECUTOR_MAIN.init(Executor::new()); diff --git a/samples/hello_world/src/lib.rs b/samples/hello_world/src/lib.rs index ce2a33e..0361d5b 100644 --- a/samples/hello_world/src/lib.rs +++ b/samples/hello_world/src/lib.rs @@ -11,5 +11,5 @@ extern "C" fn rust_main() { zephyr::set_logger().unwrap(); } - info!("Hello world from Rust on {}", zephyr::kconfig::CONFIG_BOARD); + info!("Hello world from Rust on {}", zephyr::kconfig::CONFIG_BOARD_TARGET); } diff --git a/samples/philosophers/src/lib.rs b/samples/philosophers/src/lib.rs index 473e84b..a576bb9 100644 --- a/samples/philosophers/src/lib.rs +++ b/samples/philosophers/src/lib.rs @@ -65,7 +65,10 @@ trait ForkSync: core::fmt::Debug + Sync + Send { #[no_mangle] extern "C" fn rust_main() { - printkln!("Hello world from Rust on {}", zephyr::kconfig::CONFIG_BOARD); + printkln!( + "Hello world from Rust on {}", + zephyr::kconfig::CONFIG_BOARD_TARGET + ); printkln!("Time tick: {}", zephyr::time::SYS_FREQUENCY); let stats = &STAT_MUTEX; From 49ffeb31b911dc614d19f76d30c47025a257df8e Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 14:34:04 +0200 Subject: [PATCH 08/11] {kconfig, cmake}: add options to build nightly and std from source Some targets need to be built with nightly and `-Z build-std=core,alloc` --- CMakeLists.txt | 18 ++++++++++++++++-- Kconfig | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a80b266..156b17d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,18 @@ function(rust_cargo_application) endif() set(BUILD_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${RUST_TARGET}/${RUST_BUILD_TYPE}") + if(CONFIG_RUST_NIGHTLY) + set(CARGO_TOOLCHAIN_OVERRIDE "+nightly") + else() + set(CARGO_TOOLCHAIN_OVERRIDE "") + endif() + + if(CONFIG_RUST_BUILD_STD) + set(CARGO_ARGS "-Zbuild-std=core,alloc") + else() + set(CARGO_ARGS "") + endif() + set(CARGO_TARGET_DIR "${CMAKE_CURRENT_BINARY_DIR}/rust/target") set(RUST_LIBRARY "${CARGO_TARGET_DIR}/${RUST_TARGET}/${RUST_BUILD_TYPE}/librustapp.a") set(SAMPLE_CARGO_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/rust/sample-cargo-config.toml") @@ -214,7 +226,7 @@ ${config_paths} WRAPPER_FILE="${WRAPPER_FILE}" DT_AUGMENTS="${DT_AUGMENTS}" BINARY_DIR_INCLUDE_GENERATED="${BINARY_DIR_INCLUDE_GENERATED}" - cargo build + cargo ${CARGO_TOOLCHAIN_OVERRIDE} build ${rust_build_type_arg} # Override the features according to the shield given. For a general case, @@ -228,6 +240,7 @@ ${config_paths} ${command_paths} --target ${RUST_TARGET} --target-dir ${CARGO_TARGET_DIR} + ${CARGO_ARGS} COMMENT "Building Rust application" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -258,7 +271,7 @@ ${config_paths} WRAPPER_FILE="${WRAPPER_FILE}" DT_AUGMENTS="${DT_AUGMENTS}" BINARY_DIR_INCLUDE_GENERATED="${BINARY_DIR_INCLUDE_GENERATED}" - cargo doc + cargo ${CARGO_TOOLCHAIN_OVERRIDE} doc ${rust_build_type_arg} # Override the features according to the shield given. For a general case, @@ -272,6 +285,7 @@ ${config_paths} ${command_paths} --target ${RUST_TARGET} --target-dir ${CARGO_TARGET_DIR} + ${CARGO_ARGS} COMMENT "Building Rust documentation" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/Kconfig b/Kconfig index 0b2d057..094d0e1 100644 --- a/Kconfig +++ b/Kconfig @@ -31,6 +31,25 @@ config RUST_ALLOC Zephyr allocator (malloc/free). This this enabled, Rust applications can use the `alloc` crate. +config RUST_NIGHTLY + bool "Use nightly for building the target" + default y if RISCV_ISA_RV32E + help + If enabled, nightly edition will be used for building. + +if RUST_NIGHTLY + +config RUST_BUILD_STD + bool "Build standard library from source" + default y if RISCV_ISA_RV32E + help + Some targets require building standard library from source. + If enabled, this will add `-Z build-std=core,alloc` to cargo build. + Depends on nightly edition. + You need to run `rustup +nightly component add rust-src` before building. + +endif # RUST_NIGHTLY + endif # RUST endmenu From 8e05063745d4be9d7e75b328c8725831a6a390f2 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 14:34:23 +0200 Subject: [PATCH 09/11] Kconfig: enable building for RISCV_ISA_RV32E It is possible to build for that target with nightly and standard library built from source. --- Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kconfig b/Kconfig index 094d0e1..b400a60 100644 --- a/Kconfig +++ b/Kconfig @@ -8,7 +8,7 @@ menu "Rust Language Support" config RUST_SUPPORTED bool default y if ((CPU_CORTEX_M || \ - (RISCV && !RISCV_ISA_RV32E && !RISCV_ISA_RV128I) || \ + (RISCV && !RISCV_ISA_RV128I) || \ (ARCH_POSIX && 64BIT)) && \ !TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) help From c5877cee6d5b74f6d874d56e658d736ca9fba156 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 22 Aug 2025 16:32:58 +0200 Subject: [PATCH 10/11] samples: enable support for nrf54l15dk/nrf54l15/cpuflpr Due to memory constraints, only samples built in release configuration can be enabled. Signed-off-by: Marcin Szymczyk --- samples/async-philosophers/sample.yaml | 1 + samples/hello_world/sample.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/async-philosophers/sample.yaml b/samples/async-philosophers/sample.yaml index d72fcdc..8d39914 100644 --- a/samples/async-philosophers/sample.yaml +++ b/samples/async-philosophers/sample.yaml @@ -16,6 +16,7 @@ common: - qemu_riscv64 - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuflpr tests: sample.rust.work-philosopher: tags: introduction diff --git a/samples/hello_world/sample.yaml b/samples/hello_world/sample.yaml index 990ab13..4c5e138 100644 --- a/samples/hello_world/sample.yaml +++ b/samples/hello_world/sample.yaml @@ -16,6 +16,7 @@ common: - qemu_riscv64 - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuflpr tests: sample.rust.helloworld: tags: introduction From c7499dbf628b99e44d7714884b6c47c4167d9f68 Mon Sep 17 00:00:00 2001 From: David Brown Date: Thu, 4 Sep 2025 13:38:42 -0700 Subject: [PATCH 11/11] samples: hello_world: Fix formatting The longer identifier for the board messages causes rustfmt to flow this onto multiple lines. Apply this change so that the check will pass during CI. Signed-off-by: David Brown --- samples/hello_world/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/hello_world/src/lib.rs b/samples/hello_world/src/lib.rs index 0361d5b..34ddd20 100644 --- a/samples/hello_world/src/lib.rs +++ b/samples/hello_world/src/lib.rs @@ -11,5 +11,8 @@ extern "C" fn rust_main() { zephyr::set_logger().unwrap(); } - info!("Hello world from Rust on {}", zephyr::kconfig::CONFIG_BOARD_TARGET); + info!( + "Hello world from Rust on {}", + zephyr::kconfig::CONFIG_BOARD_TARGET + ); }