diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b6a09fe9..ca270d967 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -58,6 +58,11 @@ jobs: # rustfmt: Used by bindgen for liboscore components: rust-src, rustfmt + - name: Install Rust for Xtensa + uses: esp-rs/xtensa-toolchain@v1.5 + with: + buildtargets: esp32s3 + - name: rust cache if: steps.result-cache.outputs.cache-hit != 'true' uses: Swatinem/rust-cache@v2 @@ -82,7 +87,7 @@ jobs: - name: "limit build unless nightly build" if: github.event_name != 'schedule' run: | - echo "LAZE_BUILDERS=ai-c3,espressif-esp32-c6-devkitc-1,microbit-v2,nrf52840dk,nrf5340dk,rpi-pico,rpi-pico-w,st-nucleo-h755zi-q,st-nucleo-wb55" >> "$GITHUB_ENV" + echo "LAZE_BUILDERS=ai-c3,espressif-esp32-c6-devkitc-1,espressif-esp32-s3-wroom-1,microbit-v2,nrf52840dk,nrf5340dk,rpi-pico,rpi-pico-w,st-nucleo-h755zi-q,st-nucleo-wb55" >> "$GITHUB_ENV" - name: "riot-rs compilation test" if: steps.result-cache.outputs.cache-hit != 'true' diff --git a/Cargo.lock b/Cargo.lock index 2a54669e6..453bc2873 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -892,7 +892,7 @@ dependencies = [ [[package]] name = "cyw43" version = "0.2.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "cortex-m", "cortex-m-rt", @@ -909,7 +909,7 @@ dependencies = [ [[package]] name = "cyw43-pio" version = "0.2.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "cyw43", "embassy-rp", @@ -1153,7 +1153,7 @@ dependencies = [ [[package]] name = "embassy-executor" version = "0.6.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "cortex-m", "critical-section", @@ -1187,7 +1187,7 @@ dependencies = [ [[package]] name = "embassy-hal-internal" version = "0.2.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "cortex-m", "critical-section", @@ -1217,7 +1217,7 @@ dependencies = [ [[package]] name = "embassy-net" version = "0.4.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "defmt", "document-features", @@ -1234,7 +1234,7 @@ dependencies = [ [[package]] name = "embassy-net-driver" version = "0.2.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "defmt", ] @@ -1242,7 +1242,7 @@ dependencies = [ [[package]] name = "embassy-net-driver-channel" version = "0.3.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "embassy-futures", "embassy-net-driver", @@ -1278,7 +1278,7 @@ dependencies = [ [[package]] name = "embassy-nrf" version = "0.2.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "embassy-rp" version = "0.2.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "atomic-polyfill", "cfg-if", @@ -1356,7 +1356,7 @@ dependencies = [ [[package]] name = "embassy-stm32" version = "0.1.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "aligned", "bit_field", @@ -1414,7 +1414,7 @@ dependencies = [ [[package]] name = "embassy-sync" version = "0.6.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "cfg-if", "critical-section", @@ -1446,7 +1446,7 @@ dependencies = [ [[package]] name = "embassy-time-driver" version = "0.1.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "document-features", ] @@ -1454,7 +1454,7 @@ dependencies = [ [[package]] name = "embassy-time-queue-driver" version = "0.1.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" [[package]] name = "embassy-usb" @@ -1475,7 +1475,7 @@ dependencies = [ [[package]] name = "embassy-usb-driver" version = "0.1.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "defmt", ] @@ -1498,7 +1498,7 @@ dependencies = [ [[package]] name = "embassy-usb-synopsys-otg" version = "0.1.0" -source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#973754a8329ad75a0864bd2f5da7ab95364039e1" +source = "git+https://github.com/kaspar030/embassy?branch=for-riot-rs-2024-09-19#afdd20dc1f721a3be5704b2bb5f8572f0a3f8ca3" dependencies = [ "critical-section", "embassy-sync 0.6.0", @@ -1794,6 +1794,7 @@ dependencies = [ "esp-hal-procmacros", "esp-metadata", "esp-riscv-rt", + "esp-synopsys-usb-otg", "esp32", "esp32c2", "esp32c3", @@ -1809,7 +1810,9 @@ dependencies = [ "riscv", "serde", "strum", + "usb-device", "void", + "xtensa-lx", "xtensa-lx-rt", ] @@ -1883,6 +1886,19 @@ dependencies = [ "riscv-rt-macros", ] +[[package]] +name = "esp-synopsys-usb-otg" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8938451cb19032f13365328ea66ab38c8d16deecdf322067442297110eb74468" +dependencies = [ + "critical-section", + "embedded-hal 0.2.7", + "ral-registers", + "usb-device", + "vcell", +] + [[package]] name = "esp-wifi" version = "0.8.0" @@ -2014,6 +2030,14 @@ dependencies = [ "riot-rs-rt", ] +[[package]] +name = "espressif-esp32-s3-wroom-1" +version = "0.1.0" +dependencies = [ + "riot-rs-debug", + "riot-rs-rt", +] + [[package]] name = "example-random" version = "0.1.0" @@ -2647,9 +2671,9 @@ checksum = "744a4c881f502e98c2241d2e5f50040ac73b30194d64452bb6260393b53f0dc9" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libloading" @@ -3525,6 +3549,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" +[[package]] +name = "ral-registers" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46b71a9d9206e8b46714c74255adcaea8b11e0350c1d8456165073c3f75fc81a" + [[package]] name = "rand" version = "0.8.5" @@ -3565,9 +3595,9 @@ version = "0.1.1" [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "62871f2d65009c0256aed1b9cfeeb8ac272833c404e13d53d400cd0dad7a2ac0" dependencies = [ "bitflags 2.6.0", ] @@ -3659,6 +3689,7 @@ dependencies = [ "cfg-if", "cortex-m", "defmt", + "esp-hal", ] [[package]] @@ -3669,6 +3700,7 @@ dependencies = [ "cfg-if", "dwm1001", "espressif-esp32-c6-devkitc-1", + "espressif-esp32-s3-wroom-1", "linkme", "microbit", "microbit-v2", @@ -4600,9 +4632,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap 2.5.0", "serde", @@ -4946,9 +4978,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "c52ac009d615e79296318c1bcce2d422aaca15ad08515e344feeda07df67a587" dependencies = [ "memchr", ] diff --git a/laze-project.yml b/laze-project.yml index b907d3822..a378ca0ea 100644 --- a/laze-project.yml +++ b/laze-project.yml @@ -12,8 +12,6 @@ contexts: - ?defmt env: RUSTFLAGS: - - "-Clink-arg=--nmagic" - - "-Clink-arg=${LINK_ARG_PREFIX}--no-eh-frame-hdr" - --cfg builder=\"${builder}\" - --cfg context=\"${builder}\" - --cfg context=\"riot-rs\" @@ -63,7 +61,7 @@ contexts: pool: console always: true cmd: >- - cd ${relpath} && ${CARGO_ENV} cargo ${CARGO_ARGS} build --${PROFILE} ${FEATURES} + cd ${relpath} && ${CARGO_ENV} cargo ${CARGO_TOOLCHAIN} ${CARGO_ARGS} build --${PROFILE} ${FEATURES} && cp ${relroot}/${build-dir}/bin/${builder}/${app}/cargo/${RUSTC_TARGET}/${PROFILE}/${riot_binary} ${relroot}/${out} - name: GIT_DOWNLOAD @@ -77,13 +75,13 @@ contexts: cargo: cmd: - - cd ${relpath} && ${CARGO_ENV} cargo ${CARGO_ARGS} + - cd ${relpath} && ${CARGO_ENV} cargo ${CARGO_TOOLCHAIN} ${CARGO_ARGS} build: false run: build: false cmd: - - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_ARGS} run --${PROFILE} ${FEATURES} + - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_TOOLCHAIN} ${CARGO_ARGS} run --${PROFILE} ${FEATURES} cargo-test: cmd: @@ -92,7 +90,7 @@ contexts: debug: cmd: - - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_ARGS} run --${PROFILE} ${FEATURES} + - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_TOOLCHAIN} ${CARGO_ARGS} run --${PROFILE} ${FEATURES} build: false ignore_ctrl_c: true @@ -104,12 +102,12 @@ contexts: bloat: cmd: - - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_ARGS} bloat --${PROFILE} ${FEATURES} + - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_TOOLCHAIN} ${CARGO_ARGS} bloat --${PROFILE} ${FEATURES} build: false tree: cmd: - - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_ARGS} tree ${FEATURES} + - cd ${appdir} && ${CARGO_ENV} cargo ${CARGO_TOOLCHAIN} ${CARGO_ARGS} tree ${FEATURES} build: false flash: @@ -278,8 +276,6 @@ contexts: - --cfg context=\"esp\" # linkall first - -Clink-arg=-Tlinkall.x - - -Clink-arg=-Tlinkme-esp-fixup.x - - -Clink-arg=-Tlinkme.x # this might be needed for backtraces # - -C force-frame-pointers CARGO_ARGS: @@ -288,6 +284,8 @@ contexts: - name: esp32c3 parent: esp + selects: + - riscv env: RUSTFLAGS: - --cfg context=\"esp32c3\" @@ -296,12 +294,25 @@ contexts: - name: esp32c6 parent: esp + selects: + - riscv env: RUSTFLAGS: - --cfg context=\"esp32c6\" RUSTC_TARGET: riscv32imac-unknown-none-elf CARGO_TARGET_PREFIX: CARGO_TARGET_RISCV32IMAC_UNKNOWN_NONE_ELF + - name: esp32s3 + parent: esp + selects: + - xtensa + env: + CARGO_TOOLCHAIN: +esp + RUSTFLAGS: + - --cfg context=\"esp32s3\" + RUSTC_TARGET: xtensa-esp32s3-none-elf + CARGO_TARGET_PREFIX: CARGO_TARGET_XTENSA_ESP32S3_NONE_ELF + - name: stm32 help: STM32 support (based on embassy-stm32) parent: riot-rs @@ -358,6 +369,8 @@ modules: global: OBJCOPY: arm-none-eabi-objcopy RUSTFLAGS: + - -Clink-arg=--nmagic + - -Clink-arg=${LINK_ARG_PREFIX}--no-eh-frame-hdr - -Clink-arg=-Tlinkme.x - -Clink-arg=-Tlink.x - -Clink-arg=-Tdevice.x @@ -414,6 +427,18 @@ modules: RUSTFLAGS: - --cfg armv7m + - name: xtensa + env: + global: + RUSTFLAGS: + - --cfg context=\"xtensa\" + + - name: riscv + env: + global: + RUSTFLAGS: + - --cfg context=\"riscv\" + - name: rp-link-arg help: helper module that ensures link-rp.x is added behind cortex-m ld scripts env: @@ -630,6 +655,7 @@ modules: - nrf - rp - stm32 + - esp - name: wifi-esp context: @@ -779,6 +805,9 @@ builders: - name: espressif-esp32-c6-devkitc-1 parent: esp32c6 + - name: espressif-esp32-s3-wroom-1 + parent: esp32s3 + - name: nrf5340dk parent: nrf5340 diff --git a/src/riot-rs-bench/Cargo.toml b/src/riot-rs-bench/Cargo.toml index 5bcffaf36..75b519a65 100644 --- a/src/riot-rs-bench/Cargo.toml +++ b/src/riot-rs-bench/Cargo.toml @@ -15,3 +15,6 @@ defmt = { workspace = true, optional = true } [target.'cfg(context = "cortex-m")'.dependencies] cortex-m = { workspace = true, features = ["critical-section-single-core"] } + +[target.'cfg(context = "esp")'.dependencies] +esp-hal = { workspace = true } diff --git a/src/riot-rs-bench/src/esp.rs b/src/riot-rs-bench/src/esp.rs new file mode 100644 index 000000000..45cf14f6f --- /dev/null +++ b/src/riot-rs-bench/src/esp.rs @@ -0,0 +1,28 @@ +use esp_hal::{ + peripherals, + timer::systimer::{SystemTimer, Unit as _}, +}; + +use crate::Error; + +#[allow(missing_docs)] +pub fn benchmark ()>(iterations: usize, f: F) -> Result { + let mut systimer_periph = unsafe { peripherals::SYSTIMER::steal() }; + let timer = SystemTimer::new(&mut systimer_periph); + + // Reset counter of unit0, which is read in `SystemTimer::now()`. + timer.unit0.set_count(0); + + while SystemTimer::now() == 0 {} + + let before = SystemTimer::now(); + + for _ in 0..iterations { + f(); + } + + SystemTimer::now() + .checked_sub(before) + .map(|total| total as usize / iterations) + .ok_or(Error::SystemTimerWrapped) +} diff --git a/src/riot-rs-bench/src/lib.rs b/src/riot-rs-bench/src/lib.rs index 1cb1a99c0..8c993bb73 100644 --- a/src/riot-rs-bench/src/lib.rs +++ b/src/riot-rs-bench/src/lib.rs @@ -8,8 +8,10 @@ cfg_if::cfg_if! { if #[cfg(context = "cortex-m")] { mod cortexm; use cortexm as bench; - } - else if #[cfg(context = "riot-rs")] { + } else if #[cfg(context = "esp")] { + mod esp; + use esp as bench; + } else if #[cfg(context = "riot-rs")] { // When run with laze but the architecture is not supported compile_error!("benchmarking is not supported for this architecture"); } else { diff --git a/src/riot-rs-boards/Cargo.toml b/src/riot-rs-boards/Cargo.toml index 93865777a..f65a6d990 100644 --- a/src/riot-rs-boards/Cargo.toml +++ b/src/riot-rs-boards/Cargo.toml @@ -16,6 +16,7 @@ riot-rs-rt = { path = "../riot-rs-rt" } ai-c3 = { optional = true, path = "ai-c3" } espressif-esp32-c6-devkitc-1 = { optional = true, path = "espressif-esp32-c6-devkitc-1" } +espressif-esp32-s3-wroom-1 = { optional = true, path = "espressif-esp32-s3-wroom-1" } dwm1001 = { optional = true, path = "dwm1001" } microbit = { optional = true, path = "microbit" } microbit-v2 = { optional = true, path = "microbit-v2" } diff --git a/src/riot-rs-boards/espressif-esp32-s3-wroom-1/Cargo.toml b/src/riot-rs-boards/espressif-esp32-s3-wroom-1/Cargo.toml new file mode 100644 index 000000000..6dcfe097b --- /dev/null +++ b/src/riot-rs-boards/espressif-esp32-s3-wroom-1/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "espressif-esp32-s3-wroom-1" +version = "0.1.0" +authors = ["Elena Frank "] +license.workspace = true +edition = "2021" + +[dependencies] +riot-rs-rt = { workspace = true, features = ["_esp32s3"] } +riot-rs-debug.workspace = true diff --git a/src/riot-rs-boards/espressif-esp32-s3-wroom-1/src/lib.rs b/src/riot-rs-boards/espressif-esp32-s3-wroom-1/src/lib.rs new file mode 100644 index 000000000..f2b338c79 --- /dev/null +++ b/src/riot-rs-boards/espressif-esp32-s3-wroom-1/src/lib.rs @@ -0,0 +1,7 @@ +#![no_std] + +use riot_rs_debug::log::debug; + +pub fn init() { + debug!("espressif-esp32-s3-wroom-1::init()"); +} diff --git a/src/riot-rs-boards/src/lib.rs b/src/riot-rs-boards/src/lib.rs index 37e836946..08739b75d 100644 --- a/src/riot-rs-boards/src/lib.rs +++ b/src/riot-rs-boards/src/lib.rs @@ -8,6 +8,8 @@ cfg_if! { pub use ai_c3 as board; } else if #[cfg(feature = "espressif-esp32-c6-devkitc-1")] { pub use espressif_esp32_c6_devkitc_1 as board; + } else if #[cfg(feature = "espressif-esp32-s3-wroom-1")] { + pub use espressif_esp32_s3_wroom_1 as board; } else if #[cfg(feature = "nrf52dk")] { pub use nrf52dk as board; } else if #[cfg(feature = "dwm1001")] { diff --git a/src/riot-rs-debug/Cargo.toml b/src/riot-rs-debug/Cargo.toml index 7db58f3f4..509239ea1 100644 --- a/src/riot-rs-debug/Cargo.toml +++ b/src/riot-rs-debug/Cargo.toml @@ -33,6 +33,9 @@ esp-println = { workspace = true, features = ["esp32c3"] } [target.'cfg(context = "esp32c6")'.dependencies] esp-println = { workspace = true, features = ["esp32c6"] } +[target.'cfg(context = "esp32s3")'.dependencies] +esp-println = { workspace = true, features = ["esp32s3"] } + [features] debug-console = [] defmt = ["dep:defmt", "esp-println?/defmt-espflash"] diff --git a/src/riot-rs-esp/Cargo.toml b/src/riot-rs-esp/Cargo.toml index 64ab6c5a4..15f52a633 100644 --- a/src/riot-rs-esp/Cargo.toml +++ b/src/riot-rs-esp/Cargo.toml @@ -56,6 +56,15 @@ esp-wifi = { workspace = true, default-features = false, features = [ "esp32c6", ], optional = true } +[target.'cfg(context = "esp32s3")'.dependencies] +esp-hal = { workspace = true, features = ["esp32s3"] } +esp-hal-embassy = { workspace = true, default-features = false, features = [ + "esp32s3", +] } +esp-wifi = { workspace = true, default-features = false, features = [ + "esp32s3", +], optional = true } + [features] ## Enables GPIO interrupt support. external-interrupts = ["riot-rs-embassy-common/external-interrupts"] diff --git a/src/riot-rs-esp/src/lib.rs b/src/riot-rs-esp/src/lib.rs index 0deca2be7..8e81cf463 100644 --- a/src/riot-rs-esp/src/lib.rs +++ b/src/riot-rs-esp/src/lib.rs @@ -90,7 +90,6 @@ pub fn init() -> OptionalPeripherals { let timer = SystemTimer::new(peripherals.SYSTIMER.take().unwrap()) .split::(); - #[cfg(target_arch = "riscv32")] let init = initialize( EspWifiInitFor::Wifi, timer.alarm0, diff --git a/src/riot-rs-rt/Cargo.toml b/src/riot-rs-rt/Cargo.toml index 5c94b30c2..c407457a0 100644 --- a/src/riot-rs-rt/Cargo.toml +++ b/src/riot-rs-rt/Cargo.toml @@ -38,10 +38,11 @@ silent-panic = [] _panic-handler = [] # internal -# These two features are used by `build.rs`, which doesn't "see" context +# These features are used by `build.rs`, which doesn't "see" context # variables. _esp32c3 = [] _esp32c6 = [] +_esp32s3 = [] [dev-dependencies] riot-rs-boards = { path = "../riot-rs-boards" } diff --git a/src/riot-rs-rt/build.rs b/src/riot-rs-rt/build.rs index fcc8a4da3..058c357e9 100644 --- a/src/riot-rs-rt/build.rs +++ b/src/riot-rs-rt/build.rs @@ -8,13 +8,5 @@ fn main() { std::fs::copy("isr_stack.ld.in", out.join("isr_stack.x")).unwrap(); std::fs::copy("linkme.x", out.join("linkme.x")).unwrap(); - if env::var_os("CARGO_FEATURE__ESP32C3").is_some() { - std::fs::copy("linkme-esp32c3-fixup.x", out.join("linkme-esp-fixup.x")).unwrap(); - } - - if env::var_os("CARGO_FEATURE__ESP32C6").is_some() { - std::fs::copy("linkme-esp32c6-fixup.x", out.join("linkme-esp-fixup.x")).unwrap(); - } - println!("cargo:rustc-link-search={}", out.display()); } diff --git a/src/riot-rs-rt/linkme-esp32c3-fixup.x b/src/riot-rs-rt/linkme-esp32c3-fixup.x deleted file mode 100644 index e73dd91ed..000000000 --- a/src/riot-rs-rt/linkme-esp32c3-fixup.x +++ /dev/null @@ -1 +0,0 @@ -REGION_ALIAS("FLASH", IROM); diff --git a/src/riot-rs-rt/linkme-esp32c6-fixup.x b/src/riot-rs-rt/linkme-esp32c6-fixup.x deleted file mode 100644 index 352184123..000000000 --- a/src/riot-rs-rt/linkme-esp32c6-fixup.x +++ /dev/null @@ -1 +0,0 @@ -REGION_ALIAS("FLASH", ROM); diff --git a/src/riot-rs-threads/Cargo.toml b/src/riot-rs-threads/Cargo.toml index 7220f502c..b9e4fcdb4 100644 --- a/src/riot-rs-threads/Cargo.toml +++ b/src/riot-rs-threads/Cargo.toml @@ -26,6 +26,9 @@ esp-hal = { workspace = true, features = ["esp32c3"] } [target.'cfg(context = "esp32c6")'.dependencies] esp-hal = { workspace = true, features = ["esp32c6"] } +[target.'cfg(context = "esp32s3")'.dependencies] +esp-hal = { workspace = true, features = ["esp32s3"] } + [target.'cfg(context = "cortex-m")'.dependencies] # cortex-m specifics cortex-m.workspace = true diff --git a/src/riot-rs-threads/src/arch/mod.rs b/src/riot-rs-threads/src/arch/mod.rs index 9cd270e1f..eeff25352 100644 --- a/src/riot-rs-threads/src/arch/mod.rs +++ b/src/riot-rs-threads/src/arch/mod.rs @@ -28,12 +28,13 @@ cfg_if::cfg_if! { if #[cfg(context = "cortex-m")] { mod cortex_m; pub use cortex_m::Cpu; - } - else if #[cfg(any(context = "esp32c3", context = "esp32c6"))] { + } else if #[cfg(context = "riscv")] { mod riscv; pub use riscv::Cpu; - } - else { + } else if #[cfg(context = "xtensa")] { + mod xtensa; + pub use xtensa::Cpu; + } else { pub struct Cpu; impl Arch for Cpu { type ThreadData = (); diff --git a/src/riot-rs-threads/src/arch/riscv.rs b/src/riot-rs-threads/src/arch/riscv.rs index 413039940..7d36e2a67 100644 --- a/src/riot-rs-threads/src/arch/riscv.rs +++ b/src/riot-rs-threads/src/arch/riscv.rs @@ -42,7 +42,8 @@ impl Arch for Cpu { fn start_threading() { interrupt::disable(EspHalCpu::ProCpu, Interrupt::FROM_CPU_INTR1); Self::schedule(); - // TODO: handle unwrap error? + // Panics if `FROM_CPU_INTR1` is among `esp_hal::interrupt::RESERVED_INTERRUPTS`, + // which isn't the case. interrupt::enable(Interrupt::FROM_CPU_INTR1, interrupt::Priority::min()).unwrap(); } } diff --git a/src/riot-rs-threads/src/arch/xtensa.rs b/src/riot-rs-threads/src/arch/xtensa.rs new file mode 100644 index 000000000..8d6b76562 --- /dev/null +++ b/src/riot-rs-threads/src/arch/xtensa.rs @@ -0,0 +1,140 @@ +use esp_hal::{ + interrupt, + peripherals::{Interrupt, SYSTEM}, + trapframe::TrapFrame, +}; + +use crate::{cleanup, Arch, THREADS}; + +pub struct Cpu; + +impl Arch for Cpu { + type ThreadData = TrapFrame; + const DEFAULT_THREAD_DATA: Self::ThreadData = default_trap_frame(); + + fn schedule() { + unsafe { + (&*SYSTEM::PTR) + .cpu_intr_from_cpu_1() + .modify(|_, w| w.cpu_intr_from_cpu_1().set_bit()); + } + } + + fn setup_stack(thread: &mut crate::thread::Thread, stack: &mut [u8], func: usize, arg: usize) { + let stack_start = stack.as_ptr() as usize; + let task_stack_ptr = stack_start + stack.len(); + // 16 byte alignment. + let stack_pos = task_stack_ptr - (task_stack_ptr % 0x10); + + thread.sp = stack_pos; + thread.data.A1 = stack_pos as u32; + thread.data.A6 = arg as u32; + // Usually A0 holds the return address. + // However, xtensa features so-called Windowed registers, which allow + // to shift the used registers when calling procedure. + // The xtensa-lx-rt does this when calling the exception handler using + // call4, which shifts the window by 4. + // See `xtensa_lx_rt::exception::asm::__default_naked_exception`. + thread.data.A4 = cleanup as u32; + thread.data.PC = func as u32; + + // Copied from esp-wifi::preempt::preempt_xtensa + + // For windowed ABI set WOE and CALLINC (pretend task was 'call4'd). + thread.data.PS = 0x00040000 | (1 & 3) << 16; + } + + fn start_threading() { + interrupt::disable(esp_hal::Cpu::ProCpu, Interrupt::FROM_CPU_INTR1); + Self::schedule(); + // Panics if `FROM_CPU_INTR1` is among `esp_hal::interrupt::RESERVED_INTERRUPTS`, + // which isn't the case. + interrupt::enable(Interrupt::FROM_CPU_INTR1, interrupt::Priority::min()).unwrap(); + } +} + +const fn default_trap_frame() -> TrapFrame { + TrapFrame { + PC: 0, + PS: 0, + A0: 0, + A1: 0, + A2: 0, + A3: 0, + A4: 0, + A5: 0, + A6: 0, + A7: 0, + A8: 0, + A9: 0, + A10: 0, + A11: 0, + A12: 0, + A13: 0, + A14: 0, + A15: 0, + SAR: 0, + EXCCAUSE: 0, + EXCVADDR: 0, + LBEG: 0, + LEND: 0, + LCOUNT: 0, + THREADPTR: 0, + SCOMPARE1: 0, + BR: 0, + ACCLO: 0, + ACCHI: 0, + M0: 0, + M1: 0, + M2: 0, + M3: 0, + } +} + +/// Handler for software interrupt 0, which we use for context switching. +#[allow(non_snake_case)] +#[no_mangle] +extern "C" fn FROM_CPU_INTR1(trap_frame: &mut TrapFrame) { + unsafe { + // clear FROM_CPU_INTR1 + (&*SYSTEM::PTR) + .cpu_intr_from_cpu_1() + .modify(|_, w| w.cpu_intr_from_cpu_1().clear_bit()); + + sched(trap_frame) + } +} + +/// Probes the runqueue for the next thread and switches context if needed. +/// +/// # Safety +/// +/// This method might switch the current register state that is saved in the +/// `trap_frame`. +/// It should only be called from inside the trap handler that is responsible for +/// context switching. +unsafe fn sched(trap_frame: &mut TrapFrame) { + loop { + if THREADS.with_mut(|mut threads| { + let Some(next_pid) = threads.runqueue.get_next() else { + return false; + }; + + if let Some(current_pid) = threads.current_pid() { + if next_pid == current_pid { + return true; + } + threads.threads[usize::from(current_pid)].data = *trap_frame; + } + threads.current_thread = Some(next_pid); + *trap_frame = threads.threads[usize::from(next_pid)].data; + true + }) { + break; + } + // The esp-hal implementation of critical-section doesn't disable all interrupts. + // Thus we should release our hold on `THREADS` before we `waiti`, to prevent + // that another interrupt handler will try to borrow it while we still have it borrowed. + unsafe { core::arch::asm!("waiti 0") }; + } +} diff --git a/src/riot-rs-threads/src/lib.rs b/src/riot-rs-threads/src/lib.rs index a32635136..1fe18cf11 100644 --- a/src/riot-rs-threads/src/lib.rs +++ b/src/riot-rs-threads/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(not(test), no_std)] #![feature(naked_functions)] #![feature(used_with_arg)] +#![cfg_attr(target_arch = "xtensa", feature(asm_experimental_arch))] // Disable indexing lints for now, possible panics are documented or rely on internally-enforced // invariants #![allow(clippy::indexing_slicing)] diff --git a/tests/benchmarks/bench_sched_yield/laze.yml b/tests/benchmarks/bench_sched_yield/laze.yml index b8277bc23..a80d01389 100644 --- a/tests/benchmarks/bench_sched_yield/laze.yml +++ b/tests/benchmarks/bench_sched_yield/laze.yml @@ -2,4 +2,5 @@ apps: - name: bench_sched_yield selects: - sw/benchmark + - sw/threading - ?release