Skip to content

Commit

Permalink
Xtensa vectored interrupts (#103)
Browse files Browse the repository at this point in the history
* Xtensa interrupt vectoring: peripheral source

- Initial Xtensa vectoring, updated esp32 gpio example to use new interrupt macro.
- Only peripheral sources supported.
- Only level one priority supported.
- CPU & Edge interrupts still need to be handled.

* Xtensa interrupt vectoring: CPU & EDGE

- Add support for handling CPU interrupts and edge interrupts
- PR required to xtensa-lx-rt for CPU handlers

* Xtensa interrupt vectoring: Priority

- Finally implement priortization
- Only three priorities available at the moment. Xtensa programmer guide
  discourages using highpri interrupts in Rust/C. Guide also mentions
  using software priortization to increase the number of Priorities
  available

* support CPU interrupts, using patch xtensa-lx-rt

* Update example

* Add support & examples for the s2 & s3 too

* Fix formatting and missing imports

* Run interrupt handling in ram, optionally run the vector handler in ram in the examples

* Use xtensa_lx::Mutex CS when enabling interrupts

* Run clippy on each target

* Remove redundant features

* Fix C3 builds

* make enable unsafe. Add note about preallocated interrupts in vectored mode.

* Remove `INTERRUPT_LEVELS` static

The interrupt levels static introduces a few issues
  - A lock is needed when configuring interrupts to keep
    INTERRUPT_LEVELS in a consistent state
  - Interrupts enabled from outside the Rust domain wouldn't be
    serviced, this is the case with the wifi blobs

To remove it, the prioty configuration is now calculated dynamically in
the interrupt handler. Essentially INTERRUPT_LEVELS is now created once
the interrupt triggers. It has some benefits, such as only having to
look at interrupts configured on the current core, not both, but there
is of course an overhead with doing this in the interrupt.

* Allow raw interrupts on levels 4-7, whilst also supporting vectoring on levels 1-3

* rename core number features

* Fix examples and formatting

* use xtensa-lx-rt release, update pacs

* Support passing the trap frame into interrupt handlers

* cfg away the #[interrupt] macro when not using vectoring

* rename enable to map

move vectored feature to chip specific hals

* export vectored functions

- rename `enable_with_priority` to `enable`
- add docs for interrupt macro

* Update all examples to use vectored interrupts
  • Loading branch information
MabezDev authored Jul 25, 2022
1 parent 34b1e09 commit 1789780
Show file tree
Hide file tree
Showing 31 changed files with 851 additions and 534 deletions.
35 changes: 27 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,44 @@ jobs:
# The `hello_rgb` example requires the `smartled` feature to be enabled
args: -Zbuild-std=core --examples --manifest-path=${{ matrix.chip }}-hal/Cargo.toml --target=xtensa-${{ matrix.chip }}-none-elf --features=smartled

clippy:
name: Clippy
clippy-riscv:
name: Run clippy on RISC-V builds
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
chip: [esp32, esp32c3, esp32s2, esp32s3]
toolchain: [stable, nightly]
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
default: true
target: riscv32imc-unknown-none-elf
toolchain: ${{ matrix.toolchain }}
components: clippy
default: true
- uses: Swatinem/rust-cache@v1
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path=esp32c3-hal/Cargo.toml --target=riscv32imc-unknown-none-elf -- --no-deps -D warnings --A clippy::too-many-arguments --A clippy::module-inception

clippy-xtensa:
name: Run clippy on Xtensa builds
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
chip: [esp32, esp32s2, esp32s3]
steps:
- uses: actions/checkout@v2
- uses: esp-rs/xtensa-toolchain@v1.2
with:
default: true
ldproxy: false
buildtargets: ${{ matrix.chip }}
- uses: Swatinem/rust-cache@v1
- uses: actions-rs/cargo@v1
with:
command: clippy
# I find `clippy::too-many-arguments` to be rather rather arbitrary.
# As for `clippy::module-inception`... don't tell me what to do ;)
args: --manifest-path=${{ matrix.chip }}-hal/Cargo.toml -- --no-deps -D warnings --A clippy::too-many-arguments --A clippy::module-inception
args: -Zbuild-std=core --manifest-path=${{ matrix.chip }}-hal/Cargo.toml --target=xtensa-${{ matrix.chip }}-none-elf -- --no-deps -D warnings --A clippy::too-many-arguments --A clippy::module-inception
17 changes: 5 additions & 12 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
{
"editor.formatOnSave": true,

"rust-analyzer.cargo.buildScripts.enable": true,
"rust-analyzer.cargo.noDefaultFeatures": true,

"rust-analyzer.checkOnSave.allTargets": false,

"rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "crate",

"rust-analyzer.procMacro.attributes.enable": false,
"rust-analyzer.procMacro.enable": true,

// -----------------------------------------------------------------------
// Since we have to handle multiple toolchains AND multiple targets, we
// we need to give Rust Analyzer some directions.
Expand All @@ -20,16 +15,14 @@
// developing for. This will propagate to the `esp-hal-common` crate too,
// as it is a dependency. Changing target/project requires reloading
// Rust Analyzer.

// "rust-analyzer.cargo.target": "xtensa-esp32-none-elf",
"rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf",
"rust-analyzer.cargo.target": "xtensa-esp32-none-elf",
// "rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf",
// "rust-analyzer.cargo.target": "xtensa-esp32s2-none-elf",
// "rust-analyzer.cargo.target": "xtensa-esp32s3-none-elf",

"rust-analyzer.linkedProjects": [
// "esp32-hal/Cargo.toml",
"esp32c3-hal/Cargo.toml",
"esp32-hal/Cargo.toml",
// "esp32c3-hal/Cargo.toml",
// "esp32s2-hal/Cargo.toml",
// "esp32s3-hal/Cargo.toml",
],
}
}
26 changes: 11 additions & 15 deletions esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,21 @@ smart-leds-trait = { version = "0.2.1", optional = true }
# Each supported device MUST have its PAC included below along with a
# corresponding feature. We rename the PAC packages because we cannot
# have dependencies and features with the same names.
#
# Please note: for now we use git-dependencies from the `with_source` branch however we pin the dependency
# to specific commits.
esp32_pac = { package = "esp32", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true }
esp32c3_pac = { package = "esp32c3", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true }
esp32s2_pac = { package = "esp32s2", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true }
esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true }
esp32_pac = { package = "esp32", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true }
esp32c3_pac = { package = "esp32c3", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true }
esp32s2_pac = { package = "esp32s2", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true }
esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true }

[features]
esp32 = [ "esp32_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32", "xtensa-lx/esp32"]
esp32c3 = ["esp32c3_pac/rt", "risc_v", "single_core"]
esp32s2 = ["esp32s2_pac/rt", "xtensa", "single_core", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2"]
esp32s3 = ["esp32s3_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3"]
esp32 = ["esp32_pac/rt" , "procmacros/xtensa", "multi_core" , "xtensa-lx-rt/esp32", "xtensa-lx/esp32"]
esp32c3 = ["esp32c3_pac/rt", "procmacros/riscv" , "single_core", "riscv", "riscv-atomic-emulation-trap"]
esp32s2 = ["esp32s2_pac/rt", "procmacros/xtensa", "single_core", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2"]
esp32s3 = ["esp32s3_pac/rt", "procmacros/xtensa", "multi_core" , "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3"]

# Architecture (should not be enabled directly, but instead by a PAC's feature)
risc_v = ["riscv", "riscv-atomic-emulation-trap"]
xtensa = ["procmacros/rtc_slow"]

# Core Count (should not be enabled directly, but instead by a PAC's feature)
single_core = []
dual_core = []
multi_core = []

# To support `ufmt`
ufmt = ["ufmt-write"]
Expand All @@ -68,3 +62,5 @@ smartled = ["smart-leds-trait"]

# Implement the `embedded-hal==1.0.0-alpha.x` traits
eh1 = ["embedded-hal-1"]
# To use vectored interrupts (calling the handlers defined in the PAC)
vectored = ["procmacros/interrupt"]
Loading

0 comments on commit 1789780

Please sign in to comment.