Unify: Remove the chip-specific HAL packages, adapt esp-hal for direct use [1/?] (#1196)
* Remove the chip-specific HAL packages * Update some doc comments which were missed, fix build script for ESP32/S2 * Refactor/update `esp-hal-procmacros` * Create the `examples` package, add back all of the previously existing examples * Use `xtask` automation package for checking examples and documentation in CI * Combine the `rt-riscv` and `rt-xtensa` features into a single `rt` feature * Bump MSRV to 1.76.0 (shocking!) * Re-document the features for the HAL * No need to re-export the `riscv` package like this * Make clippy happy, improve CI clippy checks * Update `CHANGELOG.md` * riscv: zero bss Co-authored-by: Björn Quentin <bjoernQ@users.noreply.github.com> * Address a number of review comments * Correct pin number in `hello_rgb` example for ESP32-C3 * Address the remaining review comments * More small tweaks/improvements * Fix RMT examples (#11) * Fix RMT examples * Remove logger-init * Make I2S examples work on ESP32 (#12) * Make I2S examples work on ESP32 * Remove logger init * Fix the direct-vectoring examples on all RISCV chips (#10) * Update GPIOs for some examples... * Embassy timer example fixes (#13) * Switch to generic queue instead of integrated for all examples * changelog * Update GPIO in another example, make `rustfmt` happy * Fix ESP32-S2 PSRAM * Avoid UART0 and SPI flash pins (#15) * Avoid UART0 and SPI flash pins * Fix spi_eh1_device_loopback for non-ESP32 * Update examples/src/bin/gpio_interrupt.rs Co-authored-by: Juraj Sadel <jurajsadel@gmail.com> --------- Co-authored-by: Juraj Sadel <jurajsadel@gmail.com> --------- Co-authored-by: Scott Mabin <scott@mabez.dev> Co-authored-by: Björn Quentin <bjoernQ@users.noreply.github.com> Co-authored-by: bjoernQ <bjoern.quentin@mobile-j.de> Co-authored-by: Juraj Sadel <jurajsadel@gmail.com>
This commit is contained in:
parent
9a95c0aa88
commit
6a663f8b1a
747
.github/workflows/ci.yml
vendored
747
.github/workflows/ci.yml
vendored
@ -1,3 +1,16 @@
|
||||
# NOTE:
|
||||
#
|
||||
# When adding support for a new chip to `esp-hal`, there are a number of
|
||||
# updates which must be made to the CI workflow in order to reflect this; the
|
||||
# changes are:
|
||||
#
|
||||
# 1.) In the 'esp-hal' job, add the name of the chip to the `matrix.soc` array.
|
||||
# 1a.) If the device has a low-power core (which is supported in
|
||||
# `esp-lp-hal`), then update the `if` condition to build prerequisites.
|
||||
# 2.) In the 'msrv-riscv' job, add checks as needed for the new chip.
|
||||
# 3.) In the 'clippy-riscv' job, add checks as needed for the new chip.
|
||||
# 3.) In the 'rustfmt' job, add checks as needed for the new chip.
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
@ -17,7 +30,7 @@ on:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MSRV: "1.67.0"
|
||||
MSRV: "1.76.0"
|
||||
|
||||
# Cancel any currently running workflows from the same PR, branch, or
|
||||
# tag when a new workflow is triggered.
|
||||
@ -29,69 +42,85 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
# --------------------------------------------------------------------------
|
||||
# Check Packages
|
||||
# Build Packages
|
||||
|
||||
esp-hal-smartled:
|
||||
esp-hal:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
soc: [
|
||||
# RISC-V devices:
|
||||
"esp32c2",
|
||||
"esp32c3",
|
||||
"esp32c6",
|
||||
"esp32h2",
|
||||
"esp32p4",
|
||||
# Xtensa devices:
|
||||
"esp32",
|
||||
"esp32s2",
|
||||
"esp32s3",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
|
||||
# Install the Rust toolchain for RISC-V devices:
|
||||
- if: ${{ !contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.soc) }}
|
||||
uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
|
||||
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf,riscv32imafc-unknown-none-elf
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
- uses: esp-rs/xtensa-toolchain@v1.5
|
||||
# Install the Rust toolchain for Xtensa devices:
|
||||
- if: contains(fromJson('["esp32", "esp32s2", "esp32s3"]'), matrix.soc)
|
||||
uses: esp-rs/xtensa-toolchain@v1.5
|
||||
with:
|
||||
buildtargets: ${{ matrix.soc }}
|
||||
default: true
|
||||
ldproxy: false
|
||||
override: false
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# Build all RISC-V targets:
|
||||
- name: build (esp32c3)
|
||||
run: cd esp-hal-smartled/ && cargo +nightly build -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=esp32c3
|
||||
- name: build (esp32c6)
|
||||
run: cd esp-hal-smartled/ && cargo +nightly build -Zbuild-std=core --target=riscv32imac-unknown-none-elf --features=esp32c6
|
||||
- name: build (esp32h2)
|
||||
run: cd esp-hal-smartled/ && cargo +nightly build -Zbuild-std=core --target=riscv32imac-unknown-none-elf --features=esp32h2
|
||||
# Build all Xtensa targets:
|
||||
- name: build (esp32)
|
||||
run: cd esp-hal-smartled/ && cargo +esp build -Zbuild-std=core --target=xtensa-esp32-none-elf --features=esp32
|
||||
- name: build (esp32s2)
|
||||
run: cd esp-hal-smartled/ && cargo +esp build -Zbuild-std=core --target=xtensa-esp32s2-none-elf --features=esp32s2
|
||||
- name: build (esp32s3)
|
||||
run: cd esp-hal-smartled/ && cargo +esp build -Zbuild-std=core --target=xtensa-esp32s3-none-elf --features=esp32s3
|
||||
# Ensure documentation can be built (requires a chip feature!)
|
||||
- name: rustdoc
|
||||
run: cd esp-hal-smartled/ && cargo doc -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=esp32c3
|
||||
# Build all supported examples for the low-power core first (if present):
|
||||
- if: contains(fromJson('["esp32c6", "esp32s2", "esp32s3"]'), matrix.soc)
|
||||
name: Build prerequisites (esp-lp-hal)
|
||||
run: cargo xtask build-examples esp-lp-hal ${{ matrix.soc }}
|
||||
|
||||
# Build all supported examples for the specified device:
|
||||
- name: Build examples
|
||||
run: cargo xtask build-examples esp-hal ${{ matrix.soc }}
|
||||
# Ensure we can build the documentation for the specified device:
|
||||
- name: Build documentation
|
||||
run: cargo xtask build-documentation esp-hal ${{ matrix.soc }}
|
||||
|
||||
esp-lp-hal:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
soc: ["esp32c6", "esp32s2", "esp32s3"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Install the Rust toolchain for RISC-V devices:
|
||||
- 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
|
||||
# Build all supported examples for the specified device:
|
||||
- name: Build examples
|
||||
run: cargo xtask build-examples esp-lp-hal ${{ matrix.soc }}
|
||||
# Ensure we can build the documentation for the specified device:
|
||||
- name: Build documentation
|
||||
run: cargo xtask build-documentation esp-lp-hal ${{ matrix.soc }}
|
||||
|
||||
esp-riscv-rt:
|
||||
runs-on: ubuntu-latest
|
||||
@ -100,519 +129,29 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
|
||||
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf,riscv32imafc-unknown-none-elf
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# Build for all RISC-V targets (no features):
|
||||
- name: Build esp-riscv-rt (riscv32imc, no features)
|
||||
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imc-unknown-none-elf
|
||||
- name: Build esp-riscv-rt (riscv32imac, no features)
|
||||
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imac-unknown-none-elf
|
||||
- name: Build esp-riscv-rt (riscv32imafc, no features)
|
||||
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imafc-unknown-none-elf
|
||||
# Build for all RISC-V targets (all features):
|
||||
- name: Build esp-riscv-rt (riscv32imc, all features)
|
||||
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imc-unknown-none-elf --features=ci
|
||||
- name: Build esp-riscv-rt (riscv32imac, all features)
|
||||
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imac-unknown-none-elf --features=ci
|
||||
- name: Build esp-riscv-rt (riscv32imafc, all features)
|
||||
run: cd esp-riscv-rt/ && cargo build -Zbuild-std=core --target=riscv32imafc-unknown-none-elf --features=ci
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp-riscv-rt/ && cargo doc
|
||||
|
||||
esp32-hal:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: esp-rs/xtensa-toolchain@v1.5
|
||||
with:
|
||||
default: true
|
||||
buildtargets: esp32
|
||||
ldproxy: false
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# Perform a full build initially to verify that the examples not only
|
||||
# build, but also link successfully.
|
||||
- name: build esp32-hal (no features)
|
||||
run: cd esp32-hal/ && cargo build --examples
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32-hal (common features)
|
||||
run: |
|
||||
cd esp32-hal/
|
||||
cargo build --examples --features=eh1,ufmt,log
|
||||
cargo build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32-hal (embassy)
|
||||
run: |
|
||||
cd esp32-hal/
|
||||
cargo check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo check --example=embassy_multicore --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo check --example=embassy_multicore_interrupt --features=embassy,embassy-time-timg0,embassy-executor-interrupt
|
||||
cargo check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32-hal (embassy, async)
|
||||
run: |
|
||||
cd esp32-hal/
|
||||
cargo check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
|
||||
cargo check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
- name: check esp32-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32-hal/
|
||||
cargo check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,defmt
|
||||
cargo check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,log
|
||||
- name: check esp32-hal (psram)
|
||||
run: cd esp32-hal/ && cargo check --example=psram --features=psram-2m --release # This example requires release!
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32-hal (no default features)
|
||||
run: cd esp32-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32-hal/ && cargo doc --features=eh1
|
||||
|
||||
esp32c2-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.
|
||||
# We also use this as an opportunity to verify that the examples link
|
||||
# for each supported image format.
|
||||
- name: build esp32c2-hal (no features)
|
||||
run: cd esp32c2-hal/ && cargo build --examples
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32c2-hal (common features)
|
||||
run: |
|
||||
cd esp32c2-hal/
|
||||
cargo +nightly build --examples --features=eh1,ufmt,log
|
||||
cargo +nightly build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32c2-hal (async, systick)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
- name: check esp32c2-hal (async, timg0)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
- name: check esp32c2-hal (async, gpio)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-systick,embassy-executor-thread,async
|
||||
- name: check esp32c2-hal (async, multiprio)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32c2-hal (async, spi)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-systick,embassy-executor-thread,async
|
||||
- name: check esp32c2-hal (async, serial)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-systick,embassy-executor-thread,async
|
||||
- name: check esp32c2-hal (async, i2c)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-systick,embassy-executor-thread,async
|
||||
- name: check esp32c2-hal (interrupt-preemption)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
|
||||
- name: check esp32c2-hal (direct-vectoring)
|
||||
run: cd esp32c2-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
|
||||
- name: check esp32c2-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32c2-hal/
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32c2-hal (no default features)
|
||||
run: cd esp32c2-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32c2-hal/ && cargo doc --features=eh1
|
||||
|
||||
esp32c3-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 esp32c3-hal (no features)
|
||||
run: cd esp32c3-hal/ && cargo +nightly build --examples
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32c3-hal (common features)
|
||||
run: |
|
||||
cd esp32c3-hal/
|
||||
cargo +nightly build --examples --features=eh1,ufmt,log
|
||||
cargo +nightly build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32c3-hal (embassy)
|
||||
run: |
|
||||
cd esp32c3-hal/
|
||||
cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32c3-hal (embassy, async)
|
||||
run: |
|
||||
cd esp32c3-hal/
|
||||
cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
|
||||
cargo +nightly check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_usb_serial_jtag --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
- name: check esp32c3-hal (interrupt-preemption)
|
||||
run: cd esp32c3-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
|
||||
- name: check esp32c3-hal (direct-vectoring)
|
||||
run: cd esp32c3-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
|
||||
- name: check esp32c3-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32c3-hal/
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32c3-hal (no default features)
|
||||
run: cd esp32c3-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32c3-hal/ && cargo doc --features=eh1
|
||||
|
||||
esp32c6-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
|
||||
|
||||
# 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.
|
||||
# We also use this as an opportunity to verify that the examples link
|
||||
# for each supported image format.
|
||||
- name: build esp32c6-hal (no features)
|
||||
run: cd esp32c6-hal/ && cargo +nightly build --examples
|
||||
- name: build esp32c6-hal (flip-link feature)
|
||||
run: cd esp32c6-hal/ && cargo +nightly build --examples --features=flip-link
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32c6-hal (common features)
|
||||
run: |
|
||||
cd esp32c6-hal/
|
||||
cargo +nightly build --examples --features=eh1,ufmt,log
|
||||
cargo +nightly build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32c6-hal (embassy)
|
||||
run: |
|
||||
cd esp32c6-hal/
|
||||
cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32c6-hal (embassy, async)
|
||||
run: |
|
||||
cd esp32c6-hal/
|
||||
cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
|
||||
cargo +nightly check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_usb_serial_jtag --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_parl_io_tx --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_parl_io_rx --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
- name: check esp32c6-hal (interrupt-preemption)
|
||||
run: cd esp32c6-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
|
||||
- name: check esp32c6-hal (direct-vectoring)
|
||||
run: cd esp32c6-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
|
||||
- name: check esp32c6-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32c6-hal/
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32c6-hal (no default features)
|
||||
run: cd esp32c6-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32c6-hal/ && cargo doc --features=eh1
|
||||
|
||||
esp32h2-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.
|
||||
# We also use this as an opportunity to verify that the examples link
|
||||
# for each supported image format.
|
||||
- name: build esp32h2-hal (no features)
|
||||
run: cd esp32h2-hal/ && cargo +nightly build --examples
|
||||
- name: build esp32h2-hal (flip-link feature)
|
||||
run: cd esp32h2-hal/ && cargo +nightly build --examples --features=flip-link
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32h2-hal (common features)
|
||||
run: |
|
||||
cd esp32h2-hal/
|
||||
cargo +nightly build --examples --features=eh1,ufmt,log
|
||||
cargo +nightly build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32h2-hal (embassy)
|
||||
run: |
|
||||
cd esp32h2-hal/
|
||||
cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32h2-hal (embassy, async)
|
||||
run: |
|
||||
cd esp32h2-hal/
|
||||
cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
|
||||
cargo +nightly check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_usb_serial_jtag --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_parl_io_tx --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +nightly check --example=embassy_parl_io_rx --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
- name: check esp32h2-hal (interrupt-preemption)
|
||||
run: cd esp32h2-hal/ && cargo +nightly check --example=interrupt_preemption --features=interrupt-preemption
|
||||
- name: check esp32h2-hal (direct-vectoring)
|
||||
run: cd esp32h2-hal/ && cargo +nightly check --example=direct-vectoring --features=direct-vectoring
|
||||
- name: check esp32h2-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32h2-hal/
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,defmt
|
||||
cargo +nightly check --examples --features=embassy,embassy-time-timg0,embassy-executor-thread,log
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32h2-hal (no default features)
|
||||
run: cd esp32h2-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32h2-hal/ && cargo doc --features=eh1
|
||||
|
||||
esp32p4-hal:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imafc-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.
|
||||
# We also use this as an opportunity to verify that the examples link
|
||||
# for each supported image format.
|
||||
- name: build esp32p4-hal (no features)
|
||||
run: cd esp32p4-hal/ && cargo +nightly build --examples
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32p4-hal (common features)
|
||||
run: |
|
||||
cd esp32p4-hal/
|
||||
cargo +nightly build --examples --features=eh1,ufmt,log
|
||||
cargo +nightly build --examples --features=eh1,ufmt,defmt
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32p4-hal (no default features)
|
||||
run: cd esp32p4-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32p4-hal/ && cargo doc --features=eh1
|
||||
|
||||
esp32s2-hal:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: esp-rs/xtensa-toolchain@v1.5
|
||||
with:
|
||||
default: true
|
||||
buildtargets: esp32s2
|
||||
ldproxy: false
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imc-unknown-none-elf
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# 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.
|
||||
- name: check esp32s2-hal (no features)
|
||||
run: cd esp32s2-hal/ && cargo +esp build --examples
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32s2-hal (common features)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo +esp build --examples --features=eh1,ufmt,log
|
||||
cargo +esp build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32s2-hal (embassy, timg0)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32s2-hal (embassy, systick)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32s2-hal (embassy, timg0, async)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread --release
|
||||
cargo +esp check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
- name: check esp32s2-hal (embassy, systick, async)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
- name: check esp32s2-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,defmt
|
||||
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,log
|
||||
- name: check esp32s2-hal (psram)
|
||||
run: cd esp32s2-hal/ && cargo +esp check --example=psram --features=psram-2m --release # This example requires release!
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32s2-hal (no default features)
|
||||
run: cd esp32s2-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32s2-hal/ && cargo +esp doc --features=eh1
|
||||
|
||||
esp32s3-hal:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: esp-rs/xtensa-toolchain@v1.5
|
||||
with:
|
||||
default: true
|
||||
buildtargets: esp32s3
|
||||
ldproxy: false
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imc-unknown-none-elf
|
||||
toolchain: nightly
|
||||
components: rust-src
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# 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.
|
||||
# We also use this as an opportunity to verify that the examples link
|
||||
# for each supported image format.
|
||||
- name: build esp32s3-hal (no features)
|
||||
run: cd esp32s3-hal/ && cargo +esp build --examples
|
||||
# Subsequent steps can just check the examples instead, as we're already
|
||||
# confident that they link.
|
||||
- name: check esp32s3-hal (common features)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo +esp build --examples --features=eh1,ufmt,log
|
||||
cargo +esp build --examples --features=eh1,ufmt,defmt
|
||||
- name: check esp32s3-hal (embassy, timg0)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_multicore --features=embassy,embassy-time-timg0,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_multicore_interrupt --features=embassy,embassy-time-timg0,embassy-executor-interrupt
|
||||
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-timg0,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32s3-hal (embassy, systick)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo +esp check --example=embassy_hello_world --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_multicore --features=embassy,embassy-time-systick,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_multicore_interrupt --features=embassy,embassy-time-systick,embassy-executor-interrupt
|
||||
cargo +esp check --example=embassy_multiprio --features=embassy,embassy-time-systick,embassy-executor-thread,embassy-executor-interrupt
|
||||
- name: check esp32s3-hal (embassy, timg0, async)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2s_read --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2s_sound --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_rmt_rx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_rmt_tx --features=embassy,embassy-time-timg0,async,embassy-executor-thread
|
||||
- name: check esp32s3-hal (embassy, systick, async)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo +esp check --example=embassy_wait --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_spi --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_serial --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_i2c --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
cargo +esp check --example=embassy_usb_serial_jtag --features=embassy,embassy-time-systick,async,embassy-executor-thread
|
||||
- name: check esp32s3-hal (octal psram and psram)
|
||||
run: | # This examples require release!
|
||||
cd esp32s3-hal/
|
||||
cargo +esp check --example=octal_psram --features=opsram-2m --release
|
||||
cargo +esp check --example=psram --features=psram-2m --release
|
||||
- name: check esp32s3-hal (embassy, log/defmt)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,defmt
|
||||
cargo +esp check --examples --features=embassy,embassy-time-timg0,embassy-executor-interrupt,embassy-executor-thread,log
|
||||
# Make sure we can build without default features enabled, too!
|
||||
- name: check esp32s3-hal (no default features)
|
||||
run: cd esp32s3-hal/ && cargo build --no-default-features
|
||||
# Ensure documentation can be built
|
||||
- name: rustdoc
|
||||
run: cd esp32s3-hal/ && cargo doc --features=eh1
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# MSRV
|
||||
|
||||
@ -625,56 +164,38 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf #,riscv32imafc-unknown-none-elf
|
||||
target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf
|
||||
toolchain: ${{ env.MSRV }}
|
||||
components: rust-src
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# TODO:
|
||||
# - Enable additional (all?) features for MSRV check
|
||||
|
||||
# Verify the MSRV for all RISC-V chips.
|
||||
- name: msrv (esp-hal)
|
||||
run: |
|
||||
cargo xtask build-package --features=esp32c2 --target=riscv32imc-unknown-none-elf esp-hal
|
||||
cargo xtask build-package --features=esp32c3 --target=riscv32imc-unknown-none-elf esp-hal
|
||||
cargo xtask build-package --features=esp32c6 --target=riscv32imac-unknown-none-elf esp-hal
|
||||
cargo xtask build-package --features=esp32h2 --target=riscv32imac-unknown-none-elf esp-hal
|
||||
cargo xtask build-package --features=esp32p4 --target=riscv32imafc-unknown-none-elf esp-hal
|
||||
- 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/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
- name: msrv (esp32c3-hal)
|
||||
run: |
|
||||
cd esp32c3-hal/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
- name: msrv (esp32c6-hal)
|
||||
run: |
|
||||
cd esp32c6-hal/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
- name: msrv (esp32h2-hal)
|
||||
run: |
|
||||
cd esp32h2-hal/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
# - name: msrv (esp32p4-hal)
|
||||
# run: |
|
||||
# cd esp32p4-hal/
|
||||
# cargo build --features=eh1,ufmt,log
|
||||
# cargo build --features=defmt
|
||||
cargo xtask build-package --features=esp32c6 --target=riscv32imac-unknown-none-elf esp-lp-hal
|
||||
cargo xtask build-package --features=esp32s2 --target=riscv32imc-unknown-none-elf esp-lp-hal
|
||||
cargo xtask build-package --features=esp32s3 --target=riscv32imc-unknown-none-elf esp-lp-hal
|
||||
|
||||
msrv-xtensa:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUSTC_BOOTSTRAP: 1
|
||||
|
||||
# TODO:
|
||||
# - Enable additional (all?) features for MSRV check
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
target: riscv32imc-unknown-none-elf
|
||||
toolchain: ${{ env.MSRV }}
|
||||
components: rust-src
|
||||
- uses: esp-rs/xtensa-toolchain@v1.5
|
||||
with:
|
||||
ldproxy: false
|
||||
@ -682,21 +203,11 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# Verify the MSRV for all Xtensa chips:
|
||||
- name: msrv (esp32-hal)
|
||||
- name: msrv (esp-hal)
|
||||
run: |
|
||||
cd esp32-hal/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
- name: msrv (esp32s2-hal)
|
||||
run: |
|
||||
cd esp32s2-hal/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
- name: msrv (esp32s3-hal)
|
||||
run: |
|
||||
cd esp32s3-hal/
|
||||
cargo build --features=eh1,ufmt,log
|
||||
cargo build --features=defmt
|
||||
cargo xtask build-package --toolchain=esp --features=esp32 --target=xtensa-esp32-none-elf esp-hal
|
||||
cargo xtask build-package --toolchain=esp --features=esp32s2 --target=xtensa-esp32s2-none-elf esp-hal
|
||||
cargo xtask build-package --toolchain=esp --features=esp32s3 --target=xtensa-esp32s3-none-elf esp-hal
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Lint
|
||||
@ -709,28 +220,34 @@ jobs:
|
||||
- uses: dtolnay/rust-toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
targets: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf # ,riscv32imafc-unknown-none-elf
|
||||
targets: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf,riscv32imafc-unknown-none-elf
|
||||
components: clippy,rust-src
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# Run 'cargo clippy' on all packages targeting RISC-V:
|
||||
- name: clippy (esp32c2-hal)
|
||||
run: cargo clippy --manifest-path=esp-hal/Cargo.toml --target=riscv32imc-unknown-none-elf --features=esp32c2 -- -D warnings
|
||||
- name: clippy (esp32c3-hal)
|
||||
run: cargo clippy --manifest-path=esp-hal/Cargo.toml --target=riscv32imc-unknown-none-elf --features=esp32c3 -- -D warnings
|
||||
- name: clippy (esp32c6-hal)
|
||||
run: cargo clippy --manifest-path=esp-hal/Cargo.toml --target=riscv32imac-unknown-none-elf --features=esp32c6 -- -D warnings
|
||||
- name: clippy (esp32h2-hal)
|
||||
run: cargo clippy --manifest-path=esp-hal/Cargo.toml --target=riscv32imac-unknown-none-elf --features=esp32h2 -- -D warnings
|
||||
# - name: clippy (esp32p4-hal)
|
||||
# run: cargo clippy --manifest-path=esp-hal/Cargo.toml --target=riscv32imafc-unknown-none-elf --features=esp32p4 -- -D warnings
|
||||
|
||||
## esp-hal:
|
||||
- name: clippy (esp-hal, esp32c2)
|
||||
run: cd esp-hal && cargo clippy --features=esp32c2 --target=riscv32imc-unknown-none-elf -- -D warnings
|
||||
- name: clippy (esp-hal, esp32c3)
|
||||
run: cd esp-hal && cargo clippy --features=esp32c3 --target=riscv32imc-unknown-none-elf -- -D warnings
|
||||
- name: clippy (esp-hal, esp32c6)
|
||||
run: cd esp-hal && cargo clippy --features=esp32c6 --target=riscv32imac-unknown-none-elf -- -D warnings
|
||||
- name: clippy (esp-hal, esp32h2)
|
||||
run: cd esp-hal && cargo clippy --features=esp32h2 --target=riscv32imac-unknown-none-elf -- -D warnings
|
||||
# TODO: Re-enable when able
|
||||
# - name: clippy (esp-hal, esp32p4)
|
||||
# run: cd esp-hal && cargo clippy --features=esp32p4 --target=riscv32imafc-unknown-none-elf -- -D warnings
|
||||
## esp-hal-smartled:
|
||||
- name: clippy (esp-hal-smartled)
|
||||
run: cd esp-hal-smartled && cargo clippy --features=esp32c6 --target=riscv32imac-unknown-none-elf -- -D warnings
|
||||
## esp-lp-hal:
|
||||
- name: clippy (esp-lp-hal, esp32c6)
|
||||
run: cd esp-lp-hal && cargo clippy --features=esp32c6 -- -D warnings
|
||||
run: cd esp-lp-hal && cargo clippy --features=esp32c6 --target=riscv32imac-unknown-none-elf -- -D warnings
|
||||
- name: clippy (esp-lp-hal, esp32s2)
|
||||
run: cd esp-lp-hal && cargo clippy --features=esp32s2 -- -D warnings
|
||||
run: cd esp-lp-hal && cargo clippy --features=esp32s2 --target=riscv32imc-unknown-none-elf -- -D warnings
|
||||
- name: clippy (esp-lp-hal, esp32s3)
|
||||
run: cd esp-lp-hal && cargo clippy --features=esp32s3 -- -D warnings
|
||||
run: cd esp-lp-hal && cargo clippy --features=esp32s3 --target=riscv32imc-unknown-none-elf -- -D warnings
|
||||
# esp-riscv-rt:
|
||||
- name: clippy (esp-riscv-rt)
|
||||
run: cd esp-riscv-rt && cargo clippy --target=riscv32imc-unknown-none-elf -- -D warnings
|
||||
|
||||
@ -746,12 +263,12 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
# Run 'cargo clippy' on all packages targeting Xtensa:
|
||||
- name: clippy (esp32-hal)
|
||||
run: cargo clippy -Zbuild-std=core --manifest-path=esp-hal/Cargo.toml --target=xtensa-esp32-none-elf --features=esp32 -- -D warnings
|
||||
- name: clippy (esp32s2-hal)
|
||||
run: cargo clippy -Zbuild-std=core --manifest-path=esp-hal/Cargo.toml --target=xtensa-esp32s2-none-elf --features=esp32s2 -- -D warnings
|
||||
- name: clippy (esp32s3-hal)
|
||||
run: cargo clippy -Zbuild-std=core --manifest-path=esp-hal/Cargo.toml --target=xtensa-esp32s3-none-elf --features=esp32s3 -- -D warnings
|
||||
- name: clippy (esp-hal, esp32)
|
||||
run: cd esp-hal && cargo clippy -Zbuild-std=core --features=esp32 --target=xtensa-esp32-none-elf -- -D warnings
|
||||
- name: clippy (esp-hal, esp32s2)
|
||||
run: cd esp-hal && cargo clippy -Zbuild-std=core --features=esp32s2 --target=xtensa-esp32s2-none-elf -- -D warnings
|
||||
- name: clippy (esp-hal, esp32s3)
|
||||
run: cd esp-hal && cargo clippy -Zbuild-std=core --features=esp32s3 --target=xtensa-esp32s3-none-elf -- -D warnings
|
||||
|
||||
rustfmt:
|
||||
runs-on: ubuntu-latest
|
||||
@ -777,19 +294,5 @@ jobs:
|
||||
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 (esp32-hal)
|
||||
run: cargo fmt --all --manifest-path=esp32-hal/Cargo.toml -- --check
|
||||
- name: rustfmt (esp32c2-hal)
|
||||
run: cargo fmt --all --manifest-path=esp32c2-hal/Cargo.toml -- --check
|
||||
- name: rustfmt (esp32c3-hal)
|
||||
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 (esp32h2-hal)
|
||||
run: cargo fmt --all --manifest-path=esp32h2-hal/Cargo.toml -- --check
|
||||
- name: rustfmt (esp32p4-hal)
|
||||
run: cargo fmt --all --manifest-path=esp32p4-hal/Cargo.toml -- --check
|
||||
- name: rustfmt (esp32s2-hal)
|
||||
run: cargo fmt --all --manifest-path=esp32s2-hal/Cargo.toml -- --check
|
||||
- name: rustfmt (esp32s3-hal)
|
||||
run: cargo fmt --all --manifest-path=esp32s3-hal/Cargo.toml -- --check
|
||||
- name: rustfmt (examples)
|
||||
run: cargo fmt --all --manifest-path=examples/Cargo.toml -- --check
|
||||
|
||||
@ -52,7 +52,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Lift the minimal buffer size requirement for I2S (#1189)
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove `xtal-26mhz` and `xtal-40mhz` features (#1165)
|
||||
- All chip-specific HAL packages have been removed (#1196)
|
||||
|
||||
### Breaking
|
||||
|
||||
@ -60,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- The `DAC` driver's constructor is now `new` instead of `dac`, to be more consistent with other APIs (#1100)
|
||||
- The DMA peripheral is now called `Dma` for devices with both PDMA and GDMA controllers (#1125)
|
||||
- The `ADC` driver's constructor is now `new` instead of `adc`, to be more consistent with other APIs (#1133)
|
||||
- `embassy-executor`'s `integrated-timers` is no longer enabled by default.
|
||||
|
||||
## [0.15.0] - 2024-01-19
|
||||
|
||||
@ -147,7 +150,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- RISC-V: Fix stack allocation (#988)
|
||||
- ESP32-C6: Fix used RAM (#997)
|
||||
- ESP32-H2: Fix used RAM (#1003)
|
||||
- Fix SPI slave DMA dma\_read and dma\_write (#1013)
|
||||
- Fix SPI slave DMA dma_read and dma_write (#1013)
|
||||
- ESP32-C6/H2: Fix disabling of interrupts (#1040)
|
||||
|
||||
### Removed
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["xtask"]
|
||||
exclude = [
|
||||
"esp-hal",
|
||||
@ -14,4 +15,5 @@ exclude = [
|
||||
"esp32p4-hal",
|
||||
"esp32s2-hal",
|
||||
"esp32s3-hal",
|
||||
"examples",
|
||||
]
|
||||
|
||||
@ -2,27 +2,27 @@
|
||||
name = "esp-hal-procmacros"
|
||||
version = "0.8.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
description = "Procedural macros for ESP-HAL"
|
||||
rust-version = "1.76.0"
|
||||
description = "Procedural macros for esp-hal"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["esp32c3", "embassy", "interrupt", "ram"]
|
||||
features = ["embassy", "has-ulp-core", "interrupt", "ram", "is-ulp-core"]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
darling = "0.20.3"
|
||||
document-features = "0.2.7"
|
||||
darling = "0.20.5"
|
||||
document-features = "0.2.8"
|
||||
litrs = "0.4.1"
|
||||
object = { version = "0.32.1", optional = true }
|
||||
proc-macro-crate = "2.0.1"
|
||||
object = { version = "0.32.2", optional = true }
|
||||
proc-macro-crate = "3.1.0"
|
||||
proc-macro-error = "1.0.4"
|
||||
proc-macro2 = "1.0.70"
|
||||
quote = "1.0.33"
|
||||
syn = { version = "2.0.40", features = ["extra-traits", "full"] }
|
||||
proc-macro2 = "1.0.78"
|
||||
quote = "1.0.35"
|
||||
syn = { version = "2.0.48", features = ["extra-traits", "full"] }
|
||||
|
||||
[features]
|
||||
## Provide a `#[main]` procmacro to mark the entry point for Embassy applications.
|
||||
@ -36,26 +36,14 @@ ram = []
|
||||
## Indicates the target devices has RTC slow memory available.
|
||||
rtc_slow = []
|
||||
|
||||
#! ### Chip Support Feature Flags
|
||||
## Target the ESP32.
|
||||
esp32 = []
|
||||
## Target the ESP32-C2.
|
||||
esp32c2 = []
|
||||
## Target the ESP32-C3.
|
||||
esp32c3 = []
|
||||
## Target the ESP32-C6.
|
||||
esp32c6 = ["dep:object"]
|
||||
## Target the ESP32-C6's low-power core.
|
||||
esp32c6-lp = []
|
||||
## Target the ESP32-H2.
|
||||
esp32h2 = []
|
||||
## Target the ESP32-P4.
|
||||
esp32p4 = []
|
||||
## Target the ESP32-S2.
|
||||
esp32s2 = ["dep:object"]
|
||||
## Target the ESP32-S2's ultra-low-power core.
|
||||
esp32s2-ulp = []
|
||||
## Target the ESP32-S3.
|
||||
esp32s3 = ["dep:object"]
|
||||
## Target the ESP32-S3's ultra-low-power core.
|
||||
esp32s3-ulp = []
|
||||
#! ### Low-power Core Feature Flags
|
||||
## Indicate that the SoC contains an LP core.
|
||||
has-lp-core = ["dep:object"]
|
||||
## Indicate that the SoC contains a ULP core.
|
||||
has-ulp-core = ["dep:object"]
|
||||
## Provide an `#[entry]` macro for running applications on the ESP32-C6/P4's
|
||||
## LP core.
|
||||
is-lp-core = []
|
||||
## Provide an `#[entry]` macro for running applications on the ESP32-S2/S3's
|
||||
## ULP core.
|
||||
is-ulp-core = []
|
||||
|
||||
@ -23,7 +23,7 @@ pub(crate) mod main {
|
||||
|
||||
use darling::{export::NestedMeta, FromMeta};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use proc_macro_crate::FoundCrate;
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{ReturnType, Type};
|
||||
|
||||
@ -162,19 +162,17 @@ pub(crate) mod main {
|
||||
}
|
||||
|
||||
pub fn main() -> TokenStream {
|
||||
let (hal_crate, hal_crate_name) = crate::get_hal_crate();
|
||||
let hal_crate = if cfg!(any(feature = "is-lp-core", feature = "is-ulp-core")) {
|
||||
crate_name("esp-lp-hal")
|
||||
} else {
|
||||
crate_name("esp-hal")
|
||||
};
|
||||
|
||||
let executor = match hal_crate {
|
||||
Ok(FoundCrate::Itself) => {
|
||||
quote!( #hal_crate_name::embassy::executor::Executor )
|
||||
}
|
||||
Ok(FoundCrate::Name(ref name)) => {
|
||||
let executor = if let Ok(FoundCrate::Name(ref name)) = hal_crate {
|
||||
let ident = Ident::new(&name, Span::call_site().into());
|
||||
quote!( #ident::embassy::executor::Executor )
|
||||
}
|
||||
Err(_) => {
|
||||
} else {
|
||||
quote!(crate::embassy::executor::Executor)
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use proc_macro2::{Group, TokenTree};
|
||||
use proc_macro2::{Group, TokenStream, TokenTree};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream, Result},
|
||||
Ident,
|
||||
@ -54,3 +55,26 @@ impl Parse for MakeGpioEnumDispatchMacro {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_match_arms(input: MakeGpioEnumDispatchMacro) -> Vec<TokenStream> {
|
||||
let mut arms = Vec::new();
|
||||
for (gpio_type, num) in input.elements {
|
||||
let enum_name = format_ident!("ErasedPin");
|
||||
let variant_name = format_ident!("Gpio{}", num);
|
||||
|
||||
if input.filter.contains(&gpio_type) {
|
||||
arms.push({
|
||||
quote! { #enum_name::#variant_name($target) => $body }
|
||||
});
|
||||
} else {
|
||||
arms.push({
|
||||
quote! {
|
||||
#[allow(unused)]
|
||||
#enum_name::#variant_name($target) => { panic!("Unsupported") }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
arms
|
||||
}
|
||||
|
||||
@ -75,12 +75,8 @@
|
||||
#![doc = document_features::document_features!()]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
|
||||
#[cfg(feature = "ram")]
|
||||
use darling::{ast::NestedMeta, Error as DarlingError, FromMeta};
|
||||
#[allow(unused)]
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro_error::proc_macro_error;
|
||||
use quote::quote;
|
||||
use syn::parse_macro_input;
|
||||
|
||||
#[cfg(feature = "embassy")]
|
||||
mod embassy;
|
||||
@ -88,80 +84,11 @@ mod embassy;
|
||||
mod enum_dispatch;
|
||||
#[cfg(feature = "interrupt")]
|
||||
mod interrupt;
|
||||
#[cfg(any(
|
||||
feature = "esp32c6-lp",
|
||||
feature = "esp32s2-ulp",
|
||||
feature = "esp32s3-ulp"
|
||||
))]
|
||||
#[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))]
|
||||
mod lp_core;
|
||||
|
||||
#[cfg(any(
|
||||
feature = "esp32c6",
|
||||
feature = "esp32s2",
|
||||
feature = "esp32s3",
|
||||
feature = "interrupt"
|
||||
))]
|
||||
fn get_hal_crate() -> (
|
||||
Result<proc_macro_crate::FoundCrate, proc_macro_crate::Error>,
|
||||
proc_macro2::Ident,
|
||||
) {
|
||||
use proc_macro::Span;
|
||||
use proc_macro2::Ident;
|
||||
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")]
|
||||
let hal_crate = crate_name("esp32c2-hal");
|
||||
#[cfg(feature = "esp32c3")]
|
||||
let hal_crate = crate_name("esp32c3-hal");
|
||||
#[cfg(feature = "esp32c6")]
|
||||
let hal_crate = crate_name("esp32c6-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 = "esp32s3")]
|
||||
let hal_crate = crate_name("esp32s3-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")]
|
||||
let hal_crate_name = Ident::new("esp32c2_hal", Span::call_site().into());
|
||||
#[cfg(feature = "esp32c3")]
|
||||
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 = "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 = "esp32s3")]
|
||||
let hal_crate_name = Ident::new("esp32s3_hal", Span::call_site().into());
|
||||
|
||||
(hal_crate, hal_crate_name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "ram")]
|
||||
#[derive(Debug, Default, FromMeta)]
|
||||
#[derive(Debug, Default, darling::FromMeta)]
|
||||
#[darling(default)]
|
||||
struct RamArgs {
|
||||
rtc_fast: bool,
|
||||
@ -181,15 +108,17 @@ struct RamArgs {
|
||||
/// Not all targets support RTC slow ram.
|
||||
#[cfg(feature = "ram")]
|
||||
#[proc_macro_attribute]
|
||||
#[proc_macro_error]
|
||||
#[proc_macro_error::proc_macro_error]
|
||||
pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
use darling::{ast::NestedMeta, Error, FromMeta};
|
||||
use proc_macro::Span;
|
||||
use proc_macro_error::abort;
|
||||
use syn::{parse, Item};
|
||||
|
||||
let attr_args = match NestedMeta::parse_meta_list(args.into()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
return TokenStream::from(DarlingError::from(e).write_errors());
|
||||
return TokenStream::from(Error::from(e).write_errors());
|
||||
}
|
||||
};
|
||||
|
||||
@ -205,7 +134,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
}
|
||||
};
|
||||
|
||||
let item: syn::Item = syn::parse(input).expect("failed to parse input");
|
||||
let item: Item = parse(input).expect("failed to parse input");
|
||||
|
||||
#[cfg(not(feature = "rtc_slow"))]
|
||||
if rtc_slow {
|
||||
@ -215,7 +144,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
);
|
||||
}
|
||||
|
||||
let is_fn = matches!(item, syn::Item::Fn(_));
|
||||
let is_fn = matches!(item, Item::Fn(_));
|
||||
let section_name = match (is_fn, rtc_fast, rtc_slow, uninitialized, zeroed) {
|
||||
(true, false, false, false, false) => Ok(".rwtext"),
|
||||
(true, true, false, false, false) => Ok(".rtc_fast.text"),
|
||||
@ -235,11 +164,11 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
};
|
||||
|
||||
let section = match (is_fn, section_name) {
|
||||
(true, Ok(section_name)) => quote! {
|
||||
(true, Ok(section_name)) => quote::quote! {
|
||||
#[link_section = #section_name]
|
||||
#[inline(never)] // make certain function is not inlined
|
||||
},
|
||||
(false, Ok(section_name)) => quote! {
|
||||
(false, Ok(section_name)) => quote::quote! {
|
||||
#[link_section = #section_name]
|
||||
},
|
||||
(_, Err(_)) => {
|
||||
@ -247,7 +176,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
}
|
||||
};
|
||||
|
||||
let output = quote! {
|
||||
let output = quote::quote! {
|
||||
#section
|
||||
#item
|
||||
};
|
||||
@ -285,10 +214,12 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
use std::iter;
|
||||
|
||||
use darling::{ast::NestedMeta, Error};
|
||||
use proc_macro::Span;
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro_crate::FoundCrate;
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use proc_macro_error::abort;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse::Error as ParseError,
|
||||
spanned::Spanned,
|
||||
@ -306,7 +237,7 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let attr_args = match NestedMeta::parse_meta_list(args.into()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
return TokenStream::from(darling::Error::from(e).write_errors());
|
||||
return TokenStream::from(Error::from(e).write_errors());
|
||||
}
|
||||
};
|
||||
|
||||
@ -321,11 +252,9 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut ident_s = &ident.clone();
|
||||
|
||||
if attr_args.len() == 1 {
|
||||
match &attr_args[0] {
|
||||
NestedMeta::Meta(Meta::Path(x)) => {
|
||||
if let NestedMeta::Meta(Meta::Path(x)) = &attr_args[0] {
|
||||
ident_s = x.get_ident().unwrap();
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
abort!(
|
||||
Span::call_site(),
|
||||
format!(
|
||||
@ -335,7 +264,6 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX should we blacklist other attributes?
|
||||
|
||||
@ -373,19 +301,17 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
proc_macro2::Span::call_site(),
|
||||
);
|
||||
|
||||
let (hal_crate, hal_crate_name) = get_hal_crate();
|
||||
let hal_crate = if cfg!(any(feature = "is-lp-core", feature = "is-ulp-core")) {
|
||||
crate_name("esp-lp-hal")
|
||||
} else {
|
||||
crate_name("esp-hal")
|
||||
};
|
||||
|
||||
let interrupt_in_hal_crate = match hal_crate {
|
||||
Ok(FoundCrate::Itself) => {
|
||||
quote!( #hal_crate_name::peripherals::Interrupt::#ident_s )
|
||||
}
|
||||
Ok(FoundCrate::Name(ref name)) => {
|
||||
let interrupt_in_hal_crate = if let Ok(FoundCrate::Name(ref name)) = hal_crate {
|
||||
let ident = Ident::new(&name, Span::call_site().into());
|
||||
quote!( #ident::peripherals::Interrupt::#ident_s )
|
||||
}
|
||||
Err(_) => {
|
||||
} else {
|
||||
quote!( crate::peripherals::Interrupt::#ident_s )
|
||||
}
|
||||
};
|
||||
|
||||
f.block.stmts.extend(iter::once(
|
||||
@ -406,17 +332,11 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
|
||||
let export_name = ident_s.to_string();
|
||||
|
||||
let trap_frame_in_hal_crate = match hal_crate {
|
||||
Ok(FoundCrate::Itself) => {
|
||||
quote!(#hal_crate_name::trapframe::TrapFrame)
|
||||
}
|
||||
Ok(FoundCrate::Name(ref name)) => {
|
||||
let trap_frame_in_hal_crate = if let Ok(FoundCrate::Name(ref name)) = hal_crate {
|
||||
let ident = Ident::new(&name, Span::call_site().into());
|
||||
quote!( #ident::trapframe::TrapFrame )
|
||||
}
|
||||
Err(_) => {
|
||||
} else {
|
||||
quote!(crate::trapframe::TrapFrame)
|
||||
}
|
||||
};
|
||||
|
||||
let context_call =
|
||||
@ -445,34 +365,14 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
#[cfg(feature = "enum-dispatch")]
|
||||
#[proc_macro]
|
||||
pub fn make_gpio_enum_dispatch_macro(input: TokenStream) -> TokenStream {
|
||||
use quote::format_ident;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use self::enum_dispatch::MakeGpioEnumDispatchMacro;
|
||||
use self::enum_dispatch::{build_match_arms, MakeGpioEnumDispatchMacro};
|
||||
|
||||
let input = parse_macro_input!(input as MakeGpioEnumDispatchMacro);
|
||||
|
||||
let mut arms = Vec::new();
|
||||
for (gpio_type, num) in input.elements {
|
||||
let enum_name = format_ident!("ErasedPin");
|
||||
let variant_name = format_ident!("Gpio{}", num);
|
||||
|
||||
if input.filter.contains(&gpio_type) {
|
||||
let arm = {
|
||||
quote! { #enum_name::#variant_name($target) => $body }
|
||||
};
|
||||
arms.push(arm);
|
||||
} else {
|
||||
let arm = {
|
||||
quote! {
|
||||
#[allow(unused)]
|
||||
#enum_name::#variant_name($target) => { panic!("Unsupported") }
|
||||
}
|
||||
};
|
||||
arms.push(arm);
|
||||
}
|
||||
}
|
||||
let input = syn::parse_macro_input!(input as MakeGpioEnumDispatchMacro);
|
||||
|
||||
let macro_name = format_ident!("{}", input.name);
|
||||
let arms = build_match_arms(input);
|
||||
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
@ -497,35 +397,36 @@ pub fn make_gpio_enum_dispatch_macro(input: TokenStream) -> TokenStream {
|
||||
/// let lp_core_code = load_lp_code!("path.elf");
|
||||
/// lp_core_code.run(&mut lp_core, lp_core::LpCoreWakeupSource::HpCpu, lp_pin);
|
||||
/// ````
|
||||
#[cfg(any(feature = "esp32c6", feature = "esp32s2", feature = "esp32s3"))]
|
||||
#[cfg(any(feature = "has-lp-core", feature = "has-ulp-core"))]
|
||||
#[proc_macro]
|
||||
pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
use std::{fs, path};
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use object::{Object, ObjectSection, ObjectSymbol};
|
||||
use litrs::StringLit;
|
||||
use object::{File, Object, ObjectSection, ObjectSymbol, Section, SectionKind};
|
||||
use parse::Error;
|
||||
use proc_macro::Span;
|
||||
use proc_macro_crate::FoundCrate;
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use quote::quote;
|
||||
use syn::{parse, Ident};
|
||||
|
||||
let (hal_crate, hal_crate_name) = get_hal_crate();
|
||||
let hal_crate = if cfg!(any(feature = "is-lp-core", feature = "is-ulp-core")) {
|
||||
crate_name("esp-lp-hal")
|
||||
} else {
|
||||
crate_name("esp-hal")
|
||||
};
|
||||
|
||||
let hal_crate = match hal_crate {
|
||||
Ok(FoundCrate::Itself) => {
|
||||
quote!( #hal_crate_name )
|
||||
}
|
||||
Ok(FoundCrate::Name(ref name)) => {
|
||||
let hal_crate = if let Ok(FoundCrate::Name(ref name)) = hal_crate {
|
||||
let ident = Ident::new(&name, Span::call_site().into());
|
||||
quote!( #ident )
|
||||
}
|
||||
Err(_) => {
|
||||
} else {
|
||||
quote!(crate)
|
||||
}
|
||||
};
|
||||
|
||||
let first_token = match input.into_iter().next() {
|
||||
Some(token) => token,
|
||||
None => {
|
||||
return parse::Error::new(
|
||||
return Error::new(
|
||||
Span::call_site().into(),
|
||||
"You need to give the path to an ELF file",
|
||||
)
|
||||
@ -533,10 +434,10 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
.into();
|
||||
}
|
||||
};
|
||||
let arg = match litrs::StringLit::try_from(&first_token) {
|
||||
let arg = match StringLit::try_from(&first_token) {
|
||||
Ok(arg) => arg,
|
||||
Err(_) => {
|
||||
return parse::Error::new(
|
||||
return Error::new(
|
||||
Span::call_site().into(),
|
||||
"You need to give the path to an ELF file",
|
||||
)
|
||||
@ -546,33 +447,34 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
};
|
||||
let elf_file = arg.value();
|
||||
|
||||
if !path::Path::new(elf_file).exists() {
|
||||
return parse::Error::new(Span::call_site().into(), "File not found")
|
||||
if !Path::new(elf_file).exists() {
|
||||
return Error::new(Span::call_site().into(), "File not found")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
|
||||
let bin_data = fs::read(elf_file).unwrap();
|
||||
let obj_file = object::File::parse(&*bin_data).unwrap();
|
||||
let obj_file = File::parse(&*bin_data).unwrap();
|
||||
let sections = obj_file.sections();
|
||||
|
||||
let mut sections: Vec<object::Section> = sections
|
||||
let mut sections: Vec<Section> = sections
|
||||
.into_iter()
|
||||
.filter(|section| match section.kind() {
|
||||
object::SectionKind::Text
|
||||
| object::SectionKind::ReadOnlyData
|
||||
| object::SectionKind::Data
|
||||
| object::SectionKind::UninitializedData => true,
|
||||
SectionKind::Text
|
||||
| SectionKind::ReadOnlyData
|
||||
| SectionKind::Data
|
||||
| SectionKind::UninitializedData => true,
|
||||
_ => false,
|
||||
})
|
||||
.collect();
|
||||
sections.sort_by(|a, b| a.address().partial_cmp(&b.address()).unwrap());
|
||||
|
||||
let mut binary: Vec<u8> = Vec::new();
|
||||
#[cfg(feature = "esp32c6")]
|
||||
let mut last_address = 0x50_000_000;
|
||||
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
|
||||
let mut last_address = 0x0;
|
||||
let mut last_address = if cfg!(feature = "has-lp-core") {
|
||||
0x5000_0000
|
||||
} else {
|
||||
0x0
|
||||
};
|
||||
|
||||
for section in sections {
|
||||
if section.address() > last_address {
|
||||
@ -590,7 +492,7 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
.find(|s| s.name().unwrap().starts_with("__ULP_MAGIC_"));
|
||||
|
||||
if let None = magic_symbol {
|
||||
return parse::Error::new(
|
||||
return Error::new(
|
||||
Span::call_site().into(),
|
||||
"Given file doesn't seem to be an LP/ULP core application.",
|
||||
)
|
||||
@ -611,7 +513,7 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
.filter(|v: &proc_macro2::TokenStream| !v.is_empty())
|
||||
.collect();
|
||||
|
||||
#[cfg(feature = "esp32c6")]
|
||||
#[cfg(feature = "has-lp-core")]
|
||||
let imports = quote! {
|
||||
use #hal_crate::lp_core::LpCore;
|
||||
use #hal_crate::lp_core::LpCoreWakeupSource;
|
||||
@ -620,24 +522,23 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
use #hal_crate::uart::lp_uart::LpUart;
|
||||
use #hal_crate::i2c::lp_i2c::LpI2c;
|
||||
};
|
||||
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
|
||||
#[cfg(feature = "has-ulp-core")]
|
||||
let imports = quote! {
|
||||
use #hal_crate::ulp_core::UlpCore as LpCore;
|
||||
use #hal_crate::ulp_core::UlpCoreWakeupSource as LpCoreWakeupSource;
|
||||
use #hal_crate::gpio::*;
|
||||
};
|
||||
|
||||
#[cfg(feature = "esp32c6")]
|
||||
#[cfg(feature = "has-lp-core")]
|
||||
let rtc_code_start = quote! { _rtc_fast_data_start };
|
||||
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
|
||||
#[cfg(feature = "has-ulp-core")]
|
||||
let rtc_code_start = quote! { _rtc_slow_data_start };
|
||||
|
||||
quote! {
|
||||
{
|
||||
#imports
|
||||
|
||||
struct LpCoreCode {
|
||||
}
|
||||
struct LpCoreCode {}
|
||||
|
||||
static LP_CODE: &[u8] = &[#(#binary),*];
|
||||
|
||||
@ -660,25 +561,26 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
LpCoreCode {
|
||||
}
|
||||
LpCoreCode {}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "esp32c6-lp",
|
||||
feature = "esp32s2-ulp",
|
||||
feature = "esp32s3-ulp"
|
||||
))]
|
||||
#[proc_macro_error]
|
||||
#[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))]
|
||||
#[proc_macro_error::proc_macro_error]
|
||||
#[proc_macro_attribute]
|
||||
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
use proc_macro2::{Ident, Span};
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse, parse_macro_input, spanned::Spanned, FnArg, ItemFn};
|
||||
use syn::{
|
||||
parse::{self, Error},
|
||||
parse_macro_input,
|
||||
spanned::Spanned,
|
||||
FnArg,
|
||||
ItemFn,
|
||||
};
|
||||
|
||||
use self::lp_core::{extract_pin, get_simplename, make_magic_symbol_name};
|
||||
|
||||
@ -692,7 +594,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
};
|
||||
|
||||
if !args.is_empty() {
|
||||
return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
|
||||
return Error::new(Span::call_site(), "This attribute accepts no arguments")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
@ -708,7 +610,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let param_name = format_ident!("param{}", num);
|
||||
match arg {
|
||||
FnArg::Receiver(_) => {
|
||||
return parse::Error::new(arg.span(), "invalid argument")
|
||||
return Error::new(arg.span(), "invalid argument")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
@ -717,7 +619,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
"GpioPin" => {
|
||||
let pin = extract_pin(&t.ty);
|
||||
if used_pins.contains(&pin) {
|
||||
return parse::Error::new(arg.span(), "duplicate pin")
|
||||
return Error::new(arg.span(), "duplicate pin")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
@ -737,7 +639,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
return parse::Error::new(arg.span(), "invalid argument to main")
|
||||
return Error::new(arg.span(), "invalid argument to main")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
@ -798,7 +700,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
/// // Function body
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(all(feature = "embassy"))]
|
||||
#[cfg(feature = "embassy")]
|
||||
#[proc_macro_attribute]
|
||||
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
use self::embassy::{
|
||||
@ -806,8 +708,8 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
Args,
|
||||
};
|
||||
|
||||
let args = parse_macro_input!(args as Args);
|
||||
let f = parse_macro_input!(item as syn::ItemFn);
|
||||
let args = syn::parse_macro_input!(args as Args);
|
||||
let f = syn::parse_macro_input!(item as syn::ItemFn);
|
||||
|
||||
run(&args.meta, f, main()).unwrap_or_else(|x| x).into()
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
name = "esp-hal-smartled"
|
||||
version = "0.8.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
rust-version = "1.76.0"
|
||||
description = "RMT adapter for smartleds"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
@ -2,16 +2,10 @@
|
||||
name = "esp-hal"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
description = "HAL implementations for peripherals common among Espressif devices; should not be used directly"
|
||||
rust-version = "1.76.0"
|
||||
description = "Bare-metal HAL for Espressif devices"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
# Prevent multiple copies of this crate in the same binary.
|
||||
# Needed because different copies might get different features, causing
|
||||
# confusing build errors due to expected features not getting enabled
|
||||
# on the unintentional copy.
|
||||
# This is especially common when mixing crates from crates.io and git.
|
||||
links = "esp-hal"
|
||||
|
||||
[dependencies]
|
||||
@ -20,12 +14,19 @@ bitfield = "0.14.0"
|
||||
cfg-if = "1.0.0"
|
||||
critical-section = "1.1.2"
|
||||
defmt = { version = "=0.3.5", optional = true }
|
||||
document-features = "0.2.8"
|
||||
embassy-executor = { version = "0.5.0", optional = true }
|
||||
embassy-futures = { version = "0.1.1", optional = true }
|
||||
embassy-sync = { version = "0.5.0", optional = true }
|
||||
embassy-time-driver = { version = "0.1.0", optional = true }
|
||||
embedded-can = { version = "0.4.1", optional = true }
|
||||
embedded-dma = "0.2.0"
|
||||
embedded-hal = { version = "0.2.7", features = ["unproven"] }
|
||||
embedded-hal-1 = { version = "1.0.0", optional = true, package = "embedded-hal" }
|
||||
embedded-hal-async = { version = "1.0.0", optional = true }
|
||||
embedded-hal-nb = { version = "1.0.0", optional = true }
|
||||
embedded-io = { version = "0.6.1", optional = true }
|
||||
embedded-io-async = { version = "0.6.1", optional = true }
|
||||
enumset = "1.1.3"
|
||||
esp-synopsys-usb-otg = { version = "0.4.0", optional = true, features = ["fs", "esp32sx"] }
|
||||
fugit = "0.3.7"
|
||||
@ -34,134 +35,47 @@ nb = "1.1.0"
|
||||
paste = "1.0.14"
|
||||
portable-atomic = { version = "1.6.0", default-features = false }
|
||||
procmacros = { version = "0.8.0", features = ["enum-dispatch", "ram"], package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
|
||||
riscv = { version = "0.11.0", optional = true }
|
||||
strum = { version = "0.25.0", default-features = false, features = ["derive"] }
|
||||
void = { version = "1.0.2", default-features = false }
|
||||
usb-device = { version = "0.3.1", optional = true }
|
||||
rand_core = { version = "0.6.4" }
|
||||
|
||||
# async
|
||||
embedded-hal-async = { version = "1.0.0", optional = true }
|
||||
embedded-io-async = { version = "0.6.1", optional = true }
|
||||
embassy-executor = { version = "0.5.0", optional = true }
|
||||
embassy-futures = { version = "0.1.1", optional = true }
|
||||
embassy-sync = { version = "0.5.0", optional = true }
|
||||
embassy-time-driver = { version = "0.1.0", optional = true }
|
||||
|
||||
# RISC-V
|
||||
riscv = { version = "0.11.0", optional = true }
|
||||
esp-riscv-rt = { version = "0.6.1", optional = true, path = "../esp-riscv-rt" }
|
||||
|
||||
# Xtensa
|
||||
xtensa-lx = { version = "0.8.0", optional = true }
|
||||
xtensa-lx-rt = { version = "0.16.0", optional = true }
|
||||
|
||||
# Part of `ufmt` containing only `uWrite` trait
|
||||
rand_core = "0.6.4"
|
||||
ufmt-write = { version = "0.1.0", optional = true }
|
||||
xtensa-lx = { version = "0.9.0", optional = true }
|
||||
|
||||
# IMPORTANT:
|
||||
# Each supported device MUST have its PAC included below along with a
|
||||
# corresponding feature.
|
||||
esp32 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ef39b1c", features = ["critical-section"], optional = true }
|
||||
esp32 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32c2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32c3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32p4 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32s2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
esp32s3 = { git = "https://github.com/esp-rs/esp-pacs", rev = "bbf7d5a", features = ["critical-section"], optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "riscv32")'.dependencies]
|
||||
esp-riscv-rt = { version = "0.6.1", optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "xtensa")'.dependencies]
|
||||
xtensa-lx-rt = { version = "0.16.0", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
basic-toml = "0.1.8"
|
||||
serde = { version = "1.0.195", features = ["derive"] }
|
||||
|
||||
[features]
|
||||
esp32 = ["dep:esp32", "xtensa", "procmacros/esp32", "xtensa-lx/esp32", "xtensa-lx-rt?/esp32"]
|
||||
esp32c2 = ["dep:esp32c2", "riscv", "procmacros/esp32c2", "portable-atomic/unsafe-assume-single-core"]
|
||||
esp32c3 = ["dep:esp32c3", "riscv", "procmacros/esp32c3", "portable-atomic/unsafe-assume-single-core"]
|
||||
esp32c6 = ["dep:esp32c6", "riscv", "procmacros/esp32c6"]
|
||||
esp32h2 = ["dep:esp32h2", "riscv", "procmacros/esp32h2"]
|
||||
esp32p4 = ["dep:esp32p4", "riscv", "procmacros/esp32p4"]
|
||||
esp32s2 = ["dep:esp32s2", "xtensa", "procmacros/esp32s2", "xtensa-lx/esp32s2", "xtensa-lx-rt?/esp32s2", "usb-otg", "portable-atomic/critical-section"]
|
||||
esp32s3 = ["dep:esp32s3", "xtensa", "procmacros/esp32s3", "xtensa-lx/esp32s3", "xtensa-lx-rt?/esp32s3", "usb-otg"]
|
||||
default = ["rt", "vectored"]
|
||||
|
||||
# Runetime support
|
||||
rt-riscv = ["esp-riscv-rt/zero-bss", "esp32c2?/rt", "esp32c3?/rt", "esp32c6?/rt", "esp32h2?/rt", "esp32p4?/rt"]
|
||||
rt-xtensa = ["dep:xtensa-lx-rt", "esp32?/rt", "esp32s2?/rt", "esp32s3?/rt"]
|
||||
riscv = ["dep:riscv", "critical-section/restore-state-u8", "esp-riscv-rt?/zero-bss"]
|
||||
xtensa = ["dep:xtensa-lx", "critical-section/restore-state-u32"]
|
||||
|
||||
# Only certain chips support flip-link (ESP32-C6 and ESPS32-H2)
|
||||
flip-link = ["esp-riscv-rt/fix-sp"]
|
||||
bluetooth = []
|
||||
|
||||
# PSRAM support
|
||||
psram-2m = []
|
||||
psram-4m = []
|
||||
psram-8m = []
|
||||
|
||||
# Octal RAM support
|
||||
opsram-2m = []
|
||||
opsram-4m = []
|
||||
opsram-8m = []
|
||||
opsram-16m = []
|
||||
|
||||
# PSRAM 80Mhz frequency support
|
||||
psram-80mhz = []
|
||||
|
||||
# USB OTG support (ESP32-S2 and ESP32-S3 only! Enabled by default)
|
||||
usb-otg = ["esp-synopsys-usb-otg", "usb-device"]
|
||||
|
||||
# Interrupt-related feature:
|
||||
# - Use direct interrupt vectoring (RISC-V only!)
|
||||
# - Use interrupt preemption (RISC-V only!)
|
||||
# - Use vectored interrupts (calling the handlers defined in the PAC)
|
||||
direct-vectoring = ["esp-riscv-rt/direct-vectoring"]
|
||||
interrupt-preemption = ["esp-riscv-rt/interrupt-preemption"]
|
||||
vectored = ["procmacros/interrupt"]
|
||||
|
||||
# Enable logging
|
||||
log = ["dep:log"]
|
||||
|
||||
# Trait implementation features:
|
||||
# - Implement the `embedded-hal@1.0.0-rc.x` traits (and friends)
|
||||
# - Implement the `embedded-io` traits where able
|
||||
# - Implement the `ufmt_write::Write` trait where able
|
||||
eh1 = ["embedded-hal-1", "embedded-hal-nb", "embedded-can"]
|
||||
embedded-io = ["dep:embedded-io"]
|
||||
ufmt = ["ufmt-write"]
|
||||
|
||||
# Support for asynchronous operation, implementing traits from
|
||||
# `embedded-hal-async` and `embedded-io-async`
|
||||
async = [
|
||||
"embedded-hal-async",
|
||||
"eh1",
|
||||
"embassy-sync",
|
||||
"embassy-futures",
|
||||
"embedded-io",
|
||||
"embedded-io-async",
|
||||
]
|
||||
|
||||
# Embassy support
|
||||
embassy = ["embassy-time-driver", "procmacros/embassy"]
|
||||
|
||||
embassy-executor-interrupt = ["embassy", "embassy-executor"]
|
||||
embassy-executor-thread = ["embassy", "embassy-executor"]
|
||||
|
||||
embassy-integrated-timers = ["embassy-executor?/integrated-timers"]
|
||||
|
||||
embassy-time-systick = []
|
||||
embassy-time-timg0 = []
|
||||
|
||||
# Architecture-specific features (intended for internal use)
|
||||
riscv = ["dep:riscv", "critical-section/restore-state-u8"]
|
||||
xtensa = ["critical-section/restore-state-u32"]
|
||||
|
||||
# Initialize / clear data sections and RTC memory
|
||||
rv-init-data = ["esp-riscv-rt/init-data", "esp-riscv-rt/init-rw-text"]
|
||||
rv-zero-rtc-bss = ["esp-riscv-rt/zero-rtc-fast-bss"]
|
||||
rv-init-rtc-data = ["esp-riscv-rt/init-rtc-fast-data", "esp-riscv-rt/init-rtc-fast-text"]
|
||||
|
||||
# Configuration for placing device drivers in the IRAM for faster access
|
||||
place-spi-driver-in-ram = []
|
||||
|
||||
# Enable the `impl-register-debug` feature for the selected PAC
|
||||
## Enable debug features in the HAL (used for development).
|
||||
debug = [
|
||||
"esp32?/impl-register-debug",
|
||||
"esp32c2?/impl-register-debug",
|
||||
@ -172,8 +86,71 @@ debug = [
|
||||
"esp32s2?/impl-register-debug",
|
||||
"esp32s3?/impl-register-debug",
|
||||
]
|
||||
## Enable logging output using the `log` crate.
|
||||
log = ["dep:log"]
|
||||
## Enable runtime support.
|
||||
rt = [
|
||||
"dep:esp-riscv-rt",
|
||||
"dep:xtensa-lx-rt",
|
||||
"esp32?/rt",
|
||||
"esp32c2?/rt",
|
||||
"esp32c3?/rt",
|
||||
"esp32c6?/rt",
|
||||
"esp32h2?/rt",
|
||||
"esp32p4?/rt",
|
||||
"esp32s2?/rt",
|
||||
"esp32s3?/rt",
|
||||
]
|
||||
## Enable interrupt vectoring.
|
||||
vectored = ["procmacros/interrupt"]
|
||||
|
||||
# Enable support for `defmt`, for `esp-hal` and also for all our dependencies
|
||||
#! ### Chip Support Feature Flags
|
||||
## Target the ESP32.
|
||||
esp32 = ["dep:esp32", "xtensa", "xtensa-lx/spin", "xtensa-lx-rt?/esp32"]
|
||||
## Target the ESP32-C2.
|
||||
esp32c2 = ["dep:esp32c2", "riscv", "portable-atomic/unsafe-assume-single-core"]
|
||||
## Target the ESP32-C3.
|
||||
esp32c3 = ["dep:esp32c3", "riscv", "portable-atomic/unsafe-assume-single-core", "rv-zero-rtc-bss"]
|
||||
## Target the ESP32-C6.
|
||||
esp32c6 = ["dep:esp32c6", "riscv", "procmacros/has-lp-core", "rv-zero-rtc-bss"]
|
||||
## Target the ESP32-H2.
|
||||
esp32h2 = ["dep:esp32h2", "riscv", "rv-zero-rtc-bss"]
|
||||
## Target the ESP32-P4.
|
||||
esp32p4 = ["dep:esp32p4", "riscv", "procmacros/has-lp-core", "rv-zero-rtc-bss"]
|
||||
## Target the ESP32-S2.
|
||||
esp32s2 = ["dep:esp32s2", "xtensa", "portable-atomic/critical-section", "procmacros/has-ulp-core", "xtensa-lx-rt?/esp32s2", "usb-otg"]
|
||||
## Target the ESP32-S3.
|
||||
esp32s3 = ["dep:esp32s3", "xtensa", "procmacros/has-ulp-core", "xtensa-lx/spin", "xtensa-lx-rt?/esp32s3", "usb-otg"]
|
||||
|
||||
#! ### RISC-V Exclusive Feature Flags
|
||||
## Enable direct interrupt vectoring.
|
||||
direct-vectoring = ["esp-riscv-rt/direct-vectoring"]
|
||||
## Move the stack to start of RAM to get zero-cost stack overflow protection
|
||||
## (ESP32-C6 and ESPS32-H2 only!).
|
||||
flip-link = ["esp-riscv-rt/fix-sp"]
|
||||
## Enable interrupt preemption.
|
||||
interrupt-preemption = ["esp-riscv-rt/interrupt-preemption"]
|
||||
## Configuration for placing device drivers in the IRAM for faster access.
|
||||
place-spi-driver-in-ram = []
|
||||
## Initialize the `.data` section of memory.
|
||||
rv-init-data = ["esp-riscv-rt?/init-data", "esp-riscv-rt?/init-rw-text"]
|
||||
## Zero the `.bss` section of low-power memory.
|
||||
rv-zero-rtc-bss = ["esp-riscv-rt?/zero-rtc-fast-bss"]
|
||||
## Initialize the `.data` section of low-power memory.
|
||||
rv-init-rtc-data = ["esp-riscv-rt?/init-rtc-fast-data", "esp-riscv-rt?/init-rtc-fast-text"]
|
||||
|
||||
#! ### Trait Implementation Feature Flags
|
||||
## Enable support for asynchronous operation, with interfaces provided by
|
||||
## `embedded-hal-async` and `embedded-io-async`.
|
||||
async = [
|
||||
"embedded-hal-async",
|
||||
"eh1",
|
||||
"embassy-sync",
|
||||
"embassy-futures",
|
||||
"embedded-io",
|
||||
"embedded-io-async",
|
||||
]
|
||||
## Implement `defmt::Format` on certain types.
|
||||
defmt = [
|
||||
"dep:defmt",
|
||||
"embassy-executor?/defmt",
|
||||
@ -183,3 +160,48 @@ defmt = [
|
||||
"embedded-io/defmt-03",
|
||||
"embedded-io-async?/defmt-03",
|
||||
]
|
||||
## Implement the traits defined in the `1.0.0` releases of `embedded-hal` and
|
||||
## `embedded-hal-nb` for the relevant peripherals.
|
||||
eh1 = ["embedded-hal-1", "embedded-hal-nb", "embedded-can"]
|
||||
## Implement the traits defined in `embedded-io` for certain peripherals.
|
||||
embedded-io = ["dep:embedded-io"]
|
||||
## Implement the `ufmt_write::uWrite` trait for certain peripherals.
|
||||
ufmt = ["dep:ufmt-write"]
|
||||
|
||||
#! ### Embassy Feature Flags
|
||||
## Enable support for `embassy`, a modern asynchronous embedded framework.
|
||||
embassy = ["embassy-time-driver", "procmacros/embassy"]
|
||||
## Use the interrupt-mode embassy executor.
|
||||
embassy-executor-interrupt = ["embassy", "embassy-executor"]
|
||||
## Use the thread-mode embassy executor.
|
||||
embassy-executor-thread = ["embassy", "embassy-executor"]
|
||||
## Uses hardware timers as alarms for the executors. Using this feature
|
||||
## limits the number of executors to the number of hardware alarms provided
|
||||
## by the time driver.
|
||||
embassy-integrated-timers = ["embassy-executor?/integrated-timers"]
|
||||
## Enable the embassy time driver using the `SYSTIMER` peripheral. The
|
||||
## `SYSTIMER` peripheral has three alarams available for use.
|
||||
embassy-time-systick = []
|
||||
## Enable the embassy time driver using the `TIMG0` peripheral. The `TIMG0`
|
||||
## peripheral has two alarms available for use.
|
||||
embassy-time-timg0 = []
|
||||
|
||||
#! ### PSRAM Feature Flags
|
||||
## Use externally connected PSRAM (2MB).
|
||||
psram-2m = []
|
||||
## Use externally connected PSRAM (4MB).
|
||||
psram-4m = []
|
||||
## Use externally connected PSRAM (8MB).
|
||||
psram-8m = []
|
||||
## PSRAM 80Mhz frequency support
|
||||
psram-80mhz = []
|
||||
|
||||
#! ### Octal RAM Feature Flags
|
||||
## Use externally connected Octal RAM (2MB).
|
||||
opsram-2m = []
|
||||
## Use externally connected Octal RAM (4MB).
|
||||
opsram-4m = []
|
||||
## Use externally connected Octal RAM (8MB).
|
||||
opsram-8m = []
|
||||
## Use externally connected Octal RAM (16MB).
|
||||
opsram-16m = []
|
||||
|
||||
@ -249,6 +249,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
copy_dir_all(&config_symbols, "ld/sections", &out)?;
|
||||
copy_dir_all(&config_symbols, format!("ld/{device_name}"), &out)?;
|
||||
|
||||
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||
File::create(out.join("memory_extras.x"))?.write_all(&generate_memory_extras())?;
|
||||
|
||||
// Generate the eFuse table from the selected device's CSV file:
|
||||
gen_efuse_table(device_name, out)?;
|
||||
|
||||
@ -412,3 +415,43 @@ fn detect_atomic_extension(ext: &str) -> bool {
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(feature = "esp32")]
|
||||
fn generate_memory_extras() -> Vec<u8> {
|
||||
let reserve_dram = if cfg!(feature = "bluetooth") {
|
||||
"0x10000"
|
||||
} else {
|
||||
"0x0"
|
||||
};
|
||||
|
||||
format!(
|
||||
"
|
||||
/* reserved at the start of DRAM for e.g. the BT stack */
|
||||
RESERVE_DRAM = {reserve_dram};
|
||||
"
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
#[cfg(feature = "esp32s2")]
|
||||
fn generate_memory_extras() -> Vec<u8> {
|
||||
let reserved_cache = if cfg!(any(
|
||||
feature = "psram-2m",
|
||||
feature = "psram-4m",
|
||||
feature = "psram-8m"
|
||||
)) {
|
||||
"0x4000"
|
||||
} else {
|
||||
"0x2000"
|
||||
};
|
||||
|
||||
format!(
|
||||
"
|
||||
/* reserved at the start of DRAM/IRAM */
|
||||
RESERVE_CACHES = {reserved_cache};
|
||||
"
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
//! #[cfg(feature = "embassy-time-systick")]
|
||||
//! embassy::init(
|
||||
//! &clocks,
|
||||
//! esp32c6_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
//! esp_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
//! );
|
||||
//!
|
||||
//! #[cfg(feature = "embassy-time-timg0")]
|
||||
@ -46,9 +46,9 @@
|
||||
//! let input = io.pins.gpio9.into_pull_down_input();
|
||||
//!
|
||||
//! // Async requires the GPIO interrupt to wake futures
|
||||
//! esp32c6_hal::interrupt::enable(
|
||||
//! esp32c6_hal::peripherals::Interrupt::GPIO,
|
||||
//! esp32c6_hal::interrupt::Priority::Priority1,
|
||||
//! esp_hal::interrupt::enable(
|
||||
//! esp_hal::peripherals::Interrupt::GPIO,
|
||||
//! esp_hal::interrupt::Priority::Priority1,
|
||||
//! )
|
||||
//! .unwrap();
|
||||
//!
|
||||
|
||||
@ -12,8 +12,11 @@
|
||||
//! interrupt15() => Priority::Priority15
|
||||
//! ```
|
||||
|
||||
use esp_riscv_rt::riscv::register::{mcause, mtvec};
|
||||
// TODO: Add safety doc comments as needed and remove allow attribute
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
|
||||
pub use esp_riscv_rt::TrapFrame;
|
||||
use riscv::register::{mcause, mtvec};
|
||||
|
||||
#[cfg(not(any(plic, clic)))]
|
||||
pub use self::classic::*;
|
||||
@ -158,7 +161,7 @@ mod vectored {
|
||||
let interrupt_nr = status.trailing_zeros() as u16;
|
||||
// safety: cast is safe because of repr(u16)
|
||||
if let Some(cpu_interrupt) =
|
||||
get_assigned_cpu_interrupt(core::mem::transmute(interrupt_nr as u16))
|
||||
get_assigned_cpu_interrupt(core::mem::transmute(interrupt_nr))
|
||||
{
|
||||
let prio = get_priority_by_core(core, cpu_interrupt);
|
||||
prios[prio as usize] |= 1 << (interrupt_nr as usize);
|
||||
@ -249,8 +252,13 @@ mod vectored {
|
||||
// defined in each hal
|
||||
fn EspDefaultHandler(interrupt: Interrupt);
|
||||
}
|
||||
|
||||
let handler = peripherals::__EXTERNAL_INTERRUPTS[interrupt as usize]._handler;
|
||||
if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() {
|
||||
|
||||
if core::ptr::eq(
|
||||
handler as *const _,
|
||||
EspDefaultHandler as *const unsafe extern "C" fn(),
|
||||
) {
|
||||
EspDefaultHandler(interrupt);
|
||||
} else {
|
||||
let handler: fn(&mut TrapFrame) = core::mem::transmute(handler);
|
||||
@ -739,7 +747,6 @@ mod classic {
|
||||
#[link_section = ".trap"]
|
||||
pub(super) unsafe extern "C" fn _handle_priority() -> u32 {
|
||||
use super::mcause;
|
||||
use crate::riscv;
|
||||
let interrupt_id: usize = mcause::read().code(); // MSB is whether its exception or interrupt.
|
||||
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
|
||||
let interrupt_priority = intr
|
||||
@ -763,10 +770,7 @@ mod classic {
|
||||
#[no_mangle]
|
||||
#[link_section = ".trap"]
|
||||
pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) {
|
||||
use crate::riscv;
|
||||
unsafe {
|
||||
riscv::interrupt::disable();
|
||||
}
|
||||
let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR;
|
||||
intr.cpu_int_thresh().write(|w| w.bits(stored_prio));
|
||||
}
|
||||
@ -792,7 +796,7 @@ mod plic {
|
||||
];
|
||||
|
||||
const DR_REG_PLIC_MX_BASE: u32 = 0x20001000;
|
||||
const PLIC_MXINT_ENABLE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x0;
|
||||
const PLIC_MXINT_ENABLE_REG: u32 = DR_REG_PLIC_MX_BASE;
|
||||
const PLIC_MXINT_TYPE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x4;
|
||||
const PLIC_MXINT_CLEAR_REG: u32 = DR_REG_PLIC_MX_BASE + 0x8;
|
||||
const PLIC_MXINT0_PRI_REG: u32 = DR_REG_PLIC_MX_BASE + 0x10;
|
||||
@ -877,7 +881,6 @@ mod plic {
|
||||
#[link_section = ".trap"]
|
||||
pub(super) unsafe extern "C" fn _handle_priority() -> u32 {
|
||||
use super::mcause;
|
||||
use crate::riscv;
|
||||
let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32;
|
||||
let interrupt_id: isize = mcause::read().code().try_into().unwrap(); // MSB is whether its exception or interrupt.
|
||||
let interrupt_priority = plic_mxint_pri_ptr.offset(interrupt_id).read_volatile();
|
||||
@ -898,10 +901,7 @@ mod plic {
|
||||
#[no_mangle]
|
||||
#[link_section = ".trap"]
|
||||
pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) {
|
||||
use crate::riscv;
|
||||
unsafe {
|
||||
riscv::interrupt::disable();
|
||||
}
|
||||
let thresh_reg = PLIC_MXINT_THRESH_REG as *mut u32;
|
||||
thresh_reg.write_volatile(stored_prio);
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// TODO: Add safety doc comments as needed and remove allow attribute
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
|
||||
use xtensa_lx::interrupt::{self, InterruptNumber};
|
||||
use xtensa_lx_rt::exception::Context;
|
||||
|
||||
@ -394,8 +397,7 @@ mod vectored {
|
||||
if let Some(handler) = cpu_interrupt_nr_to_cpu_interrupt_handler(cpu_interrupt_nr) {
|
||||
handler(level, save_frame);
|
||||
}
|
||||
} else {
|
||||
if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
|
||||
} else if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
|
||||
let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_EDGE;
|
||||
let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros();
|
||||
interrupt::clear(1 << cpu_interrupt_nr);
|
||||
@ -431,7 +433,6 @@ mod vectored {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ram]
|
||||
unsafe fn handle_interrupt(level: u32, interrupt: Interrupt, save_frame: &mut Context) {
|
||||
@ -441,7 +442,10 @@ mod vectored {
|
||||
}
|
||||
|
||||
let handler = peripherals::__INTERRUPTS[interrupt.number() as usize]._handler;
|
||||
if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() {
|
||||
if core::ptr::eq(
|
||||
handler as *const _,
|
||||
EspDefaultHandler as *const unsafe extern "C" fn(),
|
||||
) {
|
||||
EspDefaultHandler(level, interrupt);
|
||||
} else {
|
||||
let handler: fn(&mut Context) = core::mem::transmute(handler);
|
||||
@ -449,6 +453,7 @@ mod vectored {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unusual_byte_groupings)]
|
||||
#[cfg(esp32)]
|
||||
mod chip_specific {
|
||||
use super::*;
|
||||
@ -471,6 +476,7 @@ mod vectored {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unusual_byte_groupings)]
|
||||
#[cfg(esp32s2)]
|
||||
mod chip_specific {
|
||||
use super::*;
|
||||
|
||||
@ -2,43 +2,25 @@
|
||||
//! Espressif devices. Implements a number of the traits defined by
|
||||
//! [embedded-hal].
|
||||
//!
|
||||
//! This crate should not be used directly; you should use one of the
|
||||
//! device-specific HAL crates instead:
|
||||
//!
|
||||
//! - [esp32-hal]
|
||||
//! - [esp32c2-hal]
|
||||
//! - [esp32c3-hal]
|
||||
//! - [esp32c6-hal]
|
||||
//! - [esp32h2-hal]
|
||||
//! - [esp32p4-hal]
|
||||
//! - [esp32s2-hal]
|
||||
//! - [esp32s3-hal]
|
||||
//!
|
||||
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
|
||||
//! [esp32-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32-hal
|
||||
//! [esp32c2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c2-hal
|
||||
//! [esp32c3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c3-hal
|
||||
//! [esp32c6-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c6-hal
|
||||
//! [esp32h2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32h2-hal
|
||||
//! [esp32p4-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32p4-hal
|
||||
//! [esp32s2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s2-hal
|
||||
//! [esp32s3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s3-hal
|
||||
|
||||
#![no_std]
|
||||
#![allow(asm_sub_register)]
|
||||
#![cfg_attr(xtensa, feature(asm_experimental_arch))]
|
||||
#![cfg_attr(feature = "async", allow(stable_features, async_fn_in_trait))]
|
||||
//! ## Feature Flags
|
||||
#![doc = document_features::document_features!()]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
#![allow(asm_sub_register)]
|
||||
#![cfg_attr(feature = "async", allow(stable_features, async_fn_in_trait))]
|
||||
#![cfg_attr(xtensa, feature(asm_experimental_arch))]
|
||||
#![no_std]
|
||||
|
||||
// MUST be the first module
|
||||
mod fmt;
|
||||
|
||||
#[cfg(feature = "rt-riscv")]
|
||||
pub use esp_riscv_rt::{self, entry, riscv};
|
||||
#[cfg(all(riscv, feature = "rt"))]
|
||||
pub use esp_riscv_rt::{self, entry};
|
||||
pub use procmacros as macros;
|
||||
#[cfg(riscv)]
|
||||
pub use riscv;
|
||||
#[cfg(xtensa)]
|
||||
pub use xtensa_lx;
|
||||
#[cfg(feature = "rt-xtensa")]
|
||||
#[cfg(all(xtensa, feature = "rt"))]
|
||||
pub use xtensa_lx_rt::{self, entry};
|
||||
|
||||
#[cfg(adc)]
|
||||
@ -99,10 +81,7 @@ pub mod hmac;
|
||||
pub mod i2c;
|
||||
#[cfg(any(i2s0, i2s1))]
|
||||
pub mod i2s;
|
||||
#[cfg(all(
|
||||
any(dport, interrupt_core0, interrupt_core1),
|
||||
any(feature = "rt-riscv", feature = "rt-xtensa")
|
||||
))]
|
||||
#[cfg(all(any(dport, interrupt_core0, interrupt_core1), feature = "rt"))]
|
||||
pub mod interrupt;
|
||||
#[cfg(lcd_cam)]
|
||||
pub mod lcd_cam;
|
||||
@ -151,7 +130,7 @@ pub mod uart;
|
||||
pub mod usb_serial_jtag;
|
||||
|
||||
/// State of the CPU saved when entering exception or interrupt
|
||||
#[cfg(any(feature = "rt-riscv", feature = "rt-xtensa"))]
|
||||
#[cfg(feature = "rt")]
|
||||
pub mod trapframe {
|
||||
#[cfg(riscv)]
|
||||
pub use esp_riscv_rt::TrapFrame;
|
||||
|
||||
@ -34,7 +34,7 @@ pub use crate::dma::{
|
||||
DmaTransfer as _esp_hal_dma_DmaTransfer,
|
||||
DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx,
|
||||
};
|
||||
#[cfg(any(feature = "rt-riscv", feature = "rt-xtensa"))]
|
||||
#[cfg(feature = "rt")]
|
||||
pub use crate::entry;
|
||||
#[cfg(gpio)]
|
||||
pub use crate::gpio::{
|
||||
|
||||
@ -33,7 +33,7 @@ pub(crate) mod constants {
|
||||
/// ENTRY point is defined in memory.x
|
||||
/// *Note: the pre_init function is called in the original reset handler
|
||||
/// after the initializations done in this function*
|
||||
#[cfg(feature = "rt-xtensa")]
|
||||
#[cfg(feature = "rt")]
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ESP32Reset() -> ! {
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
//! let mut lp_pin = io.pins.gpio1.into_low_power();
|
||||
//! lp_pin.output_enable(true);
|
||||
//!
|
||||
//! let mut lp_core = esp32c6_hal::lp_core::LpCore::new(peripherals.LP_CORE);
|
||||
//! let mut lp_core = esp_hal::lp_core::LpCore::new(peripherals.LP_CORE);
|
||||
//! lp_core.stop();
|
||||
//! println!("lp core stopped");
|
||||
//!
|
||||
|
||||
@ -37,7 +37,7 @@ pub(crate) mod constants {
|
||||
/// ENTRY point is defined in memory.x
|
||||
/// *Note: the pre_init function is called in the original reset handler
|
||||
/// after the initializations done in this function*
|
||||
#[cfg(feature = "rt-xtensa")]
|
||||
#[cfg(feature = "rt")]
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ESP32Reset() -> ! {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
//!
|
||||
//! ## Example
|
||||
//! ```no_run
|
||||
//! let mut ulp_core = esp32s3_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
|
||||
//! let mut ulp_core = esp_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
|
||||
//! ulp_core.stop();
|
||||
//! println!("ulp core stopped");
|
||||
//!
|
||||
@ -26,7 +26,7 @@
|
||||
//! println!("copied code (len {})", CODE.len());
|
||||
//!
|
||||
//! // start ULP core
|
||||
//! ulp_core.run(esp32s3_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
|
||||
//! ulp_core.run(esp_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
|
||||
//! println!("ulpcore run");
|
||||
//!
|
||||
//! unsafe {
|
||||
|
||||
@ -34,7 +34,7 @@ pub(crate) mod constants {
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x3FD0_0000;
|
||||
}
|
||||
|
||||
#[cfg(feature = "rt-xtensa")]
|
||||
#[cfg(feature = "rt")]
|
||||
#[doc(hidden)]
|
||||
#[link_section = ".rwtext"]
|
||||
pub unsafe fn configure_cpu_caches() {
|
||||
@ -69,7 +69,7 @@ pub unsafe fn configure_cpu_caches() {
|
||||
/// ENTRY point is defined in memory.x
|
||||
/// *Note: the pre_init function is called in the original reset handler
|
||||
/// after the initializations done in this function*
|
||||
#[cfg(feature = "rt-xtensa")]
|
||||
#[cfg(feature = "rt")]
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[link_section = ".rwtext"]
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
//!
|
||||
//! ## Example
|
||||
//! ```no_run
|
||||
//! let mut ulp_core = esp32s3_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
|
||||
//! let mut ulp_core = esp_hal::ulp_core::UlpCore::new(peripherals.ULP_RISCV_CORE);
|
||||
//! ulp_core.stop();
|
||||
//! println!("ulp core stopped");
|
||||
//!
|
||||
@ -26,7 +26,7 @@
|
||||
//! println!("copied code (len {})", CODE.len());
|
||||
//!
|
||||
//! // start ULP core
|
||||
//! ulp_core.run(esp32s3_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
|
||||
//! ulp_core.run(esp_hal::ulp_core::UlpCoreWakeupSource::HpCpu);
|
||||
//! println!("ulpcore run");
|
||||
//!
|
||||
//! unsafe {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
name = "esp-lp-hal"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
rust-version = "1.76.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"
|
||||
@ -41,9 +41,9 @@ 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"]
|
||||
esp32c6 = ["dep:esp32c6-lp", "procmacros/is-lp-core", "dep:nb", "dep:paste"]
|
||||
esp32s2 = ["dep:esp32s2-ulp", "procmacros/is-ulp-core"]
|
||||
esp32s3 = ["dep:esp32s3-ulp", "procmacros/is-ulp-core"]
|
||||
|
||||
debug = [
|
||||
"esp32c6-lp?/impl-register-debug",
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
//! - SDA => GPIO6
|
||||
//! - SCL => GPIO7
|
||||
|
||||
//% CHIPS: esp32c6
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
//! Uses `LP_UART` and logs "Hello World from LP Core".
|
||||
//!
|
||||
//! Uses GPIO4 for RX and GPIO5 for TX. GPIOs can't be changed.
|
||||
//!
|
||||
//! It is neccessary to use Serial-Uart bridge connected to TX and RX to see
|
||||
//! logs from LP_UART. Make sure the LP RAM is cleared before loading the code.
|
||||
|
||||
//% CHIPS: esp32c6
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
[target.xtensa-esp32-none-elf]
|
||||
runner = "espflash flash --monitor"
|
||||
|
||||
[build]
|
||||
rustflags = [
|
||||
# GNU LD
|
||||
"-C", "link-arg=-nostartfiles",
|
||||
"-C", "link-arg=-Wl,-Tlinkall.x",
|
||||
|
||||
# LLD
|
||||
# "-C", "linker=rust-lld",
|
||||
# "-C", "link-arg=-Tlinkall.x",
|
||||
]
|
||||
target = "xtensa-esp32-none-elf"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core", "alloc"]
|
||||
@ -1,164 +0,0 @@
|
||||
[package]
|
||||
name = "esp32-hal"
|
||||
version = "0.18.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
description = "HAL for ESP32 microcontrollers"
|
||||
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]
|
||||
document-features = "0.2.7"
|
||||
esp-hal = { version = "0.15.0", features = ["esp32"], path = "../esp-hal" }
|
||||
embassy-time-driver = { version = "0.1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
aes = "0.8.3"
|
||||
critical-section = "1.1.2"
|
||||
crypto-bigint = { version = "0.5.5", default-features = false }
|
||||
embassy-executor = { version = "0.5.0", features = ["nightly"] }
|
||||
embassy-sync = "0.5.0"
|
||||
embassy-time = "0.3.0"
|
||||
embedded-graphics = "0.8.1"
|
||||
embedded-hal-1 = { version = "1.0.0", package = "embedded-hal" }
|
||||
embedded-hal-async = "1.0.0"
|
||||
embedded-io-async = "0.6.1"
|
||||
embedded-hal-bus = "0.1.0"
|
||||
esp-alloc = "0.3.0"
|
||||
esp-backtrace = { version = "0.10.0", features = ["esp32", "panic-handler", "exception-handler", "print-uart"] }
|
||||
esp-hal-smartled = { version = "0.8.0", features = ["esp32"], path = "../esp-hal-smartled" }
|
||||
esp-println = { version = "0.8.0", features = ["esp32"] }
|
||||
heapless = "0.8.0"
|
||||
lis3dh-async = "0.9.1"
|
||||
sha2 = { version = "0.10.8", default-features = false}
|
||||
smart-leds = "0.4.0"
|
||||
ssd1306 = "0.8.4"
|
||||
static_cell = { version = "2.0.0", features = ["nightly"] }
|
||||
|
||||
[features]
|
||||
default = ["embassy-integrated-timers", "rt", "vectored"]
|
||||
|
||||
## Enable support for using the Bluetooth radio.
|
||||
bluetooth = []
|
||||
## Enable debug features in the HAL (used for development).
|
||||
debug = ["esp-hal/debug"]
|
||||
## Enable logging output using the `log` crate.
|
||||
log = ["esp-hal/log", "esp-println/log"]
|
||||
## Enable runtime support.
|
||||
rt = ["esp-hal/rt-xtensa"]
|
||||
## Enable interrupt vectoring.
|
||||
vectored = ["esp-hal/vectored"]
|
||||
|
||||
#! ### Trait Implementation Feature Flags
|
||||
## Enable support for asynchronous operation, with interfaces provided by
|
||||
## `embedded-hal-async` and `embedded-io-async`.
|
||||
async = ["esp-hal/async"]
|
||||
## Implement `defmt::Format` on certain types.
|
||||
defmt = ["esp-hal/defmt", "esp-println/defmt-espflash"]
|
||||
## Implement the traits defined in the `1.0.0` releases of `embedded-hal` and
|
||||
## `embedded-hal-nb` for the relevant peripherals.
|
||||
eh1 = ["esp-hal/eh1"]
|
||||
## Implement the traits defined in `embedded-io` for certain peripherals.
|
||||
embedded-io = ["esp-hal/embedded-io"]
|
||||
## Implement the `ufmt_write::uWrite` trait for certain peripherals.
|
||||
ufmt = ["esp-hal/ufmt"]
|
||||
|
||||
#! ### PSRAM Feature Flags
|
||||
psram = []
|
||||
## Use externally connected PSRAM (2MB).
|
||||
psram-2m = ["esp-hal/psram-2m", "psram"]
|
||||
## Use externally connected PSRAM (4MB).
|
||||
psram-4m = ["esp-hal/psram-4m", "psram"]
|
||||
## Use externally connected PSRAM (8MB).
|
||||
psram-8m = ["esp-hal/psram-8m", "psram"]
|
||||
|
||||
#! ### Embassy Feature Flags
|
||||
## Enable support for `embassy`, a modern asynchronous embedded framework.
|
||||
embassy = ["esp-hal/embassy"]
|
||||
## Use the interrupt-mode embassy executor.
|
||||
embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"]
|
||||
## Use the thread-mode embassy executor.
|
||||
embassy-executor-thread = ["esp-hal/embassy-executor-thread"]
|
||||
## Uses hardware timers as alarms for the executors. Using this feature
|
||||
## limits the number of executors to the number of hardware alarms provided
|
||||
## by the time driver.
|
||||
embassy-integrated-timers = ["esp-hal/embassy-integrated-timers"]
|
||||
## Enable the embassy time driver using the `TIMG0` peripheral. The `TIMG0`
|
||||
## peripheral has two alarms available for use.
|
||||
embassy-time-timg0 = ["esp-hal/embassy-time-timg0", "embassy-time-driver/tick-hz-1_000_000"]
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
[[example]]
|
||||
name = "spi_eh1_loopback"
|
||||
required-features = ["eh1"]
|
||||
|
||||
[[example]]
|
||||
name = "spi_eh1_device_loopback"
|
||||
required-features = ["eh1"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_hello_world"
|
||||
required-features = ["embassy", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_multicore"
|
||||
required-features = ["embassy", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_multicore_interrupt"
|
||||
required-features = ["embassy", "embassy-executor-interrupt"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_multiprio"
|
||||
required-features = ["embassy", "embassy-executor-interrupt"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_wait"
|
||||
required-features = ["embassy", "embassy-executor-thread", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_spi"
|
||||
required-features = ["embassy", "embassy-executor-thread", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "psram"
|
||||
required-features = ["psram-2m"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_serial"
|
||||
required-features = ["embassy", "embassy-executor-thread", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_i2c"
|
||||
required-features = ["embassy", "embassy-executor-thread", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_rmt_tx"
|
||||
required-features = ["embassy", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_rmt_rx"
|
||||
required-features = ["embassy", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_i2s_sound"
|
||||
required-features = ["embassy", "async"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_i2s_read"
|
||||
required-features = ["embassy", "async"]
|
||||
@ -1,60 +0,0 @@
|
||||
# esp32-hal
|
||||
|
||||
[](https://crates.io/crates/esp32-hal)
|
||||
[](https://docs.rs/esp32-hal)
|
||||

|
||||
[](https://matrix.to/#/#esp-rs:matrix.org)
|
||||
|
||||
`no_std` HAL for the ESP32 from Espressif.
|
||||
|
||||
Implements a number of the traits defined in [embedded-hal](https://github.com/rust-embedded/embedded-hal).
|
||||
|
||||
This device uses the Xtensa ISA, which is not officially supported by the Rust compiler. In order to develop for this device, you must use the Rust compiler fork with Xtensa support, found at [esp-rs/rust](https://github.com/esp-rs/rust).
|
||||
|
||||
Please refer to the documentation for more information.
|
||||
|
||||
## [Documentation]
|
||||
|
||||
[documentation]: https://docs.rs/esp32-hal/
|
||||
|
||||
## Resources
|
||||
|
||||
- [Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
|
||||
- [Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32_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
|
||||
|
||||
We provide a tool, [espup](https://github.com/esp-rs/espup/), for easily installing the Rust toolchain with Xtensa support:
|
||||
|
||||
```shell
|
||||
cargo install espup
|
||||
espup install
|
||||
```
|
||||
|
||||
Following installation of the Xtensa toolchain, if you are running a Unix-like operating system (macOS, Linux) then you must additionally export the necessary environment variables:
|
||||
|
||||
```shell
|
||||
. $HOME/export-esp.sh
|
||||
```
|
||||
|
||||
See the [Installation chapter of The Rust on ESP Book](https://esp-rs.github.io/book/installation/index.html) for more details.
|
||||
|
||||
## 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.
|
||||
@ -1,36 +0,0 @@
|
||||
use std::{env, error::Error, fs::File, io::Write, path::PathBuf};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// 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());
|
||||
|
||||
let memory_extras = generate_memory_extras();
|
||||
File::create(out.join("memory_extras.x"))?.write_all(&memory_extras)?;
|
||||
|
||||
// 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");
|
||||
|
||||
#[cfg(feature = "defmt")]
|
||||
println!("cargo:rustc-link-arg=-Tdefmt.x");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_memory_extras() -> Vec<u8> {
|
||||
let reserve_dram = if cfg!(feature = "bluetooth") {
|
||||
"0x10000"
|
||||
} else {
|
||||
"0x0"
|
||||
};
|
||||
|
||||
format!(
|
||||
"
|
||||
/* reserved at the start of DRAM for e.g. the BT stack */
|
||||
RESERVE_DRAM = {reserve_dram};
|
||||
"
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
//! Connect a potentiometer to PIN25 and see the read values change when
|
||||
//! rotating the shaft. Alternatively you could also connect the PIN to GND or
|
||||
//! 3V3 to see the maximum and minimum raw values read.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
adc::{AdcConfig, Attenuation, ADC},
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::{Peripherals, ADC2},
|
||||
prelude::*,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Create ADC instances
|
||||
let mut adc2_config = AdcConfig::new();
|
||||
let mut pin25 =
|
||||
adc2_config.enable_pin(io.pins.gpio25.into_analog(), Attenuation::Attenuation11dB);
|
||||
let mut adc2 = ADC::<ADC2>::new(peripherals.ADC2, adc2_config);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
let pin25_value: u16 = nb::block!(adc2.read(&mut pin25)).unwrap();
|
||||
println!("PIN25 ADC reading = {}", pin25_value);
|
||||
delay.delay_ms(1500u32);
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
//! This shows how to configure UART
|
||||
//! You can short the TX and RX pin and see it reads what was written.
|
||||
//! Additionally you can connect a logic analzyer to TX and see how the changes
|
||||
//! of the configuration change the output signal.
|
||||
//!
|
||||
//! The following wiring is assumed:
|
||||
//! - TX => GPIO16
|
||||
//! - RX => GPIO17
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
uart::{
|
||||
config::{Config, DataBits, Parity, StopBits},
|
||||
TxRxPins,
|
||||
},
|
||||
Delay,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let config = Config {
|
||||
baudrate: 115200,
|
||||
data_bits: DataBits::DataBits8,
|
||||
parity: Parity::ParityNone,
|
||||
stop_bits: StopBits::STOP1,
|
||||
};
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let pins = TxRxPins::new_tx_rx(
|
||||
io.pins.gpio16.into_push_pull_output(),
|
||||
io.pins.gpio17.into_floating_input(),
|
||||
);
|
||||
|
||||
let mut serial1 = Uart::new_with_config(peripherals.UART1, config, Some(pins), &clocks);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
println!("Start");
|
||||
loop {
|
||||
serial1.write(0x42).ok();
|
||||
let read = block!(serial1.read());
|
||||
|
||||
match read {
|
||||
Ok(read) => println!("Read 0x{:02x}", read),
|
||||
Err(err) => println!("Error {:?}", err),
|
||||
}
|
||||
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
//! Encrypt/Decrypt a message using AES
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
use aes::{
|
||||
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
|
||||
Aes128 as Aes128SW,
|
||||
};
|
||||
use esp32_hal::{
|
||||
aes::{Aes, Mode},
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
xtensa_lx,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut aes = Aes::new(peripherals.AES);
|
||||
|
||||
let keytext = "SUp4SeCp@sSw0rd".as_bytes();
|
||||
let plaintext = "message".as_bytes();
|
||||
|
||||
// create an array with aes128 key size
|
||||
let mut keybuf = [0_u8; 16];
|
||||
keybuf[..keytext.len()].copy_from_slice(keytext);
|
||||
|
||||
// create an array with aes block size
|
||||
let mut block_buf = [0_u8; 16];
|
||||
block_buf[..plaintext.len()].copy_from_slice(plaintext);
|
||||
|
||||
let mut block = block_buf.clone();
|
||||
let pre_hw_encrypt = xtensa_lx::timer::get_cycle_count();
|
||||
aes.process(&mut block, Mode::Encryption128, &keybuf);
|
||||
let post_hw_encrypt = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for hw encrypt",
|
||||
post_hw_encrypt - pre_hw_encrypt
|
||||
);
|
||||
let hw_encrypted = block.clone();
|
||||
let pre_hw_decrypt = xtensa_lx::timer::get_cycle_count();
|
||||
aes.process(&mut block, Mode::Decryption128, &keybuf);
|
||||
let post_hw_decrypt = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for hw decrypt",
|
||||
post_hw_decrypt - pre_hw_decrypt
|
||||
);
|
||||
let hw_decrypted = block;
|
||||
|
||||
let key = GenericArray::from(keybuf);
|
||||
let mut block = GenericArray::from(block_buf);
|
||||
let cipher = Aes128SW::new(&key);
|
||||
let pre_sw_encrypt = xtensa_lx::timer::get_cycle_count();
|
||||
cipher.encrypt_block(&mut block);
|
||||
let post_sw_encrypt = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for sw encrypt",
|
||||
post_sw_encrypt - pre_sw_encrypt
|
||||
);
|
||||
let sw_encrypted = block.clone();
|
||||
let pre_sw_decrypt = xtensa_lx::timer::get_cycle_count();
|
||||
cipher.decrypt_block(&mut block);
|
||||
let post_sw_decrypt = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for sw decrypt",
|
||||
post_sw_decrypt - pre_sw_decrypt
|
||||
);
|
||||
let sw_decrypted = block;
|
||||
|
||||
assert!(eq(&sw_encrypted.into(), &hw_encrypted));
|
||||
assert!(eq(&sw_decrypted.into(), &hw_decrypted));
|
||||
|
||||
println!("done");
|
||||
|
||||
loop {}
|
||||
}
|
||||
fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool {
|
||||
slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b)
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
//! Blinks an LED
|
||||
//!
|
||||
//! This assumes that a LED is connected to the pin assigned to `led` (GPIO2).
|
||||
//! For the the DOIT ESP32 Devkit v1, GPIO2 is the onboard LED pin.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{clock::ClockControl, gpio::IO, peripherals::Peripherals, prelude::*, Delay};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Set GPIO2 as an output, and set its state high initially.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio2.into_push_pull_output();
|
||||
|
||||
led.set_high().unwrap();
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
//! Blinks three LEDs
|
||||
//!
|
||||
//! This assumes that LEDs are connected to GPIO25, 26 and 27.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::{AnyPin, Input, Output, PullDown, PushPull, IO},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Set LED GPIOs as an output.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let led1 = io.pins.gpio25.into_push_pull_output();
|
||||
let led2 = io.pins.gpio26.into_push_pull_output();
|
||||
let led3 = io.pins.gpio27.into_push_pull_output();
|
||||
|
||||
// Set GPIO9 as an input.
|
||||
let button = io.pins.gpio0.into_pull_down_input().into();
|
||||
|
||||
// You can use `into` or `degrade`
|
||||
let mut pins = [led1.into(), led2.into(), led3.degrade().into()];
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
toggle_pins(&mut pins, &button);
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_pins(leds: &mut [AnyPin<Output<PushPull>>], button: &AnyPin<Input<PullDown>>) {
|
||||
for pin in leds.iter_mut() {
|
||||
pin.toggle().unwrap();
|
||||
}
|
||||
|
||||
if button.is_low().unwrap() {
|
||||
esp_println::println!("Button");
|
||||
}
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
//! This demos a simple monitor for the XTAL frequency, by relying on a special
|
||||
//! feature of the TIMG0 (Timer Group 0). This feature counts the number of XTAL
|
||||
//! clock cycles within a given number of RTC_SLOW_CLK cycles.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
Rtc,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
rtc.rwdt.start(2000u64.millis());
|
||||
rtc.rwdt.listen();
|
||||
|
||||
esp_println::println!(
|
||||
"{: <10} XTAL frequency: {} MHz",
|
||||
"[Expected]",
|
||||
clocks.xtal_clock.to_MHz()
|
||||
);
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::RTC_CORE,
|
||||
interrupt::Priority::Priority1,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
critical_section::with(|cs| RTC.borrow_ref_mut(cs).replace(rtc));
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn RTC_CORE() {
|
||||
critical_section::with(|cs| {
|
||||
let mut rtc = RTC.borrow_ref_mut(cs);
|
||||
let rtc = rtc.as_mut().unwrap();
|
||||
|
||||
esp_println::println!(
|
||||
"{: <10} XTAL frequency: {} MHz",
|
||||
"[Monitor]",
|
||||
rtc.estimate_xtal_frequency()
|
||||
);
|
||||
|
||||
rtc.rwdt.clear_interrupt();
|
||||
});
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
//! This shows example usage of the CRC functions in ROM
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"Performing CRC calculations on test string \"{data}\""
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
let crc_hdlc = crc::crc32_le(!0xffffffff, data.as_ref());
|
||||
let crc_bzip2 = crc::crc32_be(!0xffffffff, data.as_ref());
|
||||
let crc_mpeg2 = !crc::crc32_be(!0xffffffff, data.as_ref());
|
||||
let crc_cksum = crc::crc32_be(!0, data.as_ref());
|
||||
let crc_kermit = !crc::crc16_le(!0, data.as_ref());
|
||||
let crc_genibus = crc::crc16_be(!0xffff, data.as_ref());
|
||||
let crc_rohc = !crc::crc8_le(!0xff, data.as_ref());
|
||||
let crc_smbus = !crc::crc8_be(!0, data.as_ref());
|
||||
|
||||
assert_eq!(crc_hdlc, 0xcbf43926);
|
||||
assert_eq!(crc_bzip2, 0xfc891918);
|
||||
assert_eq!(crc_mpeg2, 0x0376e6e7);
|
||||
assert_eq!(crc_cksum, 0x765e7680);
|
||||
assert_eq!(crc_kermit, 0x2189);
|
||||
assert_eq!(crc_genibus, 0xd64e);
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
//! This example shows how to use the DAC on PIN 25 and 26
|
||||
//! You can connect an LED (with a suitable resistor) or check the changing
|
||||
//! voltage using a voltmeter on those pins.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
dac::{DAC1, DAC2},
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let pin25 = io.pins.gpio25.into_analog();
|
||||
let pin26 = io.pins.gpio26.into_analog();
|
||||
|
||||
// Create DAC instances
|
||||
let mut dac1 = DAC1::new(peripherals.DAC1, pin25);
|
||||
let mut dac2 = DAC2::new(peripherals.DAC2, pin26);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let mut voltage_dac1: u8 = 200;
|
||||
let mut voltage_dac2: u8 = 255;
|
||||
loop {
|
||||
// Change voltage on the pins using write function
|
||||
voltage_dac1 = voltage_dac1.wrapping_add(1);
|
||||
dac1.write(voltage_dac1);
|
||||
|
||||
voltage_dac2 = voltage_dac2.wrapping_sub(1);
|
||||
dac2.write(voltage_dac2);
|
||||
delay.delay_ms(50u32);
|
||||
}
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
//! This shows how to continously receive data via I2S
|
||||
//!
|
||||
//! Pins used
|
||||
//! BCLK GPIO12
|
||||
//! WS GPIO13
|
||||
//! DIN GPIO14
|
||||
//!
|
||||
//! Without an additional I2S source device you can connect 3V3 or GND to DIN to
|
||||
//! read 0 or 0xFF or connect DIN to WS to read two different values
|
||||
//!
|
||||
//! You can also inspect the BCLK and WS with a logic analyzer
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma_buffers,
|
||||
embassy::{self},
|
||||
i2s::{asynch::*, DataFormat, I2s, Standard},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
#[cfg(feature = "log")]
|
||||
esp_println::logger::init_logger_from_env();
|
||||
println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.i2s0channel;
|
||||
|
||||
let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, 4092 * 4);
|
||||
|
||||
let i2s = I2s::new(
|
||||
peripherals.I2S0,
|
||||
Standard::Philips,
|
||||
DataFormat::Data16Channel16,
|
||||
44100u32.Hz(),
|
||||
dma_channel.configure(
|
||||
false,
|
||||
&mut tx_descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
let i2s_rx = i2s
|
||||
.i2s_rx
|
||||
.with_bclk(io.pins.gpio12)
|
||||
.with_ws(io.pins.gpio13)
|
||||
.with_din(io.pins.gpio14)
|
||||
.build();
|
||||
|
||||
let buffer = rx_buffer;
|
||||
println!("Start");
|
||||
|
||||
let mut data = [0u8; 5000];
|
||||
let mut transaction = i2s_rx.read_dma_circular_async(buffer).unwrap();
|
||||
loop {
|
||||
let avail = transaction.available().await;
|
||||
println!("available {}", avail);
|
||||
|
||||
let count = transaction.pop(&mut data).await.unwrap();
|
||||
println!(
|
||||
"got {} bytes, {:x?}..{:x?}",
|
||||
count,
|
||||
&data[..10],
|
||||
&data[count - 10..count]
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
//! This shows how to transmit data continously via I2S
|
||||
//!
|
||||
//! Pins used
|
||||
//! BCLK GPIO12
|
||||
//! WS GPIO13
|
||||
//! DOUT GPIO14
|
||||
//!
|
||||
//! Without an additional I2S sink device you can inspect the MCLK, BCLK, WS and
|
||||
//! DOUT with a logic analyzer
|
||||
//!
|
||||
//! You can also connect e.g. a PCM510x to hear an annoying loud sine tone (full
|
||||
//! scale), so turn down the volume before running this example.
|
||||
//!
|
||||
//! Wiring is like this
|
||||
//!
|
||||
//! | Pin | Connected to |
|
||||
//! |-------|-----------------|
|
||||
//! | BCK | GPIO12 |
|
||||
//! | DIN | GPIO14 |
|
||||
//! | LRCK | GPIO13 |
|
||||
//! | SCK | Gnd |
|
||||
//! | GND | Gnd |
|
||||
//! | VIN | +3V3 |
|
||||
//! | FLT | Gnd |
|
||||
//! | FMT | Gnd |
|
||||
//! | DEMP | Gnd |
|
||||
//! | XSMT | +3V3 |
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma_buffers,
|
||||
embassy::{self},
|
||||
i2s::{asynch::*, DataFormat, I2s, Standard},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
const SINE: [i16; 64] = [
|
||||
0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244, 28897, 30272, 31356,
|
||||
32137, 32609, 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169, 20787, 18204,
|
||||
15446, 12539, 9511, 6392, 3211, 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787, -23169,
|
||||
-25329, -27244, -28897, -30272, -31356, -32137, -32609, -32767, -32609, -32137, -31356, -30272,
|
||||
-28897, -27244, -25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
|
||||
];
|
||||
|
||||
#[main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
#[cfg(feature = "log")]
|
||||
esp_println::logger::init_logger_from_env();
|
||||
println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.i2s0channel;
|
||||
|
||||
let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32000, 0);
|
||||
|
||||
let i2s = I2s::new(
|
||||
peripherals.I2S0,
|
||||
Standard::Philips,
|
||||
DataFormat::Data16Channel16,
|
||||
44100u32.Hz(),
|
||||
dma_channel.configure(
|
||||
false,
|
||||
&mut tx_descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
let i2s_tx = i2s
|
||||
.i2s_tx
|
||||
.with_bclk(io.pins.gpio12)
|
||||
.with_ws(io.pins.gpio13)
|
||||
.with_dout(io.pins.gpio14)
|
||||
.build();
|
||||
|
||||
let data =
|
||||
unsafe { core::slice::from_raw_parts(&SINE as *const _ as *const u8, SINE.len() * 2) };
|
||||
|
||||
let buffer = tx_buffer;
|
||||
let mut idx = 0;
|
||||
for i in 0..usize::min(data.len(), buffer.len()) {
|
||||
buffer[i] = data[idx];
|
||||
|
||||
idx += 1;
|
||||
|
||||
if idx >= data.len() {
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let mut filler = [0u8; 10000];
|
||||
let mut idx = 32000 % data.len();
|
||||
|
||||
println!("Start");
|
||||
let mut transaction = i2s_tx.write_dma_circular_async(buffer).unwrap();
|
||||
|
||||
loop {
|
||||
for i in 0..filler.len() {
|
||||
filler[i] = data[(idx + i) % data.len()];
|
||||
}
|
||||
println!("Next");
|
||||
|
||||
let written = transaction.push(&filler).await.unwrap();
|
||||
idx = (idx + written) % data.len();
|
||||
println!("written {}", written);
|
||||
}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
//! This example shows how to use the interrupt executors to prioritize some
|
||||
//! tasks over others.
|
||||
//!
|
||||
//! The example creates three tasks:
|
||||
//! - A low priority task that is not actually async, but simulates some
|
||||
//! blocking work. This task will run for 5 seconds, then sleep for 5
|
||||
//! seconds.
|
||||
//! - A low priority task that is actually async, but will not be able to run
|
||||
//! while the blocking task is running.
|
||||
//! - A high priority task that prints something every second. The example
|
||||
//! demonstrates that this task will continue to run even while the low
|
||||
//! priority blocking task is running.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Instant, Ticker, Timer};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
embassy::{
|
||||
self,
|
||||
executor::{FromCpu1, InterruptExecutor},
|
||||
},
|
||||
interrupt::Priority,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
static INT_EXECUTOR_0: InterruptExecutor<FromCpu1> = InterruptExecutor::new();
|
||||
|
||||
#[interrupt]
|
||||
fn FROM_CPU_INTR1() {
|
||||
unsafe { INT_EXECUTOR_0.on_interrupt() }
|
||||
}
|
||||
|
||||
/// Periodically print something.
|
||||
#[embassy_executor::task]
|
||||
async fn high_prio() {
|
||||
println!("Starting high_prio()");
|
||||
let mut ticker = Ticker::every(Duration::from_secs(1));
|
||||
loop {
|
||||
println!("High priority ticks");
|
||||
ticker.next().await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Simulates some blocking (badly behaving) task.
|
||||
#[embassy_executor::task]
|
||||
async fn low_prio_blocking() {
|
||||
println!("Starting low-priority task that isn't actually async");
|
||||
loop {
|
||||
println!("Doing some long and complicated calculation");
|
||||
let start = Instant::now();
|
||||
while start.elapsed() < Duration::from_secs(5) {}
|
||||
println!("Calculation finished");
|
||||
Timer::after(Duration::from_secs(5)).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// A well-behaved, but starved async task.
|
||||
#[embassy_executor::task]
|
||||
async fn low_prio_async() {
|
||||
println!("Starting low-priority task that will not be able to run while the blocking task is running");
|
||||
let mut ticker = Ticker::every(Duration::from_secs(1));
|
||||
loop {
|
||||
println!("Low priority ticks");
|
||||
ticker.next().await;
|
||||
}
|
||||
}
|
||||
|
||||
#[main]
|
||||
async fn main(low_prio_spawner: Spawner) {
|
||||
println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = esp32_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
|
||||
let spawner = INT_EXECUTOR_0.start(Priority::Priority2);
|
||||
spawner.must_spawn(high_prio());
|
||||
|
||||
println!("Spawning low-priority tasks");
|
||||
low_prio_spawner.must_spawn(low_prio_async());
|
||||
low_prio_spawner.must_spawn(low_prio_blocking());
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
//! Demonstrates decoding pulse sequences with RMT
|
||||
//! Connect GPIO15 to GPIO4
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
embassy::{self},
|
||||
gpio::{Gpio15, Output, PushPull},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rmt::{asynch::RxChannelAsync, PulseCode, RxChannelConfig, RxChannelCreator},
|
||||
Rmt,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::{print, println};
|
||||
|
||||
const WIDTH: usize = 80;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
compile_error!("Run this example in release mode");
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn signal_task(mut pin: Gpio15<Output<PushPull>>) {
|
||||
loop {
|
||||
for _ in 0..10 {
|
||||
pin.toggle().unwrap();
|
||||
Timer::after(Duration::from_micros(10)).await;
|
||||
}
|
||||
Timer::after(Duration::from_millis(1000)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[main]
|
||||
async fn main(spawner: Spawner) {
|
||||
#[cfg(feature = "log")]
|
||||
esp_println::logger::init_logger_from_env();
|
||||
println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
{
|
||||
let timer_group0 = esp32_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
}
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let rmt = Rmt::new(peripherals.RMT, 80u32.MHz(), &clocks).unwrap();
|
||||
|
||||
let mut channel = rmt
|
||||
.channel2
|
||||
.configure(
|
||||
io.pins.gpio4,
|
||||
RxChannelConfig {
|
||||
clk_divider: 1,
|
||||
idle_threshold: 0b111_1111_1111_1111,
|
||||
..RxChannelConfig::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
spawner
|
||||
.spawn(signal_task(io.pins.gpio15.into_push_pull_output()))
|
||||
.unwrap();
|
||||
|
||||
let mut data = [PulseCode {
|
||||
level1: true,
|
||||
length1: 1,
|
||||
level2: false,
|
||||
length2: 1,
|
||||
}; 48];
|
||||
|
||||
loop {
|
||||
println!("receive");
|
||||
channel.receive(&mut data).await.unwrap();
|
||||
let mut total = 0usize;
|
||||
for entry in &data[..data.len()] {
|
||||
if entry.length1 == 0 {
|
||||
break;
|
||||
}
|
||||
total += entry.length1 as usize;
|
||||
|
||||
if entry.length2 == 0 {
|
||||
break;
|
||||
}
|
||||
total += entry.length2 as usize;
|
||||
}
|
||||
|
||||
for entry in &data[..data.len()] {
|
||||
if entry.length1 == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let count = WIDTH / (total / entry.length1 as usize);
|
||||
let c = if entry.level1 { '-' } else { '_' };
|
||||
for _ in 0..count + 1 {
|
||||
print!("{}", c);
|
||||
}
|
||||
|
||||
if entry.length2 == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let count = WIDTH / (total / entry.length2 as usize);
|
||||
let c = if entry.level2 { '-' } else { '_' };
|
||||
for _ in 0..count + 1 {
|
||||
print!("{}", c);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
}
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
//! Demonstrates generating pulse sequences with RMT
|
||||
//! Connect a logic analyzer to GPIO4 to see the generated pulses.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
embassy::{self},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rmt::{asynch::TxChannelAsync, PulseCode, TxChannelConfig, TxChannelCreator},
|
||||
Rmt,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
#[cfg(feature = "log")]
|
||||
esp_println::logger::init_logger_from_env();
|
||||
println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
{
|
||||
let timer_group0 = esp32_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
}
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let rmt = Rmt::new(peripherals.RMT, 80u32.MHz(), &clocks).unwrap();
|
||||
|
||||
let mut channel = rmt
|
||||
.channel0
|
||||
.configure(
|
||||
io.pins.gpio4.into_push_pull_output(),
|
||||
TxChannelConfig {
|
||||
clk_divider: 255,
|
||||
..TxChannelConfig::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut data = [PulseCode {
|
||||
level1: true,
|
||||
length1: 200,
|
||||
level2: false,
|
||||
length2: 50,
|
||||
}; 20];
|
||||
|
||||
data[data.len() - 2] = PulseCode {
|
||||
level1: true,
|
||||
length1: 3000,
|
||||
level2: false,
|
||||
length2: 500,
|
||||
};
|
||||
data[data.len() - 1] = PulseCode::default();
|
||||
|
||||
loop {
|
||||
println!("transmit");
|
||||
channel.transmit(&data).await.unwrap();
|
||||
println!("transmitted\n");
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
//! GPIO interrupt
|
||||
//!
|
||||
//! This prints "Interrupt" when the boot button is pressed.
|
||||
//! It also blinks an LED like the blinky example.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{borrow::BorrowMut, cell::RefCell};
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::{Event, Gpio0, Input, PullDown, IO},
|
||||
interrupt,
|
||||
macros::ram,
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
xtensa_lx,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static BUTTON: Mutex<RefCell<Option<Gpio0<Input<PullDown>>>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Set GPIO15 as an output, and set its state high initially.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio15.into_push_pull_output();
|
||||
let mut button = io.pins.gpio0.into_pull_down_input();
|
||||
button.listen(Event::FallingEdge);
|
||||
|
||||
critical_section::with(|cs| BUTTON.borrow_ref_mut(cs).replace(button));
|
||||
|
||||
interrupt::enable(peripherals::Interrupt::GPIO, interrupt::Priority::Priority2).unwrap();
|
||||
|
||||
led.set_high().unwrap();
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
|
||||
#[ram]
|
||||
#[interrupt]
|
||||
unsafe fn GPIO() {
|
||||
esp_println::println!(
|
||||
"GPIO Interrupt with priority {}",
|
||||
xtensa_lx::interrupt::get_level()
|
||||
);
|
||||
|
||||
critical_section::with(|cs| {
|
||||
BUTTON
|
||||
.borrow_ref_mut(cs)
|
||||
.borrow_mut()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.clear_interrupt();
|
||||
});
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
//! RGB LED Demo
|
||||
//!
|
||||
//! This example drives an 12-element RGB ring that is connected to GPIO33
|
||||
//!
|
||||
//! The LEDs in the ring are transitioning though the HSV color spectrum for
|
||||
//! - Saturation: 255
|
||||
//! - Hue: 0 - 255
|
||||
//! - Value: 255
|
||||
//!
|
||||
//! For the 12-element RGB ring to work, building the release version is going
|
||||
//! to be required.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{clock::ClockControl, peripherals, prelude::*, rmt::Rmt, Delay, IO};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_smartled::{smartLedBuffer, SmartLedsAdapter};
|
||||
use smart_leds::{
|
||||
brightness,
|
||||
gamma,
|
||||
hsv::{hsv2rgb, Hsv},
|
||||
SmartLedsWrite,
|
||||
};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = peripherals::Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Configure RMT peripheral globally
|
||||
let rmt = Rmt::new(peripherals.RMT, 80u32.MHz(), &clocks).unwrap();
|
||||
|
||||
// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
|
||||
// be used directly with all `smart_led` implementations
|
||||
// -> We need to use the macro `smartLedBuffer!` with the number of addressed
|
||||
// LEDs here to initialize the internal LED pulse buffer to the correct
|
||||
// size!
|
||||
let rmt_buffer = smartLedBuffer!(12);
|
||||
let mut led = SmartLedsAdapter::new(rmt.channel0, io.pins.gpio33, rmt_buffer, &clocks);
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let mut color = Hsv {
|
||||
hue: 0,
|
||||
sat: 255,
|
||||
val: 255,
|
||||
};
|
||||
let mut data;
|
||||
|
||||
loop {
|
||||
// Iterate over the rainbow!
|
||||
for hue in 0..=255 {
|
||||
color.hue = hue;
|
||||
// Convert from the HSV color space (where we can easily transition from one
|
||||
// color to the other) to the RGB color space that we can then send to the LED
|
||||
let rgb_color = hsv2rgb(color);
|
||||
|
||||
// Assign new color to all 12 LEDs
|
||||
data = [rgb_color; 12];
|
||||
|
||||
// When sending to the LED, we do a gamma correction first (see smart_leds
|
||||
// documentation for details) and then limit the brightness to 10 out of 255 so
|
||||
// that the output it's not too bright.
|
||||
led.write(brightness(gamma(data.iter().cloned()), 10))
|
||||
.unwrap();
|
||||
delay.delay_ms(20u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
//! This shows how to write text to uart0.
|
||||
//! You can see the output with `espflash` if you provide the `--monitor` option
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
loop {
|
||||
writeln!(uart0, "Hello world!").unwrap();
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
//! Read calibration data from BMP180 sensor
|
||||
//!
|
||||
//! This example dumps the calibration data from a BMP180 sensor
|
||||
//!
|
||||
//! The following wiring is assumed:
|
||||
//! - SDA => GPIO32
|
||||
//! - SCL => GPIO33
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{clock::ClockControl, gpio::IO, i2c::I2C, peripherals::Peripherals, prelude::*};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Create a new peripheral object with the described wiring
|
||||
// and standard I2C clock speed
|
||||
let mut i2c = I2C::new(
|
||||
peripherals.I2C0,
|
||||
io.pins.gpio32,
|
||||
io.pins.gpio33,
|
||||
100u32.kHz(),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
loop {
|
||||
let mut data = [0u8; 22];
|
||||
i2c.write_read(0x77, &[0xaa], &mut data).ok();
|
||||
|
||||
println!("{:02x?}", data);
|
||||
}
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
//! I2C Display example
|
||||
//!
|
||||
//! This example prints some text on an SSD1306-based
|
||||
//! display (via I2C)
|
||||
//!
|
||||
//! The following wiring is assumed:
|
||||
//! - SDA => GPIO32
|
||||
//! - SCL => GPIO33
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use embedded_graphics::{
|
||||
mono_font::{
|
||||
ascii::{FONT_6X10, FONT_9X18_BOLD},
|
||||
MonoTextStyleBuilder,
|
||||
},
|
||||
pixelcolor::BinaryColor,
|
||||
prelude::*,
|
||||
text::{Alignment, Text},
|
||||
};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
i2c::I2C,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Create a new peripheral object with the described wiring
|
||||
// and standard I2C clock speed
|
||||
let i2c = I2C::new(
|
||||
peripherals.I2C0,
|
||||
io.pins.gpio32,
|
||||
io.pins.gpio33,
|
||||
100u32.kHz(),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
// Start timer (5 second interval)
|
||||
timer0.start(5u64.secs());
|
||||
|
||||
// Initialize display
|
||||
let interface = I2CDisplayInterface::new(i2c);
|
||||
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
|
||||
.into_buffered_graphics_mode();
|
||||
display.init().unwrap();
|
||||
|
||||
// Specify different text styles
|
||||
let text_style = MonoTextStyleBuilder::new()
|
||||
.font(&FONT_6X10)
|
||||
.text_color(BinaryColor::On)
|
||||
.build();
|
||||
let text_style_big = MonoTextStyleBuilder::new()
|
||||
.font(&FONT_9X18_BOLD)
|
||||
.text_color(BinaryColor::On)
|
||||
.build();
|
||||
|
||||
loop {
|
||||
// Fill display bufffer with a centered text with two lines (and two text
|
||||
// styles)
|
||||
Text::with_alignment(
|
||||
"esp-hal",
|
||||
display.bounding_box().center() + Point::new(0, 0),
|
||||
text_style_big,
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
Text::with_alignment(
|
||||
"Chip: ESP32",
|
||||
display.bounding_box().center() + Point::new(0, 14),
|
||||
text_style,
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
// Write buffer to display
|
||||
display.flush().unwrap();
|
||||
// Clear display buffer
|
||||
display.clear(BinaryColor::Off).unwrap();
|
||||
|
||||
// Wait 5 seconds
|
||||
block!(timer0.wait()).unwrap();
|
||||
|
||||
// Write single-line centered text "Hello World" to buffer
|
||||
Text::with_alignment(
|
||||
"Hello World!",
|
||||
display.bounding_box().center(),
|
||||
text_style_big,
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
// Write buffer to display
|
||||
display.flush().unwrap();
|
||||
// Clear display buffer
|
||||
display.clear(BinaryColor::Off).unwrap();
|
||||
|
||||
// Wait 5 seconds
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
//! This shows how to continously receive data via I2S
|
||||
//!
|
||||
//! Pins used
|
||||
//! BCLK GPIO12
|
||||
//! WS GPIO13
|
||||
//! DIN GPIO14
|
||||
//!
|
||||
//! Without an additional I2S source device you can connect 3V3 or GND to DIN to
|
||||
//! read 0 or 0xFF or connect DIN to WS to read two different values
|
||||
//!
|
||||
//! You can also inspect the MCLK, BCLK and WS with a logic analyzer
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma_buffers,
|
||||
i2s::{DataFormat, I2s, I2sReadDma, Standard},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.i2s0channel;
|
||||
|
||||
let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, 4092 * 4);
|
||||
|
||||
let i2s = I2s::new(
|
||||
peripherals.I2S0,
|
||||
Standard::Philips,
|
||||
DataFormat::Data16Channel16,
|
||||
44100u32.Hz(),
|
||||
dma_channel.configure(
|
||||
false,
|
||||
&mut tx_descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
let i2s_rx = i2s
|
||||
.i2s_rx
|
||||
.with_bclk(io.pins.gpio12)
|
||||
.with_ws(io.pins.gpio13)
|
||||
.with_din(io.pins.gpio14)
|
||||
.build();
|
||||
|
||||
let buffer = rx_buffer;
|
||||
|
||||
let mut transfer = i2s_rx.read_dma_circular(buffer).unwrap();
|
||||
println!("Started transfer");
|
||||
|
||||
loop {
|
||||
let avail = transfer.available();
|
||||
|
||||
if avail > 0 {
|
||||
let mut rcv = [0u8; 5000];
|
||||
transfer.pop(&mut rcv[..avail]).unwrap();
|
||||
println!("Received {:x?}...", &rcv[..30]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
//! Turns on LED with the option to change LED intensity depending on `duty`
|
||||
//! value. Possible values (`u32`) are in range 0..100.
|
||||
//!
|
||||
//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO4)
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
ledc::{
|
||||
channel::{self, ChannelIFace},
|
||||
timer::{self, TimerIFace},
|
||||
HighSpeed,
|
||||
LEDC,
|
||||
},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let led = io.pins.gpio4.into_push_pull_output();
|
||||
|
||||
let ledc = LEDC::new(peripherals.LEDC, &clocks);
|
||||
let mut hstimer0 = ledc.get_timer::<HighSpeed>(timer::Number::Timer0);
|
||||
|
||||
hstimer0
|
||||
.configure(timer::config::Config {
|
||||
duty: timer::config::Duty::Duty5Bit,
|
||||
clock_source: timer::HSClockSource::APBClk,
|
||||
frequency: 24u32.kHz(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut channel0 = ledc.get_channel(channel::Number::Channel0, led);
|
||||
channel0
|
||||
.configure(channel::config::Config {
|
||||
timer: &hstimer0,
|
||||
duty_pct: 10,
|
||||
pin_config: channel::config::PinConfig::PushPull,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
channel0.start_duty_fade(0, 100, 2000).expect_err(
|
||||
"Fading from 0% to 100%, at 24kHz and 5-bit resolution, over 2 seconds, should fail",
|
||||
);
|
||||
|
||||
loop {
|
||||
// Set up a breathing LED: fade from off to on over a second, then
|
||||
// from on back off over the next second. Then loop.
|
||||
channel0.start_duty_fade(0, 100, 1000).unwrap();
|
||||
while channel0.is_duty_fade_running() {}
|
||||
channel0.start_duty_fade(100, 0, 1000).unwrap();
|
||||
while channel0.is_duty_fade_running() {}
|
||||
}
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
//! PCNT Encoder Demo
|
||||
//!
|
||||
//! This example decodes a quadrature encoder
|
||||
//!
|
||||
//! Since the PCNT units reset to zero when they reach their limits
|
||||
//! we enable an interrupt on the upper and lower limits and
|
||||
//! track the overflow in an AtomicI32
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
use core::{
|
||||
cell::RefCell,
|
||||
cmp::min,
|
||||
sync::atomic::{AtomicI32, Ordering},
|
||||
};
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal as esp_hal;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
pcnt::{channel, channel::PcntSource, unit, PCNT},
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
IO,
|
||||
};
|
||||
use esp_println::println;
|
||||
|
||||
static UNIT0: Mutex<RefCell<Option<unit::Unit>>> = Mutex::new(RefCell::new(None));
|
||||
static VALUE: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let unit_number = unit::Number::Unit1;
|
||||
|
||||
// setup a pulse couter
|
||||
println!("setup pulse counter unit 0");
|
||||
let pcnt = PCNT::new(peripherals.PCNT);
|
||||
let mut u0 = pcnt.get_unit(unit_number);
|
||||
u0.configure(unit::Config {
|
||||
low_limit: -100,
|
||||
high_limit: 100,
|
||||
filter: Some(min(10u16 * 80, 1023u16)),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
println!("setup channel 0");
|
||||
let mut ch0 = u0.get_channel(channel::Number::Channel0);
|
||||
let mut pin_a = io.pins.gpio22.into_pull_up_input();
|
||||
let mut pin_b = io.pins.gpio23.into_pull_up_input();
|
||||
|
||||
ch0.configure(
|
||||
PcntSource::from_pin(&mut pin_a),
|
||||
PcntSource::from_pin(&mut pin_b),
|
||||
channel::Config {
|
||||
lctrl_mode: channel::CtrlMode::Reverse,
|
||||
hctrl_mode: channel::CtrlMode::Keep,
|
||||
pos_edge: channel::EdgeMode::Decrement,
|
||||
neg_edge: channel::EdgeMode::Increment,
|
||||
invert_ctrl: false,
|
||||
invert_sig: false,
|
||||
},
|
||||
);
|
||||
|
||||
println!("setup channel 1");
|
||||
let mut ch1 = u0.get_channel(channel::Number::Channel1);
|
||||
ch1.configure(
|
||||
PcntSource::from_pin(&mut pin_b),
|
||||
PcntSource::from_pin(&mut pin_a),
|
||||
channel::Config {
|
||||
lctrl_mode: channel::CtrlMode::Reverse,
|
||||
hctrl_mode: channel::CtrlMode::Keep,
|
||||
pos_edge: channel::EdgeMode::Increment,
|
||||
neg_edge: channel::EdgeMode::Decrement,
|
||||
invert_ctrl: false,
|
||||
invert_sig: false,
|
||||
},
|
||||
);
|
||||
println!("subscribing to events");
|
||||
u0.events(unit::Events {
|
||||
low_limit: true,
|
||||
high_limit: true,
|
||||
thresh0: false,
|
||||
thresh1: false,
|
||||
zero: false,
|
||||
});
|
||||
|
||||
println!("enabling interrupts");
|
||||
u0.listen();
|
||||
println!("resume pulse counter unit 0");
|
||||
u0.resume();
|
||||
|
||||
critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0));
|
||||
|
||||
interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap();
|
||||
|
||||
let mut last_value: i32 = 0;
|
||||
loop {
|
||||
critical_section::with(|cs| {
|
||||
let mut u0 = UNIT0.borrow_ref_mut(cs);
|
||||
let u0 = u0.as_mut().unwrap();
|
||||
let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst);
|
||||
if value != last_value {
|
||||
println!("value: {value}");
|
||||
last_value = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn PCNT() {
|
||||
critical_section::with(|cs| {
|
||||
let mut u0 = UNIT0.borrow_ref_mut(cs);
|
||||
let u0 = u0.as_mut().unwrap();
|
||||
if u0.interrupt_set() {
|
||||
let events = u0.get_events();
|
||||
if events.high_limit {
|
||||
VALUE.fetch_add(100, Ordering::SeqCst);
|
||||
} else if events.low_limit {
|
||||
VALUE.fetch_add(-100, Ordering::SeqCst);
|
||||
}
|
||||
u0.reset_interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
//! This shows how to use PSRAM as heap-memory via esp-alloc
|
||||
//!
|
||||
//! You need an ESP32 with at least 2 MB of PSRAM memory.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, psram};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
|
||||
|
||||
fn init_psram_heap() {
|
||||
unsafe {
|
||||
ALLOCATOR.init(psram::PSRAM_VADDR_START as *mut u8, psram::PSRAM_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
#[cfg(debug_assertions)]
|
||||
compile_error!("PSRAM on ESP32 needs to be built in release mode");
|
||||
|
||||
#[cfg(feature = "log")]
|
||||
esp_println::logger::init_logger_from_env();
|
||||
|
||||
let peripherals = Peripherals::take();
|
||||
psram::init_psram(peripherals.PSRAM);
|
||||
init_psram_heap();
|
||||
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
println!("Going to access PSRAM");
|
||||
|
||||
let mut large_vec: alloc::vec::Vec<u32> = alloc::vec::Vec::with_capacity(500 * 1024 / 4);
|
||||
|
||||
for i in 0..(500 * 1024 / 4) {
|
||||
large_vec.push((i & 0xff) as u32);
|
||||
}
|
||||
|
||||
println!("vec size = {} bytes", large_vec.len() * 4);
|
||||
println!("vec address = {:p}", large_vec.as_ptr());
|
||||
println!("{:?}", &large_vec[..100]);
|
||||
|
||||
let string = alloc::string::String::from("A string allocated in PSRAM");
|
||||
println!("'{}' allocated at {:p}", &string, string.as_ptr());
|
||||
|
||||
println!("done");
|
||||
|
||||
loop {}
|
||||
}
|
||||
@ -1,166 +0,0 @@
|
||||
//! SPI write and read a flash chip
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO19
|
||||
//! MISO/IO0 GPIO18
|
||||
//! MOSI/IO1 GPIO5
|
||||
//! IO2 GPIO17
|
||||
//! IO3 GPIO16
|
||||
//! CS GPIO4
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! Connect a flash chip (GD25Q64C was used) and make sure QE in the status
|
||||
//! register is set.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma_buffers,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{
|
||||
master::{prelude::*, Address, Command, Spi},
|
||||
SpiDataMode,
|
||||
SpiMode,
|
||||
},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::{print, println};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio19;
|
||||
let miso = io.pins.gpio18;
|
||||
let mosi = io.pins.gpio5;
|
||||
let sio2 = io.pins.gpio17;
|
||||
let sio3 = io.pins.gpio16;
|
||||
let cs = io.pins.gpio4;
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.spi2channel;
|
||||
|
||||
let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(256, 320);
|
||||
|
||||
let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks)
|
||||
.with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
Some(miso),
|
||||
Some(sio2),
|
||||
Some(sio3),
|
||||
Some(cs),
|
||||
)
|
||||
.with_dma(dma_channel.configure(
|
||||
false,
|
||||
&mut tx_descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
));
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let mut zero_buf = zero_buffer();
|
||||
let send = tx_buffer;
|
||||
let mut receive = rx_buffer;
|
||||
|
||||
// write enable
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x06, SpiDataMode::Single),
|
||||
Address::None,
|
||||
0,
|
||||
zero_buf,
|
||||
)
|
||||
.unwrap();
|
||||
(zero_buf, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// erase sector
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x20, SpiDataMode::Single),
|
||||
Address::Address24(0x000000, SpiDataMode::Single),
|
||||
0,
|
||||
zero_buf,
|
||||
)
|
||||
.unwrap();
|
||||
(zero_buf, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// write enable
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x06, SpiDataMode::Single),
|
||||
Address::None,
|
||||
0,
|
||||
zero_buf,
|
||||
)
|
||||
.unwrap();
|
||||
(_, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// write data / program page
|
||||
send.fill(b'!');
|
||||
send[0..][..5].copy_from_slice(&b"Hello"[..]);
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Quad,
|
||||
Command::Command8(0x32, SpiDataMode::Single),
|
||||
Address::Address24(0x000000, SpiDataMode::Single),
|
||||
0,
|
||||
send,
|
||||
)
|
||||
.unwrap();
|
||||
(_, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
loop {
|
||||
// quad fast read
|
||||
let transfer = spi
|
||||
.read(
|
||||
SpiDataMode::Quad,
|
||||
Command::Command8(0xeb, SpiDataMode::Single),
|
||||
Address::Address32(0x000000 << 8, SpiDataMode::Quad),
|
||||
4,
|
||||
receive,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// here we could do something else while DMA transfer is in progress
|
||||
// the buffers and spi is moved into the transfer and we can get it back via
|
||||
// `wait`
|
||||
(receive, spi) = transfer.wait().unwrap();
|
||||
|
||||
println!("{:x?}", &receive);
|
||||
for b in &mut receive.iter() {
|
||||
if *b >= 32 && *b <= 127 {
|
||||
print!("{}", *b as char);
|
||||
} else {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
|
||||
fn zero_buffer() -> &'static mut [u8; 0] {
|
||||
static mut BUFFER: [u8; 0] = [0u8; 0];
|
||||
unsafe { &mut BUFFER }
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
//! This shows how to use RTC memory.
|
||||
//! RTC memory is retained during resets and during most sleep modes.
|
||||
//! Initialized memory is always re-initialized on startup.
|
||||
//! Uninitialzed memory isn't initialized on startup and can be used to keep
|
||||
//! data during resets. Zeroed memory is initialized to zero on startup.
|
||||
//! We can also run code from RTC memory.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
macros::ram,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
|
||||
#[ram(rtc_fast)]
|
||||
static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];
|
||||
|
||||
#[ram(rtc_fast, uninitialized)]
|
||||
static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2];
|
||||
|
||||
#[ram(rtc_fast, zeroed)]
|
||||
static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
// The RWDT flash boot protection must be enabled, as it is triggered as part of
|
||||
// the example.
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
rtc.rwdt.enable();
|
||||
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
println!(
|
||||
"IRAM function located at {:p}",
|
||||
function_in_ram as *const ()
|
||||
);
|
||||
unsafe {
|
||||
println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA);
|
||||
println!("SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA);
|
||||
println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA);
|
||||
|
||||
SOME_INITED_DATA[0] = 0xff;
|
||||
SOME_ZEROED_DATA[0] = 0xff;
|
||||
|
||||
println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA);
|
||||
println!("SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA);
|
||||
println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA);
|
||||
|
||||
if SOME_UNINITED_DATA[0] != 0 {
|
||||
SOME_UNINITED_DATA[0] = 0;
|
||||
SOME_UNINITED_DATA[1] = 0;
|
||||
}
|
||||
|
||||
if SOME_UNINITED_DATA[1] == 0xff {
|
||||
SOME_UNINITED_DATA[1] = 0;
|
||||
}
|
||||
|
||||
println!("Counter {}", SOME_UNINITED_DATA[1]);
|
||||
SOME_UNINITED_DATA[1] += 1;
|
||||
}
|
||||
|
||||
println!(
|
||||
"RTC_FAST function located at {:p}",
|
||||
function_in_rtc_ram as *const ()
|
||||
);
|
||||
println!("Result {}", function_in_rtc_ram());
|
||||
|
||||
loop {
|
||||
function_in_ram();
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[ram]
|
||||
fn function_in_ram() {
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
#[ram(rtc_fast)]
|
||||
fn function_in_rtc_ram() -> u32 {
|
||||
42
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
//! This shows how to read selected information from eFuses.
|
||||
//! e.g. the MAC address
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{clock::ClockControl, efuse::Efuse, peripherals::Peripherals, prelude::*};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
println!("MAC address {:02x?}", Efuse::get_mac_address());
|
||||
println!("Core Count {}", Efuse::get_core_count());
|
||||
println!("Bluetooth enabled {}", Efuse::is_bluetooth_enabled());
|
||||
println!("Chip type {:?}", Efuse::get_chip_type());
|
||||
println!("Max CPU clock {:?}", Efuse::get_max_cpu_frequency());
|
||||
println!("Flash Encryption {:?}", Efuse::get_flash_encryption());
|
||||
|
||||
loop {}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
//! Demonstrates decoding pulse sequences with RMT
|
||||
//! Connect GPIO15 to GPIO4
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rmt::{PulseCode, RxChannel, RxChannelConfig, RxChannelCreator},
|
||||
Delay,
|
||||
Rmt,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut out = io.pins.gpio15.into_push_pull_output();
|
||||
|
||||
let rmt = Rmt::new(peripherals.RMT, 80u32.MHz(), &clocks).unwrap();
|
||||
|
||||
let mut channel = rmt
|
||||
.channel0
|
||||
.configure(
|
||||
io.pins.gpio4,
|
||||
RxChannelConfig {
|
||||
clk_divider: 1,
|
||||
idle_threshold: 0b111_1111_1111_1111,
|
||||
..RxChannelConfig::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let mut data = [PulseCode {
|
||||
level1: true,
|
||||
length1: 1,
|
||||
level2: false,
|
||||
length2: 1,
|
||||
}; 48];
|
||||
|
||||
loop {
|
||||
for x in data.iter_mut() {
|
||||
x.length1 = 0;
|
||||
x.length2 = 0;
|
||||
}
|
||||
|
||||
let transaction = channel.receive(&mut data).unwrap();
|
||||
|
||||
// simulate input
|
||||
for i in 0u32..5u32 {
|
||||
out.set_high().unwrap();
|
||||
delay.delay_us(i * 10 + 20);
|
||||
out.set_low().unwrap();
|
||||
delay.delay_us(i * 20 + 20);
|
||||
}
|
||||
|
||||
match transaction.wait() {
|
||||
Ok(channel_res) => {
|
||||
channel = channel_res;
|
||||
for entry in &data[..data.len()] {
|
||||
if entry.length1 == 0 {
|
||||
break;
|
||||
}
|
||||
println!("{} {}", entry.level1, entry.length1);
|
||||
|
||||
if entry.length2 == 0 {
|
||||
break;
|
||||
}
|
||||
println!("{} {}", entry.level2, entry.length2);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
Err((_err, channel_res)) => {
|
||||
channel = channel_res;
|
||||
println!("Error");
|
||||
}
|
||||
}
|
||||
|
||||
delay.delay_ms(1500u32);
|
||||
}
|
||||
}
|
||||
@ -1,154 +0,0 @@
|
||||
//! Demonstrates the use of the RSA peripheral and compares the speed of
|
||||
//! multiple arithmetic operations.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use crypto_bigint::{
|
||||
modular::runtime_mod::{DynResidue, DynResidueParams},
|
||||
Uint,
|
||||
U1024,
|
||||
U512,
|
||||
};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rsa::{
|
||||
operand_sizes,
|
||||
Rsa,
|
||||
RsaModularExponentiation,
|
||||
RsaModularMultiplication,
|
||||
RsaMultiplication,
|
||||
},
|
||||
xtensa_lx,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
const BIGNUM_1: U512 = Uint::from_be_hex(
|
||||
"c7f61058f96db3bd87dbab08ab03b4f7f2f864eac249144adea6a65f97803b719d8ca980b7b3c0389c1c7c6\
|
||||
7dc353c5e0ec11f5fc8ce7f6073796cc8f73fa878",
|
||||
);
|
||||
const BIGNUM_2: U512 = Uint::from_be_hex(
|
||||
"1763db3344e97be15d04de4868badb12a38046bb793f7630d87cf100aa1c759afac15a01f3c4c83ec2d2f66\
|
||||
6bd22f71c3c1f075ec0e2cb0cb29994d091b73f51",
|
||||
);
|
||||
const BIGNUM_3: U512 = Uint::from_be_hex(
|
||||
"6b6bb3d2b6cbeb45a769eaa0384e611e1b89b0c9b45a045aca1c5fd6e8785b38df7118cf5dd45b9b63d293b\
|
||||
67aeafa9ba25feb8712f188cb139b7d9b9af1c361",
|
||||
);
|
||||
|
||||
const fn compute_r(modulus: &U512) -> U512 {
|
||||
let mut d = [0_u32; U512::LIMBS * 2 + 1];
|
||||
d[d.len() - 1] = 1;
|
||||
let d = Uint::from_words(d);
|
||||
d.const_rem(&modulus.resize()).0.resize()
|
||||
}
|
||||
|
||||
const fn compute_mprime(modulus: &U512) -> u32 {
|
||||
let m_inv = modulus.inv_mod2k(32).to_words()[0];
|
||||
(-1 * m_inv as i64 % 4294967296) as u32
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let rsa = peripherals.RSA;
|
||||
let mut rsa = Rsa::new(rsa);
|
||||
nb::block!(rsa.ready()).unwrap();
|
||||
mod_exp_example(&mut rsa);
|
||||
mod_multi_example(&mut rsa);
|
||||
multiplication_example(&mut rsa);
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn mod_multi_example(rsa: &mut Rsa) {
|
||||
let mut outbuf = [0_u32; U512::LIMBS];
|
||||
let mut mod_multi = RsaModularMultiplication::<operand_sizes::Op512>::new(
|
||||
rsa,
|
||||
BIGNUM_3.as_words(),
|
||||
compute_mprime(&BIGNUM_3),
|
||||
);
|
||||
let r = compute_r(&BIGNUM_3);
|
||||
let pre_hw_modmul = xtensa_lx::timer::get_cycle_count();
|
||||
mod_multi.start_step1(BIGNUM_1.as_words(), r.as_words());
|
||||
mod_multi.start_step2(BIGNUM_2.as_words());
|
||||
mod_multi.read_results(&mut outbuf);
|
||||
let post_hw_modmul = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for hw modular multiplication",
|
||||
post_hw_modmul - pre_hw_modmul
|
||||
);
|
||||
|
||||
let residue_params = DynResidueParams::new(&BIGNUM_3);
|
||||
let residue_num1 = DynResidue::new(&BIGNUM_1, residue_params);
|
||||
let residue_num2 = DynResidue::new(&BIGNUM_2, residue_params);
|
||||
let pre_sw_exp = xtensa_lx::timer::get_cycle_count();
|
||||
let sw_out = residue_num1.mul(&residue_num2);
|
||||
let post_sw_exp = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for sw modular multiplication",
|
||||
post_sw_exp - pre_sw_exp
|
||||
);
|
||||
assert_eq!(U512::from_words(outbuf), sw_out.retrieve());
|
||||
println!("modular multiplication done");
|
||||
}
|
||||
|
||||
fn mod_exp_example(rsa: &mut Rsa) {
|
||||
let mut outbuf = [0_u32; U512::LIMBS];
|
||||
let mut mod_exp = RsaModularExponentiation::<operand_sizes::Op512>::new(
|
||||
rsa,
|
||||
BIGNUM_2.as_words(),
|
||||
BIGNUM_3.as_words(),
|
||||
compute_mprime(&BIGNUM_3),
|
||||
);
|
||||
let r = compute_r(&BIGNUM_3);
|
||||
let base = &BIGNUM_1.as_words();
|
||||
let pre_hw_exp = xtensa_lx::timer::get_cycle_count();
|
||||
mod_exp.start_exponentiation(base, r.as_words());
|
||||
mod_exp.read_results(&mut outbuf);
|
||||
let post_hw_exp = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for hw modular exponentiation",
|
||||
post_hw_exp - pre_hw_exp
|
||||
);
|
||||
let residue_params = DynResidueParams::new(&BIGNUM_3);
|
||||
let residue = DynResidue::new(&BIGNUM_1, residue_params);
|
||||
let pre_sw_exp = xtensa_lx::timer::get_cycle_count();
|
||||
let sw_out = residue.pow(&BIGNUM_2);
|
||||
let post_sw_exp = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for sw modular exponentiation",
|
||||
post_sw_exp - pre_sw_exp
|
||||
);
|
||||
assert_eq!(U512::from_words(outbuf), sw_out.retrieve());
|
||||
println!("modular exponentiation done");
|
||||
}
|
||||
|
||||
fn multiplication_example(rsa: &mut Rsa) {
|
||||
let mut out = [0_u32; U1024::LIMBS];
|
||||
let mut rsamulti = RsaMultiplication::<operand_sizes::Op512>::new(rsa);
|
||||
let operand_a = BIGNUM_1.as_words();
|
||||
let operand_b = BIGNUM_2.as_words();
|
||||
let pre_hw_mul = xtensa_lx::timer::get_cycle_count();
|
||||
rsamulti.start_multiplication(operand_a, operand_b);
|
||||
rsamulti.read_results(&mut out);
|
||||
let post_hw_mul = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for hw multiplication",
|
||||
post_hw_mul - pre_hw_mul
|
||||
);
|
||||
let pre_sw_mul = xtensa_lx::timer::get_cycle_count();
|
||||
let sw_out = BIGNUM_1.mul_wide(&BIGNUM_2);
|
||||
let post_sw_mul = xtensa_lx::timer::get_cycle_count();
|
||||
println!(
|
||||
"it took {} cycles for sw multiplication",
|
||||
post_sw_mul - pre_sw_mul
|
||||
);
|
||||
assert_eq!(U1024::from_words(out), sw_out.1.concat(&sw_out.0));
|
||||
println!("multiplication done");
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
//! This demos the RTC Watchdog Timer (RWDT).
|
||||
//! The RWDT is initially configured to trigger an interrupt after a given
|
||||
//! timeout. Then, upon expiration, the RWDT is restarted and then reconfigured
|
||||
//! to reset both the main system and the RTC.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
Rtc,
|
||||
Rwdt,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static RWDT: Mutex<RefCell<Option<Rwdt>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
rtc.rwdt.start(2000u64.millis());
|
||||
rtc.rwdt.listen();
|
||||
|
||||
critical_section::with(|cs| RWDT.borrow_ref_mut(cs).replace(rtc.rwdt));
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::RTC_CORE,
|
||||
interrupt::Priority::Priority1,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn RTC_CORE() {
|
||||
critical_section::with(|cs| {
|
||||
esp_println::println!("RWDT Interrupt");
|
||||
|
||||
let mut rwdt = RWDT.borrow_ref_mut(cs);
|
||||
let rwdt = rwdt.as_mut().unwrap();
|
||||
rwdt.clear_interrupt();
|
||||
|
||||
esp_println::println!("Restarting in 5 seconds...");
|
||||
|
||||
rwdt.start(5000u64.millis());
|
||||
rwdt.unlisten();
|
||||
});
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
//! This shows some of the interrupts that can be generated by UART/Serial.
|
||||
//! Use a proper serial terminal to connect to the board (espmonitor and
|
||||
//! espflash won't work)
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{cell::RefCell, fmt::Write};
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals, UART0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
uart::config::AtCmdConfig,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
|
||||
static SERIAL: Mutex<RefCell<Option<Uart<UART0>>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, b'#', None));
|
||||
uart0.set_rx_fifo_full_threshold(30).unwrap();
|
||||
uart0.listen_at_cmd();
|
||||
uart0.listen_rx_fifo_full();
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::UART0,
|
||||
interrupt::Priority::Priority2,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
critical_section::with(|cs| SERIAL.borrow_ref_mut(cs).replace(uart0));
|
||||
|
||||
loop {
|
||||
critical_section::with(|cs| {
|
||||
let mut serial = SERIAL.borrow_ref_mut(cs);
|
||||
let serial = serial.as_mut().unwrap();
|
||||
writeln!(serial, "Hello World! Send a single `#` character or send at least 30 characters and see the interrupts trigger.").ok();
|
||||
});
|
||||
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn UART0() {
|
||||
critical_section::with(|cs| {
|
||||
let mut serial = SERIAL.borrow_ref_mut(cs);
|
||||
let serial = serial.as_mut().unwrap();
|
||||
|
||||
let mut cnt = 0;
|
||||
while let nb::Result::Ok(_c) = serial.read() {
|
||||
cnt += 1;
|
||||
}
|
||||
writeln!(serial, "Read {} bytes", cnt,).ok();
|
||||
|
||||
writeln!(
|
||||
serial,
|
||||
"Interrupt AT-CMD: {} RX-FIFO-FULL: {}",
|
||||
serial.at_cmd_interrupt_set(),
|
||||
serial.rx_fifo_full_interrupt_set(),
|
||||
)
|
||||
.ok();
|
||||
|
||||
serial.reset_at_cmd_interrupt();
|
||||
serial.reset_rx_fifo_full_interrupt();
|
||||
});
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
//! Demonstrates the use of the SHA peripheral and compares the speed of
|
||||
//! hardware-accelerated and pure software hashing.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
sha::{Sha, ShaMode},
|
||||
xtensa_lx,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
use sha2::{Digest, Sha512};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes();
|
||||
let mut remaining = source_data;
|
||||
let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA512);
|
||||
|
||||
// Short hashes can be created by decreasing the output buffer to the desired
|
||||
// length
|
||||
let mut output = [0u8; 64];
|
||||
|
||||
let pre_calc = xtensa_lx::timer::get_cycle_count();
|
||||
// The hardware implementation takes a subslice of the input, and returns the
|
||||
// unprocessed parts The unprocessed parts can be input in the next
|
||||
// iteration, you can always add more data until finish() is called. After
|
||||
// finish() is called update()'s will contribute to a new hash which
|
||||
// can be extracted again with finish().
|
||||
|
||||
while remaining.len() > 0 {
|
||||
// Can add println to view progress, however println takes a few orders of
|
||||
// magnitude longer than the Sha function itself so not useful for
|
||||
// comparing processing time println!("Remaining len: {}",
|
||||
// remaining.len());
|
||||
|
||||
// All the HW Sha functions are infallible so unwrap is fine to use if you use
|
||||
// block!
|
||||
remaining = block!(hasher.update(remaining)).unwrap();
|
||||
}
|
||||
|
||||
// Finish can be called as many times as desired to get mutliple copies of the
|
||||
// output.
|
||||
block!(hasher.finish(output.as_mut_slice())).unwrap();
|
||||
|
||||
let post_calc = xtensa_lx::timer::get_cycle_count();
|
||||
let hw_time = post_calc - pre_calc;
|
||||
println!("Took {} cycles", hw_time);
|
||||
println!("SHA512 Hash output {:02x?}", output);
|
||||
|
||||
let pre_calc = xtensa_lx::timer::get_cycle_count();
|
||||
let mut hasher = Sha512::new();
|
||||
hasher.update(source_data);
|
||||
let soft_result = hasher.finalize();
|
||||
let post_calc = xtensa_lx::timer::get_cycle_count();
|
||||
let soft_time = post_calc - pre_calc;
|
||||
println!("Took {} cycles", soft_time);
|
||||
println!("SHA512 Hash output {:02x?}", soft_result);
|
||||
|
||||
assert_eq!(output, soft_result[..]);
|
||||
println!("HW SHA is {}x faster", soft_time / hw_time);
|
||||
|
||||
loop {}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
//! Demonstrates deep sleep with timer wakeup
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
entry,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rtc_cntl::{get_reset_reason, get_wakeup_cause, sleep::TimerWakeupSource, SocResetReason},
|
||||
Cpu,
|
||||
Delay,
|
||||
Rtc,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
|
||||
println!("up and runnning!");
|
||||
let reason = get_reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn);
|
||||
println!("reset reason: {:?}", reason);
|
||||
let wake_reason = get_wakeup_cause();
|
||||
println!("wake reason: {:?}", wake_reason);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
||||
println!("sleeping!");
|
||||
delay.delay_ms(100u32);
|
||||
rtc.sleep_deep(&[&timer], &mut delay);
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
//! Demonstrates deep sleep with timer and ext0 (using gpio27) wakeup
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
entry,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rtc_cntl::{
|
||||
get_reset_reason,
|
||||
get_wakeup_cause,
|
||||
sleep::{Ext0WakeupSource, TimerWakeupSource, WakeupLevel},
|
||||
SocResetReason,
|
||||
},
|
||||
Cpu,
|
||||
Delay,
|
||||
Rtc,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut ext0_pin = io.pins.gpio27;
|
||||
|
||||
println!("up and runnning!");
|
||||
let reason = get_reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn);
|
||||
println!("reset reason: {:?}", reason);
|
||||
let wake_reason = get_wakeup_cause();
|
||||
println!("wake reason: {:?}", wake_reason);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
||||
let ext0 = Ext0WakeupSource::new(&mut ext0_pin, WakeupLevel::High);
|
||||
println!("sleeping!");
|
||||
delay.delay_ms(100u32);
|
||||
rtc.sleep_deep(&[&timer, &ext0], &mut delay);
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
//! Demonstrates deep sleep with timer and ext1 (using gpio27 & gpio23) wakeup
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
entry,
|
||||
gpio::{RTCPin, IO},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rtc_cntl::{
|
||||
get_reset_reason,
|
||||
get_wakeup_cause,
|
||||
sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel},
|
||||
SocResetReason,
|
||||
},
|
||||
Cpu,
|
||||
Delay,
|
||||
Rtc,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut pin27 = io.pins.gpio27;
|
||||
let mut pin32 = io.pins.gpio32;
|
||||
|
||||
println!("up and runnning!");
|
||||
let reason = get_reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn);
|
||||
println!("reset reason: {:?}", reason);
|
||||
let wake_reason = get_wakeup_cause();
|
||||
println!("wake reason: {:?}", wake_reason);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
||||
let mut wakeup_pins: [&mut dyn RTCPin; 2] = [&mut pin27, &mut pin32];
|
||||
let ext1 = Ext1WakeupSource::new(&mut wakeup_pins, WakeupLevel::High);
|
||||
println!("sleeping!");
|
||||
delay.delay_ms(100u32);
|
||||
rtc.sleep_deep(&[&timer, &ext1], &mut delay);
|
||||
}
|
||||
@ -1,140 +0,0 @@
|
||||
//! SPI loopback test
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO19
|
||||
//! MISO GPIO25
|
||||
//! MOSI GPIO23
|
||||
//! CS 1 GPIO12
|
||||
//! CS 2 GPIO13
|
||||
//! CS 3 GPIO14
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! This example transfers data via SPI.
|
||||
//! Connect MISO and MOSI pins to see the outgoing data is read as incoming
|
||||
//! data.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use embedded_hal_1::spi::SpiDevice;
|
||||
use embedded_hal_bus::spi::RefCellDevice;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::{self, IO},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{master::Spi, SpiMode},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::{print, println};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio19;
|
||||
let miso = io.pins.gpio25;
|
||||
let mosi = io.pins.gpio23;
|
||||
|
||||
let spi_bus = Spi::new(peripherals.SPI2, 1000u32.kHz(), SpiMode::Mode0, &clocks).with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
Some(miso),
|
||||
gpio::NO_PIN,
|
||||
);
|
||||
let spi_bus = RefCell::new(spi_bus);
|
||||
let mut spi_device_1 =
|
||||
RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio12.into_push_pull_output());
|
||||
let mut spi_device_2 =
|
||||
RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio13.into_push_pull_output());
|
||||
let mut spi_device_3 =
|
||||
RefCellDevice::new_no_delay(&spi_bus, io.pins.gpio14.into_push_pull_output());
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
println!("=== SPI example with embedded-hal-1 traits ===");
|
||||
|
||||
loop {
|
||||
// --- Symmetric transfer (Read as much as we write) ---
|
||||
print!("Starting symmetric transfer...");
|
||||
let write = [0xde, 0xad, 0xbe, 0xef];
|
||||
let mut read: [u8; 4] = [0x00u8; 4];
|
||||
|
||||
spi_device_1.transfer(&mut read[..], &write[..]).unwrap();
|
||||
assert_eq!(write, read);
|
||||
spi_device_2.transfer(&mut read[..], &write[..]).unwrap();
|
||||
spi_device_3.transfer(&mut read[..], &write[..]).unwrap();
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// --- Asymmetric transfer (Read more than we write) ---
|
||||
print!("Starting asymetric transfer (read > write)...");
|
||||
let mut read: [u8; 4] = [0x00; 4];
|
||||
|
||||
spi_device_1
|
||||
.transfer(&mut read[0..2], &write[..])
|
||||
.expect("Asymmetric transfer failed");
|
||||
assert_eq!(write[0], read[0]);
|
||||
assert_eq!(read[2], 0x00u8);
|
||||
spi_device_2
|
||||
.transfer(&mut read[0..2], &write[..])
|
||||
.expect("Asymmetric transfer failed");
|
||||
spi_device_3
|
||||
.transfer(&mut read[0..2], &write[..])
|
||||
.expect("Asymmetric transfer failed");
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// --- Symmetric transfer with huge buffer ---
|
||||
// Only your RAM is the limit!
|
||||
print!("Starting huge transfer...");
|
||||
let mut write = [0x55u8; 4096];
|
||||
for byte in 0..write.len() {
|
||||
write[byte] = byte as u8;
|
||||
}
|
||||
let mut read = [0x00u8; 4096];
|
||||
|
||||
spi_device_1
|
||||
.transfer(&mut read[..], &write[..])
|
||||
.expect("Huge transfer failed");
|
||||
assert_eq!(write, read);
|
||||
spi_device_2
|
||||
.transfer(&mut read[..], &write[..])
|
||||
.expect("Huge transfer failed");
|
||||
spi_device_3
|
||||
.transfer(&mut read[..], &write[..])
|
||||
.expect("Huge transfer failed");
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// --- Symmetric transfer with huge buffer in-place (No additional allocation
|
||||
// needed) ---
|
||||
print!("Starting huge transfer (in-place)...");
|
||||
let mut write = [0x55u8; 4096];
|
||||
for byte in 0..write.len() {
|
||||
write[byte] = byte as u8;
|
||||
}
|
||||
|
||||
spi_device_1
|
||||
.transfer_in_place(&mut write[..])
|
||||
.expect("Huge transfer failed");
|
||||
for byte in 0..write.len() {
|
||||
assert_eq!(write[byte], byte as u8);
|
||||
}
|
||||
spi_device_2
|
||||
.transfer_in_place(&mut write[..])
|
||||
.expect("Huge transfer failed");
|
||||
spi_device_3
|
||||
.transfer_in_place(&mut write[..])
|
||||
.expect("Huge transfer failed");
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
//! SPI loopback test
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO19
|
||||
//! MISO GPIO25
|
||||
//! MOSI GPIO23
|
||||
//! CS GPIO22
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! This example transfers data via SPI.
|
||||
//! Connect MISO and MOSI pins to see the outgoing data is read as incoming
|
||||
//! data.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use embedded_hal_1::spi::SpiBus;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{master::Spi, SpiMode},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::{print, println};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio19;
|
||||
let miso = io.pins.gpio25;
|
||||
let mosi = io.pins.gpio23;
|
||||
let cs = io.pins.gpio22;
|
||||
|
||||
let mut spi = Spi::new(peripherals.SPI2, 1000u32.kHz(), SpiMode::Mode0, &clocks).with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
Some(miso),
|
||||
Some(cs),
|
||||
);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
println!("=== SPI example with embedded-hal-1 traits ===");
|
||||
|
||||
loop {
|
||||
// --- Symmetric transfer (Read as much as we write) ---
|
||||
print!("Starting symmetric transfer...");
|
||||
let write = [0xde, 0xad, 0xbe, 0xef];
|
||||
let mut read: [u8; 4] = [0x00u8; 4];
|
||||
|
||||
SpiBus::transfer(&mut spi, &mut read[..], &write[..]).expect("Symmetric transfer failed");
|
||||
assert_eq!(write, read);
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// --- Asymmetric transfer (Read more than we write) ---
|
||||
print!("Starting asymetric transfer (read > write)...");
|
||||
let mut read: [u8; 4] = [0x00; 4];
|
||||
|
||||
SpiBus::transfer(&mut spi, &mut read[0..2], &write[..])
|
||||
.expect("Asymmetric transfer failed");
|
||||
assert_eq!(write[0], read[0]);
|
||||
assert_eq!(read[2], 0x00u8);
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// --- Symmetric transfer with huge buffer ---
|
||||
// Only your RAM is the limit!
|
||||
print!("Starting huge transfer...");
|
||||
let mut write = [0x55u8; 4096];
|
||||
for byte in 0..write.len() {
|
||||
write[byte] = byte as u8;
|
||||
}
|
||||
let mut read = [0x00u8; 4096];
|
||||
|
||||
SpiBus::transfer(&mut spi, &mut read[..], &write[..]).expect("Huge transfer failed");
|
||||
assert_eq!(write, read);
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// --- Symmetric transfer with huge buffer in-place (No additional allocation
|
||||
// needed) ---
|
||||
print!("Starting huge transfer (in-place)...");
|
||||
let mut write = [0x55u8; 4096];
|
||||
for byte in 0..write.len() {
|
||||
write[byte] = byte as u8;
|
||||
}
|
||||
|
||||
SpiBus::transfer_in_place(&mut spi, &mut write[..]).expect("Huge transfer failed");
|
||||
for byte in 0..write.len() {
|
||||
assert_eq!(write[byte], byte as u8);
|
||||
}
|
||||
println!(" SUCCESS");
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
//! SPI read manufacturer id from flash chip
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO19
|
||||
//! MISO/IO0 GPIO18
|
||||
//! MOSI/IO1 GPIO5
|
||||
//! IO2 GPIO17
|
||||
//! IO3 GPIO16
|
||||
//! CS GPIO4
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! Connect a flash chip (GD25Q64C was used) and make sure QE in the status
|
||||
//! register is set.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{
|
||||
master::{Address, Command, HalfDuplexReadWrite, Spi},
|
||||
SpiDataMode,
|
||||
SpiMode,
|
||||
},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio19;
|
||||
let miso = io.pins.gpio18;
|
||||
let mosi = io.pins.gpio5;
|
||||
let sio2 = io.pins.gpio17;
|
||||
let sio3 = io.pins.gpio16;
|
||||
let cs = io.pins.gpio4;
|
||||
|
||||
let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks)
|
||||
.with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
Some(miso),
|
||||
Some(sio2),
|
||||
Some(sio3),
|
||||
Some(cs),
|
||||
);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
// READ MANUFACTURER ID FROM FLASH CHIP
|
||||
let mut data = [0u8; 2];
|
||||
spi.read(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x90, SpiDataMode::Single),
|
||||
Address::Address24(0x000000, SpiDataMode::Single),
|
||||
0,
|
||||
&mut data,
|
||||
)
|
||||
.unwrap();
|
||||
println!("Single {:x?}", data);
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// READ MANUFACTURER ID FROM FLASH CHIP
|
||||
let mut data = [0u8; 2];
|
||||
spi.read(
|
||||
SpiDataMode::Dual,
|
||||
Command::Command8(0x92, SpiDataMode::Single),
|
||||
Address::Address32(0x000000_00, SpiDataMode::Dual),
|
||||
0,
|
||||
&mut data,
|
||||
)
|
||||
.unwrap();
|
||||
println!("Dual {:x?}", data);
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// READ MANUFACTURER ID FROM FLASH CHIP
|
||||
let mut data = [0u8; 2];
|
||||
spi.read(
|
||||
SpiDataMode::Quad,
|
||||
Command::Command8(0x94, SpiDataMode::Single),
|
||||
Address::Address32(0x000000_00, SpiDataMode::Quad),
|
||||
4,
|
||||
&mut data,
|
||||
)
|
||||
.unwrap();
|
||||
println!("Quad {:x?}", data);
|
||||
delay.delay_ms(1500u32);
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
//! SPI loopback test
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO19
|
||||
//! MISO GPIO25
|
||||
//! MOSI GPIO23
|
||||
//! CS GPIO22
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! This example transfers data via SPI.
|
||||
//! Connect MISO and MOSI pins to see the outgoing data is read as incoming
|
||||
//! data.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{master::Spi, SpiMode},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio19;
|
||||
let miso = io.pins.gpio25;
|
||||
let mosi = io.pins.gpio23;
|
||||
let cs = io.pins.gpio22;
|
||||
|
||||
let mut spi = Spi::new(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks).with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
Some(miso),
|
||||
Some(cs),
|
||||
);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
let mut data = [0xde, 0xca, 0xfb, 0xad];
|
||||
spi.transfer(&mut data).unwrap();
|
||||
println!("{:x?}", data);
|
||||
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
//! SPI loopback test using DMA
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO19
|
||||
//! MISO GPIO25
|
||||
//! MOSI GPIO23
|
||||
//! CS GPIO22
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! This example transfers data via SPI.
|
||||
//! Connect MISO and MOSI pins to see the outgoing data is read as incoming
|
||||
//! data.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma_buffers,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{
|
||||
master::{prelude::*, Spi},
|
||||
SpiMode,
|
||||
},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio19;
|
||||
let miso = io.pins.gpio25;
|
||||
let mosi = io.pins.gpio23;
|
||||
let cs = io.pins.gpio22;
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.spi2channel;
|
||||
|
||||
let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(32000);
|
||||
|
||||
let mut spi = Spi::new(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks)
|
||||
.with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs))
|
||||
.with_dma(dma_channel.configure(
|
||||
false,
|
||||
&mut tx_descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
));
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
// DMA buffer require a static life-time
|
||||
let mut send = tx_buffer;
|
||||
let mut receive = rx_buffer;
|
||||
let mut i = 0;
|
||||
|
||||
for (i, v) in send.iter_mut().enumerate() {
|
||||
*v = (i % 255) as u8;
|
||||
}
|
||||
|
||||
loop {
|
||||
send[0] = i;
|
||||
send[send.len() - 1] = i;
|
||||
i = i.wrapping_add(1);
|
||||
|
||||
let transfer = spi.dma_transfer(send, receive).unwrap();
|
||||
// here we could do something else while DMA transfer is in progress
|
||||
let mut n = 0;
|
||||
// Check is_done until the transfer is almost done (32000 bytes at 100kHz is
|
||||
// 2.56 seconds), then move to wait().
|
||||
while !transfer.is_done() && n < 10 {
|
||||
delay.delay_ms(250u32);
|
||||
n += 1;
|
||||
}
|
||||
// the buffers and spi is moved into the transfer and we can get it back via
|
||||
// `wait`
|
||||
(receive, send, spi) = transfer.wait().unwrap();
|
||||
println!(
|
||||
"{:x?} .. {:x?}",
|
||||
&receive[..10],
|
||||
&receive[receive.len() - 10..]
|
||||
);
|
||||
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
@ -1,122 +0,0 @@
|
||||
//! This shows how to use the TIMG peripheral interrupts.
|
||||
//! There is TIMG0 and TIMG1 each of them containing two general purpose timers
|
||||
//! and a watchdog timer.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
interrupt::Priority,
|
||||
peripherals::{self, Peripherals, TIMG0, TIMG1},
|
||||
prelude::*,
|
||||
timer::{Timer, Timer0, Timer1, TimerGroup},
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static TIMER00: Mutex<RefCell<Option<Timer<Timer0<TIMG0>>>>> = Mutex::new(RefCell::new(None));
|
||||
static TIMER01: Mutex<RefCell<Option<Timer<Timer1<TIMG0>>>>> = Mutex::new(RefCell::new(None));
|
||||
static TIMER10: Mutex<RefCell<Option<Timer<Timer0<TIMG1>>>>> = Mutex::new(RefCell::new(None));
|
||||
static TIMER11: Mutex<RefCell<Option<Timer<Timer1<TIMG1>>>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer00 = timer_group0.timer0;
|
||||
let mut timer01 = timer_group0.timer1;
|
||||
|
||||
let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks);
|
||||
let mut timer10 = timer_group1.timer0;
|
||||
let mut timer11 = timer_group1.timer1;
|
||||
|
||||
interrupt::enable(peripherals::Interrupt::TG0_T0_LEVEL, Priority::Priority2).unwrap();
|
||||
interrupt::enable(peripherals::Interrupt::TG0_T1_LEVEL, Priority::Priority2).unwrap();
|
||||
interrupt::enable(peripherals::Interrupt::TG1_T0_LEVEL, Priority::Priority3).unwrap();
|
||||
interrupt::enable(peripherals::Interrupt::TG1_T1_LEVEL, Priority::Priority3).unwrap();
|
||||
|
||||
timer00.start(500u64.millis());
|
||||
timer00.listen();
|
||||
timer01.start(2500u64.millis());
|
||||
timer01.listen();
|
||||
timer10.start(1u64.secs());
|
||||
timer10.listen();
|
||||
timer11.start(3u64.secs());
|
||||
timer11.listen();
|
||||
|
||||
critical_section::with(|cs| {
|
||||
TIMER00.borrow_ref_mut(cs).replace(timer00);
|
||||
TIMER01.borrow_ref_mut(cs).replace(timer01);
|
||||
TIMER10.borrow_ref_mut(cs).replace(timer10);
|
||||
TIMER11.borrow_ref_mut(cs).replace(timer11);
|
||||
});
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn TG0_T0_LEVEL() {
|
||||
critical_section::with(|cs| {
|
||||
let mut timer = TIMER00.borrow_ref_mut(cs);
|
||||
let timer = timer.as_mut().unwrap();
|
||||
|
||||
if timer.is_interrupt_set() {
|
||||
timer.clear_interrupt();
|
||||
timer.start(500u64.millis());
|
||||
|
||||
esp_println::println!("Interrupt Level 2 - Timer0");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn TG0_T1_LEVEL() {
|
||||
critical_section::with(|cs| {
|
||||
let mut timer = TIMER01.borrow_ref_mut(cs);
|
||||
let timer = timer.as_mut().unwrap();
|
||||
|
||||
if timer.is_interrupt_set() {
|
||||
timer.clear_interrupt();
|
||||
timer.start(2500u64.millis());
|
||||
|
||||
esp_println::println!("Interrupt Level 2 - Timer1");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn TG1_T0_LEVEL() {
|
||||
critical_section::with(|cs| {
|
||||
let mut timer = TIMER10.borrow_ref_mut(cs);
|
||||
let timer = timer.as_mut().unwrap();
|
||||
|
||||
if timer.is_interrupt_set() {
|
||||
timer.clear_interrupt();
|
||||
timer.start(1u64.secs());
|
||||
|
||||
esp_println::println!("Interrupt Level 3 - Timer0");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn TG1_T1_LEVEL() {
|
||||
critical_section::with(|cs| {
|
||||
let mut timer = TIMER10.borrow_ref_mut(cs);
|
||||
let timer = timer.as_mut().unwrap();
|
||||
|
||||
if timer.is_interrupt_set() {
|
||||
timer.clear_interrupt();
|
||||
timer.start(3u64.secs());
|
||||
|
||||
esp_println::println!("Interrupt Level 3 - Timer1");
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
//! This demos the watchdog timer.
|
||||
//! Basically the same as `hello_world` but if you remove the call to
|
||||
//! `wdt.feed()` the watchdog will reset the system.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::TimerGroup};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
let mut wdt = timer_group0.wdt;
|
||||
|
||||
wdt.start(2u64.secs());
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
loop {
|
||||
wdt.feed();
|
||||
println!("Hello world!");
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "esp"
|
||||
components = ["rustfmt", "rustc-dev"]
|
||||
targets = ["xtensa-esp32-none-elf"]
|
||||
@ -1,9 +0,0 @@
|
||||
//! A bare-metal (`no_std`) Hardware Abstraction Layer for the ESP32 from
|
||||
//! Espressif.
|
||||
//!
|
||||
//! ## Feature Flags
|
||||
#![doc = document_features::document_features!()]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
#![no_std]
|
||||
|
||||
pub use esp_hal::*;
|
||||
@ -1,12 +0,0 @@
|
||||
[target.riscv32imc-unknown-none-elf]
|
||||
runner = "espflash flash --monitor"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlinkall.x",
|
||||
"-C", "force-frame-pointers",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "riscv32imc-unknown-none-elf"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core"]
|
||||
@ -1,143 +0,0 @@
|
||||
[package]
|
||||
name = "esp32c2-hal"
|
||||
version = "0.13.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
description = "HAL for ESP32-C2 microcontrollers"
|
||||
repository = "https://github.com/esp-rs/esp-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
keywords = [
|
||||
"embedded",
|
||||
"embedded-hal",
|
||||
"esp",
|
||||
"esp32c2",
|
||||
"no-std",
|
||||
]
|
||||
categories = [
|
||||
"embedded",
|
||||
"hardware-support",
|
||||
"no-std",
|
||||
]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["riscv32imc-unknown-none-elf"]
|
||||
|
||||
[dependencies]
|
||||
document-features = "0.2.7"
|
||||
esp-hal = { version = "0.15.0", features = ["esp32c2"], path = "../esp-hal" }
|
||||
embassy-time-driver = { version = "0.1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
critical-section = "1.1.2"
|
||||
crypto-bigint = { version = "0.5.5", default-features = false }
|
||||
elliptic-curve = { version = "0.13.8", default-features = false, features = ["sec1"] }
|
||||
embassy-executor = { version = "0.5.0", features = ["nightly"] }
|
||||
embassy-sync = "0.5.0"
|
||||
embassy-time = "0.3.0"
|
||||
embedded-graphics = "0.8.1"
|
||||
embedded-hal-1 = { version = "1.0.0", package = "embedded-hal" }
|
||||
embedded-hal-async = "1.0.0"
|
||||
embedded-io-async = "0.6.1"
|
||||
embedded-hal-bus = "0.1.0"
|
||||
esp-backtrace = { version = "0.10.0", features = ["esp32c2", "panic-handler", "exception-handler", "print-uart"] }
|
||||
esp-println = { version = "0.8.0", features = ["esp32c2"] }
|
||||
heapless = "0.8.0"
|
||||
hex-literal = "0.4.1"
|
||||
lis3dh-async = "0.9.1"
|
||||
p192 = { version = "0.13.0", default-features = false, features = ["arithmetic"] }
|
||||
p256 = { version = "0.13.2", default-features = false, features = ["arithmetic"] }
|
||||
sha2 = { version = "0.10.8", default-features = false}
|
||||
ssd1306 = "0.8.4"
|
||||
static_cell = { version = "2.0.0", features = ["nightly"] }
|
||||
|
||||
[features]
|
||||
default = ["embassy-integrated-timers", "rt", "vectored"]
|
||||
|
||||
## Enable debug features in the HAL (used for development).
|
||||
debug = ["esp-hal/debug"]
|
||||
## Enable direct interrupt vectoring.
|
||||
direct-vectoring = ["esp-hal/direct-vectoring"]
|
||||
## Enable interrupt preemption.
|
||||
interrupt-preemption = ["esp-hal/interrupt-preemption"]
|
||||
## Enable logging output using the `log` crate.
|
||||
log = ["esp-hal/log", "esp-println/log"]
|
||||
## Enable runtime support.
|
||||
rt = ["esp-hal/rt-riscv"]
|
||||
## Enable interrupt vectoring.
|
||||
vectored = ["esp-hal/vectored"]
|
||||
|
||||
#! ### Trait Implementation Feature Flags
|
||||
## Enable support for asynchronous operation, with interfaces provided by
|
||||
## `embedded-hal-async` and `embedded-io-async`.
|
||||
async = ["esp-hal/async"]
|
||||
## Implement `defmt::Format` on certain types.
|
||||
defmt = ["esp-hal/defmt", "esp-println/defmt-espflash"]
|
||||
## Implement the traits defined in the `1.0.0` releases of `embedded-hal` and
|
||||
## `embedded-hal-nb` for the relevant peripherals.
|
||||
eh1 = ["esp-hal/eh1"]
|
||||
## Implement the traits defined in `embedded-io` for certain peripherals.
|
||||
embedded-io = ["esp-hal/embedded-io"]
|
||||
## Implement the `ufmt_write::uWrite` trait for certain peripherals.
|
||||
ufmt = ["esp-hal/ufmt"]
|
||||
|
||||
#! ### Embassy Feature Flags
|
||||
## Enable support for `embassy`, a modern asynchronous embedded framework.
|
||||
embassy = ["esp-hal/embassy"]
|
||||
## Use the interrupt-mode embassy executor.
|
||||
embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"]
|
||||
## Use the thread-mode embassy executor.
|
||||
embassy-executor-thread = ["esp-hal/embassy-executor-thread"]
|
||||
## Uses hardware timers as alarms for the executors. Using this feature
|
||||
## limits the number of executors to the number of hardware alarms provided
|
||||
## by the time driver.
|
||||
embassy-integrated-timers = ["esp-hal/embassy-integrated-timers"]
|
||||
## Enable the embassy time driver using the `SYSTIMER` peripheral. The
|
||||
## `SYSTIMER` peripheral has three alarams available for use.
|
||||
embassy-time-systick = ["esp-hal/embassy-time-systick", "embassy-time-driver/tick-hz-16_000_000"]
|
||||
## Enable the embassy time driver using the `TIMG0` peripheral. The `TIMG0`
|
||||
## peripheral has two alarms available for use.
|
||||
embassy-time-timg0 = ["esp-hal/embassy-time-timg0", "embassy-time-driver/tick-hz-1_000_000"]
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
[[example]]
|
||||
name = "spi_eh1_loopback"
|
||||
required-features = ["eh1"]
|
||||
|
||||
[[example]]
|
||||
name = "spi_eh1_device_loopback"
|
||||
required-features = ["eh1"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_hello_world"
|
||||
required-features = ["embassy", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_multiprio"
|
||||
required-features = ["embassy", "embassy-executor-thread", "embassy-executor-interrupt"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_wait"
|
||||
required-features = ["embassy", "async", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_spi"
|
||||
required-features = ["embassy", "async", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "interrupt_preemption"
|
||||
required-features = ["interrupt-preemption"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_serial"
|
||||
required-features = ["embassy", "async", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "embassy_i2c"
|
||||
required-features = ["embassy", "async", "embassy-executor-thread"]
|
||||
|
||||
[[example]]
|
||||
name = "direct-vectoring"
|
||||
required-features = ["direct-vectoring"]
|
||||
@ -1,51 +0,0 @@
|
||||
# esp32c2-hal
|
||||
|
||||
[](https://crates.io/crates/esp32c2-hal)
|
||||
[](https://docs.rs/esp32c2-hal)
|
||||

|
||||
[](https://matrix.to/#/#esp-rs:matrix.org)
|
||||
|
||||
`no_std` HAL for the ESP32-C2 from Espressif.
|
||||
|
||||
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/esp32c2-hal/
|
||||
|
||||
## Resources
|
||||
|
||||
- [Datasheet](https://www.espressif.com/sites/default/files/documentation/esp8684_datasheet_en.pdf)
|
||||
- [Technical Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp8684_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.
|
||||
@ -1,16 +0,0 @@
|
||||
use std::{env, error::Error, path::PathBuf};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// 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());
|
||||
|
||||
// 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");
|
||||
|
||||
#[cfg(feature = "defmt")]
|
||||
println!("cargo:rustc-link-arg=-Tdefmt.x");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//! Connect a potentiometer to PIN2 and see the read values change when
|
||||
//! rotating the shaft. Alternatively you could also connect the PIN to GND or
|
||||
//! 3V3 to see the maximum and minimum raw values read.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{
|
||||
adc::{AdcConfig, Attenuation, ADC},
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
peripherals::{Peripherals, ADC1},
|
||||
prelude::*,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Create ADC instances
|
||||
let mut adc1_config = AdcConfig::new();
|
||||
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
||||
let mut adc1 = ADC::<ADC1>::new(peripherals.ADC1, adc1_config);
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
||||
println!("PIN2 ADC reading = {}", pin_value);
|
||||
delay.delay_ms(1500u32);
|
||||
}
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
//! This shows how to configure UART
|
||||
//! You can short the TX and RX pin and see it reads what was written.
|
||||
//! Additionally you can connect a logic analzyer to TX and see how the changes
|
||||
//! of the configuration change the output signal.
|
||||
//!
|
||||
//! The following wiring is assumed:
|
||||
//! - TX => GPIO1
|
||||
//! - RX => GPIO2
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
uart::{
|
||||
config::{Config, DataBits, Parity, StopBits},
|
||||
TxRxPins,
|
||||
},
|
||||
Uart,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
let config = Config {
|
||||
baudrate: 115200,
|
||||
data_bits: DataBits::DataBits8,
|
||||
parity: Parity::ParityNone,
|
||||
stop_bits: StopBits::STOP1,
|
||||
};
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let pins = TxRxPins::new_tx_rx(
|
||||
io.pins.gpio1.into_push_pull_output(),
|
||||
io.pins.gpio2.into_floating_input(),
|
||||
);
|
||||
|
||||
let mut serial1 = Uart::new_with_config(peripherals.UART1, config, Some(pins), &clocks);
|
||||
|
||||
timer0.start(250u64.millis());
|
||||
|
||||
println!("Start");
|
||||
loop {
|
||||
serial1.write(0x42).ok();
|
||||
let read = block!(serial1.read());
|
||||
|
||||
match read {
|
||||
Ok(read) => println!("Read 0x{:02x}", read),
|
||||
Err(err) => println!("Error {:?}", err),
|
||||
}
|
||||
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
//! Blinks an LED
|
||||
//!
|
||||
//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO5)
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{clock::ClockControl, gpio::IO, peripherals::Peripherals, prelude::*, Delay};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Set GPIO5 as an output, and set its state high initially.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio5.into_push_pull_output();
|
||||
|
||||
led.set_high().unwrap();
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
//! Blinks an LED
|
||||
//!
|
||||
//! This assumes that LEDs are connected to GPIO3, 4 and 5.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::{AnyPin, Input, Output, PullDown, PushPull, IO},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Set LED GPIOs as an output.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let led1 = io.pins.gpio3.into_push_pull_output();
|
||||
let led2 = io.pins.gpio4.into_push_pull_output();
|
||||
let led3 = io.pins.gpio5.into_push_pull_output();
|
||||
|
||||
// Set GPIO9 as an input.
|
||||
let button = io.pins.gpio9.into_pull_down_input().into();
|
||||
|
||||
// You can use `into` or `degrade`
|
||||
let mut pins = [led1.into(), led2.into(), led3.degrade().into()];
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
toggle_pins(&mut pins, &button);
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_pins(leds: &mut [AnyPin<Output<PushPull>>], button: &AnyPin<Input<PullDown>>) {
|
||||
for pin in leds.iter_mut() {
|
||||
pin.toggle().unwrap();
|
||||
}
|
||||
|
||||
if button.is_low().unwrap() {
|
||||
esp_println::println!("Button");
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
//! This demos a simple monitor for the XTAL frequency, by relying on a special
|
||||
//! feature of the TIMG0 (Timer Group 0). This feature counts the number of XTAL
|
||||
//! clock cycles within a given number of RTC_SLOW_CLK cycles.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
Rtc,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||
rtc.rwdt.start(2000u64.millis());
|
||||
rtc.rwdt.listen();
|
||||
|
||||
esp_println::println!(
|
||||
"{: <10} XTAL frequency: {} MHz",
|
||||
"[Expected]",
|
||||
clocks.xtal_clock.to_MHz()
|
||||
);
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::RTC_CORE,
|
||||
interrupt::Priority::Priority1,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
critical_section::with(|cs| {
|
||||
RTC.borrow_ref_mut(cs).replace(rtc);
|
||||
});
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn RTC_CORE() {
|
||||
critical_section::with(|cs| {
|
||||
let mut rtc = RTC.borrow(cs).borrow_mut();
|
||||
let rtc = rtc.as_mut().unwrap();
|
||||
|
||||
esp_println::println!(
|
||||
"{: <10} XTAL frequency: {} MHz",
|
||||
"[Monitor]",
|
||||
rtc.estimate_xtal_frequency()
|
||||
);
|
||||
|
||||
rtc.rwdt.clear_interrupt();
|
||||
});
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
//! This shows example usage of the CRC functions in ROM
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"Performing CRC calculations on test string \"{data}\""
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
let crc_hdlc = crc::crc32_le(!0xffffffff, data.as_ref());
|
||||
let crc_bzip2 = crc::crc32_be(!0xffffffff, data.as_ref());
|
||||
let crc_mpeg2 = !crc::crc32_be(!0xffffffff, data.as_ref());
|
||||
let crc_cksum = crc::crc32_be(!0, data.as_ref());
|
||||
let crc_kermit = !crc::crc16_le(!0, data.as_ref());
|
||||
let crc_genibus = crc::crc16_be(!0xffff, data.as_ref());
|
||||
let crc_rohc = !crc::crc8_le(!0xff, data.as_ref());
|
||||
let crc_smbus = !crc::crc8_be(!0, data.as_ref());
|
||||
|
||||
assert_eq!(crc_hdlc, 0xcbf43926);
|
||||
assert_eq!(crc_bzip2, 0xfc891918);
|
||||
assert_eq!(crc_mpeg2, 0x0376e6e7);
|
||||
assert_eq!(crc_cksum, 0x765e7680);
|
||||
assert_eq!(crc_kermit, 0x2189);
|
||||
assert_eq!(crc_genibus, 0xd64e);
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
//! This shows debug-assist
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32c2_hal::{
|
||||
assist_debug::DebugAssist,
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
static DA: Mutex<RefCell<Option<DebugAssist>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut da = DebugAssist::new(peripherals.ASSIST_DEBUG);
|
||||
|
||||
extern "C" {
|
||||
// top of stack
|
||||
static mut _stack_start: u32;
|
||||
// bottom of stack
|
||||
static mut _stack_end: u32;
|
||||
}
|
||||
|
||||
let stack_top = unsafe { &mut _stack_start } as *mut _ as u32;
|
||||
let stack_bottom = unsafe { &mut _stack_end } as *mut _ as u32;
|
||||
|
||||
da.enable_sp_monitor(stack_bottom + 4096, stack_top);
|
||||
|
||||
critical_section::with(|cs| DA.borrow_ref_mut(cs).replace(da));
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::ASSIST_DEBUG,
|
||||
interrupt::Priority::Priority3,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
eat_up_stack(0);
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[allow(unconditional_recursion)]
|
||||
fn eat_up_stack(v: u32) {
|
||||
println!("Iteration {v}");
|
||||
eat_up_stack(v + 1);
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn ASSIST_DEBUG() {
|
||||
critical_section::with(|cs| {
|
||||
println!("\n\nDEBUG_ASSIST interrupt");
|
||||
let mut da = DA.borrow_ref_mut(cs);
|
||||
let da = da.as_mut().unwrap();
|
||||
|
||||
if da.is_sp_monitor_interrupt_set() {
|
||||
println!("SP MONITOR TRIGGERED");
|
||||
da.clear_sp_monitor_interrupt();
|
||||
let pc = da.get_sp_monitor_pc();
|
||||
println!("PC = 0x{:x}", pc);
|
||||
}
|
||||
|
||||
loop {}
|
||||
});
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(naked_functions)]
|
||||
use core::{arch::asm, cell::RefCell};
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
system::{SoftwareInterrupt, SoftwareInterruptControl},
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static SWINT: Mutex<RefCell<Option<SoftwareInterruptControl>>> = Mutex::new(RefCell::new(None));
|
||||
#[entry]
|
||||
unsafe fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clockctrl = system.clock_control;
|
||||
let sw_int = system.software_interrupt_control;
|
||||
let _clocks = ClockControl::boot_defaults(clockctrl).freeze();
|
||||
|
||||
critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int));
|
||||
unsafe {
|
||||
asm!(
|
||||
"
|
||||
csrrwi x0, 0x7e0, 1 #what to count, for cycles write 1 for instructions write 2
|
||||
csrrwi x0, 0x7e1, 0 #disable counter
|
||||
csrrwi x0, 0x7e2, 0 #reset counter
|
||||
"
|
||||
);
|
||||
}
|
||||
esp_println::println!("MPC:{}", unsafe { fetch_performance_timer() });
|
||||
// interrupt is raised from assembly for max timer granularity.
|
||||
unsafe {
|
||||
asm!(
|
||||
"
|
||||
li t0, 0x600C0028 #FROM_CPU_INTR0 address
|
||||
li t1, 1 #Flip flag
|
||||
csrrwi x0, 0x7e1, 1 #enable timer
|
||||
sw t1, 0(t0) #trigger FROM_CPU_INTR0
|
||||
"
|
||||
)
|
||||
}
|
||||
esp_println::println!("Returned");
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
fn cpu_int_1_handler() {
|
||||
unsafe { asm!("csrrwi x0, 0x7e1, 0 #disable timer") }
|
||||
critical_section::with(|cs| {
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset(SoftwareInterrupt::SoftwareInterrupt0);
|
||||
});
|
||||
esp_println::println!("Performance counter:{}", unsafe {
|
||||
fetch_performance_timer()
|
||||
});
|
||||
}
|
||||
#[naked]
|
||||
unsafe extern "C" fn fetch_performance_timer() -> i32 {
|
||||
asm!(
|
||||
"
|
||||
csrr a0, 0x7e2
|
||||
jr ra
|
||||
",
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
@ -1,801 +0,0 @@
|
||||
//! Demonstrates the use of the ECC peripheral and compares the speed of
|
||||
//! hardware-accelerated and pure software ECC.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::ops::Mul;
|
||||
|
||||
use crypto_bigint::{
|
||||
modular::runtime_mod::{DynResidue, DynResidueParams},
|
||||
Encoding,
|
||||
U192,
|
||||
U256,
|
||||
};
|
||||
use elliptic_curve::sec1::ToEncodedPoint;
|
||||
use esp32c2_hal::{
|
||||
ecc::{Ecc, EllipticCurve, Error},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
systimer::SystemTimer,
|
||||
Rng,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::{print, println};
|
||||
use hex_literal::hex;
|
||||
|
||||
struct TestParams<'a> {
|
||||
prime_fields: &'a [&'a [u8]],
|
||||
nb_loop_mul: usize,
|
||||
nb_loop_inv: usize,
|
||||
}
|
||||
|
||||
const TEST_PARAMS_VECTOR: TestParams = TestParams {
|
||||
prime_fields: &[
|
||||
&hex!("fffffffffffffffffffffffffffffffeffffffffffffffff"),
|
||||
&hex!("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"),
|
||||
],
|
||||
nb_loop_mul: 10,
|
||||
nb_loop_inv: 20,
|
||||
};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let _system = peripherals.SYSTEM.split();
|
||||
|
||||
let mut rng = Rng::new(peripherals.RNG);
|
||||
|
||||
println!("ECC example");
|
||||
|
||||
let mut hw_ecc = Ecc::new(peripherals.ECC);
|
||||
|
||||
println!("Beginning stress tests...");
|
||||
test_affine_point_multiplication(&mut hw_ecc, &mut rng);
|
||||
test_finite_field_division(&mut hw_ecc, &mut rng);
|
||||
test_affine_point_verification(&mut hw_ecc, &mut rng);
|
||||
test_afine_point_verification_multiplication(&mut hw_ecc, &mut rng);
|
||||
test_jacobian_point_multiplication(&mut hw_ecc, &mut rng);
|
||||
test_jacobian_point_verification(&mut hw_ecc, &mut rng);
|
||||
test_afine_point_verification_jacobian_multiplication(&mut hw_ecc, &mut rng);
|
||||
println!("Finished stress tests!");
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn test_affine_point_multiplication(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning affine point multiplication tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("secp192r1..."),
|
||||
_ => print!("secp256r1..."),
|
||||
};
|
||||
let t1 = &mut [0_u8; 96];
|
||||
let (k, x) = t1.split_at_mut(prime_field.len());
|
||||
let (x, y) = x.split_at_mut(prime_field.len());
|
||||
let (y, _) = y.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul {
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let curve = match prime_field.len() {
|
||||
24 => {
|
||||
x.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P192
|
||||
}
|
||||
32 => {
|
||||
x.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P256
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
ecc.affine_point_multiplication(curve, k, x, y)
|
||||
.expect("Inputs data doesn't match the key length selected.");
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
|
||||
let t2 = &mut [0_u8; 64];
|
||||
|
||||
let (sw_x, sw_y) = t2.split_at_mut(prime_field.len());
|
||||
let (sw_y, _) = sw_y.split_at_mut(prime_field.len());
|
||||
|
||||
match prime_field.len() {
|
||||
24 => {
|
||||
let sw_k =
|
||||
p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p192::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
sw_x.copy_from_slice(q.x().unwrap().as_slice());
|
||||
sw_y.copy_from_slice(q.y().unwrap().as_slice());
|
||||
}
|
||||
32 => {
|
||||
let sw_k =
|
||||
p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p256::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
sw_x.copy_from_slice(q.x().unwrap().as_slice());
|
||||
sw_y.copy_from_slice(q.y().unwrap().as_slice());
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
for (a, b) in x.iter().zip(sw_x) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during affine point multiplication with d_a = {:02X?} ({:02X?} != {:02X?})",
|
||||
k, a, b,
|
||||
);
|
||||
}
|
||||
|
||||
for (a, b) in y.iter().zip(sw_y) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during affine point multiplication with d_a = {:02X?} ({:02X?} != {:02X?})",
|
||||
k, a, b,
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_finite_field_division(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning finite field division tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("P-192..."),
|
||||
32 => print!("P-256..."),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
let t1 = &mut [0_u8; 64];
|
||||
let (k, y) = t1.split_at_mut(prime_field.len());
|
||||
let (y, _) = y.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_inv {
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
rng.read(y).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0) || y.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b)
|
||||
|| y.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let t2 = &mut [0_u8; 96];
|
||||
let (sw_y, sw_k) = t2.split_at_mut(prime_field.len());
|
||||
let (sw_k, sw_res) = sw_k.split_at_mut(prime_field.len());
|
||||
let (sw_res, _) = sw_res.split_at_mut(prime_field.len());
|
||||
sw_y.copy_from_slice(y);
|
||||
sw_k.copy_from_slice(k);
|
||||
let curve = match prime_field.len() {
|
||||
24 => &EllipticCurve::P192,
|
||||
32 => &EllipticCurve::P256,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
ecc.finite_field_division(curve, k, y)
|
||||
.expect("Inputs data doesn't match the key length selected.");
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
|
||||
match prime_field.len() {
|
||||
24 => {
|
||||
let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field));
|
||||
let sw_y = DynResidue::new(&U192::from_be_slice(sw_y), modulus);
|
||||
let sw_k = DynResidue::new(&U192::from_be_slice(sw_k), modulus);
|
||||
let sw_inv_k = sw_k.invert().0;
|
||||
sw_res.copy_from_slice(sw_y.mul(&sw_inv_k).retrieve().to_be_bytes().as_slice());
|
||||
}
|
||||
32 => {
|
||||
let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field));
|
||||
let sw_y = DynResidue::new(&U256::from_be_slice(sw_y), modulus);
|
||||
let sw_k = DynResidue::new(&U256::from_be_slice(sw_k), modulus);
|
||||
let sw_inv_k = sw_k.invert().0;
|
||||
sw_res.copy_from_slice(sw_y.mul(&sw_inv_k).retrieve().to_be_bytes().as_slice());
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
for (a, b) in y.iter().zip(sw_res) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during finite field division with \np_y = {:02X?}\nk= {:02X?}",
|
||||
sw_y, sw_k,
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_inv as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_affine_point_verification(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning affine point verification tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("secp192r1..."),
|
||||
_ => print!("secp256r1..."),
|
||||
};
|
||||
let t1 = &mut [0_u8; 96];
|
||||
let (k, x) = t1.split_at_mut(prime_field.len());
|
||||
let (x, y) = x.split_at_mut(prime_field.len());
|
||||
let (y, _) = y.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul {
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let curve = match prime_field.len() {
|
||||
24 => {
|
||||
let sw_k =
|
||||
p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p192::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
x.copy_from_slice(q.x().unwrap().as_slice());
|
||||
y.copy_from_slice(q.y().unwrap().as_slice());
|
||||
&EllipticCurve::P192
|
||||
}
|
||||
32 => {
|
||||
let sw_k =
|
||||
p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p256::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
x.copy_from_slice(q.x().unwrap().as_slice());
|
||||
y.copy_from_slice(q.y().unwrap().as_slice());
|
||||
&EllipticCurve::P256
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
match ecc.affine_point_verification(&curve, x, y) {
|
||||
Err(Error::SizeMismatchCurve) => {
|
||||
assert!(false, "Inputs data doesn't match the key length selected.")
|
||||
}
|
||||
Err(Error::PointNotOnSelectedCurve) => assert!(
|
||||
false,
|
||||
"ECC failed while affine point verification with x = {:02X?} and y = {:02X?}.",
|
||||
x, y,
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_afine_point_verification_multiplication(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning affine point verification + multiplication tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("secp192r1..."),
|
||||
_ => print!("secp256r1..."),
|
||||
};
|
||||
let t1 = &mut [0_u8; 96];
|
||||
let (k, x) = t1.split_at_mut(prime_field.len());
|
||||
let (x, y) = x.split_at_mut(prime_field.len());
|
||||
let (y, _) = y.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul {
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let curve = match prime_field.len() {
|
||||
24 => {
|
||||
x.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P192
|
||||
}
|
||||
32 => {
|
||||
x.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P256
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
match ecc.affine_point_verification_multiplication(curve, k, x, y) {
|
||||
Err(Error::SizeMismatchCurve) => assert!(false, "Inputs data doesn't match the key length selected."),
|
||||
Err(Error::PointNotOnSelectedCurve) => assert!(
|
||||
false, "ECC failed while affine point verification + multiplication with x = {:02X?} and y = {:02X?}.",
|
||||
x, y,
|
||||
),
|
||||
_ => {},
|
||||
}
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
|
||||
let t2 = &mut [0_u8; 64];
|
||||
|
||||
let (sw_x, sw_y) = t2.split_at_mut(prime_field.len());
|
||||
let (sw_y, _) = sw_y.split_at_mut(prime_field.len());
|
||||
|
||||
match prime_field.len() {
|
||||
24 => {
|
||||
let sw_k =
|
||||
p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p192::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
sw_x.copy_from_slice(q.x().unwrap().as_slice());
|
||||
sw_y.copy_from_slice(q.y().unwrap().as_slice());
|
||||
}
|
||||
32 => {
|
||||
let sw_k =
|
||||
p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p256::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
sw_x.copy_from_slice(q.x().unwrap().as_slice());
|
||||
sw_y.copy_from_slice(q.y().unwrap().as_slice());
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
for (a, b) in x.iter().zip(sw_x) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during affine point verification + multiplication with d_a = {:02X?} ({:02X?} != {:02X?})",
|
||||
k, a, b,
|
||||
);
|
||||
}
|
||||
|
||||
for (a, b) in y.iter().zip(sw_y) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during affine point verification + multiplication with d_a = {:02X?} ({:02X?} != {:02X?})",
|
||||
k, a, b,
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_jacobian_point_multiplication(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning jacobian point multiplication tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("secp192r1..."),
|
||||
_ => print!("secp256r1..."),
|
||||
};
|
||||
let t1 = &mut [0_u8; 96];
|
||||
let (k, x) = t1.split_at_mut(prime_field.len());
|
||||
let (x, y) = x.split_at_mut(prime_field.len());
|
||||
let (y, _) = y.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul {
|
||||
let t2 = &mut [0_u8; 96];
|
||||
|
||||
let (sw_x, sw_y) = t2.split_at_mut(prime_field.len());
|
||||
let (sw_y, sw_k) = sw_y.split_at_mut(prime_field.len());
|
||||
let (sw_k, _) = sw_k.split_at_mut(prime_field.len());
|
||||
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sw_k.copy_from_slice(k);
|
||||
let curve = match prime_field.len() {
|
||||
24 => {
|
||||
x.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P192
|
||||
}
|
||||
32 => {
|
||||
x.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P256
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
ecc.jacobian_point_multiplication(curve, k, x, y)
|
||||
.expect("Inputs data doesn't match the key length selected.");
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
|
||||
match prime_field.len() {
|
||||
24 => {
|
||||
let sw_k = p192::Scalar::from(
|
||||
elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(),
|
||||
);
|
||||
let q = p192::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field));
|
||||
let x_affine =
|
||||
DynResidue::new(&U192::from_be_slice(q.x().unwrap().as_slice()), modulus);
|
||||
let y_affine =
|
||||
DynResidue::new(&U192::from_be_slice(q.y().unwrap().as_slice()), modulus);
|
||||
let z = DynResidue::new(&U192::from_be_slice(k), modulus);
|
||||
let x_jacobian = x_affine * z * z;
|
||||
let y_jacobian = y_affine * z * z * z;
|
||||
sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
}
|
||||
32 => {
|
||||
let sw_k = p256::Scalar::from(
|
||||
elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(),
|
||||
);
|
||||
let q = p256::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field));
|
||||
let x_affine =
|
||||
DynResidue::new(&U256::from_be_slice(q.x().unwrap().as_slice()), modulus);
|
||||
let y_affine =
|
||||
DynResidue::new(&U256::from_be_slice(q.y().unwrap().as_slice()), modulus);
|
||||
let z = DynResidue::new(&U256::from_be_slice(k), modulus);
|
||||
let x_jacobian = x_affine * z * z;
|
||||
let y_jacobian = y_affine * z * z * z;
|
||||
sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
for (a, b) in x.iter().zip(sw_x.iter()) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during jacobian point multiplication.\nX = {:02X?}\nX = {:02X?}",
|
||||
x, sw_x,
|
||||
);
|
||||
}
|
||||
|
||||
for (a, b) in y.iter().zip(sw_y.iter()) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during jacobian point multiplication.\nY = {:02X?}\nY = {:02X?}",
|
||||
y, sw_y,
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_jacobian_point_verification(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning jacobian point verification tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("secp192r1..."),
|
||||
_ => print!("secp256r1..."),
|
||||
};
|
||||
let t1 = &mut [0_u8; 128];
|
||||
let (k, x) = t1.split_at_mut(prime_field.len());
|
||||
let (x, y) = x.split_at_mut(prime_field.len());
|
||||
let (y, z) = y.split_at_mut(prime_field.len());
|
||||
let (z, _) = z.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul {
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
rng.read(z).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0) || z.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b)
|
||||
|| z.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let curve = match prime_field.len() {
|
||||
24 => {
|
||||
let sw_k =
|
||||
p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p192::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field));
|
||||
let x_affine =
|
||||
DynResidue::new(&U192::from_be_slice(q.x().unwrap().as_slice()), modulus);
|
||||
let y_affine =
|
||||
DynResidue::new(&U192::from_be_slice(q.y().unwrap().as_slice()), modulus);
|
||||
let z = DynResidue::new(&U192::from_be_slice(z), modulus);
|
||||
let x_jacobian = x_affine * z * z;
|
||||
let y_jacobian = y_affine * z * z * z;
|
||||
x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
&EllipticCurve::P192
|
||||
}
|
||||
32 => {
|
||||
let sw_k =
|
||||
p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap());
|
||||
let q = p256::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field));
|
||||
let x_affine =
|
||||
DynResidue::new(&U256::from_be_slice(q.x().unwrap().as_slice()), modulus);
|
||||
let y_affine =
|
||||
DynResidue::new(&U256::from_be_slice(q.y().unwrap().as_slice()), modulus);
|
||||
let z = DynResidue::new(&U256::from_be_slice(z), modulus);
|
||||
let x_jacobian = x_affine * z * z;
|
||||
let y_jacobian = y_affine * z * z * z;
|
||||
x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
&EllipticCurve::P256
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
match ecc.jacobian_point_verification(&curve, x, y, z) {
|
||||
Err(Error::SizeMismatchCurve) => {
|
||||
assert!(false, "Inputs data doesn't match the key length selected.")
|
||||
}
|
||||
Err(Error::PointNotOnSelectedCurve) => assert!(
|
||||
false,
|
||||
"ECC failed while base point verification with x = {:02X?} and y = {:02X?}.",
|
||||
x, y,
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_afine_point_verification_jacobian_multiplication(ecc: &mut Ecc, rng: &mut Rng) {
|
||||
for &prime_field in TEST_PARAMS_VECTOR.prime_fields {
|
||||
print!("Beginning affine point verification + jacobian point multiplication tests over ");
|
||||
match prime_field.len() {
|
||||
24 => print!("secp192r1..."),
|
||||
_ => print!("secp256r1..."),
|
||||
};
|
||||
let t1 = &mut [0_u8; 96];
|
||||
let (k, x) = t1.split_at_mut(prime_field.len());
|
||||
let (x, y) = x.split_at_mut(prime_field.len());
|
||||
let (y, _) = y.split_at_mut(prime_field.len());
|
||||
let mut delta_time = 0;
|
||||
for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul {
|
||||
let t2 = &mut [0_u8; 96];
|
||||
|
||||
let (sw_x, sw_y) = t2.split_at_mut(prime_field.len());
|
||||
let (sw_y, sw_k) = sw_y.split_at_mut(prime_field.len());
|
||||
let (sw_k, _) = sw_k.split_at_mut(prime_field.len());
|
||||
|
||||
loop {
|
||||
rng.read(k).unwrap();
|
||||
let is_zero = k.iter().all(|&elt| elt == 0);
|
||||
let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b);
|
||||
if is_zero == false && is_modulus == false {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sw_k.copy_from_slice(k);
|
||||
let curve = match prime_field.len() {
|
||||
24 => {
|
||||
x.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p192::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P192
|
||||
}
|
||||
32 => {
|
||||
x.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.x()
|
||||
.unwrap(),
|
||||
);
|
||||
y.copy_from_slice(
|
||||
p256::AffinePoint::GENERATOR
|
||||
.to_encoded_point(false)
|
||||
.y()
|
||||
.unwrap(),
|
||||
);
|
||||
&EllipticCurve::P256
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
let begin_time = SystemTimer::now();
|
||||
match ecc.affine_point_verification_jacobian_multiplication(curve, k, x, y) {
|
||||
Err(Error::SizeMismatchCurve) => assert!(false, "Inputs data doesn't match the key length selected."),
|
||||
Err(Error::PointNotOnSelectedCurve) => assert!(
|
||||
false, "ECC failed while affine point verification + multiplication with x = {:02X?} and y = {:02X?}.",
|
||||
x, y,
|
||||
),
|
||||
_ => {},
|
||||
}
|
||||
let end_time = SystemTimer::now();
|
||||
delta_time += end_time - begin_time;
|
||||
|
||||
match prime_field.len() {
|
||||
24 => {
|
||||
let sw_k = p192::Scalar::from(
|
||||
elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(),
|
||||
);
|
||||
let q = p192::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field));
|
||||
let x_affine =
|
||||
DynResidue::new(&U192::from_be_slice(q.x().unwrap().as_slice()), modulus);
|
||||
let y_affine =
|
||||
DynResidue::new(&U192::from_be_slice(q.y().unwrap().as_slice()), modulus);
|
||||
let z = DynResidue::new(&U192::from_be_slice(k), modulus);
|
||||
let x_jacobian = x_affine * z * z;
|
||||
let y_jacobian = y_affine * z * z * z;
|
||||
sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
}
|
||||
32 => {
|
||||
let sw_k = p256::Scalar::from(
|
||||
elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(),
|
||||
);
|
||||
let q = p256::AffinePoint::GENERATOR
|
||||
.mul(sw_k)
|
||||
.to_affine()
|
||||
.to_encoded_point(false);
|
||||
let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field));
|
||||
let x_affine =
|
||||
DynResidue::new(&U256::from_be_slice(q.x().unwrap().as_slice()), modulus);
|
||||
let y_affine =
|
||||
DynResidue::new(&U256::from_be_slice(q.y().unwrap().as_slice()), modulus);
|
||||
let z = DynResidue::new(&U256::from_be_slice(k), modulus);
|
||||
let x_jacobian = x_affine * z * z;
|
||||
let y_jacobian = y_affine * z * z * z;
|
||||
sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice());
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
for (a, b) in x.iter().zip(sw_x.iter()) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during affine point verification + jacobian point multiplication.\nX = {:02X?}\nX = {:02X?}",
|
||||
x, sw_x,
|
||||
);
|
||||
}
|
||||
|
||||
for (a, b) in y.iter().zip(sw_y.iter()) {
|
||||
assert_eq!(
|
||||
a, b,
|
||||
"ECC failed during affine point verification + jacobian point multiplication.\nY = {:02X?}\nY = {:02X?}",
|
||||
y, sw_y,
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"ok (it took {} cycles in average)",
|
||||
delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
//! embassy hello world
|
||||
//!
|
||||
//! This is an example of running the embassy executor with multiple tasks
|
||||
//! concurrently.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp32c2_hal::{clock::ClockControl, embassy, peripherals::Peripherals, prelude::*};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run() {
|
||||
loop {
|
||||
esp_println::println!("Hello world from embassy using esp-hal-async!");
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[main]
|
||||
async fn main(spawner: Spawner) {
|
||||
esp_println::println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-systick")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
);
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks),
|
||||
);
|
||||
|
||||
spawner.spawn(run()).ok();
|
||||
|
||||
loop {
|
||||
esp_println::println!("Bing!");
|
||||
Timer::after(Duration::from_millis(5_000)).await;
|
||||
}
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
//! Embassy I2C
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SDA GPIO1
|
||||
//! SCL GPIO2
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! This is an example of running the embassy executor with IC2. It uses an
|
||||
//! LIS3DH to get accelerometer data.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
i2c::I2C,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use lis3dh_async::{Lis3dh, Range, SlaveAddr};
|
||||
|
||||
#[main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-systick")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
);
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks),
|
||||
);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
let i2c0 = I2C::new(
|
||||
peripherals.I2C0,
|
||||
io.pins.gpio1,
|
||||
io.pins.gpio2,
|
||||
400u32.kHz(),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
let mut lis3dh = Lis3dh::new_i2c(i2c0, SlaveAddr::Alternate).await.unwrap();
|
||||
lis3dh.set_range(Range::G8).await.unwrap();
|
||||
|
||||
loop {
|
||||
let norm = lis3dh.accel_norm().await.unwrap();
|
||||
esp_println::println!("X: {:+.5} Y: {:+.5} Z: {:+.5}", norm.x, norm.y, norm.z);
|
||||
|
||||
Timer::after(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
//! This example shows how to use the interrupt executors to prioritize some
|
||||
//! tasks over others.
|
||||
//!
|
||||
//! The example creates three tasks:
|
||||
//! - A low priority task that is not actually async, but simulates some
|
||||
//! blocking work. This task will run for 5 seconds, then sleep for 5
|
||||
//! seconds.
|
||||
//! - A low priority task that is actually async, but will not be able to run
|
||||
//! while the blocking task is running.
|
||||
//! - A high priority task that prints something every second. The example
|
||||
//! demonstrates that this task will continue to run even while the low
|
||||
//! priority blocking task is running.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Instant, Ticker, Timer};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy::{
|
||||
self,
|
||||
executor::{FromCpu1, InterruptExecutor},
|
||||
},
|
||||
interrupt::Priority,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
static INT_EXECUTOR_0: InterruptExecutor<FromCpu1> = InterruptExecutor::new();
|
||||
|
||||
#[interrupt]
|
||||
fn FROM_CPU_INTR1() {
|
||||
unsafe { INT_EXECUTOR_0.on_interrupt() }
|
||||
}
|
||||
|
||||
/// Periodically print something.
|
||||
#[embassy_executor::task]
|
||||
async fn high_prio() {
|
||||
println!("Starting high_prio()");
|
||||
let mut ticker = Ticker::every(Duration::from_secs(1));
|
||||
loop {
|
||||
println!("High priority ticks");
|
||||
ticker.next().await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Simulates some blocking (badly behaving) task.
|
||||
#[embassy_executor::task]
|
||||
async fn low_prio_blocking() {
|
||||
println!("Starting low-priority task that isn't actually async");
|
||||
loop {
|
||||
println!("Doing some long and complicated calculation");
|
||||
let start = Instant::now();
|
||||
while start.elapsed() < Duration::from_secs(5) {}
|
||||
println!("Calculation finished");
|
||||
Timer::after(Duration::from_secs(5)).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// A well-behaved, but starved async task.
|
||||
#[embassy_executor::task]
|
||||
async fn low_prio_async() {
|
||||
println!("Starting low-priority task that will not be able to run while the blocking task is running");
|
||||
let mut ticker = Ticker::every(Duration::from_secs(1));
|
||||
loop {
|
||||
println!("Low priority ticks");
|
||||
ticker.next().await;
|
||||
}
|
||||
}
|
||||
|
||||
#[main]
|
||||
async fn main(low_prio_spawner: Spawner) {
|
||||
println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-systick")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
);
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
{
|
||||
let timer_group0 = esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
}
|
||||
|
||||
let spawner = INT_EXECUTOR_0.start(Priority::Priority2);
|
||||
spawner.must_spawn(high_prio());
|
||||
|
||||
println!("Spawning low-priority tasks");
|
||||
low_prio_spawner.must_spawn(low_prio_async());
|
||||
low_prio_spawner.must_spawn(low_prio_blocking());
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
peripherals::{Peripherals, UART0},
|
||||
prelude::*,
|
||||
uart::{config::AtCmdConfig, UartRx, UartTx},
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use static_cell::make_static;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 64;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn writer(mut tx: UartTx<'static, UART0>, signal: &'static Signal<NoopRawMutex, usize>) {
|
||||
use core::fmt::Write;
|
||||
embedded_io_async::Write::write(
|
||||
&mut tx,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_io_async::Write::flush(&mut tx).await.unwrap();
|
||||
loop {
|
||||
let bytes_read = signal.wait().await;
|
||||
signal.reset();
|
||||
write!(&mut tx, "\r\n-- received {} bytes --\r\n", bytes_read).unwrap();
|
||||
embedded_io_async::Write::flush(&mut tx).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn reader(mut rx: UartRx<'static, UART0>, signal: &'static Signal<NoopRawMutex, usize>) {
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
|
||||
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
let r = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await;
|
||||
match r {
|
||||
Ok(len) => {
|
||||
offset += len;
|
||||
esp_println::println!("Read: {len}, data: {:?}", &rbuf[..offset]);
|
||||
offset = 0;
|
||||
signal.signal(len);
|
||||
}
|
||||
Err(e) => esp_println::println!("RX Error: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[main]
|
||||
async fn main(spawner: Spawner) {
|
||||
esp_println::println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-systick")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
);
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
{
|
||||
let timer_group0 = esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
embassy::init(&clocks, timer_group0);
|
||||
}
|
||||
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0
|
||||
.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16)
|
||||
.unwrap();
|
||||
let (tx, rx) = uart0.split();
|
||||
|
||||
let signal = &*make_static!(Signal::new());
|
||||
|
||||
spawner.spawn(reader(rx, &signal)).ok();
|
||||
spawner.spawn(writer(tx, &signal)).ok();
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
//! Embassy SPI
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO6
|
||||
//! MISO GPIO2
|
||||
//! MOSI GPIO7
|
||||
//! CS GPIO10
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! Connect MISO and MOSI pins to see the outgoing data is read as incoming
|
||||
//! data.
|
||||
//!
|
||||
//! This is an example of running the embassy executor with SPI.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{DmaPriority, *},
|
||||
dma_descriptors,
|
||||
embassy,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{
|
||||
master::{prelude::*, Spi},
|
||||
SpiMode,
|
||||
},
|
||||
IO,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
esp_println::println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-systick")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
);
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks),
|
||||
);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio6;
|
||||
let miso = io.pins.gpio2;
|
||||
let mosi = io.pins.gpio7;
|
||||
let cs = io.pins.gpio10;
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.channel0;
|
||||
|
||||
let (mut descriptors, mut rx_descriptors) = dma_descriptors!(32000);
|
||||
|
||||
let mut spi = Spi::new(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks)
|
||||
.with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs))
|
||||
.with_dma(dma_channel.configure(
|
||||
false,
|
||||
&mut descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
));
|
||||
|
||||
let send_buffer = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
loop {
|
||||
let mut buffer = [0; 8];
|
||||
esp_println::println!("Sending bytes");
|
||||
embedded_hal_async::spi::SpiBus::transfer(&mut spi, &mut buffer, &send_buffer)
|
||||
.await
|
||||
.unwrap();
|
||||
esp_println::println!("Bytes recieved: {:?}", buffer);
|
||||
Timer::after(Duration::from_millis(5_000)).await;
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
//! embassy wait
|
||||
//!
|
||||
//! This is an example of asynchronously `Wait`ing for a pin state to change.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_hal_async::digital::Wait;
|
||||
use esp32c2_hal::{clock::ClockControl, embassy, peripherals::Peripherals, prelude::*, IO};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
esp_println::println!("Init!");
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
#[cfg(feature = "embassy-time-systick")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
|
||||
);
|
||||
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(
|
||||
&clocks,
|
||||
esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks),
|
||||
);
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
// GPIO 9 as input
|
||||
let mut input = io.pins.gpio9.into_pull_down_input();
|
||||
|
||||
loop {
|
||||
esp_println::println!("Waiting...");
|
||||
input.wait_for_rising_edge().await.unwrap();
|
||||
esp_println::println!("Ping!");
|
||||
Timer::after(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
//! GPIO interrupt
|
||||
//!
|
||||
//! This prints "Interrupt" when the boot button is pressed.
|
||||
//! It also blinks an LED like the blinky example.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::{Event, Gpio9, Input, PullDown, IO},
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static BUTTON: Mutex<RefCell<Option<Gpio9<Input<PullDown>>>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Set GPIO5 as an output
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio5.into_push_pull_output();
|
||||
|
||||
// Set GPIO9 as an input
|
||||
let mut button = io.pins.gpio9.into_pull_down_input();
|
||||
button.listen(Event::FallingEdge);
|
||||
|
||||
critical_section::with(|cs| BUTTON.borrow_ref_mut(cs).replace(button));
|
||||
|
||||
interrupt::enable(peripherals::Interrupt::GPIO, interrupt::Priority::Priority3).unwrap();
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn GPIO() {
|
||||
critical_section::with(|cs| {
|
||||
esp_println::println!("GPIO interrupt");
|
||||
BUTTON
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.clear_interrupt();
|
||||
});
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
//! This shows how to write text to uart0.
|
||||
//! You can see the output with `espflash` if you provide the `--monitor` option
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
loop {
|
||||
writeln!(uart0, "Hello world!").unwrap();
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
//! Read calibration data from BMP180 sensor
|
||||
//!
|
||||
//! This example dumps the calibration data from a BMP180 sensor
|
||||
//!
|
||||
//! The following wiring is assumed:
|
||||
//! - SDA => GPIO1
|
||||
//! - SCL => GPIO2
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{clock::ClockControl, gpio::IO, i2c::I2C, peripherals::Peripherals, prelude::*};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Create a new peripheral object with the described wiring
|
||||
// and standard I2C clock speed
|
||||
let mut i2c = I2C::new(
|
||||
peripherals.I2C0,
|
||||
io.pins.gpio1,
|
||||
io.pins.gpio2,
|
||||
100u32.kHz(),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
loop {
|
||||
let mut data = [0u8; 22];
|
||||
i2c.write_read(0x77, &[0xaa], &mut data).ok();
|
||||
|
||||
println!("{:02x?}", data);
|
||||
}
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
//! I2C Display example
|
||||
//!
|
||||
//! This example prints some text on an SSD1306-based
|
||||
//! display (via I2C)
|
||||
//!
|
||||
//! The following wiring is assumed:
|
||||
//! - SDA => GPIO1
|
||||
//! - SCL => GPIO2
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use embedded_graphics::{
|
||||
mono_font::{
|
||||
ascii::{FONT_6X10, FONT_9X18_BOLD},
|
||||
MonoTextStyleBuilder,
|
||||
},
|
||||
pixelcolor::BinaryColor,
|
||||
prelude::*,
|
||||
text::{Alignment, Text},
|
||||
};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
i2c::I2C,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
|
||||
// Create a new peripheral object with the described wiring
|
||||
// and standard I2C clock speed
|
||||
let i2c = I2C::new(
|
||||
peripherals.I2C0,
|
||||
io.pins.gpio1,
|
||||
io.pins.gpio2,
|
||||
100u32.kHz(),
|
||||
&clocks,
|
||||
);
|
||||
|
||||
// Start timer (5 second interval)
|
||||
timer0.start(5u64.secs());
|
||||
|
||||
// Initialize display
|
||||
let interface = I2CDisplayInterface::new(i2c);
|
||||
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
|
||||
.into_buffered_graphics_mode();
|
||||
display.init().unwrap();
|
||||
|
||||
// Specify different text styles
|
||||
let text_style = MonoTextStyleBuilder::new()
|
||||
.font(&FONT_6X10)
|
||||
.text_color(BinaryColor::On)
|
||||
.build();
|
||||
let text_style_big = MonoTextStyleBuilder::new()
|
||||
.font(&FONT_9X18_BOLD)
|
||||
.text_color(BinaryColor::On)
|
||||
.build();
|
||||
|
||||
loop {
|
||||
// Fill display bufffer with a centered text with two lines (and two text
|
||||
// styles)
|
||||
Text::with_alignment(
|
||||
"esp-hal",
|
||||
display.bounding_box().center() + Point::new(0, 0),
|
||||
text_style_big,
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
Text::with_alignment(
|
||||
"Chip: ESP32-C2",
|
||||
display.bounding_box().center() + Point::new(0, 14),
|
||||
text_style,
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
// Write buffer to display
|
||||
display.flush().unwrap();
|
||||
// Clear display buffer
|
||||
display.clear(BinaryColor::Off).unwrap();
|
||||
|
||||
// Wait 5 seconds
|
||||
block!(timer0.wait()).unwrap();
|
||||
|
||||
// Write single-line centered text "Hello World" to buffer
|
||||
Text::with_alignment(
|
||||
"Hello World!",
|
||||
display.bounding_box().center(),
|
||||
text_style_big,
|
||||
Alignment::Center,
|
||||
)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
// Write buffer to display
|
||||
display.flush().unwrap();
|
||||
// Clear display buffer
|
||||
display.clear(BinaryColor::Off).unwrap();
|
||||
|
||||
// Wait 5 seconds
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,132 +0,0 @@
|
||||
//! Interrupt Preemption
|
||||
//!
|
||||
//! An example of how an interrupt can be preempted by another with higher
|
||||
//! priority. Should show higher-numbered software interrupts happening during
|
||||
//! the handling of lower-numbered ones.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt::{self},
|
||||
peripherals::{self, Peripherals},
|
||||
prelude::*,
|
||||
riscv,
|
||||
system::{SoftwareInterrupt, SoftwareInterruptControl},
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
static SWINT: Mutex<RefCell<Option<SoftwareInterruptControl>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clockctrl = system.clock_control;
|
||||
let sw_int = system.software_interrupt_control;
|
||||
let _clocks = ClockControl::boot_defaults(clockctrl).freeze();
|
||||
|
||||
critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int));
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::FROM_CPU_INTR0,
|
||||
interrupt::Priority::Priority1,
|
||||
)
|
||||
.unwrap();
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::FROM_CPU_INTR1,
|
||||
interrupt::Priority::Priority2,
|
||||
)
|
||||
.unwrap();
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::FROM_CPU_INTR2,
|
||||
interrupt::Priority::Priority2,
|
||||
)
|
||||
.unwrap();
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::FROM_CPU_INTR3,
|
||||
interrupt::Priority::Priority15,
|
||||
)
|
||||
.unwrap();
|
||||
unsafe { riscv::interrupt::enable() }
|
||||
|
||||
// raise mid priority interrupt.
|
||||
// The handler raises one interrupt at lower priority, one at same and one at
|
||||
// higher. We expect to see the higher priority served immeiately before
|
||||
// exiting the handler Once the handler is exited we expect to see same
|
||||
// priority and low priority interrupts served in that order
|
||||
critical_section::with(|cs| {
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.raise(SoftwareInterrupt::SoftwareInterrupt1);
|
||||
});
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn FROM_CPU_INTR0() {
|
||||
esp_println::println!("SW interrupt0");
|
||||
critical_section::with(|cs| {
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset(SoftwareInterrupt::SoftwareInterrupt0);
|
||||
});
|
||||
}
|
||||
#[interrupt]
|
||||
fn FROM_CPU_INTR1() {
|
||||
esp_println::println!("SW interrupt1 entry");
|
||||
critical_section::with(|cs| {
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset(SoftwareInterrupt::SoftwareInterrupt1);
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.raise(SoftwareInterrupt::SoftwareInterrupt2); // raise interrupt at same priority
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.raise(SoftwareInterrupt::SoftwareInterrupt3); // raise interrupt at higher priority
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.raise(SoftwareInterrupt::SoftwareInterrupt0); // raise interrupt at
|
||||
// lower priority
|
||||
});
|
||||
esp_println::println!("SW interrupt1 exit");
|
||||
}
|
||||
#[interrupt]
|
||||
fn FROM_CPU_INTR2() {
|
||||
esp_println::println!("SW interrupt2");
|
||||
critical_section::with(|cs| {
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset(SoftwareInterrupt::SoftwareInterrupt2);
|
||||
});
|
||||
}
|
||||
#[interrupt]
|
||||
fn FROM_CPU_INTR3() {
|
||||
esp_println::println!("SW interrupt3");
|
||||
critical_section::with(|cs| {
|
||||
SWINT
|
||||
.borrow_ref_mut(cs)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset(SoftwareInterrupt::SoftwareInterrupt3);
|
||||
});
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
//! Turns on LED with the option to change LED intensity depending on `duty`
|
||||
//! value, then fades it. Possible starting values (`u32`) are in range 0..100.
|
||||
//!
|
||||
//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO4)
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
gpio::IO,
|
||||
ledc::{
|
||||
channel::{self, ChannelIFace},
|
||||
timer::{self, TimerIFace},
|
||||
LSGlobalClkSource,
|
||||
LowSpeed,
|
||||
LEDC,
|
||||
},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let led = io.pins.gpio4.into_push_pull_output();
|
||||
|
||||
let mut ledc = LEDC::new(peripherals.LEDC, &clocks);
|
||||
ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);
|
||||
let mut lstimer0 = ledc.get_timer::<LowSpeed>(timer::Number::Timer2);
|
||||
|
||||
lstimer0
|
||||
.configure(timer::config::Config {
|
||||
duty: timer::config::Duty::Duty5Bit,
|
||||
clock_source: timer::LSClockSource::APBClk,
|
||||
frequency: 24u32.kHz(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut channel0 = ledc.get_channel(channel::Number::Channel0, led);
|
||||
channel0
|
||||
.configure(channel::config::Config {
|
||||
timer: &lstimer0,
|
||||
duty_pct: 10,
|
||||
pin_config: channel::config::PinConfig::PushPull,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
channel0.start_duty_fade(0, 100, 2000).expect_err(
|
||||
"Fading from 0% to 100%, at 24kHz and 5-bit resolution, over 2 seconds, should fail",
|
||||
);
|
||||
|
||||
loop {
|
||||
// Set up a breathing LED: fade from off to on over a second, then
|
||||
// from on back off over the next second. Then loop.
|
||||
channel0.start_duty_fade(0, 100, 1000).unwrap();
|
||||
while channel0.is_duty_fade_running() {}
|
||||
channel0.start_duty_fade(100, 0, 1000).unwrap();
|
||||
while channel0.is_duty_fade_running() {}
|
||||
}
|
||||
}
|
||||
@ -1,167 +0,0 @@
|
||||
//! SPI write and read a flash chip
|
||||
//!
|
||||
//! Folowing pins are used:
|
||||
//! SCLK GPIO4
|
||||
//! MISOI/IO0 GPIO5
|
||||
//! MOSI/IO1 GPIO6
|
||||
//! IO2 GPIO7
|
||||
//! IO3 GPIO8
|
||||
//! CS GPIO9
|
||||
//!
|
||||
//! Depending on your target and the board you are using you have to change the
|
||||
//! pins.
|
||||
//!
|
||||
//! Connect a flash chip (GD25Q64C was used) and make sure QE in the status
|
||||
//! register is set.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma_buffers,
|
||||
gpio::IO,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
spi::{
|
||||
master::{prelude::*, Address, Command, Spi},
|
||||
SpiDataMode,
|
||||
SpiMode,
|
||||
},
|
||||
Delay,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::{print, println};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let sclk = io.pins.gpio4;
|
||||
let miso = io.pins.gpio5;
|
||||
let mosi = io.pins.gpio6;
|
||||
let sio2 = io.pins.gpio7;
|
||||
let sio3 = io.pins.gpio8;
|
||||
let cs = io.pins.gpio9;
|
||||
|
||||
let dma = Dma::new(peripherals.DMA);
|
||||
let dma_channel = dma.channel0;
|
||||
|
||||
let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(256, 320);
|
||||
|
||||
let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks)
|
||||
.with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
Some(miso),
|
||||
Some(sio2),
|
||||
Some(sio3),
|
||||
Some(cs),
|
||||
)
|
||||
.with_dma(dma_channel.configure(
|
||||
false,
|
||||
&mut tx_descriptors,
|
||||
&mut rx_descriptors,
|
||||
DmaPriority::Priority0,
|
||||
));
|
||||
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
// DMA buffer require a static life-time
|
||||
let mut zero_buf = zero_buffer();
|
||||
let send = tx_buffer;
|
||||
let mut receive = rx_buffer;
|
||||
|
||||
// write enable
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x06, SpiDataMode::Single),
|
||||
Address::None,
|
||||
0,
|
||||
zero_buf,
|
||||
)
|
||||
.unwrap();
|
||||
(zero_buf, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// erase sector
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x20, SpiDataMode::Single),
|
||||
Address::Address24(0x000000, SpiDataMode::Single),
|
||||
0,
|
||||
zero_buf,
|
||||
)
|
||||
.unwrap();
|
||||
(zero_buf, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// write enable
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Single,
|
||||
Command::Command8(0x06, SpiDataMode::Single),
|
||||
Address::None,
|
||||
0,
|
||||
zero_buf,
|
||||
)
|
||||
.unwrap();
|
||||
(_, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
// write data / program page
|
||||
send.fill(b'!');
|
||||
send[0..][..5].copy_from_slice(&b"Hello"[..]);
|
||||
let transfer = spi
|
||||
.write(
|
||||
SpiDataMode::Quad,
|
||||
Command::Command8(0x32, SpiDataMode::Single),
|
||||
Address::Address24(0x000000, SpiDataMode::Single),
|
||||
0,
|
||||
send,
|
||||
)
|
||||
.unwrap();
|
||||
(_, spi) = transfer.wait().unwrap();
|
||||
delay.delay_ms(250u32);
|
||||
|
||||
loop {
|
||||
// quad fast read
|
||||
let transfer = spi
|
||||
.read(
|
||||
SpiDataMode::Quad,
|
||||
Command::Command8(0xeb, SpiDataMode::Single),
|
||||
Address::Address32(0x000000 << 8, SpiDataMode::Quad),
|
||||
4,
|
||||
receive,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// here we could do something else while DMA transfer is in progress
|
||||
// the buffers and spi is moved into the transfer and we can get it back via
|
||||
// `wait`
|
||||
(receive, spi) = transfer.wait().unwrap();
|
||||
|
||||
println!("{:x?}", &receive);
|
||||
for b in &mut receive.iter() {
|
||||
if *b >= 32 && *b <= 127 {
|
||||
print!("{}", *b as char);
|
||||
} else {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
||||
delay.delay_ms(250u32);
|
||||
}
|
||||
}
|
||||
|
||||
fn zero_buffer() -> &'static mut [u8; 0] {
|
||||
static mut BUFFER: [u8; 0] = [0u8; 0];
|
||||
unsafe { &mut BUFFER }
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
//! This shows how to read selected information from eFuses.
|
||||
//! e.g. the MAC address
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{clock::ClockControl, efuse::Efuse, peripherals::Peripherals, prelude::*};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
println!("MAC address {:02x?}", Efuse::get_mac_address());
|
||||
println!("Flash Encryption {:?}", Efuse::get_flash_encryption());
|
||||
|
||||
loop {}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
//! Demonstrates the use of the hardware Random Number Generator (RNG)
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, Rng};
|
||||
use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
// Instantiate the Random Number Generator peripheral:
|
||||
let mut rng = Rng::new(peripherals.RNG);
|
||||
|
||||
// Generate a random word (u32):
|
||||
println!("Random u32: {}", rng.random());
|
||||
|
||||
// Fill a buffer with random bytes:
|
||||
let mut buf = [0u8; 16];
|
||||
rng.read(&mut buf).unwrap();
|
||||
println!("Random bytes: {:?}", buf);
|
||||
|
||||
loop {}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
//! Prints time in milliseconds from the RTC Timer
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c2_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, Delay, Rtc};
|
||||
use esp_backtrace as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let rtc = Rtc::new(peripherals.LPWR);
|
||||
let mut delay = Delay::new(&clocks);
|
||||
|
||||
loop {
|
||||
esp_println::println!("rtc time in milliseconds is {}", rtc.get_time_ms());
|
||||
delay.delay_ms(1000u32);
|
||||
}
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
//! This shows some of the interrupts that can be generated by UART/Serial.
|
||||
//! Use a proper serial terminal to connect to the board (espmonitor and
|
||||
//! espflash won't work)
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::{cell::RefCell, fmt::Write};
|
||||
|
||||
use critical_section::Mutex;
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
interrupt,
|
||||
peripherals::{self, Peripherals, UART0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
uart::config::AtCmdConfig,
|
||||
Cpu,
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use nb::block;
|
||||
|
||||
static SERIAL: Mutex<RefCell<Option<Uart<UART0>>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = peripherals.SYSTEM.split();
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
|
||||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
|
||||
let mut timer0 = timer_group0.timer0;
|
||||
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, b'#', None));
|
||||
uart0.set_rx_fifo_full_threshold(30).unwrap();
|
||||
uart0.listen_at_cmd();
|
||||
uart0.listen_rx_fifo_full();
|
||||
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
critical_section::with(|cs| SERIAL.borrow_ref_mut(cs).replace(uart0));
|
||||
|
||||
interrupt::enable(
|
||||
peripherals::Interrupt::UART0,
|
||||
interrupt::Priority::Priority1,
|
||||
)
|
||||
.unwrap();
|
||||
interrupt::set_kind(
|
||||
Cpu::ProCpu,
|
||||
interrupt::CpuInterrupt::Interrupt1, // Interrupt 1 handles priority one interrupts
|
||||
interrupt::InterruptKind::Edge,
|
||||
);
|
||||
|
||||
loop {
|
||||
critical_section::with(|cs| {
|
||||
writeln!(SERIAL.borrow_ref_mut(cs).as_mut().unwrap(), "Hello World! Send a single `#` character or send at least 30 characters and see the interrupts trigger.").ok();
|
||||
});
|
||||
|
||||
block!(timer0.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn UART0() {
|
||||
critical_section::with(|cs| {
|
||||
let mut serial = SERIAL.borrow_ref_mut(cs);
|
||||
let serial = serial.as_mut().unwrap();
|
||||
|
||||
let mut cnt = 0;
|
||||
while let nb::Result::Ok(_c) = serial.read() {
|
||||
cnt += 1;
|
||||
}
|
||||
writeln!(serial, "Read {} bytes", cnt,).ok();
|
||||
|
||||
writeln!(
|
||||
serial,
|
||||
"Interrupt AT-CMD: {} RX-FIFO-FULL: {}",
|
||||
serial.at_cmd_interrupt_set(),
|
||||
serial.rx_fifo_full_interrupt_set(),
|
||||
)
|
||||
.ok();
|
||||
|
||||
serial.reset_at_cmd_interrupt();
|
||||
serial.reset_rx_fifo_full_interrupt();
|
||||
});
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user