From 9bf70ff7925779436a3aaaa4abae2013594dfe3f Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 26 Jan 2024 13:46:51 +0000 Subject: [PATCH] Combine the `esp-ulp-riscv-hal` and `esp32c6-lp-hal` packages (#1115) * Combine `esp-ulp-riscv-hal` and `esp32c6-lp-hal` into a single package * Update LP core examples * Update CI workflow * Fix `LP_UART` example --- .github/workflows/ci.yml | 141 +++++++--------- .vscode/settings.json | 2 +- esp-hal-procmacros/src/lib.rs | 42 ++--- esp-lp-hal/.cargo/config.toml | 12 ++ {esp32c6-lp-hal => esp-lp-hal}/CHANGELOG.md | 5 +- esp-lp-hal/Cargo.toml | 64 +++++++ esp-lp-hal/README.md | 73 ++++++++ esp-lp-hal/build.rs | 75 +++++++++ esp-lp-hal/examples/blinky.rs | 47 ++++++ .../examples/uart.rs | 8 +- .../ld/link.x => esp-lp-hal/ld/link-lp.x | 8 +- .../ld/link.x => esp-lp-hal/ld/link-ulp.x | 2 +- esp-lp-hal/src/delay.rs | 80 +++++++++ esp-lp-hal/src/gpio.rs | 157 ++++++++++++++++++ esp-lp-hal/src/lib.rs | 150 +++++++++++++++++ {esp32c6-lp-hal => esp-lp-hal}/src/uart.rs | 10 +- esp-ulp-riscv-hal/.cargo/config.toml | 11 -- esp-ulp-riscv-hal/CHANGELOG.md | 22 --- esp-ulp-riscv-hal/Cargo.toml | 38 ----- esp-ulp-riscv-hal/README.md | 53 ------ esp-ulp-riscv-hal/build.rs | 17 -- esp-ulp-riscv-hal/examples/blinky.rs | 35 ---- esp-ulp-riscv-hal/src/delay.rs | 62 ------- esp-ulp-riscv-hal/src/gpio.rs | 122 -------------- esp-ulp-riscv-hal/src/lib.rs | 100 ----------- esp-ulp-riscv-hal/src/prelude.rs | 15 -- esp32c6-hal/examples/lp_core_basic.rs | 7 +- esp32c6-hal/examples/lp_core_uart.rs | 10 +- esp32c6-lp-hal/.cargo/config.toml | 11 -- esp32c6-lp-hal/Cargo.toml | 37 ----- esp32c6-lp-hal/README.md | 51 ------ esp32c6-lp-hal/build.rs | 15 -- esp32c6-lp-hal/examples/blinky.rs | 33 ---- esp32c6-lp-hal/src/delay.rs | 47 ------ esp32c6-lp-hal/src/gpio.rs | 108 ------------ esp32c6-lp-hal/src/lib.rs | 96 ----------- esp32c6-lp-hal/src/prelude.rs | 15 -- esp32s2-hal/examples/ulp_riscv_core_basic.rs | 5 +- esp32s3-hal/examples/ulp_riscv_core_basic.rs | 5 +- 39 files changed, 767 insertions(+), 1024 deletions(-) create mode 100644 esp-lp-hal/.cargo/config.toml rename {esp32c6-lp-hal => esp-lp-hal}/CHANGELOG.md (87%) create mode 100644 esp-lp-hal/Cargo.toml create mode 100644 esp-lp-hal/README.md create mode 100644 esp-lp-hal/build.rs create mode 100644 esp-lp-hal/examples/blinky.rs rename {esp32c6-lp-hal => esp-lp-hal}/examples/uart.rs (70%) rename esp32c6-lp-hal/ld/link.x => esp-lp-hal/ld/link-lp.x (77%) rename esp-ulp-riscv-hal/ld/link.x => esp-lp-hal/ld/link-ulp.x (97%) create mode 100644 esp-lp-hal/src/delay.rs create mode 100644 esp-lp-hal/src/gpio.rs create mode 100644 esp-lp-hal/src/lib.rs rename {esp32c6-lp-hal => esp-lp-hal}/src/uart.rs (94%) delete mode 100644 esp-ulp-riscv-hal/.cargo/config.toml delete mode 100644 esp-ulp-riscv-hal/CHANGELOG.md delete mode 100644 esp-ulp-riscv-hal/Cargo.toml delete mode 100644 esp-ulp-riscv-hal/README.md delete mode 100644 esp-ulp-riscv-hal/build.rs delete mode 100644 esp-ulp-riscv-hal/examples/blinky.rs delete mode 100644 esp-ulp-riscv-hal/src/delay.rs delete mode 100644 esp-ulp-riscv-hal/src/gpio.rs delete mode 100644 esp-ulp-riscv-hal/src/lib.rs delete mode 100644 esp-ulp-riscv-hal/src/prelude.rs delete mode 100644 esp32c6-lp-hal/.cargo/config.toml delete mode 100644 esp32c6-lp-hal/Cargo.toml delete mode 100644 esp32c6-lp-hal/README.md delete mode 100644 esp32c6-lp-hal/build.rs delete mode 100644 esp32c6-lp-hal/examples/blinky.rs delete mode 100644 esp32c6-lp-hal/src/delay.rs delete mode 100644 esp32c6-lp-hal/src/gpio.rs delete mode 100644 esp32c6-lp-hal/src/lib.rs delete mode 100644 esp32c6-lp-hal/src/prelude.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4672fd34..3bfe134dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,6 +65,34 @@ jobs: - name: rustdoc run: cd esp-hal-smartled/ && cargo doc -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=esp32c3 + esp-lp-hal: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@v1 + with: + target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf + toolchain: nightly + components: rust-src + - uses: Swatinem/rust-cache@v2 + + # Perform a full build initially to verify that the examples not only + # build, but also link successfully. + - name: build esp-lp-hal (esp32c6) + run: cd esp-lp-hal/ && cargo build --release --target=riscv32imac-unknown-none-elf --features=esp32c6 --examples + - name: build esp-lp-hal (esp32s2) + run: cd esp-lp-hal/ && cargo build --release --target=riscv32imc-unknown-none-elf --features=esp32s2 --examples + - name: build esp-lp-hal (esp32s3) + run: cd esp-lp-hal/ && cargo build --release --target=riscv32imc-unknown-none-elf --features=esp32s3 --examples + # Ensure documentation can be built + - name: rustdoc + run: | + cd esp-lp-hal/ + cargo doc --features=esp32c6 + cargo doc --features=esp32s2 + cargo doc --features=esp32s3 + esp-riscv-rt: runs-on: ubuntu-latest @@ -89,28 +117,6 @@ jobs: - name: rustdoc run: cd esp-riscv-rt/ && cargo doc - esp-ulp-riscv-hal: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@v1 - with: - target: riscv32imc-unknown-none-elf - toolchain: nightly - components: rust-src - - uses: Swatinem/rust-cache@v2 - - # Perform a full build initially to verify that the examples not only - # build, but also link successfully. - - name: build esp-ulp-riscv-hal (esp32s2) - run: cd esp-ulp-riscv-hal/ && cargo build --release --features=esp32s2 --examples - - name: build esp-ulp-riscv-hal (esp32s3) - run: cd esp-ulp-riscv-hal/ && cargo build --release --features=esp32s3 --examples - # Ensure documentation can be built - - name: rustdoc - run: cd esp-ulp-riscv-hal/ && cargo doc --features=esp32s3 - esp32-hal: runs-on: ubuntu-latest @@ -290,10 +296,12 @@ jobs: components: rust-src - uses: Swatinem/rust-cache@v2 - # build the lp-hal examples first to make sure the examples which expect - # the ELF files to be present will compile - - name: build esp32c6-lp-hal prerequisites - run: cd esp32c6-lp-hal/ && cargo +nightly build --release --examples + # Build the `esp-lp-hal` examples first to make sure the examples which + # expect these ELF files to be present will compile. + - name: build prerequisites + run: | + cd esp-lp-hal/ + cargo build --release --features=esp32c6 --target=riscv32imac-unknown-none-elf --examples # Perform a full build initially to verify that the examples not only # build, but also link successfully. @@ -346,26 +354,6 @@ jobs: - name: rustdoc run: cd esp32c6-hal/ && cargo doc --features=eh1 - esp32c6-lp-hal: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@v1 - with: - target: riscv32imac-unknown-none-elf - toolchain: nightly - components: rust-src - - uses: Swatinem/rust-cache@v2 - - # Perform a full build initially to verify that the examples not only - # build, but also link successfully. - - name: build esp32c6-lp-hal (no features) - run: cd esp32c6-lp-hal/ && cargo +nightly build --release --examples - # Ensure documentation can be built - - name: rustdoc - run: cd esp32c6-lp-hal/ && cargo doc - esp32h2-hal: runs-on: ubuntu-latest @@ -478,10 +466,12 @@ jobs: components: rust-src - uses: Swatinem/rust-cache@v2 - # build the esp-ulp-riscv-hal examples first to make sure the examples which expect - # the ELF files to be present will compile - - name: build esp-ulp-riscv-hal prerequisites - run: cd esp-ulp-riscv-hal/ && cargo +nightly build --release --features=esp32s2 --examples + # Build the `esp-lp-hal` examples first to make sure the examples which + # expect these ELF files to be present will compile. + - name: build prerequisites + run: | + cd esp-lp-hal/ + cargo +nightly build --release --features=esp32s2 --target=riscv32imc-unknown-none-elf --examples # Perform a full build initially to verify that the examples not only # build, but also link successfully. @@ -494,9 +484,6 @@ jobs: cd esp32s2-hal/ cargo +esp build --examples --features=eh1,ufmt,log cargo +esp build --examples --features=eh1,ufmt,defmt - # FIXME: `time-systick` feature disabled for now, see 'esp32s2-hal/Cargo.toml'. - # - name: check esp32s2-hal (async, systick) - # run: cd esp32s2-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-systick,executor - name: check esp32s2-hal (embassy, timg0) run: | cd esp32s2-hal/ @@ -556,10 +543,12 @@ jobs: components: rust-src - uses: Swatinem/rust-cache@v2 - # build the esp-ulp-riscv-hal examples first to make sure the examples which expect - # the ELF files to be present will compile - - name: build esp-ulp-riscv-hal prerequisites - run: cd esp-ulp-riscv-hal/ && cargo +nightly build --release --features=esp32s3 --examples + # Build the `esp-lp-hal` examples first to make sure the examples which + # expect these ELF files to be present will compile. + - name: build prerequisites + run: | + cd esp-lp-hal/ + cargo build --release --features=esp32s3 --target=riscv32imc-unknown-none-elf --examples # Perform a full build initially to verify that the examples not only # build, but also link successfully. @@ -641,12 +630,13 @@ jobs: components: rust-src - uses: Swatinem/rust-cache@v2 - # Build the esp32c6-lp-hal examples first. This is done to ensure the - # examples which expect the ELF files to be present will compile: - - name: build esp32c6-lp-hal prerequisites - run: cd esp32c6-lp-hal && cargo build --release --examples - # Verify the MSRV for all RISC-V chips. + - name: msrv (esp-lp-hal) + run: | + cd esp-lp-hal/ + cargo build --features=esp32c6 --target=riscv32imac-unknown-none-elf + cargo build --features=esp32s2 --target=riscv32imc-unknown-none-elf + cargo build --features=esp32s3 --target=riscv32imc-unknown-none-elf - name: msrv (esp32c2-hal) run: | cd esp32c2-hal/ @@ -662,10 +652,6 @@ jobs: cd esp32c6-hal/ cargo build --features=eh1,ufmt,log cargo build --features=defmt - - name: msrv (esp32c6-lp-hal) - run: | - cd esp32c6-lp-hal/ - cargo build - name: msrv (esp32h2-hal) run: | cd esp32h2-hal/ @@ -695,11 +681,6 @@ jobs: version: ${{ env.MSRV }} - uses: Swatinem/rust-cache@v2 - # Build the `esp-ulp-riscv-hal` examples first. This is done to ensure - # the examples which expect the ELF files to be present will compile: - - name: build esp-ulp-riscv-hal prerequisites - run: cd esp-ulp-riscv-hal && cargo build --release --features=esp32s3 --examples - # Verify the MSRV for all Xtensa chips: - name: msrv (esp32-hal) run: | @@ -733,20 +714,20 @@ jobs: - uses: Swatinem/rust-cache@v2 # Run 'cargo clippy' on all packages targeting RISC-V: + - name: clippy (esp-lp-hal, esp32c6) + run: cd esp-lp-hal && cargo clippy --features=esp32c6 -- -D warnings + - name: clippy (esp-lp-hal, esp32s2) + run: cd esp-lp-hal && cargo clippy --features=esp32s2 -- -D warnings + - name: clippy (esp-lp-hal, esp32s3) + run: cd esp-lp-hal && cargo clippy --features=esp32s3 -- -D warnings - name: clippy (esp-riscv-rt) run: cd esp-riscv-rt && cargo clippy --target=riscv32imc-unknown-none-elf -- -D warnings - - name: clippy (esp-ulp-riscv-hal, esp32s2) - run: cd esp-ulp-riscv-hal && cargo clippy --features=esp32s2 -- -D warnings - - name: clippy (esp-ulp-riscv-hal, esp32s3) - run: cd esp-ulp-riscv-hal && cargo clippy --features=esp32s3 -- -D warnings - name: clippy (esp32c2-hal) run: cd esp32c2-hal && cargo clippy -- -D warnings - name: clippy (esp32c3-hal) run: cd esp32c3-hal && cargo clippy -- -D warnings - name: clippy (esp32c6-hal) run: cd esp32c6-hal && cargo clippy -- -D warnings - - name: clippy (esp32c6-lp-hal) - run: cd esp32c6-lp-hal && cargo clippy -- -D warnings - name: clippy (esp32h2-hal) run: cd esp32h2-hal && cargo clippy -- -D warnings - name: clippy (esp32p4-hal) @@ -790,10 +771,10 @@ jobs: run: cargo fmt --all --manifest-path=esp-hal-procmacros/Cargo.toml -- --check - name: rustfmt (esp-hal-smartled) run: cargo fmt --all --manifest-path=esp-hal-smartled/Cargo.toml -- --check + - name: rustfmt (esp-lp-hal) + run: cargo fmt --all --manifest-path=esp-lp-hal/Cargo.toml -- --check - name: rustfmt (esp-riscv-rt) run: cargo fmt --all --manifest-path=esp-riscv-rt/Cargo.toml -- --check - - name: rustfmt (esp-ulp-riscv-hal) - run: cargo fmt --all --manifest-path=esp-ulp-riscv-hal/Cargo.toml -- --check - name: rustfmt (esp32-hal) run: cargo fmt --all --manifest-path=esp32-hal/Cargo.toml -- --check - name: rustfmt (esp32c2-hal) @@ -802,8 +783,6 @@ jobs: run: cargo fmt --all --manifest-path=esp32c3-hal/Cargo.toml -- --check - name: rustfmt (esp32c6-hal) run: cargo fmt --all --manifest-path=esp32c6-hal/Cargo.toml -- --check - - name: rustfmt (esp32c6-lp-hal) - run: cargo fmt --all --manifest-path=esp32c6-lp-hal/Cargo.toml -- --check - name: rustfmt (esp32h2-hal) run: cargo fmt --all --manifest-path=esp32h2-hal/Cargo.toml -- --check - name: rustfmt (esp32p4-hal) diff --git a/.vscode/settings.json b/.vscode/settings.json index c55cc9315..8dae47c66 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,11 +12,11 @@ // Uncomment ONE line for the chip you want to work on. // This makes rust-analyzer work on the HAL crate and all its dependencies. "rust-analyzer.linkedProjects": [ + // "esp-lp-hal/Cargo.toml" "esp32-hal/Cargo.toml" // "esp32c2-hal/Cargo.toml" // "esp32c3-hal/Cargo.toml" // "esp32c6-hal/Cargo.toml" - // "esp32c6-lp-hal/Cargo.toml" // "esp32h2-hal/Cargo.toml" // "esp32p4-hal/Cargo.toml" // "esp32s2-hal/Cargo.toml" diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index 8c01b4caa..23f64da8b 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -108,6 +108,12 @@ fn get_hal_crate() -> ( use proc_macro_crate::crate_name; // Package name: + #[cfg(any( + feature = "esp32c6-lp", + feature = "esp32s2-ulp", + feature = "esp32s3-ulp" + ))] + let hal_crate = crate_name("esp-lp-hal"); #[cfg(feature = "esp32")] let hal_crate = crate_name("esp32-hal"); #[cfg(feature = "esp32c2")] @@ -116,22 +122,22 @@ fn get_hal_crate() -> ( let hal_crate = crate_name("esp32c3-hal"); #[cfg(feature = "esp32c6")] let hal_crate = crate_name("esp32c6-hal"); - #[cfg(feature = "esp32c6-lp")] - let hal_crate = crate_name("esp32c6-lp-hal"); #[cfg(feature = "esp32h2")] let hal_crate = crate_name("esp32h2-hal"); #[cfg(feature = "esp32p4")] let hal_crate = crate_name("esp32p4-hal"); #[cfg(feature = "esp32s2")] let hal_crate = crate_name("esp32s2-hal"); - #[cfg(feature = "esp32s2-ulp")] - let hal_crate = crate_name("esp-ulp-riscv-hal"); #[cfg(feature = "esp32s3")] let hal_crate = crate_name("esp32s3-hal"); - #[cfg(feature = "esp32s3-ulp")] - let hal_crate = crate_name("esp-ulp-riscv-hal"); // Crate name: + #[cfg(any( + feature = "esp32c6-lp", + feature = "esp32s2-ulp", + feature = "esp32s3-ulp" + ))] + let hal_crate_name = Ident::new("esp_lp_hal", Span::call_site().into()); #[cfg(feature = "esp32")] let hal_crate_name = Ident::new("esp32_hal", Span::call_site().into()); #[cfg(feature = "esp32c2")] @@ -140,20 +146,14 @@ fn get_hal_crate() -> ( let hal_crate_name = Ident::new("esp32c3_hal", Span::call_site().into()); #[cfg(feature = "esp32c6")] let hal_crate_name = Ident::new("esp32c6_hal", Span::call_site().into()); - #[cfg(feature = "esp32c6-lp")] - let hal_crate_name = Ident::new("esp32c6_lp_hal", Span::call_site().into()); #[cfg(feature = "esp32h2")] let hal_crate_name = Ident::new("esp32h2_hal", Span::call_site().into()); #[cfg(feature = "esp32p4")] let hal_crate_name = Ident::new("esp32p4_hal", Span::call_site().into()); #[cfg(feature = "esp32s2")] let hal_crate_name = Ident::new("esp32s2_hal", Span::call_site().into()); - #[cfg(feature = "esp32s2-ulp")] - let hal_crate_name = Ident::new("esp_ulp_riscv_hal", Span::call_site().into()); #[cfg(feature = "esp32s3")] let hal_crate_name = Ident::new("esp32s3_hal", Span::call_site().into()); - #[cfg(feature = "esp32s3-ulp")] - let hal_crate_name = Ident::new("esp_ulp_riscv_hal", Span::call_site().into()); (hal_crate, hal_crate_name) } @@ -679,18 +679,9 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { use self::lp_core::{extract_pin, get_simplename, make_magic_symbol_name}; - #[cfg(feature = "esp32c6-lp")] - let found_crate = - crate_name("esp32c6-lp-hal").expect("esp32c6_lp_hal is present in `Cargo.toml`"); - #[cfg(any(feature = "esp32s2-ulp", feature = "esp32s3-ulp"))] - let found_crate = - crate_name("esp-ulp-riscv-hal").expect("esp-ulp-riscv-hal is present in `Cargo.toml`"); - + let found_crate = crate_name("esp-lp-hal").expect("esp-lp-hal is present in `Cargo.toml`"); let hal_crate = match found_crate { - #[cfg(feature = "esp32c6-lp")] - FoundCrate::Itself => quote!(esp32c6_lp_hal), - #[cfg(any(feature = "esp32s2-ulp", feature = "esp32s3-ulp"))] - FoundCrate::Itself => quote!(esp_ulp_riscv_hal), + FoundCrate::Itself => quote!(esp_lp_hal), FoundCrate::Name(name) => { let ident = Ident::new(&name, Span::call_site()); quote!( #ident::Something ) @@ -729,12 +720,12 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { } used_pins.push(pin); create_peripheral.push(quote!( - let mut #param_name = unsafe { the_hal::gpio::conjour().unwrap() }; + let mut #param_name = unsafe { the_hal::gpio::conjure().unwrap() }; )); } "LpUart" => { create_peripheral.push(quote!( - let mut #param_name = unsafe { the_hal::uart::conjour().unwrap() }; + let mut #param_name = unsafe { the_hal::uart::conjure().unwrap() }; )); } _ => { @@ -772,6 +763,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { main(#(#param_names),*); } + #f ) .into() diff --git a/esp-lp-hal/.cargo/config.toml b/esp-lp-hal/.cargo/config.toml new file mode 100644 index 000000000..481bd89a0 --- /dev/null +++ b/esp-lp-hal/.cargo/config.toml @@ -0,0 +1,12 @@ +[build] +# target = "riscv32imc-unknown-none-elf" # ESP32-S2 + ESP32-S3 +target = "riscv32imac-unknown-none-elf" # ESP32-C6 + +[target.'cfg(target_arch = "riscv32")'] +runner = "espflash flash --monitor" +rustflags = [ + "-C", "link-arg=-Tlink.x", +] + +[unstable] +build-std = ["core"] diff --git a/esp32c6-lp-hal/CHANGELOG.md b/esp-lp-hal/CHANGELOG.md similarity index 87% rename from esp32c6-lp-hal/CHANGELOG.md rename to esp-lp-hal/CHANGELOG.md index e87104680..0bd4376bc 100644 --- a/esp32c6-lp-hal/CHANGELOG.md +++ b/esp-lp-hal/CHANGELOG.md @@ -12,12 +12,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add the `esp32c6-lp-hal` package (#714) - Add GPIO (output) and delay functionality to `esp32c6-lp-hal` (#715) - Add GPIO input support and implement additional `embedded-hal` output traits for the C6's LP core [#720] +- Add the `ulp-riscv-hal` package (#840) - Add LP_UART basic driver (#1113) ### Changed +- Renamed to `esp-ulp-riscv-hal` (#916) + ### Fixed ### Removed -[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp32c6-lp-hal +[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-lp-hal diff --git a/esp-lp-hal/Cargo.toml b/esp-lp-hal/Cargo.toml new file mode 100644 index 000000000..8846076d3 --- /dev/null +++ b/esp-lp-hal/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "esp-lp-hal" +version = "0.1.0" +edition = "2021" +rust-version = "1.67.0" +description = "HAL for low-power RISC-V coprocessors found in ESP32 devices" +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" + +keywords = [ + "embedded", + "embedded-hal", + "esp", + "esp32", + "no-std", +] +categories = [ + "embedded", + "hardware-support", + "no-std", +] + +[dependencies] +cfg-if = "1.0.0" +embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", optional = true, features = ["unproven"] } +embedded-hal-1 = { version = "1.0.0", package = "embedded-hal", optional = true } +esp32c6-lp = { version = "0.1.0", features = ["critical-section"], optional = true } +esp32s2-ulp = { version = "0.1.0", features = ["critical-section"], optional = true } +esp32s3-ulp = { version = "0.1.0", features = ["critical-section"], optional = true } +nb = { version = "1.1.0", optional = true } +paste = { version = "1.0.14", optional = true } +procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } +riscv = { version = "0.11.0", features = ["critical-section-single-hart"] } + +[dev-dependencies] +panic-halt = "0.2.0" + +[features] +default = ["embedded-hal-02"] + +embedded-hal-02 = ["dep:embedded-hal-02"] +embedded-hal-1 = ["dep:embedded-hal-1"] + +esp32c6 = ["dep:esp32c6-lp", "procmacros/esp32c6-lp", "dep:nb", "dep:paste"] +esp32s2 = ["dep:esp32s2-ulp", "procmacros/esp32s2-ulp"] +esp32s3 = ["dep:esp32s3-ulp", "procmacros/esp32s3-ulp"] + +debug = [ + "esp32c6-lp?/impl-register-debug", + "esp32s2-ulp?/impl-register-debug", + "esp32s3-ulp?/impl-register-debug", +] + +[[example]] +name = "blinky" +required-features = ["embedded-hal-02"] + +[[example]] +name = "uart" +required-features = ["embedded-hal-02", "esp32c6"] + +[patch.crates-io] +esp32s2-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "bcab40a" } +esp32s3-ulp = { git = "https://github.com/esp-rs/esp-pacs", rev = "bcab40a" } diff --git a/esp-lp-hal/README.md b/esp-lp-hal/README.md new file mode 100644 index 000000000..168a20ea9 --- /dev/null +++ b/esp-lp-hal/README.md @@ -0,0 +1,73 @@ +# esp-lp-hal + +[![Crates.io](https://img.shields.io/crates/v/esp-lp-hal?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-lp-hal) +[![docs.rs](https://img.shields.io/docsrs/esp-lp-hal?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-lp-hal) +![Crates.io](https://img.shields.io/crates/l/esp-lp-hal?labelColor=1C2C2E&style=flat-square) +[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) + +`no_std` HAL for the low-power RISC-V coprocessors found on the ESP32-C6, ESP32-S2, and ESP32-S3 from Espressif. + +Implements a number of the traits defined in [embedded-hal](https://github.com/rust-embedded/embedded-hal). + +These devices uses the RISC-V ISA, which is officially supported by the Rust compiler via the `riscv32imc-unknown-none-elf` and `riscv32imac-unknown-none-elf` targets. + +Please refer to the documentation for more information. + +[c6-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf +[s2-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf +[s3-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf +[c6-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf +[s2-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf +[s3-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf + +## [Documentation] + +[documentation]: https://docs.rs/esp-lp-hal/ + +## Supported Devices + +| Chip | Datasheet | Technical Reference Manual | Target | +| :------: | :----------------------: | :------------------------: | :----------------------------: | +| ESP32-C6 | [ESP32-C6][c6-datasheet] | [ESP32-C6][c6-trm] | `riscv32imac-unknown-none-elf` | +| ESP32-S2 | [ESP32-S2][s2-datasheet] | [ESP32-S2][s2-trm] | `riscv32imc-unknown-none-elf` | +| ESP32-S3 | [ESP32-S3][s3-datasheet] | [ESP32-S3][s3-trm] | `riscv32imc-unknown-none-elf` | + +## Resources + +- [The Rust Programming Language](https://doc.rust-lang.org/book/) +- [The Embedded Rust Book](https://docs.rust-embedded.org/book/index.html) +- [The Rust on ESP Book](https://esp-rs.github.io/book/) +- Datasheets: + - [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) + - [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) + - [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +- Technical Reference Manuals: + - [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf) + - [ESP32-S2](https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf) + - [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf) + +## Getting Started + +### Installing the Rust Compiler Targets + +The compilation targets for these devices are officially supported by the mainline Rust compiler and can be installed using [rustup](https://rustup.rs/): + +```shell +rustup target add riscv32imc-unknown-none-elf +rustup target add riscv32imac-unknown-none-elf +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in +the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without +any additional terms or conditions. diff --git a/esp-lp-hal/build.rs b/esp-lp-hal/build.rs new file mode 100644 index 000000000..93391ecd7 --- /dev/null +++ b/esp-lp-hal/build.rs @@ -0,0 +1,75 @@ +use std::{env, error::Error, fs, path::PathBuf}; + +// Macros taken from: +// https://github.com/TheDan64/inkwell/blob/36c3b10/src/lib.rs#L81-L110 + +// Given some features, assert that AT MOST one of the features is enabled. +macro_rules! assert_unique_features { + () => {}; + + ( $first:tt $(,$rest:tt)* ) => { + $( + #[cfg(all(feature = $first, feature = $rest))] + compile_error!(concat!("Features \"", $first, "\" and \"", $rest, "\" cannot be used together")); + )* + assert_unique_features!($($rest),*); + }; +} + +// Given some features, assert that AT LEAST one of the features is enabled. +macro_rules! assert_used_features { + ( $all:tt ) => { + #[cfg(not(feature = $all))] + compile_error!(concat!("The feature flag must be provided: ", $all)); + }; + + ( $($all:tt),+ ) => { + #[cfg(not(any($(feature = $all),*)))] + compile_error!(concat!("One of the feature flags must be provided: ", $($all, ", "),*)); + }; +} + +// Given some features, assert that EXACTLY one of the features is enabled. +macro_rules! assert_unique_used_features { + ( $($all:tt),* ) => { + assert_unique_features!($($all),*); + assert_used_features!($($all),*); + } +} + +fn main() -> Result<(), Box> { + // NOTE: update when adding new device support! + // Ensure that exactly one chip has been specified: + assert_unique_used_features!("esp32c6", "esp32s2", "esp32s3"); + + // NOTE: update when adding new device support! + // Determine the name of the configured device: + let device_name = if cfg!(feature = "esp32c6") { + "esp32c6" + } else if cfg!(feature = "esp32s2") { + "esp32s2" + } else if cfg!(feature = "esp32s3") { + "esp32s3" + } else { + unreachable!() // We've confirmed exactly one known device was selected + }; + + // Define all necessary configuration symbols for the configured device: + println!("cargo:rustc-cfg={}", device_name); + + // Put the linker script somewhere the linker can find it: + let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + println!("cargo:rustc-link-search={}", out.display()); + + // Copy the required linker script to the `out` directory: + if cfg!(feature = "esp32c6") { + fs::copy("ld/link-lp.x", out.join("link.x"))?; + println!("cargo:rerun-if-changed=ld/link-lp.x"); + } else if cfg!(feature = "esp32s2") || cfg!(feature = "esp32s3") { + fs::copy("ld/link-ulp.x", out.join("link.x"))?; + println!("cargo:rerun-if-changed=ld/link-ulp.x"); + } + + // Done! + Ok(()) +} diff --git a/esp-lp-hal/examples/blinky.rs b/esp-lp-hal/examples/blinky.rs new file mode 100644 index 000000000..932da7871 --- /dev/null +++ b/esp-lp-hal/examples/blinky.rs @@ -0,0 +1,47 @@ +//! Counts a 32 bit value at a known point in memory, and blink GPIO1. +//! +//! When using the ESP32-C6's LP core, this address in memory is `0x5000_2000`. +//! +//! When using the ESP32-S2 or ESP32-S3's ULP core, this address in memory is +//! `0x5000_0400` (but is `0x400`` from the ULP's point of view!). +//! +//! Make sure the LP RAM is cleared before loading the code. + +#![no_std] +#![no_main] + +use embedded_hal_02::{blocking::delay::DelayMs, digital::v2::OutputPin}; +use esp_lp_hal::{ + delay::Delay, + gpio::{GpioPin, Output, PushPull}, + prelude::*, +}; +use panic_halt as _; + +cfg_if::cfg_if! { + if #[cfg(feature = "esp32c6")] { + const ADDRESS: u32 = 0x5000_2000; + } else if #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] { + const ADDRESS: u32 = 0x400; + } +} + +#[entry] +fn main(mut gpio1: GpioPin, 1>) -> ! { + let mut i: u32 = 0; + + let ptr = ADDRESS as *mut u32; + + loop { + i = i.wrapping_add(1u32); + unsafe { + ptr.write_volatile(i); + } + + gpio1.set_high().unwrap(); + Delay.delay_ms(500); + + gpio1.set_low().unwrap(); + Delay.delay_ms(500); + } +} diff --git a/esp32c6-lp-hal/examples/uart.rs b/esp-lp-hal/examples/uart.rs similarity index 70% rename from esp32c6-lp-hal/examples/uart.rs rename to esp-lp-hal/examples/uart.rs index acd18ae3e..3c6faec49 100644 --- a/esp32c6-lp-hal/examples/uart.rs +++ b/esp-lp-hal/examples/uart.rs @@ -8,16 +8,14 @@ use core::fmt::Write; -use esp32c6_lp_hal::{delay::Delay, prelude::*, uart::LpUart}; +use embedded_hal_02::blocking::delay::DelayMs; +use esp_lp_hal::{delay::Delay, prelude::*, uart::LpUart}; use panic_halt as _; #[entry] fn main(mut uart: LpUart) -> ! { - let _peripherals = esp32c6_lp::Peripherals::take().unwrap(); - - let mut delay = Delay::new(); loop { writeln!(uart, "Hello World from LP Core").unwrap(); - delay.delay_ms(1500); + Delay.delay_ms(1000); } } diff --git a/esp32c6-lp-hal/ld/link.x b/esp-lp-hal/ld/link-lp.x similarity index 77% rename from esp32c6-lp-hal/ld/link.x rename to esp-lp-hal/ld/link-lp.x index aa2d98ce1..f0471d64e 100644 --- a/esp32c6-lp-hal/ld/link.x +++ b/esp-lp-hal/ld/link-lp.x @@ -6,21 +6,23 @@ ENTRY(reset_vector) +VECTOR_TABLE_LENGTH = 0x80; CONFIG_ULP_COPROC_RESERVE_MEM = 1024 * 16; CONFIG_ULP_SHARED_MEM = 0; +RAM_LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM - VECTOR_TABLE_LENGTH - CONFIG_ULP_SHARED_MEM; MEMORY { /*first 128byte for exception/interrupt vectors*/ - vector_table(RX) : ORIGIN = 0x50000000, LENGTH = 0x80 - ram(RWX) : ORIGIN = 0x50000080, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM - 0x80 - CONFIG_ULP_SHARED_MEM + vector_table(RX) : ORIGIN = 0x50000000, LENGTH = VECTOR_TABLE_LENGTH + ram(RWX) : ORIGIN = 0x50000080, LENGTH = RAM_LENGTH } SECTIONS { .vector.text : { - /*exception/interrupt vectors*/ + /* Exception/interrupt vectors */ __mtvec_base = .; KEEP (*(.init.vector)) __mtvec_end = .; diff --git a/esp-ulp-riscv-hal/ld/link.x b/esp-lp-hal/ld/link-ulp.x similarity index 97% rename from esp-ulp-riscv-hal/ld/link.x rename to esp-lp-hal/ld/link-ulp.x index 89db971d7..7e6926a7f 100644 --- a/esp-ulp-riscv-hal/ld/link.x +++ b/esp-lp-hal/ld/link-ulp.x @@ -3,7 +3,6 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#include "sdkconfig.h" ENTRY(reset_vector) @@ -17,6 +16,7 @@ MEMORY SECTIONS { . = ORIGIN(ram); + .text : { *(.text.vectors) /* Default reset vector must link to offset 0x0 */ diff --git a/esp-lp-hal/src/delay.rs b/esp-lp-hal/src/delay.rs new file mode 100644 index 000000000..5a47315a9 --- /dev/null +++ b/esp-lp-hal/src/delay.rs @@ -0,0 +1,80 @@ +//! Simple blocking delay functionality. + +#[derive(Clone, Copy)] +pub struct Delay; + +impl Delay { + /// Delay for at least the number of specific microseconds. + pub fn delay_micros(&mut self, mut us: u32) { + const NANOS_PER_MICRO: u32 = 1_000; + const MAX_MICROS: u32 = u32::MAX / NANOS_PER_MICRO; + + // Avoid potential overflow if micro -> nano conversion is too large + while us > MAX_MICROS { + us -= MAX_MICROS; + self.delay_nanos(MAX_MICROS * NANOS_PER_MICRO); + } + + self.delay_nanos(us * NANOS_PER_MICRO); + } + + /// Delay for at least the number of specific nanoseconds. + pub fn delay_nanos(&mut self, ns: u32) { + let ticks_seconds = unsafe { crate::CPU_CLOCK }; + let clock = (ns as u64 * (ticks_seconds as u64)) / 1_000_000_000u64; + let t0 = cycles(); + + while cycles().wrapping_sub(t0) <= clock {} + } +} + +#[cfg(feature = "esp32c6")] +#[inline(always)] +fn cycles() -> u64 { + riscv::register::mcycle::read64() +} + +#[cfg(any(feature = "esp32s2", feature = "esp32s3"))] +#[inline(always)] +fn cycles() -> u64 { + let mut cycles: u32; + unsafe { + core::arch::asm!( + "rdcycle {cycles}", + cycles = out(reg) cycles, + ) + } + + cycles as u64 +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayUs for Delay { + #[inline(always)] + fn delay_us(&mut self, us: u64) { + self.delay_micros(us as u32); + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayUs for Delay { + #[inline(always)] + fn delay_us(&mut self, us: u32) { + self.delay_micros(us); + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayMs for Delay { + #[inline(always)] + fn delay_ms(&mut self, ms: u32) { + self.delay_micros(ms * 1000); + } +} + +#[cfg(feature = "embedded-hal-1")] +impl embedded_hal_1::delay::DelayNs for Delay { + fn delay_ns(&mut self, ns: u32) { + self.delay_nanos(ns); + } +} diff --git a/esp-lp-hal/src/gpio.rs b/esp-lp-hal/src/gpio.rs new file mode 100644 index 000000000..2fa539bfa --- /dev/null +++ b/esp-lp-hal/src/gpio.rs @@ -0,0 +1,157 @@ +//! Low-power GPIO driver +//! +//! It's assumed that GPIOs are already configured correctly by the HP core. + +use core::marker::PhantomData; + +#[cfg(feature = "esp32c6")] +type LpIo = crate::pac::LP_IO; +#[cfg(any(feature = "esp32s2", feature = "esp32s3"))] +type LpIo = crate::pac::RTC_IO; + +pub struct Unknown {} + +pub struct Input { + _mode: PhantomData, +} + +pub struct Floating; + +pub struct PullDown; + +pub struct PullUp; + +pub struct Output { + _mode: PhantomData, +} + +pub struct PushPull; + +pub struct GpioPin { + phantom: PhantomData, +} + +impl GpioPin, PIN> { + pub fn input_state(&self) -> bool { + unsafe { &*LpIo::PTR }.in_().read().bits() >> PIN & 0x1 != 0 + } +} + +impl GpioPin, PIN> { + pub fn output_state(&self) -> bool { + unsafe { &*LpIo::PTR }.out().read().bits() >> PIN & 0x1 != 0 + } + + pub fn set_output(&mut self, on: bool) { + if on { + unsafe { &*LpIo::PTR } + .out_w1ts() + .write(|w| w.out_data_w1ts().variant(1 << PIN)); + } else { + unsafe { &*LpIo::PTR } + .out_w1tc() + .write(|w| w.out_data_w1tc().variant(1 << PIN)); + } + } +} + +// Used by the `entry` procmacro: +#[doc(hidden)] +pub unsafe fn conjure() -> Option> { + if PIN > 7 { + None + } else { + Some(GpioPin { + phantom: PhantomData, + }) + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::digital::v2::InputPin for GpioPin, PIN> { + type Error = core::convert::Infallible; + + fn is_high(&self) -> Result { + Ok(self.input_state()) + } + + fn is_low(&self) -> Result { + Ok(!self.is_high()?) + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::digital::v2::OutputPin for GpioPin, PIN> { + type Error = core::convert::Infallible; + + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_output(false); + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_output(true); + Ok(()) + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::digital::v2::StatefulOutputPin + for GpioPin, PIN> +{ + fn is_set_high(&self) -> Result { + Ok(self.output_state()) + } + + fn is_set_low(&self) -> Result { + Ok(!self.is_set_high()?) + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::digital::v2::toggleable::Default + for GpioPin, PIN> +{ +} + +#[cfg(feature = "embedded-hal-1")] +impl embedded_hal_1::digital::ErrorType for GpioPin { + type Error = core::convert::Infallible; +} + +#[cfg(feature = "embedded-hal-1")] +impl embedded_hal_1::digital::InputPin for GpioPin, PIN> { + fn is_high(&mut self) -> Result { + Ok(self.input_state()) + } + + fn is_low(&mut self) -> Result { + Ok(!self.is_high()?) + } +} + +#[cfg(feature = "embedded-hal-1")] +impl embedded_hal_1::digital::OutputPin for GpioPin, PIN> { + fn set_low(&mut self) -> Result<(), Self::Error> { + self.set_output(false); + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + self.set_output(true); + Ok(()) + } +} + +#[cfg(feature = "embedded-hal-1")] +impl embedded_hal_1::digital::StatefulOutputPin + for GpioPin, PIN> +{ + fn is_set_high(&mut self) -> Result { + Ok(self.output_state()) + } + + fn is_set_low(&mut self) -> Result { + Ok(!self.is_set_high()?) + } +} diff --git a/esp-lp-hal/src/lib.rs b/esp-lp-hal/src/lib.rs new file mode 100644 index 000000000..977f7f3ee --- /dev/null +++ b/esp-lp-hal/src/lib.rs @@ -0,0 +1,150 @@ +#![allow(asm_sub_register)] +#![no_std] + +use core::arch::global_asm; + +pub mod delay; +pub mod gpio; +#[cfg(esp32c6)] +pub mod uart; + +pub mod pac { + #[cfg(feature = "esp32c6")] + pub use esp32c6_lp::*; + #[cfg(feature = "esp32s2")] + pub use esp32s2_ulp::*; + #[cfg(feature = "esp32s3")] + pub use esp32s3_ulp::*; +} + +pub mod prelude { + pub use procmacros::entry; +} + +cfg_if::cfg_if! { + if #[cfg(feature = "esp32c6")] { + // LP_FAST_CLK is not very accurate, for now use a rough estimate + const LP_FAST_CLK_HZ: u32 = 16_000_000; + const XTAL_D2_CLK_HZ: u32 = 20_000_000; + } else if #[cfg(feature = "esp32s2")] { + const LP_FAST_CLK_HZ: u32 = 8_000_000; + } else if #[cfg(feature = "esp32s3")] { + const LP_FAST_CLK_HZ: u32 = 17_500_000; + } +} + +pub static mut CPU_CLOCK: u32 = LP_FAST_CLK_HZ; + +#[cfg(feature = "esp32c6")] +global_asm!( + r#" + .section .init.vector, "ax" + /* This is the vector table. It is currently empty, but will be populated + * with exception and interrupt handlers when this is supported + */ + + .align 0x4, 0xff + .global _vector_table + .type _vector_table, @function +_vector_table: + .option push + .option norvc + + .rept 32 + nop + .endr + + .option pop + .size _vector_table, .-_vector_table + + .section .init, "ax" + .global reset_vector + +/* The reset vector, jumps to startup code */ +reset_vector: + j __start + +__start: + /* setup the stack pointer */ + la sp, __stack_top + call rust_main +loop: + j loop +"# +); + +#[cfg(any(feature = "esp32s2", feature = "esp32s3"))] +global_asm!( + r#" + .section .text.vectors + .global irq_vector + .global reset_vector + +/* The reset vector, jumps to startup code */ +reset_vector: + j __start + +/* Interrupt handler */ +.balign 16 +irq_vector: + ret + + .section .text + +__start: + /* setup the stack pointer */ + la sp, __stack_top + + call ulp_riscv_rescue_from_monitor + call rust_main + call ulp_riscv_halt +loop: + j loop +"# +); + +#[link_section = ".init.rust"] +#[export_name = "rust_main"] +unsafe extern "C" fn lp_core_startup() -> ! { + extern "Rust" { + fn main() -> !; + } + + #[cfg(feature = "esp32c6")] + if (*pac::LP_CLKRST::PTR) + .lp_clk_conf() + .read() + .fast_clk_sel() + .bit_is_set() + { + CPU_CLOCK = XTAL_D2_CLK_HZ; + } + + main(); +} + +#[cfg(any(feature = "esp32s2", feature = "esp32s3"))] +#[link_section = ".init.rust"] +#[no_mangle] +unsafe extern "C" fn ulp_riscv_rescue_from_monitor() { + // Rescue RISC-V core from monitor state. + unsafe { &*pac::RTC_CNTL::PTR } + .cocpu_ctrl() + .modify(|_, w| w.cocpu_done().clear_bit().cocpu_shut_reset_en().clear_bit()); +} + +#[cfg(any(feature = "esp32s2", feature = "esp32s3"))] +#[link_section = ".init.rust"] +#[no_mangle] +unsafe extern "C" fn ulp_riscv_halt() { + unsafe { &*pac::RTC_CNTL::PTR }.cocpu_ctrl().modify(|_, w| { + w.cocpu_shut_2_clk_dis() + .variant(0x3f) + .cocpu_done() + .set_bit() + }); + + loop { + riscv::asm::wfi(); + } +} diff --git a/esp32c6-lp-hal/src/uart.rs b/esp-lp-hal/src/uart.rs similarity index 94% rename from esp32c6-lp-hal/src/uart.rs rename to esp-lp-hal/src/uart.rs index 10b99f873..529c828cc 100644 --- a/esp32c6-lp-hal/src/uart.rs +++ b/esp-lp-hal/src/uart.rs @@ -1,11 +1,11 @@ //! Low-power UART driver -use esp32c6_lp::LP_UART; +use crate::pac::LP_UART; const UART_FIFO_SIZE: u16 = 128; #[doc(hidden)] -pub unsafe fn conjour() -> Option { +pub unsafe fn conjure() -> Option { Some(LpUart { uart: LP_UART::steal(), }) @@ -154,7 +154,8 @@ impl core::fmt::Write for LpUart { } } -impl embedded_hal::serial::Read for LpUart { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::serial::Read for LpUart { type Error = Error; fn read(&mut self) -> nb::Result { @@ -162,7 +163,8 @@ impl embedded_hal::serial::Read for LpUart { } } -impl embedded_hal::serial::Write for LpUart { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::serial::Write for LpUart { type Error = Error; fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { diff --git a/esp-ulp-riscv-hal/.cargo/config.toml b/esp-ulp-riscv-hal/.cargo/config.toml deleted file mode 100644 index 3a0e33d7d..000000000 --- a/esp-ulp-riscv-hal/.cargo/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -[target.riscv32imc-unknown-none-elf] -runner = "espflash flash --monitor" -rustflags = [ - "-C", "link-arg=-Tlink.x", -] - -[build] -target = "riscv32imc-unknown-none-elf" - -[unstable] -build-std = ["core"] diff --git a/esp-ulp-riscv-hal/CHANGELOG.md b/esp-ulp-riscv-hal/CHANGELOG.md deleted file mode 100644 index f84203d0e..000000000 --- a/esp-ulp-riscv-hal/CHANGELOG.md +++ /dev/null @@ -1,22 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -### Added - -- Add the `ulp-riscv-hal` package (#840) - -### Changed - -- Renamed to `esp-ulp-riscv-hal` (#916) - -### Fixed - -### Removed - -[Unreleased]: https://github.com/esp-rs/esp-hal/commits/main/esp-ulp-riscv-hal diff --git a/esp-ulp-riscv-hal/Cargo.toml b/esp-ulp-riscv-hal/Cargo.toml deleted file mode 100644 index 7a1131d0a..000000000 --- a/esp-ulp-riscv-hal/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "esp-ulp-riscv-hal" -version = "0.1.0" -edition = "2021" -rust-version = "1.67.0" -description = "HAL for ESP32-S2 / ESP32-S3 ULP RISC-V coprocessor" -repository = "https://github.com/esp-rs/esp-hal" -license = "MIT OR Apache-2.0" - -keywords = [ - "embedded", - "embedded-hal", - "esp", - "esp32s2", - "esp32s3", - "no-std", -] -categories = [ - "embedded", - "hardware-support", - "no-std", -] - -[dependencies] -embedded-hal = { version = "0.2.7", features = ["unproven"] } -procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros" } -paste = "1.0.14" -esp32s2-ulp = { version = "0.1.0", optional = true } -esp32s3-ulp = { version = "0.1.0", optional = true } - -[dev-dependencies] -panic-halt = "0.2.0" - -[features] -default = [] -debug = [] -esp32s2 = ["dep:esp32s2-ulp", "procmacros/esp32s2-ulp"] -esp32s3 = ["dep:esp32s3-ulp", "procmacros/esp32s3-ulp"] diff --git a/esp-ulp-riscv-hal/README.md b/esp-ulp-riscv-hal/README.md deleted file mode 100644 index 283f92eee..000000000 --- a/esp-ulp-riscv-hal/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# ulp-lp-hal - -[![Crates.io](https://img.shields.io/crates/v/esp-ulp-lp-hal?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-ulp-lp-hal) -[![docs.rs](https://img.shields.io/docsrs/esp-ulp-lp-hal?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-ulp-lp-hal) -![Crates.io](https://img.shields.io/crates/l/esp-ulp-lp-hal?labelColor=1C2C2E&style=flat-square) -[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) - -`no_std` HAL for the ESP32-S2/ESP32-S3 from Espressif's ultra-low-power coprocessor. - -Implements a number of the traits defined in [embedded-hal](https://github.com/rust-embedded/embedded-hal). - -This device uses the RISC-V ISA, which is officially supported by the Rust compiler via the `riscv32imc-unknown-none-elf` target. - -Please refer to the documentation for more information. - -## [Documentation] - -[documentation]: https://docs.rs/esp-ulp-lp-hal/ - -## Resources - -- [Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -- [Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) -- [Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf) -- [Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf) -- [The Rust Programming Language](https://doc.rust-lang.org/book/) -- [The Embedded Rust Book](https://docs.rust-embedded.org/book/index.html) -- [The Rust on ESP Book](https://esp-rs.github.io/book/) - -## Getting Started - -### Installing the Rust Compiler Target - -The compilation target for this device is officially supported by the mainline Rust compiler and can be installed using [rustup](https://rustup.rs/): - -```shell -rustup target add riscv32imc-unknown-none-elf -``` - -## License - -Licensed under either of: - -- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in -the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without -any additional terms or conditions. diff --git a/esp-ulp-riscv-hal/build.rs b/esp-ulp-riscv-hal/build.rs deleted file mode 100644 index f6e11c0bc..000000000 --- a/esp-ulp-riscv-hal/build.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::{env, fs::File, io::Write, path::PathBuf}; - -fn main() { - // Put the linker script somewhere the linker can find it - let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); - - File::create(out.join("link.x")) - .unwrap() - .write_all(include_bytes!("ld/link.x")) - .unwrap(); - - println!("cargo:rustc-link-search={}", out.display()); - - // Only re-run the build script when memory.x is changed, - // instead of when any part of the source code changes. - println!("cargo:rerun-if-changed=ld/memory.x"); -} diff --git a/esp-ulp-riscv-hal/examples/blinky.rs b/esp-ulp-riscv-hal/examples/blinky.rs deleted file mode 100644 index cd85b0698..000000000 --- a/esp-ulp-riscv-hal/examples/blinky.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! Counts a 32 bit value at 0x5000_0400 (0x400 from the ULP's point of view) -//! and blinks GPIO 1. -//! -//! Make sure the RTC RAM is cleared before loading the code. - -#![no_std] -#![no_main] - -use esp_ulp_riscv_hal::{ - delay::Delay, - gpio::{GpioPin, Output, PushPull}, - prelude::*, -}; -use panic_halt as _; - -#[entry] -fn main(mut gpio1: GpioPin, 1>) -> ! { - let mut i: u32 = 0; - - let ptr = 0x400 as *mut u32; - let mut delay = Delay::new(); - - loop { - i = i.wrapping_add(1u32); - unsafe { - ptr.write_volatile(i); - } - - gpio1.set_high().unwrap(); - delay.delay_ms(500); - - gpio1.set_low().unwrap(); - delay.delay_ms(500); - } -} diff --git a/esp-ulp-riscv-hal/src/delay.rs b/esp-ulp-riscv-hal/src/delay.rs deleted file mode 100644 index 3e55b701a..000000000 --- a/esp-ulp-riscv-hal/src/delay.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Simple blocking delay functionality -//! -//! This uses cycle count under the hood. - -use core::arch::asm; - -use embedded_hal::blocking::delay::{DelayMs, DelayUs}; - -// see components\ulp\ulp_riscv\ulp_core\include\ulp_riscv_utils.h in esp-idf -#[cfg(feature = "esp32s2")] -const CYCLES_PER_US_M10: u32 = 85; -#[cfg(feature = "esp32s3")] -const CYCLES_PER_US_M10: u32 = 175; - -pub struct Delay {} - -impl Delay { - pub fn new() -> Self { - Self {} - } -} - -impl Default for Delay { - fn default() -> Self { - Self::new() - } -} - -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: u64) { - DelayUs::::delay_us(self, us as u32); - } -} - -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: u32) { - let t0 = cycles(); - let clock = us * CYCLES_PER_US_M10 / 10; - while cycles().wrapping_sub(t0) <= clock {} - } -} - -impl DelayMs for Delay { - #[inline(always)] - fn delay_ms(&mut self, ms: u32) { - DelayUs::::delay_us(self, ms * 1000); - } -} - -#[inline(always)] -fn cycles() -> u32 { - let mut cycles; - unsafe { - asm!( - "rdcycle {cycles}", - cycles = out(reg) cycles, - ) - } - cycles -} diff --git a/esp-ulp-riscv-hal/src/gpio.rs b/esp-ulp-riscv-hal/src/gpio.rs deleted file mode 100644 index f66226cc2..000000000 --- a/esp-ulp-riscv-hal/src/gpio.rs +++ /dev/null @@ -1,122 +0,0 @@ -//! Low-power GPIO driver -//! -//! It's assumed that GPIOs are already configured correctly by the HP core. - -use core::{convert::Infallible, marker::PhantomData}; - -use crate::pac::RTC_IO; - -#[doc(hidden)] -pub unsafe fn conjour() -> Option> { - if PIN > 7 { - None - } else { - Some(GpioPin { - phantom: PhantomData, - }) - } -} - -pub struct Unknown {} - -pub struct Input { - _mode: PhantomData, -} - -pub struct Floating; - -pub struct PullDown; - -pub struct PullUp; - -pub struct Output { - _mode: PhantomData, -} - -pub struct PushPull; - -#[non_exhaustive] -pub struct GpioPin { - phantom: PhantomData, -} - -impl GpioPin, PIN> { - fn input_state(&self) -> bool { - unsafe { &*RTC_IO::PTR }.rtc_gpio_in().read().bits() >> PIN & 0x1 != 0 - } -} - -impl GpioPin, PIN> { - fn output_state(&self) -> bool { - unsafe { &*RTC_IO::PTR }.rtc_gpio_out().read().bits() >> PIN & 0x1 != 0 - } - - fn set_output_low(&mut self) { - // TODO align PAC - - #[cfg(feature = "esp32s2")] - unsafe { &*RTC_IO::PTR } - .rtc_gpio_out_w1tc() - .write(|w| w.gpio_out_data_w1tc().variant(1 << PIN)); - - #[cfg(feature = "esp32s3")] - unsafe { &*RTC_IO::PTR } - .rtc_gpio_out_w1tc() - .write(|w| w.rtc_gpio_out_data_w1tc().variant(1 << PIN)); - } - - fn set_output_high(&mut self) { - #[cfg(feature = "esp32s2")] - unsafe { &*RTC_IO::PTR } - .rtc_gpio_out_w1ts() - .write(|w| w.gpio_out_data_w1ts().variant(1 << PIN)); - - #[cfg(feature = "esp32s3")] - unsafe { &*RTC_IO::PTR } - .rtc_gpio_out_w1ts() - .write(|w| w.rtc_gpio_out_data_w1ts().variant(1 << PIN)); - } -} - -impl embedded_hal::digital::v2::InputPin for GpioPin, PIN> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(self.input_state()) - } - - fn is_low(&self) -> Result { - Ok(!self.is_high()?) - } -} - -impl embedded_hal::digital::v2::OutputPin for GpioPin, PIN> { - type Error = Infallible; - - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_output_low(); - Ok(()) - } - - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_output_high(); - Ok(()) - } -} - -impl embedded_hal::digital::v2::StatefulOutputPin - for GpioPin, PIN> -{ - fn is_set_high(&self) -> Result { - Ok(self.output_state()) - } - - fn is_set_low(&self) -> Result { - Ok(!self.is_set_high()?) - } -} - -impl embedded_hal::digital::v2::toggleable::Default - for GpioPin, PIN> -{ -} diff --git a/esp-ulp-riscv-hal/src/lib.rs b/esp-ulp-riscv-hal/src/lib.rs deleted file mode 100644 index 1a8818d8b..000000000 --- a/esp-ulp-riscv-hal/src/lib.rs +++ /dev/null @@ -1,100 +0,0 @@ -#![no_std] -#![allow(asm_sub_register)] - -use core::arch::global_asm; - -pub mod delay; -pub mod gpio; -pub mod prelude; - -#[cfg(feature = "esp32s2")] -use esp32s2_ulp as pac; -#[cfg(feature = "esp32s3")] -use esp32s3_ulp as pac; - -global_asm!( - r#" - .section .text.vectors - .global irq_vector - .global reset_vector - -/* The reset vector, jumps to startup code */ -reset_vector: - j __start - -/* Interrupt handler */ -.balign 16 -irq_vector: - ret - - .section .text - -__start: - /* setup the stack pointer */ - la sp, __stack_top - - call ulp_riscv_rescue_from_monitor - call rust_main - call ulp_riscv_halt -loop: - j loop -"# -); - -#[link_section = ".init.rust"] -#[export_name = "rust_main"] -unsafe extern "C" fn lp_core_startup() -> ! { - extern "Rust" { - fn main() -> !; - } - - main(); -} - -#[link_section = ".init.rust"] -#[export_name = "ulp_riscv_rescue_from_monitor"] -unsafe extern "C" fn ulp_riscv_rescue_from_monitor() { - // Rescue RISCV from monitor state. - let rtc_cntl = unsafe { pac::RTC_CNTL::steal() }; - - // TODO align naming in PACs - #[cfg(feature = "esp32s2")] - rtc_cntl - .cocpu_ctrl() - .modify(|_, w| w.cocpu_done().clear_bit().cocpu_shut_reset_en().clear_bit()); - #[cfg(feature = "esp32s3")] - rtc_cntl - .rtc_cocpu_ctrl() - .modify(|_, w| w.cocpu_done().clear_bit().cocpu_shut_reset_en().clear_bit()); -} - -#[link_section = ".init.rust"] -#[export_name = "ulp_riscv_halt"] -unsafe extern "C" fn ulp_riscv_halt() { - let rtc_cntl = unsafe { pac::RTC_CNTL::steal() }; - - // TODO align naming in PACs - #[cfg(feature = "esp32s2")] - { - rtc_cntl - .cocpu_ctrl() - .modify(|_, w| w.cocpu_shut_2_clk_dis().variant(0x3f)); - - rtc_cntl - .cocpu_ctrl() - .modify(|_, w| w.cocpu_done().set_bit()); - } - #[cfg(feature = "esp32s3")] - { - rtc_cntl - .rtc_cocpu_ctrl() - .modify(|_, w| w.cocpu_shut_2_clk_dis().variant(0x3f)); - - rtc_cntl - .rtc_cocpu_ctrl() - .modify(|_, w| w.cocpu_done().set_bit()); - } - - #[allow(clippy::empty_loop)] - loop {} -} diff --git a/esp-ulp-riscv-hal/src/prelude.rs b/esp-ulp-riscv-hal/src/prelude.rs deleted file mode 100644 index 883977c99..000000000 --- a/esp-ulp-riscv-hal/src/prelude.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! The prelude -//! -//! Re-exports all traits required for interacting with the various peripheral -//! drivers implemented in this crate. - -pub use embedded_hal::{ - digital::v2::{ - InputPin as _embedded_hal_digital_vs_InputPin, - OutputPin as _embedded_hal_digital_vs_OutputPin, - StatefulOutputPin as _embedded_hal_digital_vs_StatefulOutputPin, - ToggleableOutputPin as _embedded_hal_digital_vs_ToggleableOutputPin, - }, - prelude::*, -}; -pub use procmacros::entry; diff --git a/esp32c6-hal/examples/lp_core_basic.rs b/esp32c6-hal/examples/lp_core_basic.rs index ba572614d..9a08c5518 100644 --- a/esp32c6-hal/examples/lp_core_basic.rs +++ b/esp32c6-hal/examples/lp_core_basic.rs @@ -3,7 +3,7 @@ //! Code on LP core increments a counter and continuously toggles GPIO1. The //! current value is printed by the HP core. //! -//! Make sure to first compile the `esp32c6-lp-hal/examples/blinky.rs` example +//! Make sure to first compile the `esp-lp-hal/examples/blinky.rs` example #![no_std] #![no_main] @@ -35,9 +35,8 @@ fn main() -> ! { println!("lp core stopped"); // load code to LP core - let lp_core_code = load_lp_code!( - "../esp32c6-lp-hal/target/riscv32imac-unknown-none-elf/release/examples/blinky" - ); + let lp_core_code = + load_lp_code!("../esp-lp-hal/target/riscv32imac-unknown-none-elf/release/examples/blinky"); // start LP core lp_core_code.run(&mut lp_core, lp_core::LpCoreWakeupSource::HpCpu, lp_pin); diff --git a/esp32c6-hal/examples/lp_core_uart.rs b/esp32c6-hal/examples/lp_core_uart.rs index 7be142817..741b3994c 100644 --- a/esp32c6-hal/examples/lp_core_uart.rs +++ b/esp32c6-hal/examples/lp_core_uart.rs @@ -1,8 +1,9 @@ //! This shows a very basic example of running code on the LP core. //! //! Code on LP core uses LP_UART initialized on HP core. For more information -//! check `lp_core_uart` example in the `esp32c6-lp-hal. -//! Make sure to first compile the `esp32c6-lp-hal/examples/uart.rs` example +//! check `lp_core_uart` example in the `esp-lp-hal. +//! +//! Make sure to first compile the `esp-lp-hal/examples/uart.rs` example #![no_std] #![no_main] @@ -60,9 +61,8 @@ fn main() -> ! { println!("lp core stopped"); // load code to LP core - let lp_core_code = load_lp_code!( - "../esp32c6-lp-hal/target/riscv32imac-unknown-none-elf/release/examples/uart" - ); + let lp_core_code = + load_lp_code!("../esp-lp-hal/target/riscv32imac-unknown-none-elf/release/examples/uart"); // start LP core lp_core_code.run(&mut lp_core, lp_core::LpCoreWakeupSource::HpCpu, lp_uart); diff --git a/esp32c6-lp-hal/.cargo/config.toml b/esp32c6-lp-hal/.cargo/config.toml deleted file mode 100644 index 67f78b7ee..000000000 --- a/esp32c6-lp-hal/.cargo/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -[target.riscv32imac-unknown-none-elf] -runner = "espflash flash --monitor" -rustflags = [ - "-C", "link-arg=-Tlink.x", -] - -[build] -target = "riscv32imac-unknown-none-elf" - -[unstable] -build-std = ["core"] diff --git a/esp32c6-lp-hal/Cargo.toml b/esp32c6-lp-hal/Cargo.toml deleted file mode 100644 index 1038b826e..000000000 --- a/esp32c6-lp-hal/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "esp32c6-lp-hal" -version = "0.1.0" -edition = "2021" -rust-version = "1.67.0" -description = "HAL for ESP32-C6's low-power coprocessor" -repository = "https://github.com/esp-rs/esp-hal" -license = "MIT OR Apache-2.0" - -keywords = [ - "embedded", - "embedded-hal", - "esp", - "esp32c6", - "no-std", -] -categories = [ - "embedded", - "hardware-support", - "no-std", -] - -[dependencies] -critical-section = { version = "1.1.2", features = ["restore-state-u8"] } -embedded-hal = { version = "0.2.7", features = ["unproven"] } -esp32c6-lp = { version = "0.1.0", features = ["critical-section"] } -nb = "1.1.0" -paste = "1.0.14" -procmacros = { package = "esp-hal-procmacros", path = "../esp-hal-procmacros", features = ["esp32c6-lp"] } -riscv = "0.10.1" - -[dev-dependencies] -panic-halt = "0.2.0" - -[features] -default = [] -debug = ["esp32c6-lp/impl-register-debug"] diff --git a/esp32c6-lp-hal/README.md b/esp32c6-lp-hal/README.md deleted file mode 100644 index 19e61c4ba..000000000 --- a/esp32c6-lp-hal/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# esp32c6-lp-hal - -[![Crates.io](https://img.shields.io/crates/v/esp32c6-lp-hal?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp32c6-lp-hal) -[![docs.rs](https://img.shields.io/docsrs/esp32c6-lp-hal?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp32c6-lp-hal) -![Crates.io](https://img.shields.io/crates/l/esp32c6-lp-hal?labelColor=1C2C2E&style=flat-square) -[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) - -`no_std` HAL for the ESP32-C6 from Espressif's low-power coprocessor. - -Implements a number of the traits defined in [embedded-hal](https://github.com/rust-embedded/embedded-hal). - -This device uses the RISC-V ISA, which is officially supported by the Rust compiler via the `riscv32imac-unknown-none-elf` target. - -Please refer to the documentation for more information. - -## [Documentation] - -[documentation]: https://docs.rs/esp32c6-lp-hal/ - -## Resources - -- [Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) -- [Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf) -- [The Rust Programming Language](https://doc.rust-lang.org/book/) -- [The Embedded Rust Book](https://docs.rust-embedded.org/book/index.html) -- [The Rust on ESP Book](https://esp-rs.github.io/book/) - -## Getting Started - -### Installing the Rust Compiler Target - -The compilation target for this device is officially supported by the mainline Rust compiler and can be installed using [rustup](https://rustup.rs/): - -```shell -rustup target add riscv32imac-unknown-none-elf -``` - -## License - -Licensed under either of: - -- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in -the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without -any additional terms or conditions. diff --git a/esp32c6-lp-hal/build.rs b/esp32c6-lp-hal/build.rs deleted file mode 100644 index ad3b47672..000000000 --- a/esp32c6-lp-hal/build.rs +++ /dev/null @@ -1,15 +0,0 @@ -use std::{env, error::Error, fs, path::PathBuf}; - -fn main() -> Result<(), Box> { - // Put the linker script somewhere the linker can find it - let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); - println!("cargo:rustc-link-search={}", out.display()); - - fs::copy("ld/link.x", out.join("link.x"))?; - - // Only re-run the build script when memory.x is changed, - // instead of when any part of the source code changes. - println!("cargo:rerun-if-changed=ld/memory.x"); - - Ok(()) -} diff --git a/esp32c6-lp-hal/examples/blinky.rs b/esp32c6-lp-hal/examples/blinky.rs deleted file mode 100644 index c5a768d69..000000000 --- a/esp32c6-lp-hal/examples/blinky.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Counts a 32 bit value at 0x5000_2000 and blinks GPIO 1. -//! Make sure the LP RAM is cleared before loading the code. - -#![no_std] -#![no_main] - -use esp32c6_lp_hal::{ - delay::Delay, - gpio::{GpioPin, Output, PushPull}, - prelude::*, -}; -use panic_halt as _; - -#[entry] -fn main(mut gpio1: GpioPin, 1>) -> ! { - let mut i: u32 = 0; - - let ptr = 0x5000_2000 as *mut u32; - let mut delay = Delay::new(); - - loop { - i = i.wrapping_add(1u32); - unsafe { - ptr.write_volatile(i); - } - - gpio1.set_high().unwrap(); - delay.delay_ms(500); - - gpio1.set_low().unwrap(); - delay.delay_ms(500); - } -} diff --git a/esp32c6-lp-hal/src/delay.rs b/esp32c6-lp-hal/src/delay.rs deleted file mode 100644 index 2439495e5..000000000 --- a/esp32c6-lp-hal/src/delay.rs +++ /dev/null @@ -1,47 +0,0 @@ -//! Simple blocking delay functionality -//! -//! This uses the delay functionality provided by the `riscv` crate under the -//! hood. - -use embedded_hal::blocking::delay::{DelayMs, DelayUs}; - -use crate::CPU_CLOCK; - -pub struct Delay { - rv_delay: riscv::delay::McycleDelay, -} - -impl Delay { - pub fn new() -> Self { - Self { - rv_delay: riscv::delay::McycleDelay::new(unsafe { CPU_CLOCK }), - } - } -} - -impl Default for Delay { - fn default() -> Self { - Self::new() - } -} - -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: u64) { - self.rv_delay.delay_us(us); - } -} - -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: u32) { - self.rv_delay.delay_us(us); - } -} - -impl DelayMs for Delay { - #[inline(always)] - fn delay_ms(&mut self, ms: u32) { - self.rv_delay.delay_ms(ms); - } -} diff --git a/esp32c6-lp-hal/src/gpio.rs b/esp32c6-lp-hal/src/gpio.rs deleted file mode 100644 index 8226efb52..000000000 --- a/esp32c6-lp-hal/src/gpio.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Low-power GPIO driver -//! -//! It's assumed that GPIOs are already configured correctly by the HP core. - -use core::{convert::Infallible, marker::PhantomData}; - -use esp32c6_lp::LP_IO; - -#[doc(hidden)] -pub unsafe fn conjour() -> Option> { - if PIN > 7 { - None - } else { - Some(GpioPin { - phantom: PhantomData, - }) - } -} - -pub struct Unknown {} - -pub struct Input { - _mode: PhantomData, -} - -pub struct Floating; - -pub struct PullDown; - -pub struct PullUp; - -pub struct Output { - _mode: PhantomData, -} - -pub struct PushPull; - -#[non_exhaustive] -pub struct GpioPin { - phantom: PhantomData, -} - -impl GpioPin, PIN> { - fn input_state(&self) -> bool { - unsafe { &*LP_IO::PTR }.in_().read().bits() >> PIN & 0x1 != 0 - } -} - -impl GpioPin, PIN> { - fn output_state(&self) -> bool { - unsafe { &*LP_IO::PTR }.out().read().bits() >> PIN & 0x1 != 0 - } - - fn set_output_low(&mut self) { - unsafe { &*LP_IO::PTR } - .out_w1tc() - .write(|w| w.out_data_w1tc().variant(1 << PIN)); - } - - fn set_output_high(&mut self) { - unsafe { &*LP_IO::PTR } - .out_w1ts() - .write(|w| w.out_data_w1ts().variant(1 << PIN)); - } -} - -impl embedded_hal::digital::v2::InputPin for GpioPin, PIN> { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(self.input_state()) - } - - fn is_low(&self) -> Result { - Ok(!self.is_high()?) - } -} - -impl embedded_hal::digital::v2::OutputPin for GpioPin, PIN> { - type Error = Infallible; - - fn set_low(&mut self) -> Result<(), Self::Error> { - self.set_output_low(); - Ok(()) - } - - fn set_high(&mut self) -> Result<(), Self::Error> { - self.set_output_high(); - Ok(()) - } -} - -impl embedded_hal::digital::v2::StatefulOutputPin - for GpioPin, PIN> -{ - fn is_set_high(&self) -> Result { - Ok(self.output_state()) - } - - fn is_set_low(&self) -> Result { - Ok(!self.is_set_high()?) - } -} - -impl embedded_hal::digital::v2::toggleable::Default - for GpioPin, PIN> -{ -} diff --git a/esp32c6-lp-hal/src/lib.rs b/esp32c6-lp-hal/src/lib.rs deleted file mode 100644 index 4b56ff75e..000000000 --- a/esp32c6-lp-hal/src/lib.rs +++ /dev/null @@ -1,96 +0,0 @@ -#![no_std] -#![allow(asm_sub_register)] - -use core::arch::global_asm; - -pub mod delay; -pub mod gpio; -pub mod prelude; -pub mod uart; - -pub mod riscv { - //! Low level access to RISC-V processors. - //! - //! Re-exports - - pub use riscv::*; -} - -// LP_FAST_CLK is not very accurate, for now use a rough estimate -const LP_FAST_CLK_HZ: u32 = 16_000_000; -const XTAL_D2_CLK_HZ: u32 = 20_000_000; - -pub static mut CPU_CLOCK: u32 = LP_FAST_CLK_HZ; - -global_asm!( - r#" - .section .init.vector, "ax" - /* This is the vector table. It is currently empty, but will be populated - * with exception and interrupt handlers when this is supported - */ - - .align 0x4, 0xff - .global _vector_table - .type _vector_table, @function -_vector_table: - .option push - .option norvc - - .rept 32 - nop - .endr - - .option pop - .size _vector_table, .-_vector_table - - .section .init, "ax" - .global reset_vector - - /* The reset vector, jumps to startup code */ - reset_vector: - j __start - - __start: - /* setup the stack pointer */ - la sp, __stack_top - call lp_core_startup - loop: - j loop -"# -); - -#[link_section = ".init.rust"] -#[export_name = "lp_core_startup"] -unsafe extern "C" fn lp_core_startup() -> ! { - extern "Rust" { - fn main() -> !; - } - - let clkrst = &*esp32c6_lp::LP_CLKRST::PTR; - if clkrst.lp_clk_conf().read().fast_clk_sel().bit_is_set() { - CPU_CLOCK = XTAL_D2_CLK_HZ; - } - - main(); -} - -mod critical_section_impl { - struct CriticalSection; - - critical_section::set_impl!(CriticalSection); - - unsafe impl critical_section::Impl for CriticalSection { - unsafe fn acquire() -> critical_section::RawRestoreState { - let mut mstatus = 0u32; - core::arch::asm!("csrrci {0}, mstatus, 8", inout(reg) mstatus); - let interrupts_active = (mstatus & 0b1000) != 0; - interrupts_active as _ - } - - unsafe fn release(token: critical_section::RawRestoreState) { - if token != 0 { - riscv::interrupt::enable(); - } - } - } -} diff --git a/esp32c6-lp-hal/src/prelude.rs b/esp32c6-lp-hal/src/prelude.rs deleted file mode 100644 index 883977c99..000000000 --- a/esp32c6-lp-hal/src/prelude.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! The prelude -//! -//! Re-exports all traits required for interacting with the various peripheral -//! drivers implemented in this crate. - -pub use embedded_hal::{ - digital::v2::{ - InputPin as _embedded_hal_digital_vs_InputPin, - OutputPin as _embedded_hal_digital_vs_OutputPin, - StatefulOutputPin as _embedded_hal_digital_vs_StatefulOutputPin, - ToggleableOutputPin as _embedded_hal_digital_vs_ToggleableOutputPin, - }, - prelude::*, -}; -pub use procmacros::entry; diff --git a/esp32s2-hal/examples/ulp_riscv_core_basic.rs b/esp32s2-hal/examples/ulp_riscv_core_basic.rs index 5eecfa1d4..509e18875 100644 --- a/esp32s2-hal/examples/ulp_riscv_core_basic.rs +++ b/esp32s2-hal/examples/ulp_riscv_core_basic.rs @@ -29,9 +29,8 @@ fn main() -> ! { let mut ulp_core = ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE); // load code to LP core - let lp_core_code = load_lp_code!( - "../esp-ulp-riscv-hal/target/riscv32imc-unknown-none-elf/release/examples/blinky" - ); + let lp_core_code = + load_lp_code!("../esp-lp-hal/target/riscv32imc-unknown-none-elf/release/examples/blinky"); // start LP core lp_core_code.run(&mut ulp_core, ulp_core::UlpCoreWakeupSource::HpCpu, pin); diff --git a/esp32s3-hal/examples/ulp_riscv_core_basic.rs b/esp32s3-hal/examples/ulp_riscv_core_basic.rs index f90683a0e..3da9c57b1 100644 --- a/esp32s3-hal/examples/ulp_riscv_core_basic.rs +++ b/esp32s3-hal/examples/ulp_riscv_core_basic.rs @@ -31,9 +31,8 @@ fn main() -> ! { println!("ulp core stopped"); // load code to LP core - let lp_core_code = load_lp_code!( - "../esp-ulp-riscv-hal/target/riscv32imc-unknown-none-elf/release/examples/blinky" - ); + let lp_core_code = + load_lp_code!("../esp-lp-hal/target/riscv32imc-unknown-none-elf/release/examples/blinky"); // start LP core lp_core_code.run(&mut ulp_core, ulp_core::UlpCoreWakeupSource::HpCpu, pin);