From 4060c3def88f82d4e4f48de7137ce365167ef265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Wed, 20 Mar 2024 21:06:47 +0100 Subject: [PATCH] RISC-V support over CLINT (#815) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rebase to master * using interrupt_mod * bug fixes * fix other backends * Add changelog * forgot about rtic-macros * backend-specific configuration * core peripherals optional over macro argument * pre_init_preprocessing binding * CI for RISC-V (WIP) * separation of concerns * add targets for RISC-V examples * remove qemu feature * prepare examples folder * move examples all together * move ci out of examples * minor changes * add cortex-m * new xtask: proof of concept * fix build.yml * feature typo * clean rtic examples * reproduce weird issue * remove unsafe code in user app * update dependencies * allow builds on riscv32imc * let's fix QEMU * Update .github/workflows/build.yml Co-authored-by: Henrik Tjäder * New build.rs * removing test features * adapt ui test to new version of clippy * add more examples to RISC-V backend * proper configuration of heapless for riscv32imc * opt-out examples for riscv32imc * point to new version of riscv-slic * adapt new macro bindings * adapt examples and CI to stable * fix cortex-m CI * Review --------- Co-authored-by: Henrik Tjäder --- .github/workflows/build.yml | 150 +++-- .gitignore | 3 + ci/expected/hifive1/prio_inheritance.run | 17 + .../expected/hifive1}/static.run | 0 .../expected => ci/expected/hifive1}/task.run | 0 .../expected/hifive1/zero_prio_task.run | 0 .../expected/lm3s6965}/async-channel-done.run | 0 .../lm3s6965}/async-channel-no-receiver.run | 0 .../lm3s6965}/async-channel-no-sender.run | 0 .../expected/lm3s6965}/async-channel-try.run | 0 .../expected/lm3s6965}/async-channel.run | 0 .../expected/lm3s6965}/async-delay.run | 0 .../lm3s6965}/async-infinite-loop.run | 0 .../lm3s6965}/async-task-multiple-prios.run | 0 .../expected/lm3s6965}/async-task.run | 0 .../expected/lm3s6965}/async-timeout.run | 0 .../expected/lm3s6965}/big-struct-opt.run | 0 .../expected/lm3s6965}/binds.run | 0 .../expected/lm3s6965}/cancel-reschedule.run | 0 .../expected/lm3s6965}/capacity.run | 0 .../expected/lm3s6965}/cfg-whole-task.run | 0 .../expected/lm3s6965}/common.run | 0 .../expected/lm3s6965}/complex.run | 0 .../expected/lm3s6965}/declared_locals.run | 0 .../expected/lm3s6965}/destructure.run | 0 .../expected/lm3s6965}/executor-size.run | 0 .../expected/lm3s6965}/extern_binds.run | 0 .../expected/lm3s6965}/extern_spawn.run | 0 .../expected/lm3s6965}/generics.run | 0 .../expected/lm3s6965}/hardware.run | 0 .../expected/lm3s6965}/idle-wfi.run | 0 .../expected/lm3s6965}/idle.run | 0 .../expected/lm3s6965}/init.run | 0 .../expected/lm3s6965}/locals.run | 0 .../expected/lm3s6965}/lock-free.run | 0 .../expected/lm3s6965}/lock.run | 0 .../expected/lm3s6965}/message.run | 0 .../expected/lm3s6965}/multilock.run | 0 .../expected/lm3s6965}/not-sync.run | 0 .../expected/lm3s6965}/only-shared-access.run | 0 .../expected/lm3s6965}/periodic-at.run | 0 .../expected/lm3s6965}/periodic-at2.run | 0 .../expected/lm3s6965}/periodic.run | 0 .../expected/lm3s6965}/peripherals-taken.run | 0 .../expected/lm3s6965}/pool.run | 0 .../expected/lm3s6965}/preempt.run | 0 .../expected/lm3s6965}/prio-inversion.run | 0 .../expected/lm3s6965}/ramfunc.run | 0 .../expected/lm3s6965}/ramfunc.run.grep.bar | 0 .../expected/lm3s6965}/ramfunc.run.grep.foo | 0 .../lm3s6965}/resource-user-struct.run | 0 .../expected/lm3s6965}/schedule.run | 0 .../expected/lm3s6965}/shared.run | 0 .../expected/lm3s6965}/smallest.run | 0 .../expected/lm3s6965}/spawn.run | 0 .../expected/lm3s6965}/spawn_arguments.run | 0 .../expected/lm3s6965}/spawn_err.run | 0 .../expected/lm3s6965}/spawn_loop.run | 0 ci/expected/lm3s6965/static.run | 3 + .../expected/lm3s6965}/t-binds.run | 0 .../expected/lm3s6965}/t-cfg-resources.run | 0 .../expected/lm3s6965}/t-htask-main.run | 0 .../expected/lm3s6965}/t-idle-main.run | 0 .../expected/lm3s6965}/t-late-not-send.run | 0 .../expected/lm3s6965}/t-schedule.run | 0 .../expected/lm3s6965}/t-spawn.run | 0 ci/expected/lm3s6965/task.run | 5 + ci/expected/lm3s6965/zero-prio-task.run | 3 + examples/hifive1/.cargo/config.toml | 11 + examples/hifive1/Cargo.lock | 364 ++++++++++++ examples/hifive1/Cargo.toml | 22 + examples/hifive1/examples/prio_inheritance.rs | 140 +++++ examples/hifive1/examples/static.rs | 60 ++ examples/hifive1/examples/task.rs | 57 ++ examples/hifive1/examples/zero_prio_task.rs | 61 ++ examples/hifive1/rust-toolchain.toml | 4 + examples/lm3s6965/.cargo/config.toml | 13 + examples/lm3s6965/Cargo.lock | 527 ++++++++++++++++++ examples/lm3s6965/Cargo.toml | 36 ++ .../lm3s6965}/examples/async-channel-done.rs | 0 .../examples/async-channel-no-receiver.rs | 0 .../examples/async-channel-no-sender.rs | 0 .../lm3s6965}/examples/async-channel-try.rs | 0 .../lm3s6965}/examples/async-channel.rs | 0 .../lm3s6965}/examples/async-delay.rs | 0 .../examples/async-task-multiple-prios.rs | 0 .../lm3s6965}/examples/async-task.rs | 0 .../lm3s6965}/examples/async-timeout.rs | 0 .../lm3s6965}/examples/big-struct-opt.rs | 0 {rtic => examples/lm3s6965}/examples/binds.rs | 0 .../lm3s6965}/examples/common.rs | 0 .../lm3s6965}/examples/complex.rs | 0 .../lm3s6965}/examples/declared_locals.rs | 0 .../lm3s6965}/examples/destructure.rs | 0 .../lm3s6965}/examples/executor-size.rs | 0 .../lm3s6965}/examples/extern_binds.rs | 0 .../lm3s6965}/examples/extern_spawn.rs | 0 .../lm3s6965}/examples/generics.rs | 0 .../lm3s6965}/examples/hardware.rs | 0 .../lm3s6965}/examples/idle-wfi.rs | 0 {rtic => examples/lm3s6965}/examples/idle.rs | 0 {rtic => examples/lm3s6965}/examples/init.rs | 0 .../lm3s6965}/examples/locals.rs | 0 .../lm3s6965}/examples/lock-free.rs | 0 {rtic => examples/lm3s6965}/examples/lock.rs | 0 .../lm3s6965}/examples/multilock.rs | 0 .../lm3s6965}/examples/not-sync.rs | 0 .../lm3s6965}/examples/only-shared-access.rs | 0 .../lm3s6965}/examples/peripherals-taken.rs | 0 .../lm3s6965}/examples/pool.rs_old | 0 .../lm3s6965}/examples/preempt.rs | 0 .../lm3s6965}/examples/prio-inversion.rs | 0 .../lm3s6965}/examples/ramfunc.rs | 0 .../examples/resource-user-struct.rs | 0 .../lm3s6965}/examples/shared.rs | 0 .../lm3s6965}/examples/smallest.rs | 0 {rtic => examples/lm3s6965}/examples/spawn.rs | 0 .../lm3s6965}/examples/spawn_arguments.rs | 0 .../lm3s6965}/examples/spawn_err.rs | 0 .../lm3s6965}/examples/spawn_loop.rs | 0 .../lm3s6965}/examples/static.rs | 0 .../lm3s6965}/examples/t-binds.rs | 0 .../lm3s6965}/examples/t-cfg-resources.rs | 0 .../lm3s6965}/examples/t-htask-main.rs | 0 .../lm3s6965}/examples/t-idle-main.rs | 0 .../lm3s6965}/examples/t-late-not-send.rs | 0 {rtic => examples/lm3s6965}/examples/task.rs | 0 .../lm3s6965}/examples/zero-prio-task.rs | 0 rtic-macros/CHANGELOG.md | 1 + rtic-macros/Cargo.toml | 4 +- rtic-macros/src/codegen.rs | 1 + rtic-macros/src/codegen/async_dispatchers.rs | 7 +- rtic-macros/src/codegen/bindings.rs | 11 +- rtic-macros/src/codegen/bindings/cortex.rs | 18 +- rtic-macros/src/codegen/bindings/esp32c3.rs | 14 + .../src/codegen/bindings/riscv_slic.rs | 255 +++++++++ rtic-macros/src/codegen/bindings/template.rs | 86 +-- rtic-macros/src/codegen/extra_mods.rs | 9 + rtic-macros/src/codegen/main.rs | 16 +- rtic-macros/src/codegen/module.rs | 29 +- rtic-macros/src/codegen/pre_init.rs | 10 +- rtic-macros/src/codegen/util.rs | 2 - rtic-macros/src/lib.rs | 17 +- rtic-macros/src/preprocess.rs | 7 + rtic-macros/src/syntax.rs | 1 + rtic-macros/src/syntax/ast.rs | 10 +- rtic-macros/src/syntax/backend.rs | 32 ++ rtic-macros/src/syntax/backend/cortex.rs | 16 + rtic-macros/src/syntax/backend/esp32c3.rs | 16 + rtic-macros/src/syntax/backend/riscv_slic.rs | 16 + rtic-macros/src/syntax/backend/template.rs | 15 + rtic-macros/src/syntax/parse/app.rs | 28 + rtic-monotonics/CHANGELOG.md | 1 + rtic/.cargo/config.toml | 8 +- rtic/CHANGELOG.md | 1 + rtic/Cargo.toml | 14 +- rtic/build.rs | 51 +- rtic/src/export.rs | 32 +- rtic/src/export/riscv_common.rs | 3 +- rtic/src/export/riscv_esp32c3.rs | 1 + rtic/src/export/slic.rs | 19 + rtic/src/lib.rs | 1 - xtask/src/argument_parsing.rs | 194 ++++--- xtask/src/cargo_command.rs | 71 ++- xtask/src/main.rs | 66 ++- xtask/src/run.rs | 78 ++- 166 files changed, 2322 insertions(+), 315 deletions(-) create mode 100644 ci/expected/hifive1/prio_inheritance.run rename {rtic/ci/expected => ci/expected/hifive1}/static.run (100%) rename {rtic/ci/expected => ci/expected/hifive1}/task.run (100%) rename rtic/ci/expected/zero-prio-task.run => ci/expected/hifive1/zero_prio_task.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-channel-done.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-channel-no-receiver.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-channel-no-sender.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-channel-try.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-channel.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-delay.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-infinite-loop.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-task-multiple-prios.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-task.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/async-timeout.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/big-struct-opt.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/binds.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/cancel-reschedule.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/capacity.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/cfg-whole-task.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/common.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/complex.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/declared_locals.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/destructure.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/executor-size.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/extern_binds.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/extern_spawn.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/generics.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/hardware.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/idle-wfi.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/idle.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/init.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/locals.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/lock-free.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/lock.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/message.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/multilock.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/not-sync.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/only-shared-access.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/periodic-at.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/periodic-at2.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/periodic.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/peripherals-taken.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/pool.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/preempt.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/prio-inversion.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/ramfunc.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/ramfunc.run.grep.bar (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/ramfunc.run.grep.foo (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/resource-user-struct.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/schedule.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/shared.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/smallest.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/spawn.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/spawn_arguments.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/spawn_err.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/spawn_loop.run (100%) create mode 100644 ci/expected/lm3s6965/static.run rename {rtic/ci/expected => ci/expected/lm3s6965}/t-binds.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/t-cfg-resources.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/t-htask-main.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/t-idle-main.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/t-late-not-send.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/t-schedule.run (100%) rename {rtic/ci/expected => ci/expected/lm3s6965}/t-spawn.run (100%) create mode 100644 ci/expected/lm3s6965/task.run create mode 100644 ci/expected/lm3s6965/zero-prio-task.run create mode 100644 examples/hifive1/.cargo/config.toml create mode 100644 examples/hifive1/Cargo.lock create mode 100644 examples/hifive1/Cargo.toml create mode 100644 examples/hifive1/examples/prio_inheritance.rs create mode 100644 examples/hifive1/examples/static.rs create mode 100644 examples/hifive1/examples/task.rs create mode 100644 examples/hifive1/examples/zero_prio_task.rs create mode 100644 examples/hifive1/rust-toolchain.toml create mode 100644 examples/lm3s6965/.cargo/config.toml create mode 100644 examples/lm3s6965/Cargo.lock create mode 100644 examples/lm3s6965/Cargo.toml rename {rtic => examples/lm3s6965}/examples/async-channel-done.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-channel-no-receiver.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-channel-no-sender.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-channel-try.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-channel.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-delay.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-task-multiple-prios.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-task.rs (100%) rename {rtic => examples/lm3s6965}/examples/async-timeout.rs (100%) rename {rtic => examples/lm3s6965}/examples/big-struct-opt.rs (100%) rename {rtic => examples/lm3s6965}/examples/binds.rs (100%) rename {rtic => examples/lm3s6965}/examples/common.rs (100%) rename {rtic => examples/lm3s6965}/examples/complex.rs (100%) rename {rtic => examples/lm3s6965}/examples/declared_locals.rs (100%) rename {rtic => examples/lm3s6965}/examples/destructure.rs (100%) rename {rtic => examples/lm3s6965}/examples/executor-size.rs (100%) rename {rtic => examples/lm3s6965}/examples/extern_binds.rs (100%) rename {rtic => examples/lm3s6965}/examples/extern_spawn.rs (100%) rename {rtic => examples/lm3s6965}/examples/generics.rs (100%) rename {rtic => examples/lm3s6965}/examples/hardware.rs (100%) rename {rtic => examples/lm3s6965}/examples/idle-wfi.rs (100%) rename {rtic => examples/lm3s6965}/examples/idle.rs (100%) rename {rtic => examples/lm3s6965}/examples/init.rs (100%) rename {rtic => examples/lm3s6965}/examples/locals.rs (100%) rename {rtic => examples/lm3s6965}/examples/lock-free.rs (100%) rename {rtic => examples/lm3s6965}/examples/lock.rs (100%) rename {rtic => examples/lm3s6965}/examples/multilock.rs (100%) rename {rtic => examples/lm3s6965}/examples/not-sync.rs (100%) rename {rtic => examples/lm3s6965}/examples/only-shared-access.rs (100%) rename {rtic => examples/lm3s6965}/examples/peripherals-taken.rs (100%) rename {rtic => examples/lm3s6965}/examples/pool.rs_old (100%) rename {rtic => examples/lm3s6965}/examples/preempt.rs (100%) rename {rtic => examples/lm3s6965}/examples/prio-inversion.rs (100%) rename {rtic => examples/lm3s6965}/examples/ramfunc.rs (100%) rename {rtic => examples/lm3s6965}/examples/resource-user-struct.rs (100%) rename {rtic => examples/lm3s6965}/examples/shared.rs (100%) rename {rtic => examples/lm3s6965}/examples/smallest.rs (100%) rename {rtic => examples/lm3s6965}/examples/spawn.rs (100%) rename {rtic => examples/lm3s6965}/examples/spawn_arguments.rs (100%) rename {rtic => examples/lm3s6965}/examples/spawn_err.rs (100%) rename {rtic => examples/lm3s6965}/examples/spawn_loop.rs (100%) rename {rtic => examples/lm3s6965}/examples/static.rs (100%) rename {rtic => examples/lm3s6965}/examples/t-binds.rs (100%) rename {rtic => examples/lm3s6965}/examples/t-cfg-resources.rs (100%) rename {rtic => examples/lm3s6965}/examples/t-htask-main.rs (100%) rename {rtic => examples/lm3s6965}/examples/t-idle-main.rs (100%) rename {rtic => examples/lm3s6965}/examples/t-late-not-send.rs (100%) rename {rtic => examples/lm3s6965}/examples/task.rs (100%) rename {rtic => examples/lm3s6965}/examples/zero-prio-task.rs (100%) create mode 100644 rtic-macros/src/codegen/bindings/riscv_slic.rs create mode 100644 rtic-macros/src/codegen/extra_mods.rs create mode 100644 rtic-macros/src/preprocess.rs create mode 100644 rtic-macros/src/syntax/backend.rs create mode 100644 rtic-macros/src/syntax/backend/cortex.rs create mode 100644 rtic-macros/src/syntax/backend/esp32c3.rs create mode 100644 rtic-macros/src/syntax/backend/riscv_slic.rs create mode 100644 rtic-macros/src/syntax/backend/template.rs create mode 100644 rtic/src/export/slic.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 578ca407b0..3a4ed8f536 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,9 +31,9 @@ jobs: - name: cargo xtask fmt run: cargo xtask --verbose fmt -c - # Compilation check - check: - name: check + # Compilation check (lm3s6965) + checklm3s6965: + name: check (lm3s6965) runs-on: ubuntu-22.04 strategy: matrix: @@ -62,11 +62,14 @@ jobs: - name: Cache Dependencies uses: Swatinem/rust-cache@v2 - - run: cargo xtask --deny-warnings --backend ${{ matrix.backend }} check + - run: cargo xtask --deny-warnings --platform lm3s6965 --backend ${{ matrix.backend }} check - # Clippy - clippy: - name: clippy + # Compilation check (hifive1) TODO + # checkhifive1: + + # Clippy (lm3s6965) + clippylm3s6965: + name: clippy (lm3s6965) runs-on: ubuntu-22.04 strategy: matrix: @@ -98,11 +101,14 @@ jobs: - name: Cache Dependencies uses: Swatinem/rust-cache@v2 - - run: cargo xtask --deny-warnings --backend ${{ matrix.backend }} clippy + - run: cargo xtask --deny-warnings --platform lm3s6965 --backend ${{ matrix.backend }} clippy - # Verify all examples, checks - checkexamples: - name: check examples + # Clippy (hifive1) TODO + # clippyhifive1: + + # Platform lm3s6965: verify all examples, checks + checkexampleslm3s6965: + name: check examples (lm3s6965) runs-on: ubuntu-22.04 strategy: matrix: @@ -133,44 +139,46 @@ jobs: - name: Check the examples if: ${{ matrix.backend == 'thumbv8-base' }} - run: cargo xtask --backend ${{ matrix.backend }} --exampleexclude pool example-check + run: cargo xtask --platform lm3s6965 --backend ${{ matrix.backend }} --exampleexclude pool example-check - name: Check the examples if: ${{ matrix.backend != 'thumbv8-base' }} - run: cargo xtask --backend ${{ matrix.backend }} example-check - - # Check that the usage examples build - usageexamples: - name: Build usage examples + run: cargo xtask --platform lm3s6965 --backend ${{ matrix.backend }} example-check + + # Platform hifive1: verify all examples, checks + checkexampleshifive1: + name: check examples (hifive1) runs-on: ubuntu-22.04 strategy: matrix: + backend: + - riscv32-imc-clint + - riscv32-imac-clint toolchain: - stable steps: - name: Checkout uses: actions/checkout@v4 - - name: Install rust ${{ matrix.toolchain }} + - name: Install Rust ${{ matrix.toolchain }} run: | - rustup set profile minimal rustup override set ${{ matrix.toolchain }} - - name: Configure rust target (v6, v7) + - name: Configure Rust target run: | - rustup target add thumbv7em-none-eabihf - rustup target add thumbv7m-none-eabi - rustup target add thumbv6m-none-eabi - rustup component add rust-src + rustup target add riscv32imac-unknown-none-elf + rustup target add riscv32imc-unknown-none-elf - name: Cache Dependencies uses: Swatinem/rust-cache@v2 - - - name: Install flip-link - run: cargo install flip-link + + - name: Check the examples + if: ${{ matrix.backend == 'riscv32-imc-clint' }} + run: cargo xtask --platform hifive1 --backend ${{ matrix.backend }} --exampleexclude static example-check - name: Check the examples - run: cargo xtask usage-example-build + if: ${{ matrix.backend != 'riscv32-imc-clint' }} + run: cargo xtask --platform hifive1 --backend ${{ matrix.backend }} example-check buildqemu: name: Get modern QEMU, build and store @@ -192,7 +200,7 @@ jobs: - name: Install QEMU to get dependencies run: | sudo apt update - sudo apt install -y qemu-system-arm + sudo apt install -y qemu-system-arm qemu-system-riscv32 sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build - if: ${{ steps.cache-qemu.outputs.cache-hit != 'true' }} @@ -226,9 +234,9 @@ jobs: name: qemu path: qemu.tar - # Verify the example output with run-pass tests - testexamples: - name: QEMU run + # Platform lm3s6965: verify the example output with run-pass tests + testexampleslm3s6965: + name: QEMU run (lm3s6965) needs: buildqemu runs-on: ubuntu-22.04 strategy: @@ -283,7 +291,71 @@ jobs: which qemu-system-riscv32 - name: Run-pass tests - run: cargo xtask --deny-warnings --backend ${{ matrix.backend }} qemu + run: cargo xtask --deny-warnings --platform lm3s6965 --backend ${{ matrix.backend }} qemu + + # Platform hifive1: verify the example output with run-pass tests + testexampleshifive1: + name: QEMU run (hifive1) + needs: buildqemu + runs-on: ubuntu-22.04 + strategy: + matrix: + backend: + - riscv32-imc-clint + - riscv32-imac-clint + toolchain: + - stable + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust ${{ matrix.toolchain }} + run: | + rustup set profile minimal + rustup override set ${{ matrix.toolchain }} + + - name: Configure Rust target + run: | + rustup target add riscv32imac-unknown-none-elf + rustup target add riscv32imc-unknown-none-elf + + - name: Add Rust component llvm-tools-preview + run: rustup component add llvm-tools-preview + + # Use precompiled binutils + - name: Install cargo-binutils + uses: taiki-e/install-action@v2 + with: + tool: cargo-binutils + + - name: Cache Dependencies + uses: Swatinem/rust-cache@v2 + + - name: Install QEMU to get dependencies + run: | + sudo apt update + sudo apt install -y qemu-system-riscv32 + + - name: Download built QEMU + uses: actions/download-artifact@v4 + with: + name: qemu + + - name: Extract QEMU into local path + run: tar -xf qemu.tar -C /usr/local/bin + + - name: Check which QEMU is used + run: | + which qemu-system-arm + which qemu-system-riscv32 + + - name: Run-pass tests + if: ${{ matrix.backend == 'riscv32-imc-clint' }} + run: cargo xtask --deny-warnings --platform hifive1 --backend ${{ matrix.backend }} --exampleexclude static qemu + + - name: Run-pass tests + if: ${{ matrix.backend != 'riscv32-imc-clint' }} + run: cargo xtask --deny-warnings --platform hifive1 --backend ${{ matrix.backend }} qemu # Run test suite tests: @@ -719,10 +791,14 @@ jobs: if: github.event_name == 'push' && success() needs: - formatcheck - - check - - clippy - - checkexamples - - testexamples + - checklm3s6965 + # checkhifive1 TODO + - clippylm3s6965 + # clippyhifive1 TODO + - checkexampleslm3s6965 + - checkexampleshifive1 + - testexampleslm3s6965 + - testexampleshifive1 - tests - docs - mdbook diff --git a/.gitignore b/.gitignore index d081dc3a5e..88b19b544e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ Cargo.lock *.hex book-target/ + +.DS_Store +.vscode/ diff --git a/ci/expected/hifive1/prio_inheritance.run b/ci/expected/hifive1/prio_inheritance.run new file mode 100644 index 0000000000..c60b241f27 --- /dev/null +++ b/ci/expected/hifive1/prio_inheritance.run @@ -0,0 +1,17 @@ +[Idle]: Started + [SoftMedium]: Started + [SoftMedium]: Shared: 1 + [SoftHigh]: Started + [SoftHigh]: Shared: 2 + [SoftHigh]: Finished + [SoftMedium]: Finished + [SoftLow1]: Started + [SoftLow1]: Shared: 3 + [SoftLow1]: Yield + [SoftLow2]: Started + [SoftLow2]: Shared: 4 + [SoftLow2]: Yield + [SoftLow1]: Finished + [SoftLow2]: Finished +[Idle]: Shared: 4 +[Idle]: Finished diff --git a/rtic/ci/expected/static.run b/ci/expected/hifive1/static.run similarity index 100% rename from rtic/ci/expected/static.run rename to ci/expected/hifive1/static.run diff --git a/rtic/ci/expected/task.run b/ci/expected/hifive1/task.run similarity index 100% rename from rtic/ci/expected/task.run rename to ci/expected/hifive1/task.run diff --git a/rtic/ci/expected/zero-prio-task.run b/ci/expected/hifive1/zero_prio_task.run similarity index 100% rename from rtic/ci/expected/zero-prio-task.run rename to ci/expected/hifive1/zero_prio_task.run diff --git a/rtic/ci/expected/async-channel-done.run b/ci/expected/lm3s6965/async-channel-done.run similarity index 100% rename from rtic/ci/expected/async-channel-done.run rename to ci/expected/lm3s6965/async-channel-done.run diff --git a/rtic/ci/expected/async-channel-no-receiver.run b/ci/expected/lm3s6965/async-channel-no-receiver.run similarity index 100% rename from rtic/ci/expected/async-channel-no-receiver.run rename to ci/expected/lm3s6965/async-channel-no-receiver.run diff --git a/rtic/ci/expected/async-channel-no-sender.run b/ci/expected/lm3s6965/async-channel-no-sender.run similarity index 100% rename from rtic/ci/expected/async-channel-no-sender.run rename to ci/expected/lm3s6965/async-channel-no-sender.run diff --git a/rtic/ci/expected/async-channel-try.run b/ci/expected/lm3s6965/async-channel-try.run similarity index 100% rename from rtic/ci/expected/async-channel-try.run rename to ci/expected/lm3s6965/async-channel-try.run diff --git a/rtic/ci/expected/async-channel.run b/ci/expected/lm3s6965/async-channel.run similarity index 100% rename from rtic/ci/expected/async-channel.run rename to ci/expected/lm3s6965/async-channel.run diff --git a/rtic/ci/expected/async-delay.run b/ci/expected/lm3s6965/async-delay.run similarity index 100% rename from rtic/ci/expected/async-delay.run rename to ci/expected/lm3s6965/async-delay.run diff --git a/rtic/ci/expected/async-infinite-loop.run b/ci/expected/lm3s6965/async-infinite-loop.run similarity index 100% rename from rtic/ci/expected/async-infinite-loop.run rename to ci/expected/lm3s6965/async-infinite-loop.run diff --git a/rtic/ci/expected/async-task-multiple-prios.run b/ci/expected/lm3s6965/async-task-multiple-prios.run similarity index 100% rename from rtic/ci/expected/async-task-multiple-prios.run rename to ci/expected/lm3s6965/async-task-multiple-prios.run diff --git a/rtic/ci/expected/async-task.run b/ci/expected/lm3s6965/async-task.run similarity index 100% rename from rtic/ci/expected/async-task.run rename to ci/expected/lm3s6965/async-task.run diff --git a/rtic/ci/expected/async-timeout.run b/ci/expected/lm3s6965/async-timeout.run similarity index 100% rename from rtic/ci/expected/async-timeout.run rename to ci/expected/lm3s6965/async-timeout.run diff --git a/rtic/ci/expected/big-struct-opt.run b/ci/expected/lm3s6965/big-struct-opt.run similarity index 100% rename from rtic/ci/expected/big-struct-opt.run rename to ci/expected/lm3s6965/big-struct-opt.run diff --git a/rtic/ci/expected/binds.run b/ci/expected/lm3s6965/binds.run similarity index 100% rename from rtic/ci/expected/binds.run rename to ci/expected/lm3s6965/binds.run diff --git a/rtic/ci/expected/cancel-reschedule.run b/ci/expected/lm3s6965/cancel-reschedule.run similarity index 100% rename from rtic/ci/expected/cancel-reschedule.run rename to ci/expected/lm3s6965/cancel-reschedule.run diff --git a/rtic/ci/expected/capacity.run b/ci/expected/lm3s6965/capacity.run similarity index 100% rename from rtic/ci/expected/capacity.run rename to ci/expected/lm3s6965/capacity.run diff --git a/rtic/ci/expected/cfg-whole-task.run b/ci/expected/lm3s6965/cfg-whole-task.run similarity index 100% rename from rtic/ci/expected/cfg-whole-task.run rename to ci/expected/lm3s6965/cfg-whole-task.run diff --git a/rtic/ci/expected/common.run b/ci/expected/lm3s6965/common.run similarity index 100% rename from rtic/ci/expected/common.run rename to ci/expected/lm3s6965/common.run diff --git a/rtic/ci/expected/complex.run b/ci/expected/lm3s6965/complex.run similarity index 100% rename from rtic/ci/expected/complex.run rename to ci/expected/lm3s6965/complex.run diff --git a/rtic/ci/expected/declared_locals.run b/ci/expected/lm3s6965/declared_locals.run similarity index 100% rename from rtic/ci/expected/declared_locals.run rename to ci/expected/lm3s6965/declared_locals.run diff --git a/rtic/ci/expected/destructure.run b/ci/expected/lm3s6965/destructure.run similarity index 100% rename from rtic/ci/expected/destructure.run rename to ci/expected/lm3s6965/destructure.run diff --git a/rtic/ci/expected/executor-size.run b/ci/expected/lm3s6965/executor-size.run similarity index 100% rename from rtic/ci/expected/executor-size.run rename to ci/expected/lm3s6965/executor-size.run diff --git a/rtic/ci/expected/extern_binds.run b/ci/expected/lm3s6965/extern_binds.run similarity index 100% rename from rtic/ci/expected/extern_binds.run rename to ci/expected/lm3s6965/extern_binds.run diff --git a/rtic/ci/expected/extern_spawn.run b/ci/expected/lm3s6965/extern_spawn.run similarity index 100% rename from rtic/ci/expected/extern_spawn.run rename to ci/expected/lm3s6965/extern_spawn.run diff --git a/rtic/ci/expected/generics.run b/ci/expected/lm3s6965/generics.run similarity index 100% rename from rtic/ci/expected/generics.run rename to ci/expected/lm3s6965/generics.run diff --git a/rtic/ci/expected/hardware.run b/ci/expected/lm3s6965/hardware.run similarity index 100% rename from rtic/ci/expected/hardware.run rename to ci/expected/lm3s6965/hardware.run diff --git a/rtic/ci/expected/idle-wfi.run b/ci/expected/lm3s6965/idle-wfi.run similarity index 100% rename from rtic/ci/expected/idle-wfi.run rename to ci/expected/lm3s6965/idle-wfi.run diff --git a/rtic/ci/expected/idle.run b/ci/expected/lm3s6965/idle.run similarity index 100% rename from rtic/ci/expected/idle.run rename to ci/expected/lm3s6965/idle.run diff --git a/rtic/ci/expected/init.run b/ci/expected/lm3s6965/init.run similarity index 100% rename from rtic/ci/expected/init.run rename to ci/expected/lm3s6965/init.run diff --git a/rtic/ci/expected/locals.run b/ci/expected/lm3s6965/locals.run similarity index 100% rename from rtic/ci/expected/locals.run rename to ci/expected/lm3s6965/locals.run diff --git a/rtic/ci/expected/lock-free.run b/ci/expected/lm3s6965/lock-free.run similarity index 100% rename from rtic/ci/expected/lock-free.run rename to ci/expected/lm3s6965/lock-free.run diff --git a/rtic/ci/expected/lock.run b/ci/expected/lm3s6965/lock.run similarity index 100% rename from rtic/ci/expected/lock.run rename to ci/expected/lm3s6965/lock.run diff --git a/rtic/ci/expected/message.run b/ci/expected/lm3s6965/message.run similarity index 100% rename from rtic/ci/expected/message.run rename to ci/expected/lm3s6965/message.run diff --git a/rtic/ci/expected/multilock.run b/ci/expected/lm3s6965/multilock.run similarity index 100% rename from rtic/ci/expected/multilock.run rename to ci/expected/lm3s6965/multilock.run diff --git a/rtic/ci/expected/not-sync.run b/ci/expected/lm3s6965/not-sync.run similarity index 100% rename from rtic/ci/expected/not-sync.run rename to ci/expected/lm3s6965/not-sync.run diff --git a/rtic/ci/expected/only-shared-access.run b/ci/expected/lm3s6965/only-shared-access.run similarity index 100% rename from rtic/ci/expected/only-shared-access.run rename to ci/expected/lm3s6965/only-shared-access.run diff --git a/rtic/ci/expected/periodic-at.run b/ci/expected/lm3s6965/periodic-at.run similarity index 100% rename from rtic/ci/expected/periodic-at.run rename to ci/expected/lm3s6965/periodic-at.run diff --git a/rtic/ci/expected/periodic-at2.run b/ci/expected/lm3s6965/periodic-at2.run similarity index 100% rename from rtic/ci/expected/periodic-at2.run rename to ci/expected/lm3s6965/periodic-at2.run diff --git a/rtic/ci/expected/periodic.run b/ci/expected/lm3s6965/periodic.run similarity index 100% rename from rtic/ci/expected/periodic.run rename to ci/expected/lm3s6965/periodic.run diff --git a/rtic/ci/expected/peripherals-taken.run b/ci/expected/lm3s6965/peripherals-taken.run similarity index 100% rename from rtic/ci/expected/peripherals-taken.run rename to ci/expected/lm3s6965/peripherals-taken.run diff --git a/rtic/ci/expected/pool.run b/ci/expected/lm3s6965/pool.run similarity index 100% rename from rtic/ci/expected/pool.run rename to ci/expected/lm3s6965/pool.run diff --git a/rtic/ci/expected/preempt.run b/ci/expected/lm3s6965/preempt.run similarity index 100% rename from rtic/ci/expected/preempt.run rename to ci/expected/lm3s6965/preempt.run diff --git a/rtic/ci/expected/prio-inversion.run b/ci/expected/lm3s6965/prio-inversion.run similarity index 100% rename from rtic/ci/expected/prio-inversion.run rename to ci/expected/lm3s6965/prio-inversion.run diff --git a/rtic/ci/expected/ramfunc.run b/ci/expected/lm3s6965/ramfunc.run similarity index 100% rename from rtic/ci/expected/ramfunc.run rename to ci/expected/lm3s6965/ramfunc.run diff --git a/rtic/ci/expected/ramfunc.run.grep.bar b/ci/expected/lm3s6965/ramfunc.run.grep.bar similarity index 100% rename from rtic/ci/expected/ramfunc.run.grep.bar rename to ci/expected/lm3s6965/ramfunc.run.grep.bar diff --git a/rtic/ci/expected/ramfunc.run.grep.foo b/ci/expected/lm3s6965/ramfunc.run.grep.foo similarity index 100% rename from rtic/ci/expected/ramfunc.run.grep.foo rename to ci/expected/lm3s6965/ramfunc.run.grep.foo diff --git a/rtic/ci/expected/resource-user-struct.run b/ci/expected/lm3s6965/resource-user-struct.run similarity index 100% rename from rtic/ci/expected/resource-user-struct.run rename to ci/expected/lm3s6965/resource-user-struct.run diff --git a/rtic/ci/expected/schedule.run b/ci/expected/lm3s6965/schedule.run similarity index 100% rename from rtic/ci/expected/schedule.run rename to ci/expected/lm3s6965/schedule.run diff --git a/rtic/ci/expected/shared.run b/ci/expected/lm3s6965/shared.run similarity index 100% rename from rtic/ci/expected/shared.run rename to ci/expected/lm3s6965/shared.run diff --git a/rtic/ci/expected/smallest.run b/ci/expected/lm3s6965/smallest.run similarity index 100% rename from rtic/ci/expected/smallest.run rename to ci/expected/lm3s6965/smallest.run diff --git a/rtic/ci/expected/spawn.run b/ci/expected/lm3s6965/spawn.run similarity index 100% rename from rtic/ci/expected/spawn.run rename to ci/expected/lm3s6965/spawn.run diff --git a/rtic/ci/expected/spawn_arguments.run b/ci/expected/lm3s6965/spawn_arguments.run similarity index 100% rename from rtic/ci/expected/spawn_arguments.run rename to ci/expected/lm3s6965/spawn_arguments.run diff --git a/rtic/ci/expected/spawn_err.run b/ci/expected/lm3s6965/spawn_err.run similarity index 100% rename from rtic/ci/expected/spawn_err.run rename to ci/expected/lm3s6965/spawn_err.run diff --git a/rtic/ci/expected/spawn_loop.run b/ci/expected/lm3s6965/spawn_loop.run similarity index 100% rename from rtic/ci/expected/spawn_loop.run rename to ci/expected/lm3s6965/spawn_loop.run diff --git a/ci/expected/lm3s6965/static.run b/ci/expected/lm3s6965/static.run new file mode 100644 index 0000000000..3d3f46f674 --- /dev/null +++ b/ci/expected/lm3s6965/static.run @@ -0,0 +1,3 @@ +received message: 1 +received message: 2 +received message: 3 diff --git a/rtic/ci/expected/t-binds.run b/ci/expected/lm3s6965/t-binds.run similarity index 100% rename from rtic/ci/expected/t-binds.run rename to ci/expected/lm3s6965/t-binds.run diff --git a/rtic/ci/expected/t-cfg-resources.run b/ci/expected/lm3s6965/t-cfg-resources.run similarity index 100% rename from rtic/ci/expected/t-cfg-resources.run rename to ci/expected/lm3s6965/t-cfg-resources.run diff --git a/rtic/ci/expected/t-htask-main.run b/ci/expected/lm3s6965/t-htask-main.run similarity index 100% rename from rtic/ci/expected/t-htask-main.run rename to ci/expected/lm3s6965/t-htask-main.run diff --git a/rtic/ci/expected/t-idle-main.run b/ci/expected/lm3s6965/t-idle-main.run similarity index 100% rename from rtic/ci/expected/t-idle-main.run rename to ci/expected/lm3s6965/t-idle-main.run diff --git a/rtic/ci/expected/t-late-not-send.run b/ci/expected/lm3s6965/t-late-not-send.run similarity index 100% rename from rtic/ci/expected/t-late-not-send.run rename to ci/expected/lm3s6965/t-late-not-send.run diff --git a/rtic/ci/expected/t-schedule.run b/ci/expected/lm3s6965/t-schedule.run similarity index 100% rename from rtic/ci/expected/t-schedule.run rename to ci/expected/lm3s6965/t-schedule.run diff --git a/rtic/ci/expected/t-spawn.run b/ci/expected/lm3s6965/t-spawn.run similarity index 100% rename from rtic/ci/expected/t-spawn.run rename to ci/expected/lm3s6965/t-spawn.run diff --git a/ci/expected/lm3s6965/task.run b/ci/expected/lm3s6965/task.run new file mode 100644 index 0000000000..de45dce64b --- /dev/null +++ b/ci/expected/lm3s6965/task.run @@ -0,0 +1,5 @@ +foo - start +foo - middle +baz +foo - end +bar diff --git a/ci/expected/lm3s6965/zero-prio-task.run b/ci/expected/lm3s6965/zero-prio-task.run new file mode 100644 index 0000000000..123b0f2687 --- /dev/null +++ b/ci/expected/lm3s6965/zero-prio-task.run @@ -0,0 +1,3 @@ +init +hello from async +hello from async2 diff --git a/examples/hifive1/.cargo/config.toml b/examples/hifive1/.cargo/config.toml new file mode 100644 index 0000000000..2ce90b25db --- /dev/null +++ b/examples/hifive1/.cargo/config.toml @@ -0,0 +1,11 @@ +[target.'cfg(all(target_arch = "riscv32", target_os = "none"))'] +runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel" +# runner = "riscv64-unknown-elf-gdb -q -x gdb_init" +rustflags = [ + "-C", "link-arg=-Thifive1-link.x", +] + +[build] +# Pick ONE of these compilation targets +# target = "riscv32imc-unknown-none-elf" # non-atomic support +target = "riscv32imac-unknown-none-elf" # atomic support (partial) diff --git a/examples/hifive1/Cargo.lock b/examples/hifive1/Cargo.lock new file mode 100644 index 0000000000..7cd694c719 --- /dev/null +++ b/examples/hifive1/Cargo.lock @@ -0,0 +1,364 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "e310x" +version = "0.11.0" +source = "git+https://github.com/greenlsi/e310x.git?branch=master#50536cc5be2fd6adf7f879f002fdd98f66fb05f9" +dependencies = [ + "critical-section", + "riscv-pac", + "riscv-peripheral", + "vcell", +] + +[[package]] +name = "e310x" +version = "0.11.0" +source = "git+https://github.com/greenlsi/e310x.git#50536cc5be2fd6adf7f879f002fdd98f66fb05f9" +dependencies = [ + "riscv-pac", + "riscv-peripheral", + "vcell", +] + +[[package]] +name = "e310x-hal" +version = "0.11.0" +source = "git+https://github.com/greenlsi/e310x-hal.git?branch=master#931aea7ab142c1eb9eaadd4150946d8452229f27" +dependencies = [ + "e310x 0.11.0 (git+https://github.com/greenlsi/e310x.git?branch=master)", + "embedded-hal 0.2.7", + "nb 1.1.0", + "portable-atomic", + "riscv", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "hifive1" +version = "0.11.0" +source = "git+https://github.com/romancardenas/hifive1.git#ef8cea8b90bddb04509785d3e148ff145137520a" +dependencies = [ + "e310x-hal", + "embedded-hal 0.2.7", + "nb 1.1.0", + "riscv", +] + +[[package]] +name = "indexmap" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "riscv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", +] + +[[package]] +name = "riscv-pac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18ceb4af23fdad434f938afdc35ce895a63d84f7333bb127d8065030848eb6a6" + +[[package]] +name = "riscv-peripheral" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c799fe4e144bd4dd0c68fa33a41c1485f19730eea505d195124636e1253358" +dependencies = [ + "embedded-hal 1.0.0", + "riscv", + "riscv-pac", +] + +[[package]] +name = "riscv-rt" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0d35e32cf1383183e8885d8a9aa4402a087fd094dc34c2cb6df6687d0229dfe" +dependencies = [ + "riscv", + "riscv-rt-macros", +] + +[[package]] +name = "riscv-rt-macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d100d466dbb76681ef6a9386f3da9abc570d57394e86da0ba5af8c4408486d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "riscv-slic" +version = "0.1.0" +source = "git+https://github.com/romancardenas/riscv-slic.git?rev=2a91edb#2a91edbff50bcc73169549923d278ff953d0986e" +dependencies = [ + "critical-section", + "heapless", + "riscv", + "riscv-slic-macros", +] + +[[package]] +name = "riscv-slic-macros" +version = "0.1.0" +source = "git+https://github.com/romancardenas/riscv-slic.git?rev=2a91edb#2a91edbff50bcc73169549923d278ff953d0986e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "rtic" +version = "2.1.0" +dependencies = [ + "atomic-polyfill", + "bare-metal", + "critical-section", + "riscv", + "riscv-slic", + "rtic-core", + "rtic-macros", +] + +[[package]] +name = "rtic-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42" + +[[package]] +name = "rtic-macros" +version = "2.1.0" +dependencies = [ + "indexmap", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "rtic_hifive1" +version = "0.1.0" +dependencies = [ + "e310x 0.11.0 (git+https://github.com/greenlsi/e310x.git)", + "heapless", + "hifive1", + "riscv", + "riscv-rt", + "rtic", + "semihosting", +] + +[[package]] +name = "semihosting" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab7a0be8d9e9893dfb5ce313aa0324396936d8bf788f5ef493c9f122ad84fd8" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/examples/hifive1/Cargo.toml b/examples/hifive1/Cargo.toml new file mode 100644 index 0000000000..42d60a7104 --- /dev/null +++ b/examples/hifive1/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rtic_hifive1" +categories = ["embedded", "no-std"] +description = "Examples of RTIC apps for the HiFive1 board" +license = "MIT OR Apache-2.0" +version = "0.1.0" +edition = "2021" + +[workspace] + +[dependencies] +rtic = { path = "../../rtic" } +heapless = "0.8.0" +hifive1 = { git = "https://github.com/romancardenas/hifive1.git", features = ["board-redv"] } +e310x = { git = "https://github.com/greenlsi/e310x.git", features = ["rt"]} +riscv-rt = {version = "0.12.1", features = ["single-hart"]} +riscv = "0.11.0" +semihosting = { version = "0.1", features = ["stdio", "panic-handler"] } + +[features] +riscv-clint-backend = ["rtic/riscv-clint-backend"] +test-critical-section = [] diff --git a/examples/hifive1/examples/prio_inheritance.rs b/examples/hifive1/examples/prio_inheritance.rs new file mode 100644 index 0000000000..5fc2399646 --- /dev/null +++ b/examples/hifive1/examples/prio_inheritance.rs @@ -0,0 +1,140 @@ +#![no_main] +#![no_std] + +use riscv_rt as _; + +#[rtic::app(device = e310x, backend = HART0)] +mod app { + use core::{future::Future, pin::Pin, task::Context, task::Poll}; + use hifive1::hal::prelude::*; + use semihosting::{println, process::exit}; + + /// Dummy asynchronous function to showcase SW tasks + pub async fn yield_now(task: &str) { + /// Yield implementation + struct YieldNow { + yielded: bool, + } + println!(" [{}]: Yield", task); + + impl Future for YieldNow { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.yielded { + return Poll::Ready(()); + } + + self.yielded = true; + cx.waker().wake_by_ref(); + + Poll::Pending + } + } + + YieldNow { yielded: false }.await + } + + #[shared] + struct Shared { + counter: u32, + } + + #[local] + struct Local {} + + #[init] + fn init(_: init::Context) -> (Shared, Local) { + // Pends the SoftLow interrupt but its handler won't run until *after* + // `init` returns because interrupts are disabled + let resources = unsafe { hifive1::hal::DeviceResources::steal() }; + let peripherals = resources.peripherals; + + let clocks = + hifive1::configure_clocks(peripherals.PRCI, peripherals.AONCLK, 64.mhz().into()); + let gpio = resources.pins; + + // Configure UART for stdout + hifive1::stdout::configure( + peripherals.UART0, + hifive1::pin!(gpio, uart0_tx), + hifive1::pin!(gpio, uart0_rx), + 115_200.bps(), + clocks, + ); + + (Shared { counter: 0 }, Local {}) + } + + #[idle(shared = [counter])] + fn idle(mut cx: idle::Context) -> ! { + println!("[Idle]: Started"); + // pend the medium priority SW task only once + soft_medium::spawn().unwrap(); + cx.shared.counter.lock(|counter| { + println!("[Idle]: Shared: {}", *counter); + }); + // exit QEMU simulator + println!("[Idle]: Finished"); + exit(0); + } + + /// Medium priority SW task. It is triggered by the idle and spawns the rest of the SW tasks + #[task(shared = [counter], priority = 2)] + async fn soft_medium(mut cx: soft_medium::Context) { + // Safe access to local `static mut` variable + println!(" [SoftMedium]: Started"); + cx.shared.counter.lock(|counter| { + // Spawn the other SW tasks INSIDE the critical section (just for showing priority inheritance) + soft_low_1::spawn().unwrap(); + soft_high::spawn().unwrap(); + soft_low_2::spawn().unwrap(); + + *counter += 1; + println!(" [SoftMedium]: Shared: {}", *counter); + }); + println!(" [SoftMedium]: Finished"); + } + + /// Low priority SW task. It runs cooperatively with soft_low_2 + #[task(shared = [counter], priority = 1)] + async fn soft_low_1(mut cx: soft_low_1::Context) { + println!(" [SoftLow1]: Started"); + cx.shared.counter.lock(|counter| { + *counter += 1; + println!(" [SoftLow1]: Shared: {}", *counter); + }); + // Yield to the other SW task + yield_now("SoftLow1").await; + + println!(" [SoftLow1]: Finished"); + } + + /// Low priority SW task. It runs cooperatively with soft_low_2 + #[task(shared = [counter], priority = 1)] + async fn soft_low_2(mut cx: soft_low_2::Context) { + println!(" [SoftLow2]: Started"); + cx.shared.counter.lock(|counter| { + *counter += 1; + println!(" [SoftLow2]: Shared: {}", *counter); + }); + + // Yield to the other SW task + yield_now("SoftLow2").await; + + println!(" [SoftLow2]: Finished"); + } + + /// High priority SW task + #[task(shared = [counter], priority = 3)] + async fn soft_high(mut cx: soft_high::Context) { + println!(" [SoftHigh]: Started"); + + cx.shared.counter.lock(|counter| { + *counter += 1; + println!(" [SoftHigh]: Shared: {}", counter); + }); + + println!(" [SoftHigh]: Finished"); + } +} diff --git a/examples/hifive1/examples/static.rs b/examples/hifive1/examples/static.rs new file mode 100644 index 0000000000..34e71c646c --- /dev/null +++ b/examples/hifive1/examples/static.rs @@ -0,0 +1,60 @@ +//! zero priority task +#![no_main] +#![no_std] +#![deny(warnings)] +#![deny(unsafe_code)] +#![deny(missing_docs)] + +use hifive1 as _; +use riscv_rt as _; + +#[rtic::app(device = e310x, backend = HART0)] +mod app { + use semihosting::{process::exit, println}; + use heapless::spsc::{Consumer, Producer, Queue}; + + #[shared] + struct Shared {} + + #[local] + struct Local { + p: Producer<'static, u32, 5>, + c: Consumer<'static, u32, 5>, + } + + #[init(local = [q: Queue = Queue::new()])] + fn init(cx: init::Context) -> (Shared, Local) { + // q has 'static life-time so after the split and return of `init` + // it will continue to exist and be allocated + let (p, c) = cx.local.q.split(); + + foo::spawn().unwrap(); + + (Shared {}, Local { p, c }) + } + + #[idle(local = [c])] + fn idle(c: idle::Context) -> ! { + loop { + // Lock-free access to the same underlying queue! + if let Some(data) = c.local.c.dequeue() { + println!("received message: {}", data); + + // Run foo until data + if data == 3 { + exit(0); // Exit QEMU simulator + } else { + foo::spawn().unwrap(); + } + } + } + } + + #[task(local = [p, state: u32 = 0], priority = 1)] + async fn foo(c: foo::Context) { + *c.local.state += 1; + + // Lock-free access to the same underlying queue! + c.local.p.enqueue(*c.local.state).unwrap(); + } +} diff --git a/examples/hifive1/examples/task.rs b/examples/hifive1/examples/task.rs new file mode 100644 index 0000000000..6968edb221 --- /dev/null +++ b/examples/hifive1/examples/task.rs @@ -0,0 +1,57 @@ +//! zero priority task +#![no_main] +#![no_std] +#![deny(warnings)] +#![deny(unsafe_code)] +#![deny(missing_docs)] + +use hifive1 as _; +use riscv_rt as _; + +#[rtic::app(device = e310x, backend = HART0)] +mod app { + use semihosting::{println, process::exit}; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(_: init::Context) -> (Shared, Local) { + foo::spawn().unwrap(); + + (Shared {}, Local {}) + } + + #[task] + async fn foo(_: foo::Context) { + println!("foo - start"); + + // spawns `bar` onto the task scheduler + // `foo` and `bar` have the same priority so `bar` will not run until + // after `foo` terminates + bar::spawn().unwrap(); + + println!("foo - middle"); + + // spawns `baz` onto the task scheduler + // `baz` has higher priority than `foo` so it immediately preempts `foo` + baz::spawn().unwrap(); + + println!("foo - end"); + } + + #[task] + async fn bar(_: bar::Context) { + println!("bar"); + + exit(0); // Exit QEMU simulator + } + + #[task(priority = 2)] + async fn baz(_: baz::Context) { + println!("baz"); + } +} diff --git a/examples/hifive1/examples/zero_prio_task.rs b/examples/hifive1/examples/zero_prio_task.rs new file mode 100644 index 0000000000..2528c4fa15 --- /dev/null +++ b/examples/hifive1/examples/zero_prio_task.rs @@ -0,0 +1,61 @@ +//! zero priority task +#![no_main] +#![no_std] +#![deny(warnings)] +#![deny(unsafe_code)] +#![deny(missing_docs)] + +use core::marker::PhantomData; +use hifive1 as _; +use riscv_rt as _; + +/// Does not impl send +pub struct NotSend { + _0: PhantomData<*const ()>, +} + +#[rtic::app(device = e310x, backend = HART0)] +mod app { + use super::NotSend; + use core::marker::PhantomData; + use semihosting::{println, process::exit}; + + #[shared] + struct Shared { + x: NotSend, + } + + #[local] + struct Local { + y: NotSend, + } + + #[init] + fn init(_cx: init::Context) -> (Shared, Local) { + println!("init"); + + async_task::spawn().unwrap(); + async_task2::spawn().unwrap(); + + ( + Shared { + x: NotSend { _0: PhantomData }, + }, + Local { + y: NotSend { _0: PhantomData }, + }, + ) + } + + #[task(priority = 0, shared = [x], local = [y])] + async fn async_task(_: async_task::Context) { + println!("hello from async"); + } + + #[task(priority = 0, shared = [x])] + async fn async_task2(_: async_task2::Context) { + println!("hello from async2"); + + exit(0); // Exit QEMU simulator + } +} diff --git a/examples/hifive1/rust-toolchain.toml b/examples/hifive1/rust-toolchain.toml new file mode 100644 index 0000000000..3dc1c7e8c9 --- /dev/null +++ b/examples/hifive1/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "stable" +components = [ "rust-src", "rustfmt" ] +targets = [ "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf" ] diff --git a/examples/lm3s6965/.cargo/config.toml b/examples/lm3s6965/.cargo/config.toml new file mode 100644 index 0000000000..46b5177ed0 --- /dev/null +++ b/examples/lm3s6965/.cargo/config.toml @@ -0,0 +1,13 @@ +[target.thumbv6m-none-eabi] +runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" + +[target.thumbv7m-none-eabi] +runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" + +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[build] +target = "thumbv7m-none-eabi" diff --git a/examples/lm3s6965/Cargo.lock b/examples/lm3s6965/Cargo.lock new file mode 100644 index 0000000000..696c606ea2 --- /dev/null +++ b/examples/lm3s6965/Cargo.lock @@ -0,0 +1,527 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cortex-m-semihosting" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0" +dependencies = [ + "cortex-m", +] + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-bus" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b4e6ede84339ebdb418cd986e6320a34b017cdf99b5cc3efceec6450b06886" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "embedded-hal-async", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fugit" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" +dependencies = [ + "gcd", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "lm3s6965" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d7ed5360fee8fd434cf7995ef1d7ad42697abb538e34383a39da8df5495446" +dependencies = [ + "cortex-m", + "cortex-m-rt", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "panic-semihosting" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8a3e1233d9073d76a870223512ce4eeea43c067a94a445c13bd6d792d7b1ab" +dependencies = [ + "cortex-m", + "cortex-m-semihosting", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rtic" +version = "2.1.0" +dependencies = [ + "atomic-polyfill", + "bare-metal 1.0.0", + "cortex-m", + "critical-section", + "rtic-core", + "rtic-macros", + "rtic-monotonics", +] + +[[package]] +name = "rtic-common" +version = "1.0.1" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "rtic-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42" + +[[package]] +name = "rtic-macros" +version = "2.1.0" +dependencies = [ + "indexmap", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "rtic-monotonics" +version = "1.5.0" +dependencies = [ + "atomic-polyfill", + "cfg-if", + "cortex-m", + "embedded-hal 1.0.0", + "fugit", + "rtic-time", +] + +[[package]] +name = "rtic-sync" +version = "1.3.0" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-bus", + "heapless", + "portable-atomic", + "rtic-common", +] + +[[package]] +name = "rtic-time" +version = "1.3.0" +dependencies = [ + "critical-section", + "futures-util", + "rtic-common", +] + +[[package]] +name = "rtic_lm3s6965" +version = "0.1.0" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "cortex-m-semihosting", + "futures", + "heapless", + "lm3s6965", + "panic-semihosting", + "rtic", + "rtic-monotonics", + "rtic-sync", + "rtic-time", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] diff --git a/examples/lm3s6965/Cargo.toml b/examples/lm3s6965/Cargo.toml new file mode 100644 index 0000000000..86a7cbbb66 --- /dev/null +++ b/examples/lm3s6965/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "rtic_lm3s6965" +categories = ["embedded", "no-std"] +description = "Examples of RTIC apps for the lm3s6965 chip" +license = "MIT OR Apache-2.0" +version = "0.1.0" +edition = "2021" + +[workspace] + +[dependencies] +heapless = "0.8" +lm3s6965 = "0.2" +cortex-m = "0.7.0" +bare-metal = "1.0.0" +cortex-m-semihosting = "0.5.0" +rtic-time = { path = "../../rtic-time" } +rtic-sync = { path = "../../rtic-sync" } +rtic-monotonics = { path = "../../rtic-monotonics", features = ["cortex-m-systick"] } +rtic = { path = "../../rtic" } + +[dependencies.futures] +version = "0.3.26" +default-features = false +features = ["async-await"] + +[dependencies.panic-semihosting] +features = ["exit"] +version = "0.6.0" + +[features] +test-critical-section = ["rtic/test-critical-section"] +thumbv6-backend = ["rtic/thumbv6-backend"] +thumbv7-backend = ["rtic/thumbv7-backend"] +thumbv8base-backend = ["rtic/thumbv8base-backend"] +thumbv8main-backend = ["rtic/thumbv8main-backend"] diff --git a/rtic/examples/async-channel-done.rs b/examples/lm3s6965/examples/async-channel-done.rs similarity index 100% rename from rtic/examples/async-channel-done.rs rename to examples/lm3s6965/examples/async-channel-done.rs diff --git a/rtic/examples/async-channel-no-receiver.rs b/examples/lm3s6965/examples/async-channel-no-receiver.rs similarity index 100% rename from rtic/examples/async-channel-no-receiver.rs rename to examples/lm3s6965/examples/async-channel-no-receiver.rs diff --git a/rtic/examples/async-channel-no-sender.rs b/examples/lm3s6965/examples/async-channel-no-sender.rs similarity index 100% rename from rtic/examples/async-channel-no-sender.rs rename to examples/lm3s6965/examples/async-channel-no-sender.rs diff --git a/rtic/examples/async-channel-try.rs b/examples/lm3s6965/examples/async-channel-try.rs similarity index 100% rename from rtic/examples/async-channel-try.rs rename to examples/lm3s6965/examples/async-channel-try.rs diff --git a/rtic/examples/async-channel.rs b/examples/lm3s6965/examples/async-channel.rs similarity index 100% rename from rtic/examples/async-channel.rs rename to examples/lm3s6965/examples/async-channel.rs diff --git a/rtic/examples/async-delay.rs b/examples/lm3s6965/examples/async-delay.rs similarity index 100% rename from rtic/examples/async-delay.rs rename to examples/lm3s6965/examples/async-delay.rs diff --git a/rtic/examples/async-task-multiple-prios.rs b/examples/lm3s6965/examples/async-task-multiple-prios.rs similarity index 100% rename from rtic/examples/async-task-multiple-prios.rs rename to examples/lm3s6965/examples/async-task-multiple-prios.rs diff --git a/rtic/examples/async-task.rs b/examples/lm3s6965/examples/async-task.rs similarity index 100% rename from rtic/examples/async-task.rs rename to examples/lm3s6965/examples/async-task.rs diff --git a/rtic/examples/async-timeout.rs b/examples/lm3s6965/examples/async-timeout.rs similarity index 100% rename from rtic/examples/async-timeout.rs rename to examples/lm3s6965/examples/async-timeout.rs diff --git a/rtic/examples/big-struct-opt.rs b/examples/lm3s6965/examples/big-struct-opt.rs similarity index 100% rename from rtic/examples/big-struct-opt.rs rename to examples/lm3s6965/examples/big-struct-opt.rs diff --git a/rtic/examples/binds.rs b/examples/lm3s6965/examples/binds.rs similarity index 100% rename from rtic/examples/binds.rs rename to examples/lm3s6965/examples/binds.rs diff --git a/rtic/examples/common.rs b/examples/lm3s6965/examples/common.rs similarity index 100% rename from rtic/examples/common.rs rename to examples/lm3s6965/examples/common.rs diff --git a/rtic/examples/complex.rs b/examples/lm3s6965/examples/complex.rs similarity index 100% rename from rtic/examples/complex.rs rename to examples/lm3s6965/examples/complex.rs diff --git a/rtic/examples/declared_locals.rs b/examples/lm3s6965/examples/declared_locals.rs similarity index 100% rename from rtic/examples/declared_locals.rs rename to examples/lm3s6965/examples/declared_locals.rs diff --git a/rtic/examples/destructure.rs b/examples/lm3s6965/examples/destructure.rs similarity index 100% rename from rtic/examples/destructure.rs rename to examples/lm3s6965/examples/destructure.rs diff --git a/rtic/examples/executor-size.rs b/examples/lm3s6965/examples/executor-size.rs similarity index 100% rename from rtic/examples/executor-size.rs rename to examples/lm3s6965/examples/executor-size.rs diff --git a/rtic/examples/extern_binds.rs b/examples/lm3s6965/examples/extern_binds.rs similarity index 100% rename from rtic/examples/extern_binds.rs rename to examples/lm3s6965/examples/extern_binds.rs diff --git a/rtic/examples/extern_spawn.rs b/examples/lm3s6965/examples/extern_spawn.rs similarity index 100% rename from rtic/examples/extern_spawn.rs rename to examples/lm3s6965/examples/extern_spawn.rs diff --git a/rtic/examples/generics.rs b/examples/lm3s6965/examples/generics.rs similarity index 100% rename from rtic/examples/generics.rs rename to examples/lm3s6965/examples/generics.rs diff --git a/rtic/examples/hardware.rs b/examples/lm3s6965/examples/hardware.rs similarity index 100% rename from rtic/examples/hardware.rs rename to examples/lm3s6965/examples/hardware.rs diff --git a/rtic/examples/idle-wfi.rs b/examples/lm3s6965/examples/idle-wfi.rs similarity index 100% rename from rtic/examples/idle-wfi.rs rename to examples/lm3s6965/examples/idle-wfi.rs diff --git a/rtic/examples/idle.rs b/examples/lm3s6965/examples/idle.rs similarity index 100% rename from rtic/examples/idle.rs rename to examples/lm3s6965/examples/idle.rs diff --git a/rtic/examples/init.rs b/examples/lm3s6965/examples/init.rs similarity index 100% rename from rtic/examples/init.rs rename to examples/lm3s6965/examples/init.rs diff --git a/rtic/examples/locals.rs b/examples/lm3s6965/examples/locals.rs similarity index 100% rename from rtic/examples/locals.rs rename to examples/lm3s6965/examples/locals.rs diff --git a/rtic/examples/lock-free.rs b/examples/lm3s6965/examples/lock-free.rs similarity index 100% rename from rtic/examples/lock-free.rs rename to examples/lm3s6965/examples/lock-free.rs diff --git a/rtic/examples/lock.rs b/examples/lm3s6965/examples/lock.rs similarity index 100% rename from rtic/examples/lock.rs rename to examples/lm3s6965/examples/lock.rs diff --git a/rtic/examples/multilock.rs b/examples/lm3s6965/examples/multilock.rs similarity index 100% rename from rtic/examples/multilock.rs rename to examples/lm3s6965/examples/multilock.rs diff --git a/rtic/examples/not-sync.rs b/examples/lm3s6965/examples/not-sync.rs similarity index 100% rename from rtic/examples/not-sync.rs rename to examples/lm3s6965/examples/not-sync.rs diff --git a/rtic/examples/only-shared-access.rs b/examples/lm3s6965/examples/only-shared-access.rs similarity index 100% rename from rtic/examples/only-shared-access.rs rename to examples/lm3s6965/examples/only-shared-access.rs diff --git a/rtic/examples/peripherals-taken.rs b/examples/lm3s6965/examples/peripherals-taken.rs similarity index 100% rename from rtic/examples/peripherals-taken.rs rename to examples/lm3s6965/examples/peripherals-taken.rs diff --git a/rtic/examples/pool.rs_old b/examples/lm3s6965/examples/pool.rs_old similarity index 100% rename from rtic/examples/pool.rs_old rename to examples/lm3s6965/examples/pool.rs_old diff --git a/rtic/examples/preempt.rs b/examples/lm3s6965/examples/preempt.rs similarity index 100% rename from rtic/examples/preempt.rs rename to examples/lm3s6965/examples/preempt.rs diff --git a/rtic/examples/prio-inversion.rs b/examples/lm3s6965/examples/prio-inversion.rs similarity index 100% rename from rtic/examples/prio-inversion.rs rename to examples/lm3s6965/examples/prio-inversion.rs diff --git a/rtic/examples/ramfunc.rs b/examples/lm3s6965/examples/ramfunc.rs similarity index 100% rename from rtic/examples/ramfunc.rs rename to examples/lm3s6965/examples/ramfunc.rs diff --git a/rtic/examples/resource-user-struct.rs b/examples/lm3s6965/examples/resource-user-struct.rs similarity index 100% rename from rtic/examples/resource-user-struct.rs rename to examples/lm3s6965/examples/resource-user-struct.rs diff --git a/rtic/examples/shared.rs b/examples/lm3s6965/examples/shared.rs similarity index 100% rename from rtic/examples/shared.rs rename to examples/lm3s6965/examples/shared.rs diff --git a/rtic/examples/smallest.rs b/examples/lm3s6965/examples/smallest.rs similarity index 100% rename from rtic/examples/smallest.rs rename to examples/lm3s6965/examples/smallest.rs diff --git a/rtic/examples/spawn.rs b/examples/lm3s6965/examples/spawn.rs similarity index 100% rename from rtic/examples/spawn.rs rename to examples/lm3s6965/examples/spawn.rs diff --git a/rtic/examples/spawn_arguments.rs b/examples/lm3s6965/examples/spawn_arguments.rs similarity index 100% rename from rtic/examples/spawn_arguments.rs rename to examples/lm3s6965/examples/spawn_arguments.rs diff --git a/rtic/examples/spawn_err.rs b/examples/lm3s6965/examples/spawn_err.rs similarity index 100% rename from rtic/examples/spawn_err.rs rename to examples/lm3s6965/examples/spawn_err.rs diff --git a/rtic/examples/spawn_loop.rs b/examples/lm3s6965/examples/spawn_loop.rs similarity index 100% rename from rtic/examples/spawn_loop.rs rename to examples/lm3s6965/examples/spawn_loop.rs diff --git a/rtic/examples/static.rs b/examples/lm3s6965/examples/static.rs similarity index 100% rename from rtic/examples/static.rs rename to examples/lm3s6965/examples/static.rs diff --git a/rtic/examples/t-binds.rs b/examples/lm3s6965/examples/t-binds.rs similarity index 100% rename from rtic/examples/t-binds.rs rename to examples/lm3s6965/examples/t-binds.rs diff --git a/rtic/examples/t-cfg-resources.rs b/examples/lm3s6965/examples/t-cfg-resources.rs similarity index 100% rename from rtic/examples/t-cfg-resources.rs rename to examples/lm3s6965/examples/t-cfg-resources.rs diff --git a/rtic/examples/t-htask-main.rs b/examples/lm3s6965/examples/t-htask-main.rs similarity index 100% rename from rtic/examples/t-htask-main.rs rename to examples/lm3s6965/examples/t-htask-main.rs diff --git a/rtic/examples/t-idle-main.rs b/examples/lm3s6965/examples/t-idle-main.rs similarity index 100% rename from rtic/examples/t-idle-main.rs rename to examples/lm3s6965/examples/t-idle-main.rs diff --git a/rtic/examples/t-late-not-send.rs b/examples/lm3s6965/examples/t-late-not-send.rs similarity index 100% rename from rtic/examples/t-late-not-send.rs rename to examples/lm3s6965/examples/t-late-not-send.rs diff --git a/rtic/examples/task.rs b/examples/lm3s6965/examples/task.rs similarity index 100% rename from rtic/examples/task.rs rename to examples/lm3s6965/examples/task.rs diff --git a/rtic/examples/zero-prio-task.rs b/examples/lm3s6965/examples/zero-prio-task.rs similarity index 100% rename from rtic/examples/zero-prio-task.rs rename to examples/lm3s6965/examples/zero-prio-task.rs diff --git a/rtic-macros/CHANGELOG.md b/rtic-macros/CHANGELOG.md index 66bd9bc2c2..a0d761bb2e 100644 --- a/rtic-macros/CHANGELOG.md +++ b/rtic-macros/CHANGELOG.md @@ -11,6 +11,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top! ### Added +- Unstable support for RISC-V targets compatible with `riscv-slic` - RTIC v2 now works on stable. - Unstable ESP32-C3 support. diff --git a/rtic-macros/Cargo.toml b/rtic-macros/Cargo.toml index 423fe31129..443ed0d072 100644 --- a/rtic-macros/Cargo.toml +++ b/rtic-macros/Cargo.toml @@ -36,8 +36,8 @@ cortex-m-basepri = [] riscv-esp32c3 = [] # riscv-clic = [] # riscv-ch32 = [] - - +riscv-slic = [] + # backend API test test-template = [] diff --git a/rtic-macros/src/codegen.rs b/rtic-macros/src/codegen.rs index c04f2131f1..060db6d389 100644 --- a/rtic-macros/src/codegen.rs +++ b/rtic-macros/src/codegen.rs @@ -8,6 +8,7 @@ pub mod bindings; mod assertions; mod async_dispatchers; +mod extra_mods; mod hardware_tasks; mod idle; mod init; diff --git a/rtic-macros/src/codegen/async_dispatchers.rs b/rtic-macros/src/codegen/async_dispatchers.rs index 9144b2a3f1..3d166ca136 100644 --- a/rtic-macros/src/codegen/async_dispatchers.rs +++ b/rtic-macros/src/codegen/async_dispatchers.rs @@ -2,7 +2,7 @@ use crate::syntax::ast::App; use crate::{ analyze::Analysis, codegen::{ - bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit}, + bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit, interrupt_mod}, util, }, }; @@ -36,10 +36,9 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { }; let pend_interrupt = if level > 0 { - let device = &app.args.device; - let enum_ = util::interrupt_ident(); + let int_mod = interrupt_mod(app); - quote!(rtic::export::pend(#device::#enum_::#dispatcher_name);) + quote!(rtic::export::pend(#int_mod::#dispatcher_name);) } else { // For 0 priority tasks we don't need to pend anything quote!() diff --git a/rtic-macros/src/codegen/bindings.rs b/rtic-macros/src/codegen/bindings.rs index 60605f35d1..501ccdff98 100644 --- a/rtic-macros/src/codegen/bindings.rs +++ b/rtic-macros/src/codegen/bindings.rs @@ -2,7 +2,8 @@ feature = "cortex-m-source-masking", feature = "cortex-m-basepri", feature = "test-template", - feature = "riscv-esp32c3" + feature = "riscv-esp32c3", + feature = "riscv-slic", )))] compile_error!("No backend selected"); @@ -22,4 +23,10 @@ mod template; pub use esp32c3::*; #[cfg(feature = "riscv-esp32c3")] -mod esp32c3; \ No newline at end of file +mod esp32c3; + +#[cfg(feature = "riscv-slic")] +pub use riscv_slic::*; + +#[cfg(feature = "riscv-slic")] +mod riscv_slic; diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs index 69b5ee553e..5c56261db5 100644 --- a/rtic-macros/src/codegen/bindings/cortex.rs +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -35,6 +35,12 @@ pub fn interrupt_ident() -> Ident { Ident::new("interrupt", span) } +pub fn interrupt_mod(app: &App) -> TokenStream2 { + let device = &app.args.device; + let interrupt = interrupt_ident(); + quote!(#device::#interrupt) +} + pub fn check_stack_overflow_before_init( _app: &App, _analysis: &CodegenAnalysis, @@ -199,12 +205,16 @@ mod basepri { } } +pub fn pre_init_preprocessing(_app: &mut App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + Ok(()) +} + pub fn pre_init_checks(app: &App, _: &SyntaxAnalysis) -> Vec { let mut stmts = vec![]; // check that all dispatchers exists in the `Interrupt` enumeration regardless of whether // they are used or not - let interrupt = util::interrupt_ident(); + let interrupt = interrupt_ident(); let rt_err = util::rt_err_ident(); for name in app.args.dispatchers.keys() { @@ -217,7 +227,7 @@ pub fn pre_init_checks(app: &App, _: &SyntaxAnalysis) -> Vec { pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec { let mut stmts = vec![]; - let interrupt = util::interrupt_ident(); + let interrupt = interrupt_ident(); let rt_err = util::rt_err_ident(); let device = &app.args.device; let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS); @@ -381,3 +391,7 @@ pub fn handler_config( ) -> Vec { vec![] } + +pub fn extra_modules(_app: &App, _analysis: &SyntaxAnalysis) -> Vec { + vec![] +} diff --git a/rtic-macros/src/codegen/bindings/esp32c3.rs b/rtic-macros/src/codegen/bindings/esp32c3.rs index 4b14caed43..f8ea22a34c 100644 --- a/rtic-macros/src/codegen/bindings/esp32c3.rs +++ b/rtic-macros/src/codegen/bindings/esp32c3.rs @@ -55,10 +55,20 @@ mod esp32c3 { Ident::new("Interrupt", span) } + pub fn interrupt_mod(app: &App) -> TokenStream2 { + let device = &app.args.device; + let interrupt = interrupt_ident(); + quote!(#device::#interrupt) + } + pub fn extra_assertions(_: &App, _: &SyntaxAnalysis) -> Vec { vec![] } + pub fn pre_init_preprocessing(_app: &mut App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + Ok(()) + } + pub fn pre_init_checks(app: &App, _: &SyntaxAnalysis) -> Vec { let mut stmts = vec![]; // check that all dispatchers exists in the `Interrupt` enumeration regardless of whether @@ -232,3 +242,7 @@ mod esp32c3 { stmts } } + +pub fn extra_modules(_app: &App, _analysis: &SyntaxAnalysis) -> Vec { + vec![] +} diff --git a/rtic-macros/src/codegen/bindings/riscv_slic.rs b/rtic-macros/src/codegen/bindings/riscv_slic.rs new file mode 100644 index 0000000000..c9bf50adbf --- /dev/null +++ b/rtic-macros/src/codegen/bindings/riscv_slic.rs @@ -0,0 +1,255 @@ +use crate::{ + analyze::Analysis as CodegenAnalysis, + syntax::{ + analyze::Analysis as SyntaxAnalysis, + ast::{App, Dispatcher}, + }, +}; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use std::{collections::HashSet, vec}; +use syn::{parse, Attribute, Ident}; + +/// Utility function to get the SLIC interrupt module. +pub fn interrupt_ident() -> Ident { + let span = Span::call_site(); + Ident::new("Interrupt", span) +} + +pub fn interrupt_mod(_app: &App) -> TokenStream2 { + let interrupt = interrupt_ident(); + quote!(slic::#interrupt) +} + +/// This macro implements the [`rtic::Mutex`] trait for shared resources using the SLIC. +#[allow(clippy::too_many_arguments)] +pub fn impl_mutex( + _app: &App, + _analysis: &CodegenAnalysis, + cfgs: &[Attribute], + resources_prefix: bool, + name: &Ident, + ty: &TokenStream2, + ceiling: u8, + ptr: &TokenStream2, +) -> TokenStream2 { + let path = if resources_prefix { + quote!(shared_resources::#name) + } else { + quote!(#name) + }; + + quote!( + #(#cfgs)* + impl<'a> rtic::Mutex for #path<'a> { + type T = #ty; + + #[inline(always)] + fn lock(&mut self, f: impl FnOnce(&mut #ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R { + + const CEILING: u8 = #ceiling; + + unsafe { + rtic::export::lock(#ptr, CEILING, f) + } + } + } + ) +} + +/// This macro is used to define additional compile-time assertions in case the platform needs it. +/// The Cortex-M implementations do not use it. Thus, we think we do not need it either. +pub fn extra_assertions(_app: &App, _analysis: &SyntaxAnalysis) -> Vec { + vec![] +} + +pub fn pre_init_preprocessing(app: &mut App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + app.args.core = false; // RISC-V SLIC is not compatible with using core peripherals + if !app.args.dispatchers.is_empty() { + return Err(parse::Error::new( + Span::call_site(), + "this backend does not support explicit interrupt dispatchers; remove the `dispatchers` argument from `#[app]`", + )); + } + + // Compute the number of handlers we need to dispatch the software tasks + let soft_priorities = app + .software_tasks + .iter() + .map(|(_, task)| task.args.priority) + .filter(|prio| *prio > 0) + .collect::>(); + + for i in 0..soft_priorities.len() { + let dispatcher_ident = Ident::new(&format!("__RTICDispatcher{}", i), Span::call_site()); + app.args + .dispatchers + .insert(dispatcher_ident, Dispatcher { attrs: vec![] }); + } + + Ok(()) +} + +/// This macro is used to check at run-time that all the interruption dispatchers exist. +pub fn pre_init_checks(app: &App, _analysis: &SyntaxAnalysis) -> Vec { + let mut stmts: Vec = vec![]; + let int_mod = interrupt_mod(app); + + // check that all dispatchers exists in the `slic::Interrupt` enumeration + for name in app.args.dispatchers.keys() { + stmts.push(quote!(let _ = #int_mod::#name;)); + } + + stmts +} + +/// This macro must perform all the required operations to activate the +/// interrupt sources with their corresponding priority level. +pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec { + let mut stmts = vec![]; + + // First, we reset and disable all the interrupt controllers + stmts.push(quote!(rtic::export::clear_interrupts();)); + + // Then, we set the corresponding priorities + let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); + for (&p, name) in interrupt_ids.chain( + app.hardware_tasks + .values() + .map(|task| (&task.args.priority, &task.args.binds)), + ) { + stmts.push(quote!( + rtic::export::set_priority(slic::Interrupt::#name, #p); + )); + } + // Finally, we activate the interrupts + stmts.push(quote!(rtic::export::set_interrupts();)); + stmts +} + +/// Any additional checks that depend on the system architecture. +pub fn architecture_specific_analysis(app: &App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + // Check that there are enough external interrupts to dispatch the software tasks and the timer queue handler + let mut first = None; + let priorities = app + .software_tasks + .iter() + .map(|(name, task)| { + first = Some(name); + task.args.priority + }) + .filter(|prio| *prio > 0) + .collect::>(); + + let need = priorities.len(); + let given = app.args.dispatchers.len(); + if need > given { + let s = { + format!( + "not enough interrupts to dispatch \ + all software tasks (need: {need}; given: {given})" + ) + }; + + return Err(parse::Error::new(first.unwrap().span(), s)); + } + + if app.args.backend.is_none() { + return Err(parse::Error::new( + Span::call_site(), + "SLIC requires backend-specific configuration", + )); + } + + Ok(()) +} + +/// Macro to add statements to be executed at the beginning of all the interrupt handlers. +pub fn interrupt_entry(_app: &App, _analysis: &CodegenAnalysis) -> Vec { + vec![] +} + +/// Macro to add statements to be executed at the end of all the interrupt handlers. +pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec { + vec![] +} + +pub fn check_stack_overflow_before_init( + _app: &App, + _analysis: &CodegenAnalysis, +) -> Vec { + vec![quote!( + // Check for stack overflow using symbols from `risc-v-rt`. + extern "C" { + pub static _stack_start: u32; + pub static _ebss: u32; + } + + let stack_start = &_stack_start as *const _ as u32; + let ebss = &_ebss as *const _ as u32; + + if stack_start > ebss { + // No flip-link usage, check the SP for overflow. + if rtic::export::read_sp() <= ebss { + panic!("Stack overflow after allocating executors"); + } + } + )] +} + +pub fn async_entry( + _app: &App, + _analysis: &CodegenAnalysis, + _dispatcher_name: Ident, +) -> Vec { + vec![] +} + +/// Macro to define a maximum priority level for async tasks. +pub fn async_prio_limit(_app: &App, analysis: &CodegenAnalysis) -> Vec { + let max = if let Some(max) = analysis.max_async_prio { + quote!(#max) + } else { + quote!(u8::MAX) // No limit + }; + + vec![quote!( + /// Holds the maximum priority level for use by async HAL drivers. + #[no_mangle] + static RTIC_ASYNC_MAX_LOGICAL_PRIO: u8 = #max; + )] +} + +pub fn handler_config( + _app: &App, + _analysis: &CodegenAnalysis, + _dispatcher_name: Ident, +) -> Vec { + vec![] +} + +/// The SLIC requires us to call to the [`riscv_rtic::codegen`] macro to generate +/// the appropriate SLIC structure, interrupt enumerations, etc. +pub fn extra_modules(app: &App, _analysis: &SyntaxAnalysis) -> Vec { + let mut stmts = vec![]; + + let hw_slice: Vec<_> = app + .hardware_tasks + .values() + .map(|task| &task.args.binds) + .collect(); + let sw_slice: Vec<_> = app.args.dispatchers.keys().collect(); + + let swi_slice: Vec<_> = hw_slice.iter().chain(sw_slice.iter()).collect(); + + let device = &app.args.device; + + stmts.push(quote!( + use rtic::export::riscv_slic; + )); + let hart_id = &app.args.backend.as_ref().unwrap().hart_id; + + stmts.push(quote!(rtic::export::codegen!(pac = #device, swi = [#(#swi_slice,)*], backend = [hart_id = #hart_id]);)); + + stmts +} diff --git a/rtic-macros/src/codegen/bindings/template.rs b/rtic-macros/src/codegen/bindings/template.rs index b5488b7ce9..ecb46d5613 100644 --- a/rtic-macros/src/codegen/bindings/template.rs +++ b/rtic-macros/src/codegen/bindings/template.rs @@ -6,40 +6,55 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::{parse, Attribute, Ident}; +pub fn interrupt_ident() -> Ident { + let span = Span::call_site(); + Ident::new("interrupt", span) +} + +pub fn interrupt_mod(app: &App) -> TokenStream2 { + let device = &app.args.device; + let interrupt = interrupt_ident(); + quote!(#device::#interrupt) +} + pub fn impl_mutex( - _app: &App, - _analysis: &CodegenAnalysis, - _cfgs: &[Attribute], - _resources_prefix: bool, - _name: &Ident, - _ty: &TokenStream2, - _ceiling: u8, - _ptr: &TokenStream2, + app: &App, + analysis: &CodegenAnalysis, + cfgs: &[Attribute], + resources_prefix: bool, + name: &Ident, + ty: &TokenStream2, + ceiling: u8, + ptr: &TokenStream2, ) -> TokenStream2 { quote!() } -pub fn extra_assertions(_app: &App, _analysis: &SyntaxAnalysis) -> Vec { +pub fn extra_assertions(app: &App, analysis: &SyntaxAnalysis) -> Vec { vec![] } -pub fn pre_init_checks(_app: &App, _analysis: &SyntaxAnalysis) -> Vec { - vec![] -} - -pub fn pre_init_enable_interrupts(_app: &App, _analysis: &CodegenAnalysis) -> Vec { - vec![] -} - -pub fn architecture_specific_analysis(_app: &App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { +pub fn pre_init_preprocessing(app: &mut App, analysis: &SyntaxAnalysis) -> parse::Result<()> { Ok(()) } -pub fn interrupt_entry(_app: &App, _analysis: &CodegenAnalysis) -> Vec { +pub fn pre_init_checks(app: &App, analysis: &SyntaxAnalysis) -> Vec { vec![] } -pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec { +pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec { + vec![] +} + +pub fn architecture_specific_analysis(app: &App, analysis: &SyntaxAnalysis) -> parse::Result<()> { + Ok(()) +} + +pub fn interrupt_entry(app: &App, analysis: &CodegenAnalysis) -> Vec { + vec![] +} + +pub fn interrupt_exit(app: &App, analysis: &CodegenAnalysis) -> Vec { vec![] } @@ -51,20 +66,25 @@ pub fn check_stack_overflow_before_init( } pub fn async_entry( - _app: &App, - _analysis: &CodegenAnalysis, - _dispatcher_name: Ident, -) -> Vec { - vec![] -} - -pub fn async_prio_limit(app: &App, _analysis: &CodegenAnalysis) -> Vec { - vec![] -} -pub fn handler_config( - _app: &App, - _analysis: &CodegenAnalysis, + app: &App, + analysis: &CodegenAnalysis, dispatcher_name: Ident, ) -> Vec { vec![] } + +pub fn async_prio_limit(app: &App, analysis: &CodegenAnalysis) -> Vec { + vec![] +} + +pub fn handler_config( + app: &App, + analysis: &CodegenAnalysis, + dispatcher_name: Ident, +) -> Vec { + vec![] +} + +pub fn extra_modules(app: &App, analysis: &SyntaxAnalysis) -> Vec { + vec![] +} diff --git a/rtic-macros/src/codegen/extra_mods.rs b/rtic-macros/src/codegen/extra_mods.rs new file mode 100644 index 0000000000..b92dda6771 --- /dev/null +++ b/rtic-macros/src/codegen/extra_mods.rs @@ -0,0 +1,9 @@ +use super::bindings::extra_modules; +use crate::analyze::Analysis; +use crate::syntax::ast::App; +use proc_macro2::TokenStream as TokenStream2; + +/// Generates code that runs before `#[init]` +pub fn codegen(app: &App, analysis: &Analysis) -> Vec { + extra_modules(app, analysis) +} diff --git a/rtic-macros/src/codegen/main.rs b/rtic-macros/src/codegen/main.rs index 56127962b4..80f2cf6b8a 100644 --- a/rtic-macros/src/codegen/main.rs +++ b/rtic-macros/src/codegen/main.rs @@ -1,4 +1,3 @@ -use super::{assertions, post_init, pre_init}; use crate::{ analyze::Analysis, codegen::{bindings, util}, @@ -7,8 +6,12 @@ use crate::{ use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use super::{assertions, extra_mods, post_init, pre_init}; + /// Generates code for `fn main` pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { + let extra_mods_stmts = extra_mods::codegen(app, analysis); + let assertion_stmts = assertions::codegen(app, analysis); let pre_init_stmts = pre_init::codegen(app, analysis); @@ -40,9 +43,18 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { let main = util::suffixed("main"); let init_name = &app.init.name; + + let init_args = if app.args.core { + quote!(core.into(), executors_size) + } else { + quote!(executors_size) + }; + let msp_check = bindings::check_stack_overflow_before_init(app, analysis); quote!( + #(#extra_mods_stmts)* + #[doc(hidden)] #[no_mangle] unsafe extern "C" fn #main() -> ! { @@ -63,7 +75,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { // Wrap late_init_stmts in a function to ensure that stack space is reclaimed. __rtic_init_resources(||{ - let (shared_resources, local_resources) = #init_name(#init_name::Context::new(core.into(), executors_size)); + let (shared_resources, local_resources) = #init_name(#init_name::Context::new(#init_args)); #(#post_init_stmts)* }); diff --git a/rtic-macros/src/codegen/module.rs b/rtic-macros/src/codegen/module.rs index c8afe076fa..17c8ce7dfd 100644 --- a/rtic-macros/src/codegen/module.rs +++ b/rtic-macros/src/codegen/module.rs @@ -1,5 +1,5 @@ use crate::syntax::{ast::App, Context}; -use crate::{analyze::Analysis, codegen::util}; +use crate::{analyze::Analysis, codegen::bindings::interrupt_mod, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; @@ -16,16 +16,20 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { match ctxt { Context::Init => { - fields.push(quote!( - /// Core peripherals - pub core: rtic::export::Peripherals - )); - fields.push(quote!( /// The space used to allocate async executors in bytes. pub executors_size: usize )); + if app.args.core { + fields.push(quote!( + /// Core peripherals + pub core: rtic::export::Peripherals + )); + + values.push(quote!(core: core)); + } + if app.args.peripherals { let device = &app.args.device; @@ -43,8 +47,6 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { )); values.push(quote!(cs: rtic::export::CriticalSection::new())); - - values.push(quote!(core)); values.push(quote!(executors_size)); } @@ -98,7 +100,11 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { }; let core = if ctxt.is_init() { - Some(quote!(core: rtic::export::Peripherals, executors_size: usize)) + if app.args.core { + Some(quote!(core: rtic::export::Peripherals, executors_size: usize)) + } else { + Some(quote!(executors_size: usize)) + } } else { None }; @@ -144,10 +150,9 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { task_cfgs = cfgs.clone(); let pend_interrupt = if priority > 0 { - let device = &app.args.device; - let enum_ = util::interrupt_ident(); + let int_mod = interrupt_mod(app); let interrupt = &analysis.interrupts.get(&priority).expect("UREACHABLE").0; - quote!(rtic::export::pend(#device::#enum_::#interrupt);) + quote!(rtic::export::pend(#int_mod::#interrupt);) } else { quote!() }; diff --git a/rtic-macros/src/codegen/pre_init.rs b/rtic-macros/src/codegen/pre_init.rs index a2d0e8c135..8de75ffd34 100644 --- a/rtic-macros/src/codegen/pre_init.rs +++ b/rtic-macros/src/codegen/pre_init.rs @@ -11,10 +11,12 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec { // Disable interrupts -- `init` must run with interrupts disabled stmts.push(quote!(rtic::export::interrupt::disable();)); - stmts.push(quote!( - // To set the variable in cortex_m so the peripherals cannot be taken multiple times - let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into(); - )); + if app.args.core { + stmts.push(quote!( + // To set the variable in cortex_m so the peripherals cannot be taken multiple times + let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into(); + )); + } stmts.append(&mut pre_init_checks(app, analysis)); diff --git a/rtic-macros/src/codegen/util.rs b/rtic-macros/src/codegen/util.rs index b4682ee8b5..dda7e29035 100644 --- a/rtic-macros/src/codegen/util.rs +++ b/rtic-macros/src/codegen/util.rs @@ -3,8 +3,6 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{Ident, PatType}; -//hook the target specific interrupt_ident function -pub use super::bindings::interrupt_ident; const RTIC_INTERNAL: &str = "__rtic_internal"; diff --git a/rtic-macros/src/lib.rs b/rtic-macros/src/lib.rs index 38eed8f3b2..c464ab0481 100644 --- a/rtic-macros/src/lib.rs +++ b/rtic-macros/src/lib.rs @@ -14,13 +14,14 @@ macro_rules! with_backend { feature = "cortex-m-source-masking", feature = "cortex-m-basepri", feature = "test-template", - feature = "riscv-esp32c3" + feature = "riscv-esp32c3", + feature = "riscv-slic", ))] $($tokens)* }; } -with_backend! { mod: [analyze, check, codegen, syntax] } +with_backend! { mod: [analyze, check, codegen, preprocess, syntax] } with_backend! { use std::{fs, env, path::Path}; } with_backend! { use proc_macro::TokenStream; } @@ -47,11 +48,18 @@ with_backend! { /// Should never panic, cargo feeds a path which is later converted to a string #[proc_macro_attribute] pub fn app(_args: TokenStream, _input: TokenStream) -> TokenStream { - let (app, analysis) = match syntax::parse(_args, _input) { + let (mut app, analysis) = match syntax::parse(_args, _input) { Err(e) => return e.to_compile_error().into(), Ok(x) => x, }; + // Modify app based on backend before continuing + if let Err(e) = preprocess::app(&mut app, &analysis) { + return e.to_compile_error().into(); + } + let app = app; + // App is not mutable after this point + if let Err(e) = check::app(&app, &analysis) { return e.to_compile_error().into(); } @@ -109,6 +117,7 @@ with_backend! { feature = "cortex-m-source-masking", feature = "cortex-m-basepri", feature = "test-template", - feature = "riscv-esp32c3" + feature = "riscv-esp32c3", + feature = "riscv-slic", )))] compile_error!("Cannot compile. No backend feature selected."); diff --git a/rtic-macros/src/preprocess.rs b/rtic-macros/src/preprocess.rs new file mode 100644 index 0000000000..2fcd10b3a3 --- /dev/null +++ b/rtic-macros/src/preprocess.rs @@ -0,0 +1,7 @@ +use crate::codegen::bindings::pre_init_preprocessing; +use crate::syntax::{analyze::Analysis, ast::App}; +use syn::parse; + +pub fn app(app: &mut App, analysis: &Analysis) -> parse::Result<()> { + pre_init_preprocessing(app, analysis) +} diff --git a/rtic-macros/src/syntax.rs b/rtic-macros/src/syntax.rs index d6f5a476b5..a44b1ec71e 100644 --- a/rtic-macros/src/syntax.rs +++ b/rtic-macros/src/syntax.rs @@ -12,6 +12,7 @@ use crate::syntax::ast::App; mod accessors; pub mod analyze; pub mod ast; +mod backend; mod check; mod parse; diff --git a/rtic-macros/src/syntax/ast.rs b/rtic-macros/src/syntax/ast.rs index f0067b8ece..06feb1fae6 100644 --- a/rtic-macros/src/syntax/ast.rs +++ b/rtic-macros/src/syntax/ast.rs @@ -2,7 +2,7 @@ use syn::{Attribute, Expr, Ident, Item, ItemUse, Pat, PatType, Path, Stmt, Type}; -use crate::syntax::Map; +use crate::syntax::{backend::BackendArgs, Map}; /// The `#[app]` attribute #[derive(Debug)] @@ -60,11 +60,17 @@ pub struct AppArgs { /// Device pub device: Path, - /// Peripherals + /// Core peripherals + pub core: bool, + + /// Device peripherals pub peripherals: bool, /// Interrupts used to dispatch software tasks pub dispatchers: Dispatchers, + + /// Backend-specific arguments + pub backend: Option, } /// The `init`-ialization function diff --git a/rtic-macros/src/syntax/backend.rs b/rtic-macros/src/syntax/backend.rs new file mode 100644 index 0000000000..460ef560bf --- /dev/null +++ b/rtic-macros/src/syntax/backend.rs @@ -0,0 +1,32 @@ +#[cfg(not(any( + feature = "cortex-m-source-masking", + feature = "cortex-m-basepri", + feature = "test-template", + feature = "riscv-esp32c3", + feature = "riscv-slic", +)))] +compile_error!("No backend selected"); + +#[cfg(any(feature = "cortex-m-source-masking", feature = "cortex-m-basepri"))] +pub use cortex::*; + +#[cfg(feature = "test-template")] +pub use template::*; + +#[cfg(feature = "riscv-esp32c3")] +pub use esp32c3::*; + +#[cfg(feature = "riscv-slic")] +pub use riscv_slic::*; + +#[cfg(any(feature = "cortex-m-source-masking", feature = "cortex-m-basepri"))] +mod cortex; + +#[cfg(feature = "test-template")] +mod template; + +#[cfg(feature = "riscv-esp32c3")] +mod esp32c3; + +#[cfg(feature = "riscv-slic")] +mod riscv_slic; diff --git a/rtic-macros/src/syntax/backend/cortex.rs b/rtic-macros/src/syntax/backend/cortex.rs new file mode 100644 index 0000000000..b53e927a61 --- /dev/null +++ b/rtic-macros/src/syntax/backend/cortex.rs @@ -0,0 +1,16 @@ +use syn::{ + parse::{Parse, ParseStream}, + Error, Result, +}; + +#[derive(Debug)] +pub struct BackendArgs(); + +impl Parse for BackendArgs { + fn parse(input: ParseStream) -> Result { + Err(Error::new( + input.span(), + "cortex backend does not accept any arguments", + )) + } +} diff --git a/rtic-macros/src/syntax/backend/esp32c3.rs b/rtic-macros/src/syntax/backend/esp32c3.rs new file mode 100644 index 0000000000..33143f4436 --- /dev/null +++ b/rtic-macros/src/syntax/backend/esp32c3.rs @@ -0,0 +1,16 @@ +use syn::{ + parse::{Parse, ParseStream}, + Error, Result, +}; + +#[derive(Debug)] +pub struct BackendArgs(); + +impl Parse for BackendArgs { + fn parse(input: ParseStream) -> Result { + Err(Error::new( + input.span(), + "esp32c3 backend does not accept any arguments", + )) + } +} diff --git a/rtic-macros/src/syntax/backend/riscv_slic.rs b/rtic-macros/src/syntax/backend/riscv_slic.rs new file mode 100644 index 0000000000..2ed8e7735d --- /dev/null +++ b/rtic-macros/src/syntax/backend/riscv_slic.rs @@ -0,0 +1,16 @@ +use syn::{ + parse::{Parse, ParseStream}, + Ident, Result, +}; + +#[derive(Debug)] +pub struct BackendArgs { + pub hart_id: Ident, +} + +impl Parse for BackendArgs { + fn parse(input: ParseStream) -> Result { + let hart_id = input.parse()?; + Ok(BackendArgs { hart_id }) + } +} diff --git a/rtic-macros/src/syntax/backend/template.rs b/rtic-macros/src/syntax/backend/template.rs new file mode 100644 index 0000000000..6dad114a1d --- /dev/null +++ b/rtic-macros/src/syntax/backend/template.rs @@ -0,0 +1,15 @@ +use syn::{ + parse::{Parse, ParseStream}, + Result, +}; + +#[derive(Debug)] +pub struct BackendArgs { + // Define your backend-specific input here +} + +impl Parse for BackendArgs { + fn parse(input: ParseStream) -> Result { + todo!("define how to parse your backend-specific arguments") + } +} diff --git a/rtic-macros/src/syntax/parse/app.rs b/rtic-macros/src/syntax/parse/app.rs index efcafbef2a..469bcb880c 100644 --- a/rtic-macros/src/syntax/parse/app.rs +++ b/rtic-macros/src/syntax/parse/app.rs @@ -13,6 +13,7 @@ use crate::syntax::{ App, AppArgs, Dispatcher, Dispatchers, HardwareTask, Idle, IdleArgs, Init, InitArgs, LocalResource, SharedResource, SoftwareTask, }, + backend::BackendArgs, parse::{self as syntax_parse, util}, Either, Map, Set, }; @@ -24,8 +25,10 @@ impl AppArgs { (|input: ParseStream<'_>| -> parse::Result { let mut custom = Set::new(); let mut device = None; + let mut core = true; let mut peripherals = true; let mut dispatchers = Dispatchers::new(); + let mut backend = None; loop { if input.is_empty() { @@ -59,6 +62,17 @@ impl AppArgs { } } + "core" => { + if let Ok(p) = input.parse::() { + core = p.value; + } else { + return Err(parse::Error::new( + ident.span(), + "unexpected argument value; this should be a boolean", + )); + } + } + "peripherals" => { if let Ok(p) = input.parse::() { peripherals = p.value; @@ -113,6 +127,18 @@ impl AppArgs { )); } } + + "backend" => { + if let Ok(p) = input.parse::() { + backend = Some(p); + } else { + return Err(parse::Error::new( + ident.span(), + "unable to parse backend configuration", + )); + } + } + _ => { return Err(parse::Error::new(ident.span(), "unexpected argument")); } @@ -134,8 +160,10 @@ impl AppArgs { Ok(AppArgs { device, + core, peripherals, dispatchers, + backend, }) }) .parse2(tokens) diff --git a/rtic-monotonics/CHANGELOG.md b/rtic-monotonics/CHANGELOG.md index af391434d7..ef5840fd63 100644 --- a/rtic-monotonics/CHANGELOG.md +++ b/rtic-monotonics/CHANGELOG.md @@ -9,6 +9,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top! ### Changed +- Tweak `build.rs` to avoid warnings in Nightly 1.78+ - Removed unused `rust-toolchain.toml` ## v1.5.0 - 2024-01-10 diff --git a/rtic/.cargo/config.toml b/rtic/.cargo/config.toml index ddec65047b..15958602d8 100644 --- a/rtic/.cargo/config.toml +++ b/rtic/.cargo/config.toml @@ -4,7 +4,13 @@ runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semiho [target.thumbv7m-none-eabi] runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" -[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +[target.riscv32imc-unknown-none-elf] +runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel" + +[target.riscv32imac-unknown-none-elf] +runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel" + +[target.'cfg(all(any(target_arch = "arm", target_arch = "riscv32"), target_os = "none"))'] rustflags = [ "-C", "link-arg=-Tlink.x", ] diff --git a/rtic/CHANGELOG.md b/rtic/CHANGELOG.md index 0f6e85dd72..c2cd678a78 100644 --- a/rtic/CHANGELOG.md +++ b/rtic/CHANGELOG.md @@ -17,6 +17,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top! ### Added +- Unstable support for RISC-V targets compatible with `riscv-slic` - Unstable support for ESP32-C3 ### Fixed diff --git a/rtic/Cargo.toml b/rtic/Cargo.toml index 2fcda6dbbd..f23c65000f 100644 --- a/rtic/Cargo.toml +++ b/rtic/Cargo.toml @@ -31,11 +31,12 @@ features = ["rtic-macros/test-template"] name = "rtic" [dependencies] +riscv-slic = { git = "https://github.com/romancardenas/riscv-slic.git", rev = "2a91edb", optional = true } esp32c3 = { version = "0.20.0", optional = true} riscv = {version = "0.11.0", optional = true} cortex-m = { version = "0.7.0", optional = true } bare-metal = "1.0.0" -#portable-atomic = { version = "0.3.19" } +# portable-atomic = { version = "0.3.19" } atomic-polyfill = "1" rtic-monotonics = { path = "../rtic-monotonics", version = "1.4.0", optional = true } rtic-macros = { path = "../rtic-macros", version = "=2.1.0" } @@ -43,12 +44,8 @@ rtic-core = "1" critical-section = "1" [dev-dependencies] -heapless = "0.8" lm3s6965 = "0.2" cortex-m-semihosting = "0.5.0" -rtic-time = { path = "../rtic-time" } -rtic-sync = { path = "../rtic-sync" } -rtic-monotonics = { path = "../rtic-monotonics", features = ["cortex-m-systick"] } [dev-dependencies.futures] version = "0.3.26" @@ -71,12 +68,7 @@ thumbv8main-backend = ["cortex-m", "rtic-macros/cortex-m-basepri"] # riscv-clic-backend = ["rtic-macros/riscv-clic"] # riscv-ch32-backend = ["rtic-macros/riscv-ch32"] riscv-esp32c3-backend = ["esp32c3", "riscv", "rtic-macros/riscv-esp32c3"] +riscv-clint-backend = ["riscv", "riscv-slic/clint-backend", "rtic-macros/riscv-slic"] # needed for testing -rtic-uitestv7 = ["thumbv7-backend"] -rtic-uitestv6 = ["thumbv6-backend"] test-critical-section = ["cortex-m/critical-section-single-core", "rtic-monotonics/systick-100hz"] - -# [[example]] -# name = "pool" -# required-features = ["test-critical-section"] diff --git a/rtic/build.rs b/rtic/build.rs index 6a02188558..8c87b568c1 100644 --- a/rtic/build.rs +++ b/rtic/build.rs @@ -1,27 +1,38 @@ use std::env; fn main() { - let target = env::var("TARGET").unwrap(); + // Get the backend feature selected by the user + let mut backends: Vec<_> = env::vars() + .filter_map(|(key, _value)| { + if key.starts_with("CARGO_FEATURE") && key.ends_with("BACKEND") { + // strip 'CARGO_FEATURE_', convert to lowercase, and replace '_' with '-' + Some(key[14..].to_lowercase().replace('_', "-")) + } else { + None + } + }) + .collect(); + if backends.len() > 1 { + panic!("More than one backend feature selected: {:?}", backends); + } + let backend = backends.pop().expect("No backend feature selected."); - // These targets all have know support for the BASEPRI register. - if target.starts_with("thumbv7m") - | target.starts_with("thumbv7em") - | target.starts_with("thumbv8m.main") - { - println!("cargo:rustc-cfg=feature=\"cortex-m-basepri\""); - } else if target.starts_with("thumbv6m") | target.starts_with("thumbv8m.base") { - println!("cargo:rustc-cfg=feature=\"cortex-m-source-masking\""); - //this should not be this general - //riscv processors differ in interrupt implementation - //even within the same target - //need some other way to discern - } else if target.starts_with("riscv32i") { - println!("cargo:rustc-cfg=feature=\"riscv-esp32c3\""); - - // TODO: Add feature here for risc-v targets - // println!("cargo:rustc-cfg=feature=\"riscv\""); - } else if target.starts_with("thumb") || target.starts_with("riscv32") { - panic!("Unknown target '{target}'. Need to update logic in build.rs."); + match backend.as_str() { + "thumbv6-backend" | "thumbv8base-backend" => { + println!("cargo:rustc-cfg=feature=\"cortex-m-source-masking\""); + } + "thumbv7-backend" | "thumbv8main-backend" => { + println!("cargo:rustc-cfg=feature=\"cortex-m-basepri\""); + } + "riscv-esp32c3-backend" => { + println!("cargo:rustc-cfg=feature=\"riscv-esp32c3\""); + } + "riscv-clint-backend" => { + println!("cargo:rustc-cfg=feature=\"riscv-slic\""); + } + _ => { + panic!("Unknown backend feature: {:?}", backend); + } } println!("cargo:rerun-if-changed=build.rs"); diff --git a/rtic/src/export.rs b/rtic/src/export.rs index 0fc995eac8..4fd8e7870a 100644 --- a/rtic/src/export.rs +++ b/rtic/src/export.rs @@ -12,41 +12,37 @@ pub use cortex_common::*; mod cortex_common; // Cortex-M target with basepri support -#[cfg(any(feature = "cortex-m-basepri", feature = "rtic-uitestv7"))] +#[cfg(feature = "cortex-m-basepri")] mod cortex_basepri; -#[cfg(any(feature = "cortex-m-basepri", feature = "rtic-uitestv7"))] +#[cfg(feature = "cortex-m-basepri")] pub use cortex_basepri::*; // Cortex-M target with source mask support -#[cfg(any(feature = "cortex-m-source-masking", feature = "rtic-uitestv6"))] +#[cfg(feature = "cortex-m-source-masking")] mod cortex_source_mask; -#[cfg(any(feature = "cortex-m-source-masking", feature = "rtic-uitestv6"))] +#[cfg(feature = "cortex-m-source-masking")] pub use cortex_source_mask::*; -// RISC-V target (any) #[cfg(feature = "riscv")] -pub use riscv_common::*; +pub mod riscv_common; #[cfg(feature = "riscv")] -mod riscv_common; +pub use riscv_common::*; #[cfg(feature = "riscv-esp32c3")] mod riscv_esp32c3; #[cfg(feature = "riscv-esp32c3")] pub use riscv_esp32c3::*; -#[inline(always)] -pub fn assert_send() -where - T: Send, -{ -} +#[cfg(feature = "riscv-slic")] +mod slic; +#[cfg(feature = "riscv-slic")] +pub use slic::*; #[inline(always)] -pub fn assert_sync() -where - T: Sync, -{ -} +pub fn assert_send() {} + +#[inline(always)] +pub fn assert_sync() {} diff --git a/rtic/src/export/riscv_common.rs b/rtic/src/export/riscv_common.rs index 6189335f0d..d3028b4d07 100644 --- a/rtic/src/export/riscv_common.rs +++ b/rtic/src/export/riscv_common.rs @@ -1,10 +1,9 @@ /// GENERIC RE-EXPORTS: needed for all RTIC backends -pub use riscv::interrupt; /// Read the stack pointer. #[inline(always)] pub fn read_sp() -> u32 { let r; - unsafe { asm!("mv {}, sp", out(reg) r, options(nomem, nostack, preserves_flags)) }; + unsafe { core::arch::asm!("mv {}, sp", out(reg) r, options(nomem, nostack, preserves_flags)) }; r } diff --git a/rtic/src/export/riscv_esp32c3.rs b/rtic/src/export/riscv_esp32c3.rs index de091135a7..5780d40729 100644 --- a/rtic/src/export/riscv_esp32c3.rs +++ b/rtic/src/export/riscv_esp32c3.rs @@ -1,5 +1,6 @@ use esp32c3::INTERRUPT_CORE0; //priority threshold control pub use esp32c3::{Interrupt, Peripherals}; +pub use riscv::interrupt; pub use riscv::register::mcause; //low level interrupt enable/disable #[cfg(all(feature = "riscv-esp32c3", not(feature = "riscv-esp32c3-backend")))] diff --git a/rtic/src/export/slic.rs b/rtic/src/export/slic.rs new file mode 100644 index 0000000000..f0c17a32cb --- /dev/null +++ b/rtic/src/export/slic.rs @@ -0,0 +1,19 @@ +pub use riscv_slic::{lock, pend, run, InterruptNumber}; + +#[cfg(all(feature = "riscv-slic", not(feature = "riscv-clint-backend")))] +compile_error!("Building for the riscv-slic, but 'riscv-clint-backend' not selected"); + +/// USE CASE RE-EXPORTS: needed for SLIC-only +pub use riscv_slic::{self, clear_interrupts, codegen, set_interrupts, set_priority}; + +pub mod interrupt { + pub fn disable() { + riscv_slic::disable(); + riscv_slic::clear_interrupts(); + } + + pub unsafe fn enable() { + riscv_slic::set_interrupts(); + riscv_slic::enable(); + } +} diff --git a/rtic/src/lib.rs b/rtic/src/lib.rs index bbdd5e23f1..2932c2284f 100644 --- a/rtic/src/lib.rs +++ b/rtic/src/lib.rs @@ -45,7 +45,6 @@ pub mod mutex { #[doc(hidden)] pub mod export; -#[cfg(feature = "cortex-m")] pub use export::pend; use core::cell::UnsafeCell; diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index 3893c610ea..a3a404f1e5 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -1,4 +1,7 @@ -use crate::{cargo_command::CargoCommand, Target, ARMV6M, ARMV7M, ARMV8MBASE, ARMV8MMAIN}; +use crate::{ + cargo_command::CargoCommand, Target, ARMV6M, ARMV7M, ARMV8MBASE, ARMV8MMAIN, RISCV32IMAC, + RISCV32IMC, +}; use clap::{Args, Parser, Subcommand}; use core::fmt; @@ -84,7 +87,7 @@ impl Package { }; features - .into_iter() + .iter() .map(ToString::to_string) .map(Some) .chain(std::iter::once(None)) @@ -101,12 +104,7 @@ impl TestMetadata { pub fn match_package(package: Package, backend: Backends) -> CargoCommand<'static> { match package { Package::Rtic => { - let features = format!( - "{},{}", - backend.to_rtic_feature(), - backend.to_rtic_uitest_feature() - ); - let features = Some(backend.to_target().and_features(&features)); + let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); CargoCommand::Test { package: Some(package.name()), features, @@ -155,6 +153,9 @@ pub enum Backends { Thumbv7, Thumbv8Base, Thumbv8Main, + RiscvEsp32C3, + Riscv32ImcClint, // not working yet (issues with portable-atomic features...) + Riscv32ImacClint, } impl Backends { @@ -165,6 +166,8 @@ impl Backends { Backends::Thumbv7 => ARMV7M, Backends::Thumbv8Base => ARMV8MBASE, Backends::Thumbv8Main => ARMV8MMAIN, + Backends::Riscv32ImcClint => RISCV32IMC, + Backends::RiscvEsp32C3 | Backends::Riscv32ImacClint => RISCV32IMAC, } } @@ -175,6 +178,8 @@ impl Backends { Backends::Thumbv7 => "thumbv7-backend", Backends::Thumbv8Base => "thumbv8base-backend", Backends::Thumbv8Main => "thumbv8main-backend", + Backends::RiscvEsp32C3 => "riscv-esp32c3-backend", + Backends::Riscv32ImcClint | Backends::Riscv32ImacClint => "riscv-clint-backend", } } #[allow(clippy::wrong_self_convention)] @@ -182,13 +187,8 @@ impl Backends { match self { Backends::Thumbv6 | Backends::Thumbv8Base => "cortex-m-source-masking", Backends::Thumbv7 | Backends::Thumbv8Main => "cortex-m-basepri", - } - } - #[allow(clippy::wrong_self_convention)] - pub fn to_rtic_uitest_feature(&self) -> &'static str { - match self { - Backends::Thumbv6 | Backends::Thumbv8Base => "rtic-uitestv6", - Backends::Thumbv7 | Backends::Thumbv8Main => "rtic-uitestv7", + Backends::RiscvEsp32C3 => "riscv-esp32c3", + Backends::Riscv32ImcClint | Backends::Riscv32ImacClint => "riscv-clint", } } } @@ -200,14 +200,127 @@ pub enum BuildOrCheck { Build, } +#[derive(clap::ValueEnum, Copy, Clone, Default, Debug)] +pub enum Platforms { + Hifive1, + #[default] + Lm3s6965, + Nrf52840, + Rp2040, + Stm32f3, + Stm32f411, + Teensy4, +} + +impl Platforms { + pub fn name(&self) -> String { + let name = match self { + Platforms::Hifive1 => "hifive1", + Platforms::Lm3s6965 => "lm3s6965", + Platforms::Nrf52840 => "nrf52840", + Platforms::Rp2040 => "rp2040", + Platforms::Stm32f3 => "stm32f3", + Platforms::Stm32f411 => "stm32f411", + Platforms::Teensy4 => "teensy4", + }; + name.to_string() + } + + /// Rust flags needed for the platform when building + pub fn rust_flags(&self) -> Vec { + let c = "-C".to_string(); + match self { + Platforms::Hifive1 => vec![c, "link-arg=-Thifive1-link.x".to_string()], + Platforms::Lm3s6965 => vec![c, "link-arg=-Tlink.x".to_string()], + Platforms::Nrf52840 => vec![ + c.clone(), + "linker=flip-link".to_string(), + c.clone(), + "link-arg=-Tlink.x".to_string(), + c.clone(), + "link-arg=-Tdefmt.x".to_string(), + c, + "link-arg=--nmagic".to_string(), + ], + Platforms::Rp2040 => vec![ + c.clone(), + "link-arg=--nmagic".to_string(), + c, + "link-arg=-Tlink.x".to_string(), + ], + Platforms::Stm32f3 => vec![ + c.clone(), + "link-arg=--nmagic".to_string(), + c, + "link-arg=-Tlink.x".to_string(), + ], + Platforms::Stm32f411 => vec![ + c.clone(), + "link-arg=-Tlink.x".to_string(), + c, + "link-arg=-Tdefmt.x".to_string(), + ], + Platforms::Teensy4 => vec![c, "link-arg=-Tt4link.x".to_string()], + } + } + + /// Get the default backend for the platform + pub fn default_backend(&self) -> Backends { + match self { + Platforms::Hifive1 => Backends::Riscv32ImcClint, + Platforms::Lm3s6965 => Backends::Thumbv7, + Platforms::Nrf52840 => unimplemented!(), + Platforms::Rp2040 => unimplemented!(), + Platforms::Stm32f3 => unimplemented!(), + Platforms::Stm32f411 => unimplemented!(), + Platforms::Teensy4 => unimplemented!(), + } + } + + /// Get the features needed given the selected platform and backend. + /// If the backend is not supported for the platform, return Err. + /// If the backend is supported, but no special features are needed, return Ok(None). + pub fn features(&self, backend: &Backends) -> Result, ()> { + match self { + Platforms::Hifive1 => match backend.to_target() { + RISCV32IMC | RISCV32IMAC => Ok(None), + _ => Err(()), + }, + Platforms::Lm3s6965 => match backend.to_target() { + ARMV6M => Ok(Some("thumbv6-backend")), + ARMV7M => Ok(Some("thumbv7-backend")), + ARMV8MBASE => Ok(Some("thumbv8base-backend")), + ARMV8MMAIN => Ok(Some("thumbv8main-backend")), + _ => Err(()), + }, + Platforms::Nrf52840 => unimplemented!(), + Platforms::Rp2040 => unimplemented!(), + Platforms::Stm32f3 => unimplemented!(), + Platforms::Stm32f411 => unimplemented!(), + Platforms::Teensy4 => unimplemented!(), + } + } +} + #[derive(Parser, Clone)] pub struct Globals { /// Error out on warnings #[arg(short = 'D', long)] pub deny_warnings: bool, + /// For which platform to build. + /// + /// If omitted, the default platform (i.e., lm3s6965) is used. + /// + /// Example: `cargo xtask --platform lm3s6965` + #[arg(value_enum, short, default_value = "lm3s6965", long, global = true)] + pub platform: Option, + /// For which backend to build. - #[arg(value_enum, short, default_value = "thumbv7", long, global = true)] + /// + /// If omitted, the default backend for the selected platform is used + /// (check [`Platforms::default_backend`]). + #[arg(value_enum, short, long, global = true)] pub backend: Option, /// List of comma separated examples to include, all others are excluded @@ -316,55 +429,6 @@ pub enum Commands { /// Build books with mdbook Book(Arg), - - /// Check one or more usage examples. - /// - /// Usage examples are located in ./examples - UsageExampleCheck(UsageExamplesOpt), - - /// Build one or more usage examples. - /// - /// Usage examples are located in ./examples - #[clap(alias = "./examples")] - UsageExampleBuild(UsageExamplesOpt), -} - -#[derive(Args, Clone, Debug)] -pub struct UsageExamplesOpt { - /// The usage examples to build. All usage examples are selected if this argument is not provided. - /// - /// Example: `rp2040_local_i2c_init,stm32f3_blinky`. - examples: Option, -} - -impl UsageExamplesOpt { - pub fn examples(&self) -> anyhow::Result> { - let usage_examples: Vec<_> = std::fs::read_dir("./examples")? - .filter_map(Result::ok) - .filter(|p| p.metadata().ok().map(|p| p.is_dir()).unwrap_or(false)) - .filter_map(|p| p.file_name().to_str().map(ToString::to_string)) - .collect(); - - let selected_examples: Option> = self - .examples - .clone() - .map(|s| s.split(",").map(ToString::to_string).collect()); - - if let Some(selected_examples) = selected_examples { - if let Some(unfound_example) = selected_examples - .iter() - .find(|e| !usage_examples.contains(e)) - { - Err(anyhow::anyhow!( - "Usage example {unfound_example} does not exist" - )) - } else { - Ok(selected_examples) - } - } else { - Ok(usage_examples) - } - } } #[derive(Args, Debug, Clone)] diff --git a/xtask/src/cargo_command.rs b/xtask/src/cargo_command.rs index c5387c2703..78e81b1d77 100644 --- a/xtask/src/cargo_command.rs +++ b/xtask/src/cargo_command.rs @@ -1,4 +1,4 @@ -use crate::{ExtraArguments, Target}; +use crate::{ExtraArguments, Platforms, Target}; use core::fmt; use std::path::PathBuf; @@ -15,6 +15,7 @@ pub enum CargoCommand<'a> { #[allow(dead_code)] Run { cargoarg: &'a Option<&'a str>, + platform: Platforms, // to tell which platform. If None, it assumes lm3s6965 example: &'a str, target: Option>, features: Option, @@ -23,6 +24,7 @@ pub enum CargoCommand<'a> { }, Qemu { cargoarg: &'a Option<&'a str>, + platform: Platforms, // to tell which platform. If None, it assumes lm3s6965 example: &'a str, target: Option>, features: Option, @@ -32,6 +34,7 @@ pub enum CargoCommand<'a> { }, ExampleBuild { cargoarg: &'a Option<&'a str>, + platform: Platforms, // to tell which platform. If None, it assumes lm3s6965 example: &'a str, target: Option>, features: Option, @@ -41,10 +44,12 @@ pub enum CargoCommand<'a> { }, ExampleCheck { cargoarg: &'a Option<&'a str>, + platform: Platforms, // to tell which platform. If None, it assumes lm3s6965 example: &'a str, target: Option>, features: Option, mode: BuildMode, + dir: Option, deny_warnings: bool, }, Build { @@ -94,6 +99,7 @@ pub enum CargoCommand<'a> { }, ExampleSize { cargoarg: &'a Option<&'a str>, + platform: Platforms, // to tell which platform. If None, it assumes lm3s6965 example: &'a str, target: Option>, features: Option, @@ -137,6 +143,7 @@ impl core::fmt::Display for CargoCommand<'_> { features: &Option, cargoarg: &&Option<&str>, path: Option<&PathBuf>, + // no need to add platform, as it is implicit in the path ) -> String { let feat = feat(features); let carg = carg(cargoarg); @@ -179,6 +186,7 @@ impl core::fmt::Display for CargoCommand<'_> { match self { CargoCommand::Run { cargoarg, + platform: _, example, target, features, @@ -193,6 +201,7 @@ impl core::fmt::Display for CargoCommand<'_> { } CargoCommand::Qemu { cargoarg, + platform: _, example, target, features, @@ -206,6 +215,7 @@ impl core::fmt::Display for CargoCommand<'_> { } CargoCommand::ExampleBuild { cargoarg, + platform: _, example, target, features, @@ -219,16 +229,18 @@ impl core::fmt::Display for CargoCommand<'_> { } CargoCommand::ExampleCheck { cargoarg, + platform: _, example, target, features, mode, + dir, deny_warnings, - } => write!( - f, - "Check example {example} {}", - details(*deny_warnings, target, Some(mode), features, cargoarg, None) - ), + } => { + let warns = *deny_warnings; + let details = details(warns, target, Some(mode), features, cargoarg, dir.as_ref()); + write!(f, "Check example {example} {details}",) + } CargoCommand::Build { cargoarg, package, @@ -329,17 +341,14 @@ impl core::fmt::Display for CargoCommand<'_> { .clone() .map(|t| format!("test {t}")) .unwrap_or("all tests".into()); - let deny_warnings = if *deny_warnings { - format!("deny warnings, ") - } else { - format!("") - }; - let feat = feat(features); - write!(f, "Run {test} in {p} ({deny_warnings}features: {feat})") + + let details = details(*deny_warnings, &None, None, features, &&None, None); + write!(f, "Run {test} in {p} {details}") } CargoCommand::Book { arguments: _ } => write!(f, "Build the book"), CargoCommand::ExampleSize { cargoarg, + platform: _, example, target, features, @@ -475,6 +484,7 @@ impl<'a> CargoCommand<'a> { // For future embedded-ci, for now the same as Qemu CargoCommand::Run { cargoarg, + platform: _, example, features, mode, @@ -491,6 +501,7 @@ impl<'a> CargoCommand<'a> { ), CargoCommand::Qemu { cargoarg, + platform: _, example, features, mode, @@ -606,6 +617,7 @@ impl<'a> CargoCommand<'a> { } CargoCommand::ExampleBuild { cargoarg, + platform: _, example, features, mode, @@ -624,9 +636,11 @@ impl<'a> CargoCommand<'a> { ), CargoCommand::ExampleCheck { cargoarg, + platform: _, example, features, mode, + dir: _, // Target is added by build_args target: _, // deny_warnings is exposed through `extra_env` @@ -640,6 +654,7 @@ impl<'a> CargoCommand<'a> { ), CargoCommand::ExampleSize { cargoarg, + platform: _, example, features, mode, @@ -664,6 +679,7 @@ impl<'a> CargoCommand<'a> { pub fn chdir(&self) -> Option<&PathBuf> { match self { CargoCommand::Qemu { dir, .. } + | CargoCommand::ExampleCheck { dir, .. } | CargoCommand::ExampleBuild { dir, .. } | CargoCommand::ExampleSize { dir, .. } | CargoCommand::Build { dir, .. } @@ -687,20 +703,35 @@ impl<'a> CargoCommand<'a> { } } - pub fn extra_env(&self) -> Option<(&str, &str)> { + pub fn extra_env(&self) -> Option<(&str, String)> { match self { // Clippy is a special case: it sets deny warnings // through an argument to rustc. CargoCommand::Clippy { .. } => None, - CargoCommand::Doc { .. } => Some(("RUSTDOCFLAGS", "-D warnings")), + CargoCommand::Doc { .. } => Some(("RUSTDOCFLAGS", "-D warnings".to_string())), - CargoCommand::Qemu { deny_warnings, .. } - | CargoCommand::ExampleBuild { deny_warnings, .. } - | CargoCommand::ExampleSize { deny_warnings, .. } => { + CargoCommand::Qemu { + platform, + deny_warnings, + .. + } + | CargoCommand::ExampleBuild { + platform, + deny_warnings, + .. + } + | CargoCommand::ExampleSize { + platform, + deny_warnings, + .. + } => { if *deny_warnings { + let rust_flags = platform.rust_flags().join(" "); + let rust_flags = format!("-D warnings {}", rust_flags); // NOTE: this also needs the link-arg because .cargo/config.toml // is ignored if you set the RUSTFLAGS env variable. - Some(("RUSTFLAGS", "-D warnings -C link-arg=-Tlink.x")) + Some(("RUSTFLAGS", rust_flags)) + // TODO make this configurable } else { None } @@ -711,7 +742,7 @@ impl<'a> CargoCommand<'a> { | CargoCommand::Build { deny_warnings, .. } | CargoCommand::Test { deny_warnings, .. } => { if *deny_warnings { - Some(("RUSTFLAGS", "-D warnings")) + Some(("RUSTFLAGS", "-D warnings".to_string())) } else { None } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 90ba13fbe7..0c56b4271e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -11,12 +11,12 @@ use std::{path::Path, str}; use log::{error, info, log_enabled, trace, Level}; use crate::{ - argument_parsing::{Backends, BuildOrCheck, Cli, Commands}, + argument_parsing::{BuildOrCheck, Cli, Commands, Platforms}, build::init_build_dir, run::*, }; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct Target<'a> { triple: &'a str, has_std: bool, @@ -54,6 +54,8 @@ const ARMV6M: Target = Target::new("thumbv6m-none-eabi", false); const ARMV7M: Target = Target::new("thumbv7m-none-eabi", false); const ARMV8MBASE: Target = Target::new("thumbv8m.base-none-eabi", false); const ARMV8MMAIN: Target = Target::new("thumbv8m.main-none-eabi", false); +const RISCV32IMC: Target = Target::new("riscv32imc-unknown-none-elf", false); +const RISCV32IMAC: Target = Target::new("riscv32imac-unknown-none-elf", false); fn main() -> anyhow::Result<()> { // if there's an `xtask` folder, we're *probably* at the root of this repo (we can't just @@ -65,13 +67,6 @@ fn main() -> anyhow::Result<()> { )); } - let examples: Vec<_> = std::fs::read_dir("./rtic/examples")? - .filter_map(|p| p.ok()) - .map(|p| p.path()) - .filter(|p| p.display().to_string().ends_with(".rs")) - .map(|path| path.file_stem().unwrap().to_str().unwrap().to_string()) - .collect(); - let cli = Cli::parse(); let globals = &cli.globals; @@ -94,12 +89,35 @@ fn main() -> anyhow::Result<()> { ); log::debug!("Partial features: {}", globals.partial); + let platform = if let Some(platform) = globals.platform { + platform + } else { + Platforms::default() + }; + let backend = if let Some(backend) = globals.backend { backend } else { - Backends::default() + platform.default_backend() }; + // Check if the platform supports the backend + if platform.features(&backend).is_err() { + return Err(anyhow::anyhow!( + "platform {:?} does not support backend {:?}", + platform, + backend + )); + } + + let examples_path = format!("./examples/{}/examples", platform.name()); + let examples: Vec<_> = std::fs::read_dir(examples_path)? + .filter_map(|p| p.ok()) + .map(|p| p.path()) + .filter(|p| p.display().to_string().ends_with(".rs")) + .map(|path| path.file_stem().unwrap().to_str().unwrap().to_string()) + .collect(); + let example = globals.example.clone(); let exampleexclude = globals.exampleexclude.clone(); @@ -163,42 +181,45 @@ fn main() -> anyhow::Result<()> { Commands::Format(args) => cargo_format(globals, &cargologlevel, &args.package, args.check), Commands::Clippy(args) => { info!("Running clippy on backend: {backend:?}"); - cargo_clippy(globals, &cargologlevel, &args, backend) + cargo_clippy(globals, &cargologlevel, args, backend) } Commands::Check(args) => { info!("Checking on backend: {backend:?}"); - cargo(globals, BuildOrCheck::Check, &cargologlevel, &args, backend) + cargo(globals, BuildOrCheck::Check, &cargologlevel, args, backend) } Commands::Build(args) => { info!("Building for backend: {backend:?}"); - cargo(globals, BuildOrCheck::Build, &cargologlevel, &args, backend) + cargo(globals, BuildOrCheck::Build, &cargologlevel, args, backend) } Commands::ExampleCheck => { - info!("Checking on backend: {backend:?}"); + info!("Checking on platform: {platform:?}, backend: {backend:?}"); cargo_example( globals, BuildOrCheck::Check, &cargologlevel, + platform, backend, &examples_to_run, ) } Commands::ExampleBuild => { - info!("Building for backend: {backend:?}"); + info!("Building for platform: {platform:?}, backend: {backend:?}"); cargo_example( globals, BuildOrCheck::Build, &cargologlevel, + platform, backend, &examples_to_run, ) } Commands::Size(args) => { // x86_64 target not valid - info!("Measuring for backend: {backend:?}"); + info!("Measuring for platform: {platform:?}, backend: {backend:?}"); build_and_check_size( globals, &cargologlevel, + platform, backend, &examples_to_run, &args.arguments, @@ -206,10 +227,11 @@ fn main() -> anyhow::Result<()> { } Commands::Qemu(args) | Commands::Run(args) => { // x86_64 target not valid - info!("Testing for backend: {backend:?}"); + info!("Testing for platform: {platform:?}, backend: {backend:?}"); qemu_run_examples( globals, &cargologlevel, + platform, backend, &examples_to_run, args.overwrite_expected, @@ -221,20 +243,12 @@ fn main() -> anyhow::Result<()> { } Commands::Test(args) => { info!("Running cargo test on backend: {backend:?}"); - cargo_test(globals, &args, backend) + cargo_test(globals, args, backend) } Commands::Book(args) => { info!("Running mdbook"); cargo_book(globals, &args.arguments) } - Commands::UsageExampleCheck(examples) => { - info!("Checking usage examples"); - cargo_usage_example(globals, BuildOrCheck::Check, examples.examples()?) - } - Commands::UsageExampleBuild(examples) => { - info!("Building usage examples"); - cargo_usage_example(globals, BuildOrCheck::Build, examples.examples()?) - } }; handle_results(globals, final_run_results).map_err(|_| anyhow::anyhow!("Commands failed")) diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 605755116d..ff81e6a256 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -15,7 +15,9 @@ mod iter; use iter::{into_iter, CoalescingRunner}; use crate::{ - argument_parsing::{Backends, BuildOrCheck, ExtraArguments, Globals, PackageOpt, TestMetadata}, + argument_parsing::{ + Backends, BuildOrCheck, ExtraArguments, Globals, PackageOpt, Platforms, TestMetadata, + }, cargo_command::{BuildMode, CargoCommand}, }; @@ -62,7 +64,12 @@ fn command_parser( }; match *command { - CargoCommand::Qemu { example, .. } | CargoCommand::Run { example, .. } => { + CargoCommand::Qemu { + platform, example, .. + } + | CargoCommand::Run { + platform, example, .. + } => { /// Check if `run` was successful. /// returns Ok in case the run went as expected, /// Err otherwise @@ -99,8 +106,9 @@ fn command_parser( res } + let platform_name = platform.name(); let run_file = format!("{example}.run"); - let expected_output_file = ["rtic", "ci", "expected", &run_file] + let expected_output_file = ["ci", "expected", &platform_name, &run_file] .iter() .collect::() .into_os_string() @@ -191,72 +199,41 @@ pub fn cargo<'c>( runner.run_and_coalesce() } -/// Cargo command to build a usage example. -/// -/// The usage examples are in examples/ -pub fn cargo_usage_example( - globals: &Globals, - operation: BuildOrCheck, - usage_examples: Vec, -) -> Vec> { - into_iter(&usage_examples) - .map(|example| { - let path = format!("examples/{example}"); - - let command = match operation { - BuildOrCheck::Check => CargoCommand::Check { - cargoarg: &None, - mode: BuildMode::Release, - dir: Some(path.into()), - package: None, - target: None, - features: None, - deny_warnings: globals.deny_warnings, - }, - BuildOrCheck::Build => CargoCommand::Build { - cargoarg: &None, - package: None, - target: None, - features: None, - mode: BuildMode::Release, - dir: Some(path.into()), - deny_warnings: globals.deny_warnings, - }, - }; - (globals, command, false) - }) - .run_and_coalesce() -} - /// Cargo command to either build or check all examples /// -/// The examples are in rtic/examples +/// The examples are in examples//examples pub fn cargo_example<'c>( globals: &Globals, operation: BuildOrCheck, cargoarg: &'c Option<&'c str>, + platform: Platforms, backend: Backends, examples: &'c [String], ) -> Vec> { let runner = into_iter(examples).map(|example| { + let path = format!("examples/{}", platform.name()); + let dir = Some(PathBuf::from(path)); let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); let command = match operation { BuildOrCheck::Check => CargoCommand::ExampleCheck { cargoarg, + platform, example, target: Some(backend.to_target()), features, mode: BuildMode::Release, + dir, deny_warnings: globals.deny_warnings, }, BuildOrCheck::Build => CargoCommand::ExampleBuild { cargoarg, + platform, example, target: Some(backend.to_target()), features, mode: BuildMode::Release, - dir: Some(PathBuf::from("./rtic")), + dir, deny_warnings: globals.deny_warnings, }, }; @@ -368,9 +345,12 @@ pub fn cargo_book<'c>( /// Run examples /// /// Supports updating the expected output via the overwrite argument +/// +/// The examples are in examples//examples pub fn qemu_run_examples<'c>( globals: &Globals, cargoarg: &'c Option<&'c str>, + platform: Platforms, backend: Backends, examples: &'c [String], overwrite: bool, @@ -380,11 +360,13 @@ pub fn qemu_run_examples<'c>( into_iter(examples) .flat_map(|example| { + let path = format!("examples/{}", platform.name()); + let dir = Some(PathBuf::from(path)); let target = target.into(); - let dir = Some(PathBuf::from("./rtic")); let cmd_build = CargoCommand::ExampleBuild { cargoarg: &None, + platform, example, target, features: features.clone(), @@ -395,6 +377,7 @@ pub fn qemu_run_examples<'c>( let cmd_qemu = CargoCommand::Qemu { cargoarg, + platform, example, target, features: features.clone(), @@ -413,6 +396,7 @@ pub fn qemu_run_examples<'c>( pub fn build_and_check_size<'c>( globals: &Globals, cargoarg: &'c Option<&'c str>, + platform: Platforms, backend: Backends, examples: &'c [String], arguments: &'c Option, @@ -422,27 +406,31 @@ pub fn build_and_check_size<'c>( let runner = into_iter(examples) .flat_map(|example| { + let path = format!("examples/{}", platform.name()); + let dir = Some(PathBuf::from(path)); let target = target.into(); // Make sure the requested example(s) are built let cmd_build = CargoCommand::ExampleBuild { cargoarg: &Some("--quiet"), + platform, example, target, features: features.clone(), mode: BuildMode::Release, - dir: Some(PathBuf::from("./rtic")), + dir: dir.clone(), deny_warnings: globals.deny_warnings, }; let cmd_size = CargoCommand::ExampleSize { cargoarg, + platform, example, target, features: features.clone(), mode: BuildMode::Release, arguments: arguments.clone(), - dir: Some(PathBuf::from("./rtic")), + dir, deny_warnings: globals.deny_warnings, };