├── book ├── src │ ├── 04_0_intro_advanced_examples.md │ ├── 03_0_intro_workshop.md │ ├── 02_3_repository.md │ ├── SUMMARY.md │ ├── 02_1_hardware.md │ ├── 03_3_button.md │ ├── 01_intro.md │ ├── 02_0_preparations.md │ ├── 03_2_blinky.md │ ├── 03_1_panic.md │ ├── 03_7_defmt.md │ ├── 03_4_interrupt.md │ ├── 02_4_hello_world.md │ ├── 03_5_dma_spi.md │ ├── 03_6_http_client.md │ ├── 02_2_software.md │ ├── 04_1_stack_overflow_protection.md │ └── assets │ │ └── esp-logo-black.svg └── book.toml ├── intro ├── defmt │ ├── rust-toolchain.toml │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── examples │ │ └── defmt.rs ├── dma │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── Cargo.toml │ ├── .cargo │ │ └── config.toml │ ├── diagram.json │ ├── src │ │ └── main.rs │ ├── examples │ │ └── dma.rs │ └── Cargo.lock ├── panic │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── src │ │ └── main.rs │ ├── examples │ │ └── panic.rs │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ └── diagram.json ├── blinky │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ ├── diagram.json │ ├── examples │ │ └── blinky.rs │ └── Cargo.lock ├── button │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ ├── examples │ │ └── button.rs │ ├── diagram.json │ └── Cargo.lock ├── hello-world │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── src │ │ └── main.rs │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ └── diagram.json ├── http-client │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── .cargo │ │ └── config.toml │ ├── diagram.json │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── examples │ │ └── http-client.rs └── button-interrupt │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── .cargo │ └── config.toml │ ├── Cargo.toml │ ├── src │ └── main.rs │ ├── diagram.json │ └── examples │ └── button-interrupt.rs ├── .github ├── hello-world.test.yaml ├── panic.test.yaml ├── dependabot.yml ├── stack-overflow-detection.test.yaml ├── http-client.test.yaml ├── blinky.test.yaml ├── workflows │ ├── issue_handler.yml │ ├── book.yml │ ├── ci.yml │ └── wokwi_projects.yml ├── button-interrupt.test.yaml └── button.test.yaml ├── advanced └── stack-overflow-detection │ ├── rust-toolchain.toml │ ├── wokwi.toml │ ├── Cargo.toml │ ├── .cargo │ └── config.toml │ ├── diagram.json │ ├── src │ └── main.rs │ └── examples │ └── stack-overflow-detection.rs ├── .gitignore ├── README.md ├── LICENSE-MIT ├── .devcontainer ├── devcontainer.json └── Dockerfile └── LICENSE-APACHE /book/src/04_0_intro_advanced_examples.md: -------------------------------------------------------------------------------- 1 | # Advanced Examples 2 | 3 | In this chapter you will learn about more advanced features and concepts. 4 | -------------------------------------------------------------------------------- /intro/defmt/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | 6 | -------------------------------------------------------------------------------- /.github/hello-world.test.yaml: -------------------------------------------------------------------------------- 1 | name: hello-world test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "Hello world!" 7 | -------------------------------------------------------------------------------- /.github/panic.test.yaml: -------------------------------------------------------------------------------- 1 | name: panic test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "!! A panic occured in " 7 | -------------------------------------------------------------------------------- /intro/dma/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/panic/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/blinky/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/button/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/hello-world/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/http-client/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/button-interrupt/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2023-11-14" 3 | components = ["rust-src"] 4 | targets = ["riscv32imc-unknown-none-elf"] 5 | -------------------------------------------------------------------------------- /intro/hello-world/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | firmware = "target/riscv32imc-unknown-none-elf/release/hello_world" 4 | elf = "target/riscv32imc-unknown-none-elf/release/hello_world" 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | # Check for updates every Monday 6 | schedule: 7 | interval: "weekly" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/stack-overflow-detection.test.yaml: -------------------------------------------------------------------------------- 1 | name: stack-overflow-detection test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "Safe stack" 7 | - wait-serial: "Possible Stack Overflow Detected" 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | **/target/ 5 | 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | 9 | # MSVC Windows builds of rustc generate these, which store debugging information 10 | *.pdb 11 | 12 | book/book 13 | -------------------------------------------------------------------------------- /.github/http-client.test.yaml: -------------------------------------------------------------------------------- 1 | name: http-client test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "Wait to get connected" 7 | - wait-serial: "Wait to get an ip address" 8 | - wait-serial: "Making HTTP request" 9 | - wait-serial: "< Hello fellow Rustaceans! >" 10 | -------------------------------------------------------------------------------- /.github/blinky.test.yaml: -------------------------------------------------------------------------------- 1 | name: blinky test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "Hello world!" 7 | - delay: 100ms 8 | - expect-pin: 9 | part-id: esp 10 | pin: 7 11 | value: 0 12 | - delay: 550ms 13 | - expect-pin: 14 | part-id: esp 15 | pin: 7 16 | value: 1 17 | -------------------------------------------------------------------------------- /intro/dma/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/dma" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/dma" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/dma' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/dma' 10 | -------------------------------------------------------------------------------- /intro/panic/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/panic" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/panic" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/panic' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/panic' 10 | -------------------------------------------------------------------------------- /intro/blinky/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/blinky" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/blinky" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/blinky' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/blinky' 10 | -------------------------------------------------------------------------------- /intro/button/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/button" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/button" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/button' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/button' 10 | -------------------------------------------------------------------------------- /book/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Björn Quentin", "Sergio Gasquez"] 3 | description = "Embedded Rust (no_std) on Espressif training material" 4 | language = "en" 5 | multilingual = false 6 | src = "src" 7 | title = "Embedded Rust (no_std) on Espressif" 8 | 9 | [rust] 10 | edition = "2021" 11 | 12 | [output.html] 13 | git-repository-url = "https://github.com/esp-rs/no_std-training" 14 | -------------------------------------------------------------------------------- /intro/http-client/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/http_client" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/http_client" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/http-client' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/http-client' 10 | -------------------------------------------------------------------------------- /intro/button-interrupt/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/button_interrupt" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/button_interrupt" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/button-interrupt' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/button-interrupt' 10 | -------------------------------------------------------------------------------- /intro/panic/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{peripherals::Peripherals, prelude::*, system::SystemControl}; 6 | use esp_println::println; 7 | 8 | #[entry] 9 | fn main() -> ! { 10 | let peripherals = Peripherals::take(); 11 | let _system = SystemControl::new(peripherals.SYSTEM); 12 | 13 | println!("Hello world!"); 14 | 15 | loop {} 16 | } 17 | -------------------------------------------------------------------------------- /intro/hello-world/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{peripherals::Peripherals, prelude::*, system::SystemControl}; 6 | use esp_println::println; 7 | 8 | #[entry] 9 | fn main() -> ! { 10 | let peripherals = Peripherals::take(); 11 | let _system = SystemControl::new(peripherals.SYSTEM); 12 | 13 | println!("Hello world!"); 14 | 15 | loop {} 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/issue_handler.yml: -------------------------------------------------------------------------------- 1 | name: Add new issues to project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@v1.0.2 14 | with: 15 | project-url: https://github.com/orgs/esp-rs/projects/2 16 | github-token: ${{ secrets.PAT }} 17 | -------------------------------------------------------------------------------- /intro/dma/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dma" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | 7 | [dependencies] 8 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 9 | esp-backtrace = { version = "0.13.0", features = [ 10 | "esp32c3", 11 | "panic-handler", 12 | "exception-handler", 13 | "println", 14 | ] } 15 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 16 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | # Exercise 4 | # firmware = "target/riscv32imc-unknown-none-elf/release/stack_overflow_detection" 5 | # elf = "target/riscv32imc-unknown-none-elf/release/stack_overflow_detection" 6 | 7 | # Solution 8 | firmware = 'target/riscv32imc-unknown-none-elf/release/examples/stack-overflow-detection' 9 | elf = 'target/riscv32imc-unknown-none-elf/release/examples/stack-overflow-detection' 10 | -------------------------------------------------------------------------------- /intro/panic/examples/panic.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{peripherals::Peripherals, prelude::*, system::SystemControl}; 6 | use esp_println::println; 7 | 8 | #[entry] 9 | fn main() -> ! { 10 | let peripherals = Peripherals::take(); 11 | let _system = SystemControl::new(peripherals.SYSTEM); 12 | 13 | println!("Hello world!"); 14 | 15 | panic!("This is a panic"); 16 | 17 | loop {} 18 | } 19 | -------------------------------------------------------------------------------- /intro/blinky/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /intro/button/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /intro/dma/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /intro/panic/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stack-overflow-detection" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | 7 | [dependencies] 8 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 9 | esp-backtrace = { version = "0.13.0", features = ["esp32c3", "panic-handler", "exception-handler", "println"] } 10 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 11 | critical-section = "1.1.2" 12 | -------------------------------------------------------------------------------- /intro/hello-world/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /intro/button-interrupt/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /book/src/03_0_intro_workshop.md: -------------------------------------------------------------------------------- 1 | # Intro Workshop 2 | 3 | This workshop guides you through the basics of embedded development, at the end of 4 | the workshop we will be able to interact with the outside world. The content includes: 5 | - A `panic` example 6 | - A blinky example 7 | - A button example 8 | - A button with interrupt example 9 | 10 | ## Preparations 11 | 12 | Please go through the [preparations](./02_0_preparations.md) chapter to prepare for this workshop. 13 | 14 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 8 | # NOTE: May negatively impact performance of produced code 9 | "-C", "force-frame-pointers", 10 | ] 11 | 12 | target = "riscv32imc-unknown-none-elf" 13 | 14 | [unstable] 15 | build-std = ["core"] 16 | -------------------------------------------------------------------------------- /intro/blinky/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blinky" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | 8 | [dependencies] 9 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 10 | esp-backtrace = { version = "0.13.0", features = [ 11 | "esp32c3", 12 | "panic-handler", 13 | "exception-handler", 14 | "println", 15 | ] } 16 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 17 | -------------------------------------------------------------------------------- /intro/button/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "button" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | 8 | [dependencies] 9 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 10 | esp-backtrace = { version = "0.13.0", features = [ 11 | "esp32c3", 12 | "panic-handler", 13 | "exception-handler", 14 | "println", 15 | ] } 16 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 17 | -------------------------------------------------------------------------------- /intro/panic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | 8 | [dependencies] 9 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 10 | esp-backtrace = { version = "0.13.0", features = [ 11 | "esp32c3", 12 | "panic-handler", 13 | "exception-handler", 14 | "println", 15 | ] } 16 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 17 | -------------------------------------------------------------------------------- /intro/hello-world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello_world" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | 8 | [dependencies] 9 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 10 | esp-backtrace = { version = "0.13.0", features = [ 11 | "esp32c3", 12 | "panic-handler", 13 | "exception-handler", 14 | "println", 15 | ] } 16 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 17 | -------------------------------------------------------------------------------- /.github/button-interrupt.test.yaml: -------------------------------------------------------------------------------- 1 | name: button-interrupt test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "Hello world!" 7 | # Press once 8 | - set-control: 9 | part-id: btn1 10 | control: pressed 11 | value: 0 12 | - delay: 100ms 13 | - set-control: 14 | part-id: btn1 15 | control: pressed 16 | value: 1 17 | - wait-serial: "GPIO interrupt" 18 | -------------------------------------------------------------------------------- /intro/http-client/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | # TODO: Explain 8 | "-C", "link-arg=-Trom_functions.x", 9 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 10 | # NOTE: May negatively impact performance of produced code 11 | "-C", "force-frame-pointers", 12 | ] 13 | 14 | target = "riscv32imc-unknown-none-elf" 15 | 16 | [unstable] 17 | build-std = ["core"] 18 | -------------------------------------------------------------------------------- /intro/button-interrupt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "button-interrupt" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | 8 | [dependencies] 9 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 10 | esp-backtrace = { version = "0.13.0", features = [ 11 | "esp32c3", 12 | "panic-handler", 13 | "exception-handler", 14 | "println", 15 | ] } 16 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 17 | critical-section = "1.1.2" 18 | -------------------------------------------------------------------------------- /intro/defmt/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32imc-unknown-none-elf] 2 | runner = "espflash flash --monitor -L defmt" 3 | 4 | [build] 5 | rustflags = [ 6 | "-C", "link-arg=-Tlinkall.x", 7 | 8 | # Add `defmt`linking options 9 | "-C", "link-arg=-Tdefmt.x", 10 | 11 | # Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.) 12 | # NOTE: May negatively impact performance of produced code 13 | "-C", "force-frame-pointers", 14 | 15 | ] 16 | 17 | target = "riscv32imc-unknown-none-elf" 18 | 19 | [unstable] 20 | build-std = ["core"] 21 | -------------------------------------------------------------------------------- /.github/button.test.yaml: -------------------------------------------------------------------------------- 1 | name: button test 2 | version: 1 3 | author: Sergio Gasquez Arcos 4 | 5 | steps: 6 | - wait-serial: "Hello world!" 7 | - delay: 100ms 8 | # Press once 9 | - set-control: 10 | part-id: btn1 11 | control: pressed 12 | value: 1 13 | - delay: 50ms 14 | - expect-pin: 15 | part-id: esp 16 | pin: 7 17 | value: 0 18 | - set-control: 19 | part-id: btn1 20 | control: pressed 21 | value: 0 22 | - delay: 50ms 23 | - expect-pin: 24 | part-id: esp 25 | pin: 7 26 | value: 1 27 | -------------------------------------------------------------------------------- /intro/defmt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "defmt" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | 8 | [dependencies] 9 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 10 | esp-backtrace = { version = "0.13.0", features = [ 11 | "esp32c3", 12 | "panic-handler", 13 | "exception-handler", 14 | "defmt", 15 | ] } 16 | esp-println = { version = "0.10.0", features = [ 17 | "esp32c3", 18 | "log", 19 | "defmt-espflash", 20 | ] } 21 | defmt = "0.3.8" 22 | -------------------------------------------------------------------------------- /intro/button/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{ 6 | gpio::{Input, Io, Level, Output, Pull}, 7 | peripherals::Peripherals, 8 | prelude::*, 9 | system::SystemControl, 10 | }; 11 | use esp_println::println; 12 | 13 | #[entry] 14 | fn main() -> ! { 15 | let peripherals = Peripherals::take(); 16 | let _system = SystemControl::new(peripherals.SYSTEM); 17 | 18 | println!("Hello world!"); 19 | 20 | // Set GPIO7 as an output, and set its state high initially. 21 | 22 | // Check the button state and set the LED state accordingly. 23 | loop {} 24 | } 25 | -------------------------------------------------------------------------------- /book/src/02_3_repository.md: -------------------------------------------------------------------------------- 1 | # Workshop repository 2 | 3 | The entire material can be found at . 4 | 5 | ✅ Clone and change into the workshop repository: 6 | 7 | ```console 8 | git clone "https://github.com/esp-rs/no_std-training.git" 9 | cd no_std-training 10 | ``` 11 | 12 | ❗ Windows users may have problems with long path names. Follow these steps to substitute the path: 13 | 14 | ```console 15 | git clone https://github.com/esp-rs/no_std-training.git 16 | subst r: no_std-trainings 17 | cd r:\ 18 | ``` 19 | 20 | ## Repository contents 21 | 22 | - `book/`: markdown sources of this book 23 | - `intro/`: code examples and exercises for the introduction course 24 | -------------------------------------------------------------------------------- /intro/defmt/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | // Build the `esp_println` and `esp_backtrace` libs 5 | 6 | use esp_hal::{ 7 | clock::ClockControl, delay::Delay, peripherals::Peripherals, prelude::*, system::SystemControl, 8 | }; 9 | 10 | #[entry] 11 | fn main() -> ! { 12 | let peripherals = Peripherals::take(); 13 | let system = SystemControl::new(peripherals.SYSTEM); 14 | let clocks = ClockControl::max(system.clock_control).freeze(); 15 | let delay = Delay::new(&clocks); 16 | 17 | // Print a log or a message using defmt 18 | 19 | // Use a panic! macro to trigger a panic 20 | 21 | loop { 22 | defmt::println!("Loop..."); 23 | delay.delay_millis(500u32); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /intro/blinky/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{ 6 | clock::ClockControl, 7 | delay::Delay, 8 | gpio::{Io, Level, Output}, 9 | peripherals::Peripherals, 10 | prelude::*, 11 | system::SystemControl, 12 | }; 13 | use esp_println::println; 14 | 15 | #[entry] 16 | fn main() -> ! { 17 | let peripherals = Peripherals::take(); 18 | let system = SystemControl::new(peripherals.SYSTEM); 19 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 20 | 21 | println!("Hello world!"); 22 | 23 | // Set GPIO7 as an output, and set its state high initially. 24 | 25 | // Initialize the Delay peripheral, and use it to toggle the LED state in a 26 | // loop. 27 | loop {} 28 | } 29 | -------------------------------------------------------------------------------- /intro/blinky/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -126.57, 10 | "left": 46.35, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | } 15 | ], 16 | "connections": [ 17 | [ 18 | "esp:21", 19 | "$serialMonitor:RX", 20 | "", 21 | [] 22 | ], 23 | [ 24 | "esp:20", 25 | "$serialMonitor:TX", 26 | "", 27 | [] 28 | ] 29 | ], 30 | "serialMonitor": { 31 | "display": "auto" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /intro/panic/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -126.57, 10 | "left": 46.35, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | } 15 | ], 16 | "connections": [ 17 | [ 18 | "esp:21", 19 | "$serialMonitor:RX", 20 | "", 21 | [] 22 | ], 23 | [ 24 | "esp:20", 25 | "$serialMonitor:TX", 26 | "", 27 | [] 28 | ] 29 | ], 30 | "serialMonitor": { 31 | "display": "auto" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /intro/hello-world/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -126.57, 10 | "left": 46.35, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | } 15 | ], 16 | "connections": [ 17 | [ 18 | "esp:21", 19 | "$serialMonitor:RX", 20 | "", 21 | [] 22 | ], 23 | [ 24 | "esp:20", 25 | "$serialMonitor:TX", 26 | "", 27 | [] 28 | ] 29 | ], 30 | "serialMonitor": { 31 | "display": "auto" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /intro/http-client/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -126.57, 10 | "left": 46.35, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | } 15 | ], 16 | "connections": [ 17 | [ 18 | "esp:21", 19 | "$serialMonitor:RX", 20 | "", 21 | [] 22 | ], 23 | [ 24 | "esp:20", 25 | "$serialMonitor:TX", 26 | "", 27 | [] 28 | ] 29 | ], 30 | "serialMonitor": { 31 | "display": "auto" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /book/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./01_intro.md) 4 | - [Preparations](./02_0_preparations.md) 5 | - [Hardware](./02_1_hardware.md) 6 | - [Software](./02_2_software.md) 7 | - [Workshop repository](./02_3_repository.md) 8 | - [Hello World](02_4_hello_world.md) 9 | - [Intro workshop](./03_0_intro_workshop.md) 10 | - [Panic!](./03_1_panic.md) 11 | - [Blinky](./03_2_blinky.md) 12 | - [Detect a button press](./03_3_button.md) 13 | - [Detect a button press with interrupt](./03_4_interrupt.md) 14 | - [DMA](./03_5_dma_spi.md) 15 | - [HTTP Client](./03_6_http_client.md) 16 | - [Using `defmt`](./03_7_defmt.md) 17 | - [Advanced level examples](./04_0_intro_advanced_examples.md) 18 | - [Stack overflow protection with Debug Assist](./04_1_stack_overflow_protection.md) 19 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -126.57, 10 | "left": 46.35, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | } 15 | ], 16 | "connections": [ 17 | [ 18 | "esp:21", 19 | "$serialMonitor:RX", 20 | "", 21 | [] 22 | ], 23 | [ 24 | "esp:20", 25 | "$serialMonitor:TX", 26 | "", 27 | [] 28 | ] 29 | ], 30 | "serialMonitor": { 31 | "display": "auto" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # no_std training 2 | 3 | [![CI](https://github.com/esp-rs/no_std-training/actions/workflows/ci.yml/badge.svg)](https://github.com/esp-rs/no_std-training/actions/workflows/ci.yml) 4 | 5 | This repository contains Training Material for learning to use Embedded Rust with `no_std` with the Espressif ESP32-C3. 6 | 7 | We suggest you start by reading [the book](https://esp-rs.github.io/no_std-training/). 8 | 9 | ## Contents 10 | 11 | * Some introductory level examples: 12 | * A basic hello-world ([Source](./intro/hello-world)) 13 | * A `panic` example([Source](./intro/panic)) 14 | * A blinky example([Source](./intro/blinky)) 15 | * A button example([Source](./intro/button)) 16 | * A button with interrupt example([Source](./intro/button-interrupt)) 17 | * An HTTP client example([Source](./intro/http-client)) 18 | -------------------------------------------------------------------------------- /intro/defmt/examples/defmt.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | // ANCHOR: println_include 5 | use esp_backtrace as _; 6 | use esp_println as _; 7 | // ANCHOR_END: println_include 8 | use esp_hal::{ 9 | clock::ClockControl, delay::Delay, peripherals::Peripherals, prelude::*, system::SystemControl, 10 | }; 11 | 12 | #[entry] 13 | fn main() -> ! { 14 | let peripherals = Peripherals::take(); 15 | let system = SystemControl::new(peripherals.SYSTEM); 16 | let clocks = ClockControl::max(system.clock_control).freeze(); 17 | let delay = Delay::new(&clocks); 18 | 19 | defmt::trace!("trace"); 20 | defmt::debug!("debug"); 21 | defmt::info!("info"); 22 | defmt::warn!("warn"); 23 | defmt::error!("error"); 24 | 25 | // panic!("Very useful panic message"); 26 | 27 | loop { 28 | defmt::println!("Loop..."); 29 | delay.delay_millis(500u32); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /intro/button/examples/button.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{ 6 | gpio::{Input, Io, Level, Output, Pull}, 7 | peripherals::Peripherals, 8 | prelude::*, 9 | system::SystemControl, 10 | }; 11 | use esp_println::println; 12 | 13 | #[entry] 14 | fn main() -> ! { 15 | let peripherals = Peripherals::take(); 16 | let _system = SystemControl::new(peripherals.SYSTEM); 17 | 18 | println!("Hello world!"); 19 | 20 | // Set GPIO7 as an output, and set its state high initially. 21 | let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); 22 | let mut led = Output::new(io.pins.gpio7, Level::Low); 23 | let button = Input::new(io.pins.gpio9, Pull::Up); 24 | 25 | // Check the button state and set the LED state accordingly. 26 | loop { 27 | if button.is_high() { 28 | led.set_high(); 29 | } else { 30 | led.set_low(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /intro/blinky/examples/blinky.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_backtrace as _; 5 | use esp_hal::{ 6 | clock::ClockControl, 7 | delay::Delay, 8 | gpio::{Io, Level, Output}, 9 | peripherals::Peripherals, 10 | prelude::*, 11 | system::SystemControl, 12 | }; 13 | use esp_println::println; 14 | 15 | #[entry] 16 | fn main() -> ! { 17 | let peripherals = Peripherals::take(); 18 | let system = SystemControl::new(peripherals.SYSTEM); 19 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 20 | 21 | println!("Hello world!"); 22 | 23 | // Set GPIO7 as an output, and set its state high initially. 24 | let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); 25 | let mut led = Output::new(io.pins.gpio7, Level::Low); 26 | 27 | led.set_high(); 28 | 29 | // Initialize the Delay peripheral, and use it to toggle the LED state in a 30 | // loop. 31 | let delay = Delay::new(&clocks); 32 | 33 | loop { 34 | led.toggle(); 35 | delay.delay_millis(500u32); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 esp-rs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /intro/http-client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http-client" 3 | version = "0.1.0" 4 | authors = ["Sergio Gasquez "] 5 | edition = "2021" 6 | license = "MIT OR Apache-2.0" 7 | # TODO: Explain 8 | resolver = "2" 9 | 10 | # TODO: Explain 11 | [profile.release] 12 | # Explicitly disable LTO which the Xtensa codegen backend has issues 13 | lto = "off" 14 | opt-level = 3 15 | [profile.dev] 16 | lto = "off" 17 | 18 | [dependencies] 19 | esp-hal = { version = "0.19.0", features = ["esp32c3"] } 20 | esp-backtrace = { version = "0.13.0", features = [ 21 | "esp32c3", 22 | "panic-handler", 23 | "exception-handler", 24 | "println", 25 | ] } 26 | esp-println = { version = "0.10.0", features = ["esp32c3"] } 27 | esp-wifi = { version = "0.7.0", features = [ 28 | "esp32c3", 29 | "wifi-default", 30 | "utils", 31 | "phy-enable-usb", 32 | ] } 33 | smoltcp = { version = "0.11.0", default-features = false, features = [ 34 | "proto-igmp", 35 | "proto-ipv4", 36 | "socket-tcp", 37 | "socket-icmp", 38 | "socket-udp", 39 | "medium-ethernet", 40 | "proto-dhcpv4", 41 | "socket-raw", 42 | "socket-dhcpv4", 43 | ] } 44 | embedded-io = "0.6.1" 45 | heapless = { version = "0.8.0", default-features = false } 46 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::cell::RefCell; 5 | 6 | use critical_section::Mutex; 7 | use esp_backtrace as _; 8 | use esp_hal::{ 9 | assist_debug::DebugAssist, clock::ClockControl, peripherals::Peripherals, prelude::*, 10 | system::SystemControl, 11 | }; 12 | use esp_println::println; 13 | 14 | #[entry] 15 | fn main() -> ! { 16 | let peripherals = Peripherals::take(); 17 | let system = SystemControl::new(peripherals.SYSTEM); 18 | let _ = ClockControl::boot_defaults(system.clock_control).freeze(); 19 | 20 | // get the debug assist driver 21 | let da = DebugAssist::new(peripherals.ASSIST_DEBUG, Some(interrupt_handler)); 22 | 23 | boom(); 24 | 25 | loop {} 26 | } 27 | 28 | #[inline(never)] 29 | fn boom() { 30 | deadly_recursion([0u8; 2048]); 31 | } 32 | 33 | #[ram] 34 | #[allow(unconditional_recursion)] 35 | fn deadly_recursion(data: [u8; 2048]) { 36 | static mut COUNTER: u32 = 0; 37 | 38 | println!( 39 | "Iteration {}, data {:02x?}...", 40 | unsafe { COUNTER }, 41 | &data[0..10] 42 | ); 43 | 44 | unsafe { 45 | COUNTER = COUNTER.wrapping_add(1); 46 | }; 47 | 48 | deadly_recursion([0u8; 2048]); 49 | } 50 | 51 | #[handler(priority = esp_hal::interrupt::Priority::min())] 52 | fn interrupt_handler() {} 53 | -------------------------------------------------------------------------------- /book/src/02_1_hardware.md: -------------------------------------------------------------------------------- 1 | # Checking the hardware 2 | 3 | Connect the Espressif Rust Board to your computer. Verify, a tiny red control LED lights up. 4 | 5 | The device should also expose its UART serial port over USB: 6 | 7 | **Windows**: a USB Serial Device (COM port) in the Device Manager under the Ports section. 8 | 9 | **Linux**: a USB device under `lsusb`. 10 | The device will have a VID (vendor ID) of `303a` and a PID (product ID) of `1001` -- the `0x` prefix will be omitted in the output of `lsusb`: 11 | 12 | ``` console 13 | $ lsusb | grep USB 14 | Bus 006 Device 035: ID 303a:1001 Espressif USB JTAG/serial debug unit 15 | ``` 16 | 17 | Another way to see the device is to see which permissions and port is associated to the device is to check the `/by-id` folder: 18 | ``` console 19 | $ ls -l /dev/serial/by-id 20 | lrwxrwxrwx 1 root root .... usb-Espressif_USB_JTAG_serial_debug_unit_60:55:F9:C0:27:18-if00 -> ../../ttyACM0 21 | 22 | ``` 23 | > If you are using a ESP32-C3-DevKitC-02 the command is `$ ls /dev/ttyUSB*` 24 | 25 | **macOS**: The device will show up as part of the USB tree in `system_profiler`: 26 | 27 | ```console 28 | $ system_profiler SPUSBDataType | grep -A 11 "USB JTAG" 29 | 30 | USB JTAG/serial debug unit: 31 | 32 | Product ID: 0x1001 33 | Vendor ID: 0x303a 34 | (...) 35 | ``` 36 | 37 | The device will also show up in the `/dev` directory as a `tty.usbmodem` device: 38 | 39 | ``` console 40 | $ ls /dev/tty.usbmodem* 41 | /dev/tty.usbmodem0 42 | ``` 43 | -------------------------------------------------------------------------------- /intro/button-interrupt/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::cell::RefCell; 5 | use critical_section::Mutex; 6 | use esp_backtrace as _; 7 | use esp_hal::{ 8 | clock::ClockControl, 9 | delay::Delay, 10 | gpio::{self, Event, Gpio9, Input, Io, Level, Output, Pull}, 11 | peripherals::Peripherals, 12 | prelude::*, 13 | system::SystemControl, 14 | }; 15 | use esp_println::println; 16 | 17 | static BUTTON: Mutex>>> = Mutex::new(RefCell::new(None)); 18 | 19 | #[entry] 20 | fn main() -> ! { 21 | let peripherals = Peripherals::take(); 22 | let system = SystemControl::new(peripherals.SYSTEM); 23 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 24 | 25 | println!("Hello world!"); 26 | 27 | let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); 28 | // Set the interrupt handler for GPIO interrupts. 29 | 30 | // Set GPIO7 as an output, and set its state high initially. 31 | let mut led = Output::new(io.pins.gpio7, Level::Low); 32 | 33 | // Set GPIO9 as an input 34 | let mut button = Input::new(io.pins.gpio9, Pull::Up); 35 | 36 | let delay = Delay::new(&clocks); 37 | loop {} 38 | } 39 | 40 | #[handler] 41 | fn handler() { 42 | critical_section::with(|cs| { 43 | println!("GPIO interrupt"); 44 | BUTTON 45 | .borrow_ref_mut(cs) 46 | .as_mut() 47 | .unwrap() 48 | .clear_interrupt(); 49 | }); 50 | } 51 | -------------------------------------------------------------------------------- /intro/button/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -99.32, 10 | "left": 34.67, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | }, 15 | { 16 | "type": "wokwi-pushbutton", 17 | "id": "btn1", 18 | "top": 2.81, 19 | "left": -49.66, 20 | "rotate": 90, 21 | "attrs": { 22 | "color": "green", 23 | "bounce": "0" 24 | } 25 | } 26 | ], 27 | "connections": [ 28 | [ 29 | "esp:21", 30 | "$serialMonitor:RX", 31 | "", 32 | [] 33 | ], 34 | [ 35 | "esp:20", 36 | "$serialMonitor:TX", 37 | "", 38 | [] 39 | ], 40 | [ 41 | "esp:9", 42 | "btn1:1.r", 43 | "green", 44 | [ 45 | "h0" 46 | ] 47 | ], 48 | [ 49 | "esp:GND", 50 | "btn1:2.r", 51 | "black", 52 | [ 53 | "h-97.82", 54 | "v114.6", 55 | "h26" 56 | ] 57 | ] 58 | ], 59 | "serialMonitor": { 60 | "display": "auto" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /intro/dma/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -99.32, 10 | "left": 34.67, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | }, 15 | { 16 | "type": "wokwi-pushbutton", 17 | "id": "btn1", 18 | "top": 2.81, 19 | "left": -49.66, 20 | "rotate": 90, 21 | "attrs": { 22 | "color": "green", 23 | "bounce": "0" 24 | } 25 | } 26 | ], 27 | "connections": [ 28 | [ 29 | "esp:21", 30 | "$serialMonitor:RX", 31 | "", 32 | [] 33 | ], 34 | [ 35 | "esp:20", 36 | "$serialMonitor:TX", 37 | "", 38 | [] 39 | ], 40 | [ 41 | "esp:9", 42 | "btn1:1.r", 43 | "green", 44 | [ 45 | "h0" 46 | ] 47 | ], 48 | [ 49 | "esp:GND", 50 | "btn1:2.r", 51 | "black", 52 | [ 53 | "h-97.82", 54 | "v114.6", 55 | "h26" 56 | ] 57 | ] 58 | ], 59 | "serialMonitor": { 60 | "display": "auto" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /intro/button-interrupt/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Sergio Gasquez Arcos", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "board-esp32-c3-rust-1", 8 | "id": "esp", 9 | "top": -99.32, 10 | "left": 34.67, 11 | "attrs": { 12 | "builder": "rust-nostd-esp" 13 | } 14 | }, 15 | { 16 | "type": "wokwi-pushbutton", 17 | "id": "btn1", 18 | "top": 2.81, 19 | "left": -49.66, 20 | "rotate": 90, 21 | "attrs": { 22 | "color": "green", 23 | "bounce": "0" 24 | } 25 | } 26 | ], 27 | "connections": [ 28 | [ 29 | "esp:21", 30 | "$serialMonitor:RX", 31 | "", 32 | [] 33 | ], 34 | [ 35 | "esp:20", 36 | "$serialMonitor:TX", 37 | "", 38 | [] 39 | ], 40 | [ 41 | "esp:9", 42 | "btn1:1.r", 43 | "green", 44 | [ 45 | "h0" 46 | ] 47 | ], 48 | [ 49 | "esp:GND", 50 | "btn1:2.r", 51 | "black", 52 | [ 53 | "h-97.82", 54 | "v114.6", 55 | "h26" 56 | ] 57 | ] 58 | ], 59 | "serialMonitor": { 60 | "display": "auto" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "no_std-training", 3 | // Comment the image and use the build property to build the image from the 4 | // Dockerfile instead of downloading it from https://hub.docker.com/r/espressif/rust-nostd-training 5 | // "image": "docker.io/espressif/rust-nostd-training", 6 | "build": { 7 | "dockerfile": "Dockerfile", 8 | "args": { 9 | "NIGHTLY_VERSION": "nightly-2023-11-14" 10 | } 11 | }, 12 | "customizations": { 13 | "vscode": { 14 | "settings": { 15 | "editor.formatOnPaste": true, 16 | "editor.formatOnSave": true, 17 | "editor.formatOnSaveMode": "modifications", 18 | "editor.formatOnType": true, 19 | "lldb.executable": "/usr/bin/lldb", 20 | "files.watcherExclude": { 21 | "**/target/**": true 22 | }, 23 | "rust-analyzer.checkOnSave.command": "clippy", 24 | "[rust]": { 25 | "editor.defaultFormatter": "rust-lang.rust-analyzer" 26 | } 27 | }, 28 | "extensions": [ 29 | "rust-lang.rust-analyzer", 30 | "tamasfe.even-better-toml", 31 | "vadimcn.vscode-lldb", 32 | "serayuzgur.crates", 33 | "mutantdino.resourcemonitor", 34 | "yzhang.markdown-all-in-one" 35 | ] 36 | } 37 | }, 38 | "remoteUser": "esp", 39 | "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", 40 | "workspaceFolder": "/workspace" 41 | } 42 | -------------------------------------------------------------------------------- /intro/dma/src/main.rs: -------------------------------------------------------------------------------- 1 | // To easily test this you can connect GPIO2 and GPIO4 2 | // This way we will receive was we send. (loopback) 3 | 4 | #![no_std] 5 | #![no_main] 6 | 7 | use esp_backtrace as _; 8 | use esp_hal::{ 9 | clock::ClockControl, 10 | delay::Delay, 11 | dma::Dma, 12 | dma::DmaPriority, 13 | dma_buffers, 14 | gpio::Io, 15 | peripherals::Peripherals, 16 | prelude::*, 17 | spi::{ 18 | master::{prelude::*, Spi}, 19 | SpiMode, 20 | }, 21 | system::SystemControl, 22 | }; 23 | use esp_println::{print, println}; 24 | 25 | #[entry] 26 | fn main() -> ! { 27 | let peripherals = Peripherals::take(); 28 | let system = SystemControl::new(peripherals.SYSTEM); 29 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 30 | 31 | let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); 32 | let sclk = io.pins.gpio0; 33 | let miso = io.pins.gpio2; 34 | let mosi = io.pins.gpio4; 35 | let cs = io.pins.gpio5; 36 | 37 | let mut spi = Spi::new(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks).with_pins( 38 | Some(sclk), 39 | Some(mosi), 40 | Some(miso), 41 | Some(cs), 42 | ); 43 | 44 | let mut delay = Delay::new(&clocks); 45 | 46 | loop { 47 | // ANCHOR: transfer 48 | // To transfer much larger amounts of data we can use DMA and 49 | // the CPU can even do other things while the transfer is in progress 50 | let mut data = [0x01u8, 0x02, 0x03, 0x04]; 51 | spi.transfer(&mut data).unwrap(); 52 | // ANCHOR_END: transfer 53 | println!("{:x?}", data); 54 | 55 | delay.delay_millis(2500u32); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /intro/button-interrupt/examples/button-interrupt.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::cell::RefCell; 5 | use critical_section::Mutex; 6 | use esp_backtrace as _; 7 | use esp_hal::{ 8 | clock::ClockControl, 9 | delay::Delay, 10 | gpio::{Event, Gpio9, Input, Io, Level, Output, Pull}, 11 | peripherals::Peripherals, 12 | prelude::*, 13 | system::SystemControl, 14 | }; 15 | use esp_println::println; 16 | 17 | static BUTTON: Mutex>>> = Mutex::new(RefCell::new(None)); 18 | 19 | #[entry] 20 | fn main() -> ! { 21 | let peripherals = Peripherals::take(); 22 | let system = SystemControl::new(peripherals.SYSTEM); 23 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 24 | 25 | println!("Hello world!"); 26 | 27 | let mut io = Io::new(peripherals.GPIO, peripherals.IO_MUX); 28 | // Set the interrupt handler for GPIO interrupts. 29 | io.set_interrupt_handler(handler); 30 | // Set GPIO7 as an output, and set its state high initially. 31 | let mut led = Output::new(io.pins.gpio7, Level::Low); 32 | 33 | // Set GPIO9 as an input 34 | let mut button = Input::new(io.pins.gpio9, Pull::Up); 35 | 36 | // ANCHOR: critical_section 37 | critical_section::with(|cs| { 38 | button.listen(Event::FallingEdge); 39 | BUTTON.borrow_ref_mut(cs).replace(button) 40 | }); 41 | // ANCHOR_END: critical_section 42 | 43 | let delay = Delay::new(&clocks); 44 | loop { 45 | led.toggle(); 46 | delay.delay_millis(500u32); 47 | } 48 | } 49 | 50 | #[handler] 51 | fn handler() { 52 | critical_section::with(|cs| { 53 | println!("GPIO interrupt"); 54 | BUTTON 55 | .borrow_ref_mut(cs) 56 | .as_mut() 57 | .unwrap() 58 | .clear_interrupt(); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/book.yml: -------------------------------------------------------------------------------- 1 | name: Book CI 2 | on: 3 | push: 4 | paths: 5 | - "book/" 6 | - "book/**" 7 | - ".github/workflows/book.yml" 8 | - "**book**" 9 | pull_request: 10 | paths: 11 | - "book/" 12 | - "book/**" 13 | - ".github/workflows/book.yml" 14 | - "**book**" 15 | 16 | env: 17 | MDBOOK_VERSION: "0.4.28" 18 | 19 | jobs: 20 | build: 21 | name: Build 22 | runs-on: ubuntu-latest 23 | permissions: 24 | contents: read 25 | steps: 26 | - name: Checkout the repository 27 | uses: actions/checkout@v4 28 | 29 | - name: Install Python dependencies 30 | run: | 31 | pip3 install --user python-dateutil linkchecker 32 | - name: Put pip binary directory into path 33 | run: echo "~/.local/bin" >> $GITHUB_PATH 34 | 35 | - name: Download mdBook ${{ env.MDBOOK_VERSION }} 36 | run: | 37 | mkdir -p /tmp/mdbook 38 | curl -Lo- https://github.com/rust-lang/mdBook/releases/download/v${{ env.MDBOOK_VERSION }}/mdbook-v${{ env.MDBOOK_VERSION }}-x86_64-unknown-linux-gnu.tar.gz | tar -C /tmp/mdbook -xzv 39 | 40 | - name: Build the contents of the book 41 | run: /tmp/mdbook/mdbook build book/ -d /tmp/book 42 | 43 | - name: Check links 44 | run: linkchecker book 45 | 46 | - name: Upload GitHub Pages content 47 | uses: actions/upload-pages-artifact@v3 48 | with: 49 | path: /tmp/book 50 | 51 | deploy: 52 | name: Deploy 53 | runs-on: ubuntu-latest 54 | 55 | needs: [build] 56 | if: github.event_name == 'push' && github.ref == 'refs/heads/main' 57 | 58 | environment: 59 | name: github-pages 60 | url: ${{ steps.deployment.outputs.page_url }} 61 | permissions: 62 | contents: read 63 | pages: write 64 | id-token: write 65 | 66 | steps: 67 | - name: Deploy to GitHub Pages 68 | uses: actions/deploy-pages@v4 69 | id: deployment 70 | -------------------------------------------------------------------------------- /book/src/03_3_button.md: -------------------------------------------------------------------------------- 1 | # Detect a button press 2 | 3 | We are now going to make the LED ligth only when we press a button, we will create a 4 | project that reads the state of the button GPIO and reacts to its state. 5 | 6 | 7 | ## Setup 8 | 9 | ✅ Go to `intro/button` directory. 10 | 11 | ✅ Open the prepared project skeleton in `intro/button`. 12 | 13 | ✅ Open the docs for this project with the following command: 14 | 15 | ``` 16 | cargo doc --open 17 | ``` 18 | 19 | `intro/button/examples/button.rs` contains the solution. You can run it with the following command: 20 | 21 | ```shell 22 | cargo run --release --example button 23 | ``` 24 | 25 | ## Exercise 26 | 27 | Most of the dev-boards have a button, in our case, we will use the one labeled [`BOOT` on `GPIO9`]. 28 | 29 | 30 | ✅ Initiate the Io peripheral, and create variable for the LED and button, the LED can be created using the 31 | [`into_push_pull_output` function][into-push-pull-output] as before while the button can be obtained using 32 | [`into_pull_up_input` function][into-pull-up-input]. 33 | 34 | Similarly to turning a `GPIO` into an `output` we can turn it into an `input`. Then we can get the current state of the `input` pin with `is_high` and similar functions. 35 | 36 | ✅ In the `loop`, add some logic so if the button is not pressed, the LED is lit. If the button is pressed, the LED is off. 37 | 38 | [`BOOT` on `GPIO9`]: https://github.com/esp-rs/esp-rust-board#ios 39 | [into-pull-up-input]: https://docs.esp-rs.org/esp-hal/esp-hal/0.16.1/esp32c3/esp_hal/gpio/struct.GpioPin.html#method.into_pull_up_input 40 | [into-push-pull-output]: https://docs.esp-rs.org/esp-hal/esp-hal/0.16.1/esp32c3/esp_hal/gpio/struct.GpioPin.html#method.into_push_pull_output 41 | 42 | ## Simulation 43 | 44 | This project is available for simulation through two methods: 45 | - Wokwi projects: 46 | - Exercise: Currently not available 47 | - [Solution](https://wokwi.com/projects/382725583123606529?build-cache=disable) 48 | - Wokwi files are also present in the project folder to simulate it with Wokwi VS Code extension: 49 | 1. Press F1, select `Wokwi: Select Config File` and choose `intro/button/wokwi.toml` 50 | - Edit the `wokwi.toml` file to select between exercise and solution simulation 51 | 2. Build you project 52 | 3. Press F1 again and select `Wokwi: Start Simulator` 53 | -------------------------------------------------------------------------------- /book/src/01_intro.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | # Introduction 4 | 5 | ## Content of this material 6 | 7 | The goal of this book is to provide a getting-started guide on using the Rust programming language with Espressif SoCs and modules using `no_std` (bare metal) approach. To better understand this approach, see [Developing on Bare Metal (no_std)] chapter of [The Rust on ESP Book]. 8 | 9 | The introductory trail will introduce you to the basics of embedded development and how to make the embedded board interact with the outside world by reacting to a button press, and lighting an LED. 10 | 11 | > Note that there are several examples covering the use of specific peripherals under the examples folder of `esp-hal`. See [`esp-hal/examples`]. 12 | 13 | If you would like to learn about `std` development, see [Using the Standard Library (std)] chapter of [The Rust on ESP Book] and, 14 | [Embedded Rust on Espressif] training. 15 | 16 | You can join the [esp-rs community](https://matrix.to/#/#esp-rs:matrix.org) on Matrix for all technical questions and issues! The community is open to everyone. 17 | 18 | ## The board 19 | 20 | Examples shown here usually apply to ESP32-C3 using the [ESP32-C3-DevKit-RUST-1] board. 21 | 22 | You can use any [SoC supported by `no_std`] but smaller code and configuration changes might be needed. 23 | 24 | ## Rust knowledge 25 | 26 | - Basic Rust like [The Rust Book](https://doc.rust-lang.org/book/) Chapters 1 - 6, Chapter 4 Ownership, does not need to be fully understood. 27 | - [The Rust on ESP Book](https://esp-rs.github.io/book/) is not required, but it is highly recommended, as it can help you understand the Rust on ESP ecosystem and many of the concepts that will be discussed during the training. 28 | 29 | 30 | [The Rust on ESP Book]: https://esp-rs.github.io/book/overview/bare-metal.html 31 | [Developing on Bare Metal (no_std)]: https://esp-rs.github.io/book/overview/bare-metal.html 32 | [ESP32-C3-DevKit-RUST-1]: https://github.com/esp-rs/esp-rust-board 33 | [`esp-hal/examples`]: https://github.com/esp-rs/esp-hal/tree/main/examples/src/bin 34 | [SoC supported by `no_std`]: https://esp-rs.github.io/book/overview/bare-metal.html#current-support 35 | [Using the Standard Library (std)]: https://esp-rs.github.io/book/overview/using-the-standard-library.html 36 | [Embedded Rust on Espressif]: https://esp-rs.github.io/std-training/ 37 | -------------------------------------------------------------------------------- /book/src/02_0_preparations.md: -------------------------------------------------------------------------------- 1 | # Preparations 2 | 3 | This chapter contains information about the course material, the required hardware, and an installation guide. 4 | 5 | ## Icons and Formatting We Use 6 | 7 | We use Icons to mark different kinds of information in the book: 8 | * ✅ Call for action. 9 | * ⚠️ Warnings, details that require special attention. 10 | * 🔎 Knowledge that dives deeper into a subject but which you are not required to understand, proceeding. 11 | * 💡 Hints that might help you during the exercises 12 | 13 | > Example note: Notes like this one contain helpful information 14 | 15 | ## Code Annotations 16 | 17 | In some Rust files, you can find some anchor comments: 18 | ```rust,ignore 19 | // ANCHOR: test 20 | let foo = 1; 21 | ... 22 | // ANCHOR_END: test 23 | ``` 24 | Anchor comments can be ignored, they are only used to introduce those parts of code in this book. See [`mdBook` documentation](https://rust-lang.github.io/mdBook/format/mdbook.html#including-portions-of-a-file) 25 | 26 | ## Required Hardware 27 | 28 | - [Rust ESP Board](https://github.com/esp-rs/esp-rust-board): available on Mouser, Aliexpress. [Full list of vendors](https://github.com/esp-rs/esp-rust-board#where-to-buy). 29 | - USB-C cable suitable to connect the board to your development computer. 30 | - Wi-Fi access point connected to the Internet. 31 | 32 | > No additional debugger/probe hardware is required. 33 | 34 | ## Simulating Projects 35 | 36 | Certain projects can be simulated with [Wokwi][wokwi]. Look for indications in the book to identify projects available for simulation. Simulation can be accomplished through two methods: 37 | - Using wokwi.com: Conduct the build process and code editing directly through the browser. 38 | - Using [Wokwi VS Code extension][wokwi-vscode]: Leverage VS Code to edit projects and perform builds. Utilize the Wokwi VS Code extension to simulate the resulting binaries. 39 | - This approach requires some [installation][wokwi-installation] 40 | - This approach assumes that the project is built in debug mode 41 | - This approach allows [debugging the project][wokwi-debug] 42 | 43 | [wokwi]: https://wokwi.com/ 44 | [wokwi-vscode]: https://docs.wokwi.com/vscode/getting-started 45 | [wokwi-installation]: https://docs.wokwi.com/vscode/getting-started#installation 46 | [wokwi-debug]: https://docs.wokwi.com/vscode/debugging 47 | 48 | ## Companion Material 49 | 50 | - [Official esp-rs book](https://esp-rs.github.io/book/introduction.html) 51 | -------------------------------------------------------------------------------- /book/src/03_2_blinky.md: -------------------------------------------------------------------------------- 1 | # Blinky 2 | 3 | Let's see how to create the iconic _Blinky_. 4 | 5 | 6 | ## Setup 7 | 8 | ✅ Go to `intro/blinky` directory. 9 | 10 | ✅ Open the prepared project skeleton in `intro/blinky`. 11 | 12 | ✅ Open the docs for this project with the following command: 13 | 14 | ``` 15 | cargo doc --open 16 | ``` 17 | 18 | `intro/blinky/examples/blinky.rs` contains the solution. You can run it with the following command: 19 | 20 | ```shell 21 | cargo run --release --example blinky 22 | ``` 23 | 24 | ## Exercise 25 | 26 | On [ESP32-C3-DevKit-RUST-1] there is a regular [LED connected to GPIO 7]. If you use another board consult the data-sheet. 27 | 28 | > Note that most of the development boards from Espressif today use an addressable LED which works differently and is beyond the scope of this book. In that case, you can also connect a regular LED to some of the free pins (and don't forget to add a resistor). 29 | 30 | ✅ Initiate the Io peripheral, and create a `led` variable from GPIO connected to the LED, using the 31 | [`into_push_pull_output` function][into-push-pull-output]. 32 | 33 | Here we see that we can drive the pin `high`, `low`, or `toggle` it. 34 | 35 | We also see that the HAL offers a way to delay execution. 36 | 37 | ✅ Initialize a Delay instance. 38 | 39 | ✅ Using the [`toogle()`][toogle] and [`delay_ms()`][delay-ms] methods, make the LED blink every 500 ms. 40 | 41 | 42 | [ESP32-C3-DevKit-RUST-1]: https://github.com/esp-rs/esp-rust-board 43 | [LED connected to GPIO 7]: https://github.com/esp-rs/esp-rust-board#pin-layout 44 | [into-push-pull-output]: https://docs.esp-rs.org/esp-hal/esp-hal/0.16.1/esp32c3/esp_hal/gpio/struct.GpioPin.html#method.into_push_pull_output 45 | [toogle]: https://docs.rs/embedded-hal/0.2.7/embedded_hal/digital/v2/trait.ToggleableOutputPin.html#tymethod.toggle 46 | [delay-ms]: https://docs.rs/embedded-hal/0.2.7/embedded_hal/blocking/delay/trait.DelayMs.html#tymethod.delay_ms 47 | 48 | ## Simulation 49 | 50 | This project is available for simulation through two methods: 51 | - Wokwi projects: 52 | - Exercise: Currently not available 53 | - [Solution](https://wokwi.com/projects/382725482391094273?build-cache=disable) 54 | - Wokwi files are also present in the project folder to simulate it with Wokwi VS Code extension: 55 | 1. Press F1, select `Wokwi: Select Config File` and choose `intro/blinky/wokwi.toml` 56 | - Edit the `wokwi.toml` file to select between exercise and solution simulation 57 | 2. Build you project 58 | 3. Press F1 again and select `Wokwi: Start Simulator` 59 | -------------------------------------------------------------------------------- /book/src/03_1_panic.md: -------------------------------------------------------------------------------- 1 | # Panic! 2 | 3 | When something goes terribly wrong in Rust there might occur a [panic]. 4 | 5 | 6 | ## Setup 7 | 8 | ✅ Go to `intro/panic` directory. 9 | 10 | ✅ Open the prepared project skeleton in `intro/panic`. 11 | 12 | ✅ Open the docs for this project with the following command: 13 | 14 | ``` 15 | cargo doc --open 16 | ``` 17 | 18 | `intro/panic/examples/panic.rs` contains the solution. You can run it with the following command: 19 | 20 | ```shell 21 | cargo run --example panic 22 | ``` 23 | 24 | ## Exercise 25 | 26 | ✅ In `main.rs` add a `panic!` somewhere, e.g. after our `println` 27 | 28 | ✅ Run the code 29 | 30 | ```shell 31 | cargo run 32 | ``` 33 | 34 | We see where the panic occurred, and we even see a backtrace! 35 | 36 | While in this example things are obvious, this will come in handy in more complex code. 37 | 38 | ✅ Now try running the code compiled with release profile. 39 | 40 | ```shell 41 | cargo run --release 42 | ``` 43 | 44 | Now things are less pretty: 45 | ```text 46 | !! A panic occured in 'examples\panic.rs', at line 15, column 5: 47 | This is a panic 48 | 49 | Backtrace: 50 | 51 | 0x42000100 52 | 0x42000100 - _start_rust 53 | at ??:?? 54 | ``` 55 | 56 | We still see where the panic occurred, but the backtrace is less helpful now. 57 | 58 | That is because the compiler omitted debug information and optimized the code, 59 | you might have noticed the difference in the size of the flashed binary. 60 | 61 | Generally you want to use `release` always. To get a more helpful backtrace when using the `release` profile you can add this to your `.cargo/config.toml` 62 | 63 | ```toml 64 | [profile.release] 65 | debug = true 66 | ``` 67 | 68 | This will include debug information in the ELF file - but that won't get flashed to the target so it's something you can and should always use. 69 | 70 | If you are reusing this project for other exercises, be sure to remove the line causing the explicit panic. 71 | 72 | [panic]: https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-with-panic.html 73 | 74 | ## Simulation 75 | 76 | This project is available for simulation through two methods: 77 | - Wokwi projects: 78 | - Exercise: Currently not available 79 | - [Solution](https://wokwi.com/projects/382726300037178369?build-cache=disable) 80 | - Wokwi files are also present in the project folder to simulate it with Wokwi VS Code extension: 81 | 1. Press F1, select `Wokwi: Select Config File` and choose `intro/panic/wokwi.toml` 82 | - Edit the `wokwi.toml` file to select between exercise and solution simulation 83 | 2. Build you project 84 | 3. Press F1 again and select `Wokwi: Start Simulator` 85 | -------------------------------------------------------------------------------- /book/src/03_7_defmt.md: -------------------------------------------------------------------------------- 1 | # `defmt` 2 | In this chapter, we will cover [`defmt`][defmt], a highly efficient logging framework, and how to use it in the `no_std` environment. 3 | 4 | 5 | [defmt]: https://defmt.ferrous-systems.com/ 6 | 7 | ## `defmt` Ecosystem 8 | 9 | [`esp-println`][esp-println], [`esp-backtrace`][esp-backtrace] and [`espflash`/`cargo-espflash`][espflash] provide mechanisms to use `defmt`: 10 | - `espflash` has support for different [logging formats][espflash-logformat], one of them being `defmt`. 11 | - `espflash` requires framming bytes as when using `defmt` it also needs to print non-`defmt` messages, like the bootloader prints. 12 | - It's important to note that other `defmt`-enabled tools like `probe-rs` won't be able to parse these messages due to the extra framing bytes. 13 | - Uses [rzcobs encoding](https://github.com/Dirbaio/rzcobs) 14 | - `esp-println` has a `defmt-espflash` feature, which adds framming bytes so `espflash` knows that is a `defmt` message. 15 | - `esp-backtrace` has a `defmt` feature that uses `defmt` logging to print panic and exception handler messages. 16 | 17 | 18 | [esp-println]: https://github.com/esp-rs/esp-hal/tree/main/esp-println 19 | [esp-backtrace]: https://github.com/esp-rs/esp-hal/tree/main/esp-backtrace 20 | [espflash]: https://github.com/esp-rs/espflash 21 | [espflash-logformat]: https://github.com/esp-rs/espflash/blob/main/espflash/README.md#logging-format 22 | 23 | # Setup 24 | 25 | ✅ Go to `intro/defmt` directory. 26 | 27 | ✅ Open the prepared project skeleton in `intro/defmt`. 28 | 29 | `intro/defmt/examples/defmt.rs` contains the solution. You can run it with the following command: 30 | 31 | ```shell 32 | cargo run --release --example defmt 33 | ``` 34 | 35 | ## Exercise 36 | 37 | ✅ Make sure the `defmt-espflash` feature of `esp-println` is enabled. 38 | 39 | ✅ Make sure the `defmt` feature of `esp-backtrace` is enabled. 40 | 41 | ✅ Update the [linking process](https://defmt.ferrous-systems.com/setup#linker-script) in the `.cargo/config.toml`. 42 | 43 | ✅ Make sure, the [`defmt` crate](https://crates.io/crates/defmt) is added to the dependencies. 44 | 45 | ✅ Make sure you are building `esp_println` and `esp_backtrace` 46 | ```rust,ignore 47 | {{#include ../../intro/defmt/examples/defmt.rs:println_include}} 48 | ``` 49 | 50 | ✅ Use the `defmt::println!` or any of the logging [`defmt` macros](https://docs.rs/defmt/latest/defmt/#macros) to print a message. 51 | - If you want to use any of the logging macros like `info`, `debug` 52 | - Enable the `log` feature of `esp-println` 53 | - When building the app, [set `DEFMT_LOG`](https://defmt.ferrous-systems.com/filtering.html?highlight=DEFMT_LOG#defmt_log) level. 54 | 55 | ✅ Add a `panic!` macro to trigger a panic with a `defmt` message. 56 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # There are a few Dockerfile restrictions when using Github Actions 2 | # See: https://docs.github.com/en/actions/creating-actions/dockerfile-support-for-github-actions 3 | 4 | FROM debian:bullseye-slim 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | ENV LC_ALL=C.UTF-8 7 | ENV LANG=C.UTF-8 8 | ARG CONTAINER_USER=esp 9 | ARG CONTAINER_GROUP=esp 10 | ARG NIGHTLY_VERSION=nightly-2023-11-14 11 | ARG ESP_BOARD=esp32c3 12 | 13 | RUN apt-get update \ 14 | && apt-get install -y git curl ninja-build llvm-dev libclang-dev \ 15 | clang unzip python3 python3-pip pkg-config libssl-dev \ 16 | && apt-get clean -y \ 17 | && rm -rf /var/lib/apt/lists/* /tmp/library-scripts 18 | 19 | RUN adduser --disabled-password --gecos "" ${CONTAINER_USER} 20 | USER ${CONTAINER_USER} 21 | WORKDIR /home/${CONTAINER_USER} 22 | 23 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ 24 | --default-toolchain ${NIGHTLY_VERSION} -y --profile minimal \ 25 | --component rust-src,clippy,rustfmt --target riscv32imc-unknown-none-elf 26 | 27 | ENV PATH=${PATH}:$HOME/.cargo/bin 28 | 29 | RUN ARCH=$($HOME/.cargo/bin/rustup show | grep "Default host" | sed -e 's/.* //') && \ 30 | curl -L "https://github.com/esp-rs/espflash/releases/latest/download/cargo-espflash-${ARCH}.zip" -o "${HOME}/.cargo/bin/cargo-espflash.zip" && \ 31 | unzip "${HOME}/.cargo/bin/cargo-espflash.zip" -d "${HOME}/.cargo/bin/" && \ 32 | rm "${HOME}/.cargo/bin/cargo-espflash.zip" && \ 33 | chmod u+x "${HOME}/.cargo/bin/cargo-espflash" && \ 34 | curl -L "https://github.com/esp-rs/espflash/releases/latest/download/espflash-${ARCH}.zip" -o "${HOME}/.cargo/bin/espflash.zip" && \ 35 | unzip "${HOME}/.cargo/bin/espflash.zip" -d "${HOME}/.cargo/bin/" && \ 36 | rm "${HOME}/.cargo/bin/espflash.zip" && \ 37 | chmod u+x "${HOME}/.cargo/bin/espflash" && \ 38 | curl -L "https://github.com/esp-rs/esp-web-flash-server/releases/latest/download/web-flash-${ARCH}.zip" -o "${HOME}/.cargo/bin/web-flash.zip" && \ 39 | unzip "${HOME}/.cargo/bin/web-flash.zip" -d "${HOME}/.cargo/bin/" && \ 40 | rm "${HOME}/.cargo/bin/web-flash.zip" && \ 41 | chmod u+x "${HOME}/.cargo/bin/web-flash" && \ 42 | GENERATE_VERSION=$(git ls-remote --refs --sort="version:refname" --tags "https://github.com/cargo-generate/cargo-generate" | cut -d/ -f3- | tail -n1) && \ 43 | GENERATE_URL="https://github.com/cargo-generate/cargo-generate/releases/latest/download/cargo-generate-${GENERATE_VERSION}-${ARCH}.tar.gz" && \ 44 | curl -L "${GENERATE_URL}" -o "${HOME}/.cargo/bin/cargo-generate.tar.gz" && \ 45 | tar xf "${HOME}/.cargo/bin/cargo-generate.tar.gz" -C "${HOME}/.cargo/bin/" && \ 46 | rm "${HOME}/.cargo/bin/cargo-generate.tar.gz" && \ 47 | chmod u+x "${HOME}/.cargo/bin/cargo-generate" 48 | 49 | CMD "/bin/bash" 50 | -------------------------------------------------------------------------------- /book/src/03_4_interrupt.md: -------------------------------------------------------------------------------- 1 | # Detect a button press with interrupt 2 | 3 | Now, instead of polling the button pin, we will use interrupts. [Interrupts] offer a mechanism by which the processor handles asynchronous events and fatal errors. 4 | 5 | 6 | ## Setup 7 | 8 | ✅ Go to `intro/button-interrupt` directory. 9 | 10 | ✅ Open the prepared project skeleton in `intro/button-interrupt`. 11 | 12 | ✅ Open the docs for this project with the following command: 13 | 14 | ``` 15 | cargo doc --open 16 | ``` 17 | 18 | `intro/button-interrupt/examples/button-interrupt.rs` contains the solution. You can run it with the following command: 19 | 20 | ```shell 21 | cargo run --release --example button-interrupt 22 | ``` 23 | 24 | ## Exercise 25 | 26 | Inspecting the code, the first thing we notice is the `static BUTTON`. We need it since in the interrupt handler we have to clear the pending interrupt on the button and we somehow need to pass the button from main to the interrupt handler. 27 | 28 | Since an interrupt handler can't have arguments we need a static to get the button into the interrupt handler. 29 | 30 | We need the `Mutex` to make access to the button safe. 31 | 32 | > Please note that this is not the Mutex you might know from `libstd` but it's the Mutex from [`critical-section`] (and that's why we need to add it as a dependency). 33 | 34 | ✅ We need to set the interrupt handler for the GPIO interrupts. 35 | 36 | ✅ Let's add a [`critical-section`], using the `with()` method and enable an interrupt for falling edges: 37 | 38 | ```rust,ignore 39 | {{#include ../../intro/button-interrupt/examples/button-interrupt.rs:critical_section}} 40 | ``` 41 | In this line we move our button into the `static BUTTON` for the interrupt handler to get hold of it. 42 | 43 | The code running inside the `critical_section::with` closure runs within a critical section, 44 | `cs` is a token that you can use to "prove" that to some API. 45 | 46 | The interrupt handler is defined via the `#[handler]` macro. 47 | Here, the name of the function must match the interrupt. 48 | 49 | [Interrupts]: https://docs.rust-embedded.org/book/start/interrupts.html 50 | [`critical-section`]: https://crates.io/crates/critical-section 51 | 52 | ## Simulation 53 | 54 | This project is available for simulation through two methods: 55 | - Wokwi projects: 56 | - Exercise: Currently not available 57 | - [Solution](https://wokwi.com/projects/382723722184136705?build-cache=disable) 58 | - Wokwi files are also present in the project folder to simulate it with Wokwi VS Code extension: 59 | 1. Press F1, select `Wokwi: Select Config File` and choose `intro/button-interrupt/wokwi.toml` 60 | - Edit the `wokwi.toml` file to select between exercise and solution simulation 61 | 2. Build you project 62 | 3. Press F1 again and select `Wokwi: Start Simulator` 63 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - "book/" 7 | - "book/**" 8 | - "**/README.md" 9 | - ".github/workflows/wokwi_projects.yml" 10 | pull_request: 11 | paths-ignore: 12 | - "book/" 13 | - "book/**" 14 | - "**/README.md" 15 | - ".github/workflows/wokwi_projects.yml" 16 | schedule: 17 | - cron: "50 7 * * *" 18 | 19 | env: 20 | CARGO_TERM_COLOR: always 21 | SSID: Wokwi-GUEST 22 | PASSWORD: "" 23 | 24 | jobs: 25 | hello-world: 26 | name: hello-world 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v4 30 | 31 | - uses: dtolnay/rust-toolchain@v1 32 | with: 33 | target: riscv32imc-unknown-none-elf 34 | toolchain: nightly 35 | components: rust-src 36 | 37 | - run: cargo build --release 38 | working-directory: intro/hello-world 39 | 40 | - name: Wokwi CI check 41 | if: github.actor == 'esp-rs' 42 | uses: wokwi/wokwi-ci-action@v1 43 | with: 44 | token: ${{ secrets.WOKWI_CLI_TOKEN }} 45 | path: intro/hello-world 46 | timeout: 30000 47 | scenario: ${{ github.workspace }}/.github/hello-world.test.yaml 48 | fail_text: 'Error' 49 | 50 | examples: 51 | name: ${{ matrix.project.name }} 52 | runs-on: ubuntu-latest 53 | strategy: 54 | fail-fast: false 55 | matrix: 56 | project: 57 | - name: "blinky" 58 | path: "intro/blinky" 59 | - name: "button" 60 | path: "intro/button" 61 | - name: "button-interrupt" 62 | path: "intro/button-interrupt" 63 | - name: "panic" 64 | path: "intro/panic" 65 | - name: "http-client" 66 | path: "intro/http-client" 67 | - name: "defmt" 68 | path: "intro/defmt" 69 | - name: "stack-overflow-detection" 70 | path: "advanced/stack-overflow-detection" 71 | steps: 72 | - uses: actions/checkout@v4 73 | 74 | - uses: dtolnay/rust-toolchain@v1 75 | with: 76 | target: riscv32imc-unknown-none-elf 77 | toolchain: nightly 78 | components: rust-src 79 | 80 | - run: cargo build --release --examples 81 | working-directory: ${{ matrix.project.path }} 82 | 83 | - name: Wokwi CI check 84 | if: (matrix.project.name != 'stack-overflow-detection' || matrix.project.name != 'defmt') && github.actor == 'esp-rs' 85 | uses: wokwi/wokwi-ci-action@v1 86 | with: 87 | token: ${{ secrets.WOKWI_CLI_TOKEN }} 88 | path: ${{ matrix.project.path }} 89 | timeout: 30000 90 | scenario: ${{ github.workspace }}/.github/${{ matrix.project.name }}.test.yaml 91 | fail_text: 'Error' 92 | -------------------------------------------------------------------------------- /advanced/stack-overflow-detection/examples/stack-overflow-detection.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::cell::RefCell; 5 | 6 | use critical_section::Mutex; 7 | use esp_backtrace as _; 8 | use esp_hal::{ 9 | assist_debug::DebugAssist, clock::ClockControl, peripherals::Peripherals, prelude::*, 10 | system::SystemControl, 11 | }; 12 | use esp_println::println; 13 | 14 | #[entry] 15 | fn main() -> ! { 16 | let peripherals = Peripherals::take(); 17 | let system = SystemControl::new(peripherals.SYSTEM); 18 | let _ = ClockControl::boot_defaults(system.clock_control).freeze(); 19 | 20 | // get the debug assist driver 21 | let da = DebugAssist::new(peripherals.ASSIST_DEBUG, Some(interrupt_handler)); 22 | 23 | // set up stack overflow protection 24 | install_stack_guard(da, 4096); 25 | 26 | boom(); 27 | 28 | loop {} 29 | } 30 | 31 | #[inline(never)] 32 | fn boom() { 33 | deadly_recursion([0u8; 2048]); 34 | } 35 | 36 | #[ram] 37 | #[allow(unconditional_recursion)] 38 | fn deadly_recursion(data: [u8; 2048]) { 39 | static mut COUNTER: u32 = 0; 40 | 41 | println!( 42 | "Iteration {}, data {:02x?}...", 43 | unsafe { COUNTER }, 44 | &data[0..10] 45 | ); 46 | 47 | unsafe { 48 | COUNTER = COUNTER.wrapping_add(1); 49 | }; 50 | 51 | deadly_recursion([0u8; 2048]); 52 | } 53 | 54 | // ANCHOR: debug_assists 55 | static DA: Mutex>> = Mutex::new(RefCell::new(None)); 56 | 57 | fn install_stack_guard(mut da: DebugAssist<'static>, safe_area_size: u32) { 58 | extern "C" { 59 | static mut _stack_end: u32; 60 | static mut _stack_start: u32; 61 | } 62 | let stack_low = unsafe { (&mut _stack_end as *mut _ as *mut u32) as u32 }; 63 | let stack_high = unsafe { (&mut _stack_start as *mut _ as *mut u32) as u32 }; 64 | println!( 65 | "Safe stack {} bytes", 66 | stack_high - stack_low - safe_area_size 67 | ); 68 | da.enable_region0_monitor(stack_low, stack_low + safe_area_size, true, true); 69 | 70 | critical_section::with(|cs| DA.borrow_ref_mut(cs).replace(da)); 71 | } 72 | // ANCHOR_END: debug_assists 73 | 74 | // ANCHOR: interrupt 75 | // ANCHOR: handler 76 | #[handler(priority = esp_hal::interrupt::Priority::min())] 77 | fn interrupt_handler() { 78 | // ANCHOR_END: interrupt 79 | 80 | critical_section::with(|cs| { 81 | println!("\n\nPossible Stack Overflow Detected"); 82 | let mut da = DA.borrow_ref_mut(cs); 83 | let da = da.as_mut().unwrap(); 84 | 85 | if da.is_region0_monitor_interrupt_set() { 86 | let pc = da.get_region_monitor_pc(); 87 | println!("PC = 0x{:x}", pc); 88 | da.clear_region0_monitor_interrupt(); 89 | da.disable_region0_monitor(); 90 | loop {} 91 | } 92 | }); 93 | } 94 | // ANCHOR_END: handler 95 | -------------------------------------------------------------------------------- /intro/dma/examples/dma.rs: -------------------------------------------------------------------------------- 1 | // To easily test this you can connect GPIO2 and GPIO4 2 | // This way we will receive was we send. (loopback) 3 | 4 | #![no_std] 5 | #![no_main] 6 | 7 | use esp_backtrace as _; 8 | use esp_hal::{ 9 | clock::ClockControl, 10 | delay::Delay, 11 | dma::Dma, 12 | dma::DmaPriority, 13 | dma_buffers, 14 | gpio::Io, 15 | peripherals::Peripherals, 16 | prelude::*, 17 | spi::{ 18 | master::{prelude::*, Spi}, 19 | SpiMode, 20 | }, 21 | system::SystemControl, 22 | }; 23 | use esp_println::{print, println}; 24 | 25 | #[entry] 26 | fn main() -> ! { 27 | let peripherals = Peripherals::take(); 28 | let system = SystemControl::new(peripherals.SYSTEM); 29 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 30 | 31 | let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); 32 | let sclk = io.pins.gpio0; 33 | let miso = io.pins.gpio2; 34 | let mosi = io.pins.gpio4; 35 | let cs = io.pins.gpio5; 36 | 37 | // ANCHOR: init-dma 38 | // we need to create the DMA driver and get a channel 39 | let dma = Dma::new(peripherals.DMA); 40 | let dma_channel = dma.channel0; 41 | 42 | // DMA transfers need descriptors and buffers 43 | let (mut tx_buffer, mut tx_descriptors, mut rx_buffer, mut rx_descriptors) = dma_buffers!(3200); 44 | // ANCHOR_END: init-dma 45 | 46 | // ANCHOR: configure-spi 47 | // we can call `.with_dma` on the SPI driver to make it use DMA 48 | let mut spi = Spi::new(peripherals.SPI2, 100u32.kHz(), SpiMode::Mode0, &clocks) 49 | .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) 50 | .with_dma(dma_channel.configure( 51 | false, 52 | &mut tx_descriptors, 53 | &mut rx_descriptors, 54 | DmaPriority::Priority0, 55 | )); 56 | // ANCHOR_END: configure-spi 57 | 58 | let delay = Delay::new(&clocks); 59 | 60 | // populate the tx_buffer with data to send 61 | tx_buffer.fill(0x42); 62 | 63 | loop { 64 | // ANCHOR: transfer 65 | // `dma_transfer` will move the driver and the buffers into the 66 | // returned transfer. 67 | let mut transfer = spi.dma_transfer(&mut tx_buffer, &mut rx_buffer).unwrap(); 68 | // ANCHOR_END: transfer 69 | 70 | // here the CPU could do other things while the transfer is taking done without using the CPU 71 | while !transfer.is_done() { 72 | print!("."); 73 | } 74 | 75 | // ANCHOR: transfer-wait 76 | // the buffers and spi are moved into the transfer and 77 | // we can get it back via `wait` 78 | // if the transfer isn't completed this will block 79 | transfer.wait().unwrap(); 80 | // ANCHOR_END: transfer-wait 81 | 82 | println!(); 83 | println!( 84 | "Received {:x?} .. {:x?}", 85 | &rx_buffer[..10], 86 | &rx_buffer[rx_buffer.len() - 10..] 87 | ); 88 | 89 | delay.delay_millis(2500u32); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /book/src/02_4_hello_world.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | The `hello-world` example is basically a project generated with [esp-template]. Templates are already covered in [The Rust on ESP Book], see [Generating Projects from Templates] chapter for more details on how to generate a project from the [esp-template], and [Understanding esp-template] for detail on what is inside the template project. 4 | 5 | Since we already have the code for this example, let's use it to do a consistency check! 6 | 7 | ✅ Connect the USB-C port of the board to your computer and enter the `hello-world` directory in the workshop repository: 8 | 9 | ```console 10 | cd intro/hello-world 11 | ``` 12 | 13 | ✅ Build, flash, and monitor the project: 14 | 15 | ```console 16 | $ cargo run 17 | (...) 18 | Finished release [optimized] target(s) in 1.78s 19 | (...) 20 | Chip type: esp32c3 (revision v0.3) 21 | Crystal frequency: 40MHz 22 | Flash size: 4MB 23 | Features: WiFi, BLE 24 | MAC address: 60:55:f9:c0:39:7c 25 | App/part. size: 210,608/4,128,768 bytes, 5.10% 26 | [00:00:00] [========================================] 13/13 0x0 27 | [00:00:00] [========================================] 1/1 0x8000 28 | [00:00:01] [========================================] 67/67 0x10000 29 | [00:00:01] [========================================] 67/67 0x10000 30 | [2023-07-07T08:16:32Z INFO ] Flashing has completed! 31 | Commands: 32 | CTRL+R Reset chip 33 | CTRL+C Exit 34 | (...) 35 | (...) 36 | Hello world! 37 | ``` 38 | 39 | >🔎 If `cargo run` has been successful, you can exit with `ctrl+C`. 40 | 41 | > 🔎 `cargo run` is [configured to use `espflash`](https://github.com/esp-rs/no_std-training/blob/main/intro/hello-world/.cargo/config.toml#L2) as [custom runner](https://doc.rust-lang.org/cargo/reference/config.html#target). The same output can be achieved via: 42 | > - Using `cargo-espflash`: `cargo espflash flash --release --monitor` 43 | > - Building your project and flashing it with `espflash`: `cargo build --release && espflash target/riscv32imc-unknown-none-elf/release/hello_world` 44 | > This modification is applied to all the projects in the training for convenience. 45 | 46 | > 💡 By default espflash will use a baud-rate of 115200 which is quite conservative. An easy way to increase the baud-rate is setting the environment variable `ESPFLASH_BAUD` to e.g. 921600 47 | 48 | [esp-template]: https://github.com/esp-rs/esp-template 49 | [The Rust on ESP Book]: https://esp-rs.github.io/book/ 50 | [Generating Projects from Templates]: https://esp-rs.github.io/book/writing-your-own-application/generate-project/index.html 51 | [Understanding esp-template]: https://esp-rs.github.io/book/writing-your-own-application/generate-project/esp-template.html 52 | 53 | ## Simulation 54 | 55 | This project is available for simulation through two methods: 56 | - [Wokwi project](https://wokwi.com/projects/382725628217620481?build-cache=disable) 57 | - Wokwi VS Code extension: 58 | 1. Press F1, select `Wokwi: Select Config File`, and choose `intro/hello-world/wokwi.toml`. 59 | 2. Build your project. 60 | 3. Press F1 again and select `Wokwi: Start Simulator`. 61 | -------------------------------------------------------------------------------- /.github/workflows/wokwi_projects.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Wokwi.com CI 3 | 4 | on: 5 | push: 6 | paths: 7 | - '.github/workflows/wokwi_projects.yml' 8 | pull_request: 9 | paths: 10 | - '.github/workflows/wokwi_projects.yml' 11 | schedule: 12 | - cron: "50 7 * * *" 13 | workflow_dispatch: 14 | 15 | jobs: 16 | wokwi-check: 17 | name: ${{ matrix.project.name }} 18 | if: github.repository == 'esp-rs/no_std-training' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' 19 | runs-on: ubuntu-latest 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | project: 24 | # - name: "hello-world" 25 | # id: "382725628217620481" 26 | # path: "intro/hello-world" 27 | - name: blinky 28 | id: "382725482391094273" 29 | path: "intro/blinky" 30 | - name: button 31 | id: "382725583123606529" 32 | path: "intro/button" 33 | - name: button-interrupt 34 | id: "382723722184136705" 35 | path: "intro/button-interrupt" 36 | - name: panic 37 | id: "382726300037178369" 38 | path: "intro/panic" 39 | 40 | steps: 41 | - name: Checkout the repository 42 | uses: actions/checkout@v4 43 | 44 | - name: Download project code 45 | run: | 46 | wget -q -O ${{ matrix.project.name }}.zip https://wokwi.com/api/projects/${{ matrix.project.id }}/zip 47 | unzip ${{ matrix.project.name }}.zip -d ${{ matrix.project.name }} 48 | mkdir -p ${{ matrix.project.name }}/src 49 | rm -rf ${{ matrix.project.path }}/src/*.rs 50 | cp ${{ matrix.project.name }}/*.rs ${{ matrix.project.path }}/src/ 51 | rm -rf ${{ matrix.project.path }}/Cargo.toml 52 | cp ${{ matrix.project.name }}/Cargo.toml ${{ matrix.project.path }}/Cargo.toml 53 | 54 | - name: Create wokwi.toml 55 | run: echo -e "[wokwi]\nversion = 1\nfirmware = '${{ matrix.project.name }}/${{ matrix.project.name }}'\nelf = '${{ matrix.project.name }}/${{ matrix.project.name }}'" > ${{ matrix.project.path }}/wokwi.toml 56 | 57 | - name: Update ownership 58 | run: | 59 | sudo chown 1000:1000 -R ${{ matrix.project.path }} 60 | 61 | - name: Pull Docker image 62 | run: docker image pull espressif/idf-rust:esp32c3_latest 63 | 64 | - name: Test code example in Docker image 65 | uses: addnab/docker-run-action@v3 66 | with: 67 | image: espressif/idf-rust:esp32c3_latest 68 | options: -u esp -v ${{ github.workspace }}:/home/esp/workspace 69 | run: | 70 | cd /home/esp/workspace/${{ matrix.project.path }} 71 | export SSID="Wokwi-GUEST" && export PASSWORD="" 72 | /home/esp/.cargo/bin/cargo build --release --out-dir /home/esp/workspace/${{ matrix.project.path }}/${{ matrix.project.name }} -Z unstable-options 73 | rm -rf /home/esp/workspace/${{ matrix.project.path }}/target 74 | 75 | - run: cat ${{ matrix.project.path }}/wokwi.toml 76 | 77 | - name: Wokwi CI check 78 | uses: wokwi/wokwi-ci-action@v1 79 | with: 80 | token: ${{ secrets.WOKWI_CLI_TOKEN }} 81 | path: ${{ matrix.project.path }} 82 | timeout: 30000 83 | scenario: ${{ github.workspace }}/.github/${{ matrix.project.name }}.test.yaml 84 | fail_text: 'Error' 85 | 86 | - name: Upload source code 87 | if: success() || failure() 88 | uses: actions/upload-artifact@v4 89 | with: 90 | name: ${{ matrix.project.name }}_${{ matrix.project.id }} 91 | path: ${{ matrix.project.path }} 92 | -------------------------------------------------------------------------------- /book/src/03_5_dma_spi.md: -------------------------------------------------------------------------------- 1 | # Direct Memory Access (DMA) 2 | 3 | The DMA peripheral is used to perform memory transfers in parallel to the work of the processor (the execution of the main program). 4 | 5 | In this chapter you will learn how to use DMA with esp-hal. For the example we are going to use the [SPI] peripheral. 6 | 7 | ## Setup 8 | 9 | ✅ Go to `intro/dma` directory. 10 | 11 | ✅ Open the prepared project skeleton in `intro/dma`. 12 | 13 | ✅ Open the docs for this project with the following command: 14 | 15 | ``` 16 | cargo doc --open 17 | ``` 18 | 19 | `intro/dma/examples/dma.rs` contains the solution. You can run it with the following command: 20 | 21 | ```shell 22 | cargo run --release --example dma 23 | ``` 24 | 25 | ## Exercise 26 | 27 | The project skeleton contains code to transfer a small amount of data via SPI. To make it easy to explore the example you can connect GPIO4 and GPIO2 - this way the data we send is also the data we receive. 28 | 29 | The blocking SPI transfer looks like this 30 | ```rust,ignore 31 | {{#include ../../intro/dma/src/main.rs:transfer}} 32 | ``` 33 | 34 | The `data` array in this case serves as the data to transmit as well as the buffer to receive data. 35 | 36 | ✅ First thing we need to use DMA is initializing the DMA peripheral driver and getting a channel. 37 | 38 | We also need to create a buffer for data we want to send as well as a separate buffer for the data we will receive. 39 | 40 | ```rust,ignore 41 | {{#include ../../intro/dma/examples/dma.rs:init-dma}} 42 | ``` 43 | 44 | There are also descriptors needed. That is because internally the DMA peripheral uses a [linked list] for the transfer and that is what the descriptors are needed for. 45 | For convenience we use the `dma_buffers!` macro to create the buffers and descriptors. 46 | 47 | > 🔎 You could use `cargo expand` or Rust Analyzer's `Expand macro recursively` command to see what code the macro expands to 48 | 49 | ✅ Next we need to configure the SPI peripheral driver to use DMA 50 | 51 | We need to call `.with_dma` passing a _configured_ DMA channel. 52 | To configure a DMA channel we call `configure` to enable burst-mode, pass the descriptors and set the priority. 53 | 54 | ```rust,ignore 55 | {{#include ../../intro/dma/examples/dma.rs:configure-spi}} 56 | ``` 57 | 58 | ✅ Now we are ready to start a DMA enabled SPI transfer 59 | 60 | Now we need to pass the buffers to transmit and receive individually. Please note that we now get a `DMA transfer` from calling `transmit`. 61 | 62 | ```rust,ignore 63 | {{#include ../../intro/dma/examples/dma.rs:transfer}} 64 | ``` 65 | 66 | What happens here is that the buffers and the SPI driver are moved into the `Transfer` we get. This way the buffers and the driver are inaccessible during the transfer. 67 | 68 | Now we are free to let the CPU do other things while the SPI transfer is in progress. 69 | 70 | ✅ Wait for the transfer to complete and get back the buffers and the driver instance 71 | 72 | As mentioned before the buffers and the driver are moved into the `Transfer`. 73 | 74 | ```rust,ignore 75 | {{#include ../../intro/dma/examples/dma.rs:transfer-wait}} 76 | ``` 77 | 78 | We call `wait` on the `Transfer`. It will block until the transfer is done and we get our SPI driver and the buffers. 79 | 80 | While using DMA needs more effort than letting the CPU do all the work it's not too complex once the general idea is understood. 81 | 82 | > ⚠️ You might assume that it's always preferable to use DMA. 83 | > 84 | > That's not the case: Setting up a DMA transfer consumes more CPU cycles than setting up a blocking transfer. 85 | > Especially if the amount of data to transfer is small this might hurt performance a lot. Also, if there is nothing to do for the CPU other than waiting for the transfer to finish 86 | > it's preferable to use a blocking transfer. 87 | > 88 | > However, if the amount of data to transfer is bigger, then the time needed to setup the transfer is negligible compared to the time the CPU could use to do useful things in parallel. 89 | 90 | [SPI]: https://en.wikipedia.org/wiki/Serial_Peripheral_Interface 91 | [linked list]: https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf#page=59 92 | -------------------------------------------------------------------------------- /intro/http-client/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_hal::{ 5 | clock::ClockControl, 6 | peripherals::Peripherals, 7 | prelude::*, 8 | rng::Rng, 9 | system::SystemControl, 10 | timer::{systimer::SystemTimer, PeriodicTimer}, 11 | }; 12 | 13 | use embedded_io::*; 14 | use esp_wifi::wifi::{AccessPointInfo, AuthMethod, ClientConfiguration, Configuration}; 15 | 16 | use esp_backtrace as _; 17 | use esp_println::{print, println}; 18 | use esp_wifi::wifi::utils::create_network_interface; 19 | use esp_wifi::wifi::{WifiError, WifiStaDevice}; 20 | use esp_wifi::wifi_interface::WifiStack; 21 | use esp_wifi::{current_millis, initialize, EspWifiInitFor}; 22 | use smoltcp::iface::SocketStorage; 23 | use smoltcp::wire::IpAddress; 24 | use smoltcp::wire::Ipv4Address; 25 | 26 | const SSID: &str = env!("SSID"); 27 | const PASSWORD: &str = env!("PASSWORD"); 28 | 29 | #[entry] 30 | fn main() -> ! { 31 | let peripherals = Peripherals::take(); 32 | let system = SystemControl::new(peripherals.SYSTEM); 33 | // Set clocks at maximum frequency 34 | // let clocks = 35 | 36 | // Create a timer and initialize the Wi-Fi 37 | // let timer = 38 | // let init = 39 | 40 | // Configure Wifi 41 | let wifi = peripherals.WIFI; 42 | let mut socket_set_entries: [SocketStorage; 3] = Default::default(); 43 | let (iface, device, mut controller, sockets) = 44 | create_network_interface(&init, wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); 45 | // Create a Client with your Wi-Fi credentials and default configuration. 46 | // let client_config = Configuration::Client(.....); 47 | let res = controller.set_configuration(&client_config); 48 | println!("wifi_set_configuration returned {:?}", res); 49 | 50 | // Start Wi-Fi controller, scan the available networks. 51 | controller.start().unwrap(); 52 | println!("is wifi started: {:?}", controller.is_started()); 53 | 54 | println!("Start Wifi Scan"); 55 | let res: Result<(heapless::Vec, usize), WifiError> = controller.scan_n(); 56 | if let Ok((res, _count)) = res { 57 | for ap in res { 58 | println!("{:?}", ap); 59 | } 60 | } 61 | 62 | println!("{:?}", controller.get_capabilities()); 63 | println!("wifi_connect {:?}", controller.connect()); 64 | 65 | // Wait to get connected 66 | println!("Wait to get connected"); 67 | loop { 68 | let res = controller.is_connected(); 69 | match res { 70 | Ok(connected) => { 71 | if connected { 72 | break; 73 | } 74 | } 75 | Err(err) => { 76 | println!("{:?}", err); 77 | loop {} 78 | } 79 | } 80 | } 81 | println!("{:?}", controller.is_connected()); 82 | 83 | // Wait for getting an ip address 84 | let wifi_stack = WifiStack::new(iface, device, sockets, current_millis); 85 | println!("Wait to get an ip address"); 86 | loop { 87 | wifi_stack.work(); 88 | 89 | if wifi_stack.is_iface_up() { 90 | println!("got ip {:?}", wifi_stack.get_ip_info()); 91 | break; 92 | } 93 | } 94 | 95 | println!("Start busy loop on main"); 96 | 97 | let mut rx_buffer = [0u8; 1536]; 98 | let mut tx_buffer = [0u8; 1536]; 99 | let mut socket = wifi_stack.get_socket(&mut rx_buffer, &mut tx_buffer); 100 | 101 | loop { 102 | println!("Making HTTP request"); 103 | socket.work(); 104 | 105 | // Open the socket 106 | // socket 107 | // .open(....) 108 | // .unwrap(); 109 | // Write and flush the socket 110 | // socket... 111 | // socket... 112 | 113 | let wait_end = current_millis() + 20 * 1000; 114 | loop { 115 | let mut buffer = [0u8; 512]; 116 | if let Ok(len) = socket.read(&mut buffer) { 117 | let to_print = unsafe { core::str::from_utf8_unchecked(&buffer[..len]) }; 118 | print!("{}", to_print); 119 | } else { 120 | break; 121 | } 122 | 123 | if current_millis() > wait_end { 124 | println!("Timeout"); 125 | break; 126 | } 127 | } 128 | println!(); 129 | 130 | socket.disconnect(); 131 | 132 | let wait_end = current_millis() + 5 * 1000; 133 | while current_millis() < wait_end { 134 | socket.work(); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /book/src/03_6_http_client.md: -------------------------------------------------------------------------------- 1 | # HTTP Client 2 | Next, we'll write a small client that retrieves data over an HTTP connection to the internet. 3 | 4 | For demonstration purposes we implement the http client ourselves. Usually you want to use e.g. [`reqwless`](https://crates.io/crates/reqwless) or [`edge-net`](https://crates.io/crates/edge-net) 5 | 6 | Before jumping to the exercise, let's explore how Wi-Fi works in `no_std` Rust for Espressif devices. 7 | 8 | ## Wi-Fi Ecosystem 9 | 10 | Wi-Fi support comes in the [`esp-wifi` crate][esp-wifi]. The `esp-wifi` is home to the Wi-Fi, Bluetooth and ESP-NOW driver implementations for `no_std` Rust. 11 | Check the repository README for current support, limitations and usage details. 12 | 13 | There are some other relevant crates, on which `esp-wifi` depends on: 14 | - [`smol-tcp`][smoltcp]: Event-driven TCP/IP stack implementation. 15 | - It does not require heap allocation (which is a requirement for some `no_std` projects) 16 | - For more information about the crate, see the [official documentation][smoltcp-docs] 17 | 18 | Additionally, when using async, [`embassy-net`][embassy-net] is relevant. 19 | 20 | [esp-wifi]: https://github.com/esp-rs/esp-hal/tree/main/esp-wifi 21 | [embassy-net]: https://github.com/embassy-rs/embassy/tree/main/embassy-net 22 | [smoltcp]: https://github.com/smoltcp-rs/smoltcp 23 | [smoltcp-docs]: https://docs.rs/smoltcp/latest/smoltcp/ 24 | 25 | ## Setup 26 | 27 | ✅ Go to `intro/http-client` directory. 28 | 29 | ✅ Open the prepared project skeleton in `intro/http-client`. 30 | 31 | ✅ Add your network credentials: Set the `SSID` and `PASSWORD` environment variables. 32 | 33 | `intro/http-client/examples/http-client.rs` contains the solution. You can run it with the following command: 34 | 35 | ```shell 36 | cargo run --release --example http-client 37 | ``` 38 | 39 | ✅ Read the [Optimization Level] section of the [`esp-wifi`] README. 40 | 41 | [Optimization Level]: https://github.com/esp-rs/esp-hal/tree/main/esp-wifi#optimization-level 42 | [`esp-wifi`]: https://github.com/esp-rs/esp-hal/tree/main/esp-wifi 43 | 44 | ## Exercise 45 | 46 | ✅ Bump the [`clock`][clock] frequency at which the target operates to its maximum. Consider using `ClockControl::configure` or `ClockControl::max` 47 | 48 | ✅ Create a [`timer`][timer] and initialize the Wi-Fi 49 | ```rust,ignore 50 | {{#include ../../intro/http-client/examples/http-client.rs:wifi_init}} 51 | ``` 52 | 53 | ✅ Configure Wi-Fi using Station Mode 54 | ```rust,ignore 55 | {{#include ../../intro/http-client/examples/http-client.rs:wifi_config}} 56 | ``` 57 | 58 | ✅ Create a Client with your Wi-Fi credentials and default configuration. Look for a suitable constructor in the documentation. 59 | ```rust,ignore 60 | {{#include ../../intro/http-client/examples/http-client.rs:client_config_start}} 61 | .... 62 | {{#include ../../intro/http-client/examples/http-client.rs:client_config_end}} 63 | ``` 64 | 65 | ✅ Start the Wi-Fi controller, scan the available networks, and try to connect to the one we set. 66 | ```rust,ignore 67 | {{#include ../../intro/http-client/examples/http-client.rs:wifi_connect}} 68 | ``` 69 | 70 | ✅ Then we obtain the assigned IP 71 | ```rust,ignore 72 | {{#include ../../intro/http-client/examples/http-client.rs:ip}} 73 | ``` 74 | 75 | If the connection succeeds, we proceed with the last part, making the HTTP request. 76 | 77 | By default, only unencrypted HTTP is available, which limits our options of hosts to connect to. We're going to use `www.mobile-j.de/`. 78 | 79 | To make an HTTP request, we first need to open a socket, and write to it the GET request, 80 | 81 | ✅ Open a socket with the following IPv4 address `142.250.185.115` and port `80`. See `IpAddress::Ipv4` documentation. 82 | 83 | ✅ `write` the following message to the socket and `flush` it: `b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n"` 84 | 85 | ✅ Then we wait for the response and read it out. 86 | ```rust,ignore 87 | {{#include ../../intro/http-client/examples/http-client.rs:reponse}} 88 | ``` 89 | 90 | ✅ Finally, we will close the socket and wait 91 | ```rust,ignore 92 | {{#include ../../intro/http-client/examples/http-client.rs:socket_close}} 93 | ``` 94 | 95 | [timer]: https://docs.esp-rs.org/esp-hal/esp-hal/0.16.1/esp32c3/esp32c3/systimer/index.html 96 | [clock]: https://docs.esp-rs.org/esp-hal/esp-hal/0.16.1/esp32c3/esp_hal/clock/index.html 97 | 98 | ## Simulation 99 | 100 | This project is available for simulation through two methods: 101 | - Wokwi projects: 102 | - Exercise: Currently not available 103 | - Solution: Currently not available 104 | - Wokwi files are also present in the project folder to simulate it with Wokwi VS Code extension: 105 | 1. Press F1, select `Wokwi: Select Config File` and choose `intro/http-client/wokwi.toml` 106 | - Edit the `wokwi.toml` file to select between exercise and solution simulation 107 | 2. Build you project 108 | 3. Press F1 again and select `Wokwi: Start Simulator` 109 | -------------------------------------------------------------------------------- /book/src/02_2_software.md: -------------------------------------------------------------------------------- 1 | # Software 2 | 3 | Follow the steps below for a default installation of the ESP32-C3 platform tooling. 4 | 5 | 🔎 Should you desire a customized installation (e.g. building parts from source, or adding support for Xtensa targets), instructions for doing so can be found in the [Installation](https://esp-rs.github.io/book/installation/index.html) chapter of the *Rust on ESP* Book. 6 | 7 | ## Rust toolchain 8 | 9 | ✅ If you haven't got Rust on your computer, obtain it via 10 | 11 | Furthermore, for ESP32-C3, a [*nightly* version](https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust) of the Rust toolchain is currently required, for this training we will use `nightly-2023-11-14` version. 12 | 13 | ✅ Install *nightly* Rust and add support for the target architecture using the following command: 14 | 15 | ```console 16 | rustup toolchain install nightly-2023-11-14 --component rust-src --target riscv32imc-unknown-none-elf 17 | ``` 18 | 19 | 🔎 Rust is capable of cross-compiling to any supported target (see `rustup target list`). By default, only the native architecture of your system is installed. 20 | 21 | ## Espressif toolchain 22 | 23 | Several tools are required: 24 | - [`cargo-espflash`](https://github.com/esp-rs/espflash/tree/main/cargo-espflash) - upload firmware to the microcontroller and open serial monitor with cargo integration 25 | - [`espflash`](https://github.com/esp-rs/espflash/tree/main/espflash) - upload firmware to the microcontroller and open serial monitor 26 | 27 | ✅ Install them with the following command: 28 | 29 | ```console 30 | cargo install cargo-espflash espflash 31 | ``` 32 | 33 | ⚠️ The `espflash` and `cargo-espflash` commands listed in the book assume version is >= 2 34 | 35 | ## Toolchain dependencies 36 | 37 | ### Debian/Ubuntu 38 | 39 | ```console 40 | sudo apt install llvm-dev libclang-dev clang 41 | ``` 42 | ### macOS 43 | 44 | When using the Homebrew package manager, which we recommend: 45 | ```console 46 | brew install llvm 47 | ``` 48 | 49 | ## Docker 50 | 51 | An alternative environment, is to use Docker. The repository contains a `Dockerfile` 52 | with instructions to install the Rust toolchain, and all required packages. **This virtualized environment is designed 53 | to compile the binaries for the Espressif target. Flashing binaries from containers is not possible**, hence there are two options: 54 | - Execute flashing commands, e.g., `cargo-espflash`, on the host system. If proceeding with this option, it's recommended to keep two terminals open: 55 | - In the container: compile the project 56 | - On the host: use the `cargo-espflash` sub-command to flash the program onto the embedded hardware 57 | - Use [`web-flash`](https://github.com/esp-rs/esp-web-flash-server) crate to flash the resulting binaries from the container. The container already includes `web-flash`. Here is how you would flash the build output of [`hello-world` project](./02_4_hello-world.md): 58 | ```console 59 | web-flash --chip esp32c3 target/riscv32imc-unknown-none-elf/release/hello-world 60 | ``` 61 | 62 | ✅ Install [`Docker`](https://docs.docker.com/get-docker/) for your operating system. 63 | 64 | ✅ Get the docker image: There are 2 ways of getting the Docker image: 65 | - Build the Docker image from the `Dockerfile`: 66 | ```console 67 | docker image build --tag rust-std-training --file .devcontainer/Dockerfile . 68 | ``` 69 | Building the image takes a while depending on the OS & hardware (20-30 minutes). 70 | - Download it from [Dockerhub](https://hub.docker.com/r/espressif/rust-std-training): 71 | ```console 72 | docker pull espressif/rust-std-training 73 | ``` 74 | ✅ Start the new Docker container: 75 | ```console 76 | docker run --mount type=bind,source="$(pwd)",target=/workspace,consistency=cached -it rust-std-training /bin/bash 77 | ``` 78 | 79 | This starts an interactive shell in the Docker container. It also mounts the local repository to a folder 80 | named `/workspace` inside the container. Changes to the project on the host system are reflected inside the container & vice versa. 81 | 82 | ## Additional Software 83 | 84 | ### VS Code 85 | 86 | One editor with good Rust support is [VS Code](https://code.visualstudio.com/), which is available for most platforms. 87 | When using VS Code, we recommend the following extensions to help during the development. 88 | 89 | * [`Rust Analyzer`](https://rust-analyzer.github.io/) to provide code completion & navigation 90 | * `Even Better TOML` for editing TOML based configuration files 91 | 92 | There are a few more useful extensions for advanced usage 93 | 94 | * [`lldb`](https://github.com/vadimcn/vscode-lldb) a native debugger extension based on LLDB 95 | * [`crates`](https://github.com/serayuzgur/crates) to help manage Rust dependencies 96 | 97 | ### VS Code & Devcontainer 98 | 99 | One extension for VS Code that might be helpful to develop inside a Docker container is [`Remote Containers`](https://github.com/Microsoft/vscode-remote-release). 100 | It uses the same `Dockerfile` as the [Docker setup](#docker), but builds the image and connects to it from within VS Code. 101 | Once the extension is installed, VS Code recognizes the configuration in the `.devcontainer` folder. Use the `Remote Containers - Reopen in Container` command to connect VS Code to the container. 102 | -------------------------------------------------------------------------------- /intro/http-client/examples/http-client.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use esp_hal::{ 5 | clock::ClockControl, 6 | peripherals::Peripherals, 7 | prelude::*, 8 | rng::Rng, 9 | system::SystemControl, 10 | timer::{systimer::SystemTimer, PeriodicTimer}, 11 | }; 12 | 13 | use embedded_io::*; 14 | use esp_wifi::wifi::{AccessPointInfo, AuthMethod, ClientConfiguration, Configuration}; 15 | 16 | use esp_backtrace as _; 17 | use esp_println::{print, println}; 18 | use esp_wifi::wifi::utils::create_network_interface; 19 | use esp_wifi::wifi::{WifiError, WifiStaDevice}; 20 | use esp_wifi::wifi_interface::WifiStack; 21 | use esp_wifi::{current_millis, initialize, EspWifiInitFor}; 22 | use smoltcp::iface::SocketStorage; 23 | use smoltcp::wire::IpAddress; 24 | use smoltcp::wire::Ipv4Address; 25 | 26 | const SSID: &str = env!("SSID"); 27 | const PASSWORD: &str = env!("PASSWORD"); 28 | 29 | #[entry] 30 | fn main() -> ! { 31 | let peripherals = Peripherals::take(); 32 | let system = SystemControl::new(peripherals.SYSTEM); 33 | // Set clocks at maximum frequency 34 | let clocks = ClockControl::max(system.clock_control).freeze(); 35 | 36 | // Initialize the timers used for Wifi 37 | // ANCHOR: wifi_init 38 | let timer = PeriodicTimer::new(SystemTimer::new(peripherals.SYSTIMER).alarm0.into()); 39 | let init = initialize( 40 | EspWifiInitFor::Wifi, 41 | timer, 42 | Rng::new(peripherals.RNG), 43 | peripherals.RADIO_CLK, 44 | &clocks, 45 | ) 46 | .unwrap(); 47 | // ANCHOR_END: wifi_init 48 | 49 | // Configure Wifi 50 | // ANCHOR: wifi_config 51 | let wifi = peripherals.WIFI; 52 | let mut socket_set_entries: [SocketStorage; 3] = Default::default(); 53 | let (iface, device, mut controller, sockets) = 54 | create_network_interface(&init, wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); 55 | // ANCHOR_END: wifi_config 56 | 57 | let mut auth_method = AuthMethod::WPA2Personal; 58 | if PASSWORD.is_empty() { 59 | auth_method = AuthMethod::None; 60 | } 61 | 62 | // ANCHOR: client_config_start 63 | let client_config = Configuration::Client(ClientConfiguration { 64 | // ANCHOR_END: client_config_start 65 | ssid: SSID.try_into().unwrap(), 66 | password: PASSWORD.try_into().unwrap(), 67 | auth_method, 68 | ..Default::default() // ANCHOR: client_config_end 69 | }); 70 | 71 | let res = controller.set_configuration(&client_config); 72 | println!("Wi-Fi set_configuration returned {:?}", res); 73 | // ANCHOR_END: client_config_end 74 | 75 | // ANCHOR: wifi_connect 76 | controller.start().unwrap(); 77 | println!("Is wifi started: {:?}", controller.is_started()); 78 | 79 | println!("Start Wifi Scan"); 80 | let res: Result<(heapless::Vec, usize), WifiError> = controller.scan_n(); 81 | if let Ok((res, _count)) = res { 82 | for ap in res { 83 | println!("{:?}", ap); 84 | } 85 | } 86 | 87 | println!("{:?}", controller.get_capabilities()); 88 | println!("Wi-Fi connect: {:?}", controller.connect()); 89 | 90 | // Wait to get connected 91 | println!("Wait to get connected"); 92 | loop { 93 | let res = controller.is_connected(); 94 | match res { 95 | Ok(connected) => { 96 | if connected { 97 | break; 98 | } 99 | } 100 | Err(err) => { 101 | println!("{:?}", err); 102 | loop {} 103 | } 104 | } 105 | } 106 | println!("{:?}", controller.is_connected()); 107 | // ANCHOR_END: wifi_connect 108 | 109 | // ANCHOR: ip 110 | // Wait for getting an ip address 111 | let wifi_stack = WifiStack::new(iface, device, sockets, current_millis); 112 | println!("Wait to get an ip address"); 113 | loop { 114 | wifi_stack.work(); 115 | 116 | if wifi_stack.is_iface_up() { 117 | println!("got ip {:?}", wifi_stack.get_ip_info()); 118 | break; 119 | } 120 | } 121 | // ANCHOR_END: ip 122 | 123 | println!("Start busy loop on main"); 124 | 125 | let mut rx_buffer = [0u8; 1536]; 126 | let mut tx_buffer = [0u8; 1536]; 127 | let mut socket = wifi_stack.get_socket(&mut rx_buffer, &mut tx_buffer); 128 | 129 | loop { 130 | println!("Making HTTP request"); 131 | socket.work(); 132 | 133 | socket 134 | .open(IpAddress::Ipv4(Ipv4Address::new(142, 250, 185, 115)), 80) 135 | .unwrap(); 136 | 137 | socket 138 | .write(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n") 139 | .unwrap(); 140 | socket.flush().unwrap(); 141 | 142 | // ANCHOR: reponse 143 | let wait_end = current_millis() + 20 * 1000; 144 | loop { 145 | let mut buffer = [0u8; 512]; 146 | if let Ok(len) = socket.read(&mut buffer) { 147 | let to_print = unsafe { core::str::from_utf8_unchecked(&buffer[..len]) }; 148 | print!("{}", to_print); 149 | } else { 150 | break; 151 | } 152 | 153 | if current_millis() > wait_end { 154 | println!("Timeout"); 155 | break; 156 | } 157 | } 158 | println!(); 159 | // ANCHOR_END: reponse 160 | 161 | // ANCHOR: socket_close 162 | socket.disconnect(); 163 | 164 | let wait_end = current_millis() + 5 * 1000; 165 | while current_millis() < wait_end { 166 | socket.work(); 167 | } 168 | // ANCHOR_END: socket_close 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /book/src/04_1_stack_overflow_protection.md: -------------------------------------------------------------------------------- 1 | # Stack Overflow Detection 2 | 3 | Rust is well known for its memory safety. Whenever possible the compiler enforces memory safety at compile. 4 | 5 | However, the situation is different in regards to the stack memory. It's impossible to check this at compile time and even at runtime this can be difficult. 6 | 7 | The stack is usually placed at the top of the available memory and grows from top (high addresses) to bottom (low addresses). 8 | 9 | On desktop operating systems there are measures to prevent overflowing the stack. Also, an RTOS might include mechanisms to check for stack overflows. 10 | 11 | In bare-metal however there is no common way to implement stack protection. 12 | 13 | On some platforms it's done by moving the stack to the start of the RAM so that when the stack grows above its bounding an access fault will occur. 14 | We cannot do that because on our chips there is the flash/ext-mem cache at the start of RAM which we definitely shouldn't touch. 15 | 16 | > 🔎 On ESP32-C6/ESP32-H2 cache is not located in the start of RAM which means we can move the stack there. 17 | > esp-hal offers the feature `flip-link` which will do that and you get stack-overflow protection "for free". 18 | 19 | > 🔎 esp-hal also supports [stack smashing protection](https://doc.rust-lang.org/rustc/exploit-mitigations.html#stack-smashing-protection) for all targets which in our case can also double as a simple stack overflow detector. While the overhead is very small, there is some run-time cost involved. 20 | > 21 | > To enable it you need a nightly compiler and add `"-Z", "stack-protector=all",` to `rustflags` in `.cargo/config.toml` 22 | 23 | Some of our chips (including ESP32-C3) include the debug-assist peripheral. 24 | 25 | This peripheral can monitor the stack-pointer and detect read and/or write access to specified memory areas. 26 | 27 | We could just use the stack-pointer monitoring which will work well as long as we don't use `esp-wifi`. 28 | 29 | The reason we cannot use that with `esp-wifi` is that it runs multiple tasks by quickly switching between them which includes switching stacks. In that case the stack bounds check will trigger as soon as we switch the running task for the first time. 30 | 31 | What we can do however is defining a protected area at the bottom of the stack and detect read and write access to it. As soon as the stack grows into this area, we will detect this. 32 | 33 | It is important to define this area larger (ideally twice) than the largest stack allocation we expect. Otherwise, it's possible that code will start writing to memory below the stack - possibly overwriting sensitive static data or even code residing in RAM before we can detect access to the monitored memory area. 34 | 35 | For X86 LLVM supports _probestack_ which would allow us to use a smaller safe-area. However, this feature currently isn't available for our target platforms. 36 | 37 | We can also test for the current stack usage by temporarily increasing the safe area until we see the stack memory protection trigger. 38 | 39 | ## Setup 40 | 41 | ✅ Go to `advanced/stack-overflow-detection` directory. 42 | 43 | ✅ Open the prepared project skeleton in `advanced/stack-overflow-detection`. 44 | 45 | ✅ Open the docs for this project with the following command: 46 | 47 | ``` 48 | cargo doc --open 49 | ``` 50 | 51 | ✅ Run the code 52 | 53 | ``` 54 | cargo run 55 | ``` 56 | 57 | You will see the application crash with an `Illegal instruction` exception. This is because the recursive function is placed in RAM. 58 | If you change it to run from flash you won't see a crash but the application will just freeze after printing a weird counter number. 59 | 60 | In this case it's easy to guess the cause of this behavior however in a real world application you probably won't know what exactly happened. 61 | 62 | `advanced/stack-overflow-detection/examples/stack-overflow-detection.rs` contains the solution. You can run it with the following command: 63 | 64 | ```shell 65 | cargo run --release --example stack-overflow-detection 66 | ``` 67 | 68 | ## Exercise 69 | 70 | ✅ Create a function which will set up the safe memory area and enables the appropriate interrupt 71 | 72 | The function will take the `DebugAssist` peripheral driver and the size of the safe-area. 73 | It should move the `DebugAssist` into a static variable. 74 | 75 | The resulting function should look like this 76 | ```rust,ignore 77 | {{#include ../../advanced/stack-overflow-detection/examples/stack-overflow-detection.rs:debug_assists}} 78 | ``` 79 | 80 | There is quite a lot going on here but most of this is setting up the interrupt. 81 | You should recognize most of this from the interrupt exercise in the previous chapter. 82 | 83 | The most interesting part is probably `da.enable_region0_monitor(stack_low, stack_low + safe_area_size, true, true)`. 84 | This actually configures the region to monitor as well as setting it up to trigger on reads and writes to that region. 85 | 86 | Another interesting part here is how we can get the top and bottom address of the stack from symbols created by the linker script. 87 | 88 | ✅ Create the interrupt handler 89 | 90 | As you probably remember from the introduction to interrupts we can define the interrupt handler by using the `#[interrupt]` attribute macro. 91 | The name of the function needs to match the name of the interrupt. 92 | 93 | ```rust,ignore 94 | {{#include ../../advanced/stack-overflow-detection/examples/stack-overflow-detection.rs:interrupt}} 95 | ... 96 | ``` 97 | 98 | Next, we need to get access to the debug assist peripheral driver which we stored in the static variable. 99 | 100 | We need it to get the address where the access to the monitored memory region happened. 101 | Printing this address will enable `espflash` to print the name of the function. Similar to how stack traces are printed. 102 | 103 | We can also clear the pending interrupt and disable region monitoring here. It's not strictly needed since we won't return from the interrupt handler. 104 | 105 | It is unfortunately not possible to generate a stack trace here since the stack is not in a correct state and we don't know the stack frame from which we can start generating the backtrace. 106 | 107 | The whole function should look like this 108 | ```rust,ignore 109 | {{#include ../../advanced/stack-overflow-detection/examples/stack-overflow-detection.rs:handler}} 110 | ``` 111 | -------------------------------------------------------------------------------- /book/src/assets/esp-logo-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 38 | 40 | 42 | 43 | 导航栏-菜单-logo 45 | 48 | 51 | 55 | 59 | 64 | 68 | 72 | 79 | 83 | 87 | 91 | 95 | 99 | 103 | 107 | 111 | 112 | 113 | 115 | 116 | 118 | 导航栏-菜单-logo 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /intro/dma/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.86" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 19 | 20 | [[package]] 21 | name = "bare-metal" 22 | version = "1.0.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 25 | 26 | [[package]] 27 | name = "basic-toml" 28 | version = "0.1.9" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" 31 | dependencies = [ 32 | "serde", 33 | ] 34 | 35 | [[package]] 36 | name = "bitfield" 37 | version = "0.15.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1" 40 | 41 | [[package]] 42 | name = "bitflags" 43 | version = "2.6.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 46 | 47 | [[package]] 48 | name = "bytemuck" 49 | version = "1.16.1" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" 52 | 53 | [[package]] 54 | name = "cfg-if" 55 | version = "1.0.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 58 | 59 | [[package]] 60 | name = "core-isa-parser" 61 | version = "0.2.0" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "23ec98e54b735872e54b2335c2e5a5c7fa7d9c3bfd45500f75280f84089a0083" 64 | dependencies = [ 65 | "anyhow", 66 | "enum-as-inner", 67 | "regex", 68 | "strum 0.24.1", 69 | "strum_macros 0.24.3", 70 | ] 71 | 72 | [[package]] 73 | name = "critical-section" 74 | version = "1.1.2" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" 77 | 78 | [[package]] 79 | name = "darling" 80 | version = "0.20.10" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 83 | dependencies = [ 84 | "darling_core", 85 | "darling_macro", 86 | ] 87 | 88 | [[package]] 89 | name = "darling_core" 90 | version = "0.20.10" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 93 | dependencies = [ 94 | "fnv", 95 | "ident_case", 96 | "proc-macro2", 97 | "quote", 98 | "strsim", 99 | "syn 2.0.71", 100 | ] 101 | 102 | [[package]] 103 | name = "darling_macro" 104 | version = "0.20.10" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 107 | dependencies = [ 108 | "darling_core", 109 | "quote", 110 | "syn 2.0.71", 111 | ] 112 | 113 | [[package]] 114 | name = "delegate" 115 | version = "0.12.0" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" 118 | dependencies = [ 119 | "proc-macro2", 120 | "quote", 121 | "syn 2.0.71", 122 | ] 123 | 124 | [[package]] 125 | name = "dma" 126 | version = "0.1.0" 127 | dependencies = [ 128 | "esp-backtrace", 129 | "esp-hal", 130 | "esp-println", 131 | ] 132 | 133 | [[package]] 134 | name = "document-features" 135 | version = "0.2.10" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" 138 | dependencies = [ 139 | "litrs", 140 | ] 141 | 142 | [[package]] 143 | name = "embedded-can" 144 | version = "0.4.1" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" 147 | dependencies = [ 148 | "nb", 149 | ] 150 | 151 | [[package]] 152 | name = "embedded-dma" 153 | version = "0.2.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" 156 | dependencies = [ 157 | "stable_deref_trait", 158 | ] 159 | 160 | [[package]] 161 | name = "embedded-hal" 162 | version = "1.0.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" 165 | 166 | [[package]] 167 | name = "embedded-hal-nb" 168 | version = "1.0.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" 171 | dependencies = [ 172 | "embedded-hal", 173 | "nb", 174 | ] 175 | 176 | [[package]] 177 | name = "enum-as-inner" 178 | version = "0.4.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" 181 | dependencies = [ 182 | "heck 0.4.1", 183 | "proc-macro2", 184 | "quote", 185 | "syn 1.0.109", 186 | ] 187 | 188 | [[package]] 189 | name = "enumset" 190 | version = "1.1.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" 193 | dependencies = [ 194 | "enumset_derive", 195 | ] 196 | 197 | [[package]] 198 | name = "enumset_derive" 199 | version = "0.8.1" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" 202 | dependencies = [ 203 | "darling", 204 | "proc-macro2", 205 | "quote", 206 | "syn 2.0.71", 207 | ] 208 | 209 | [[package]] 210 | name = "equivalent" 211 | version = "1.0.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 214 | 215 | [[package]] 216 | name = "esp-backtrace" 217 | version = "0.13.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "1a34817530dceba397172d6a9fb660b684a73a3a591fbe7fb0da27bed796f270" 220 | dependencies = [ 221 | "esp-build", 222 | "esp-println", 223 | ] 224 | 225 | [[package]] 226 | name = "esp-build" 227 | version = "0.1.0" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "b94a4b8d74e7cc7baabcca5b2277b41877e039ad9cd49959d48ef94dac7eab4b" 230 | dependencies = [ 231 | "quote", 232 | "syn 2.0.71", 233 | "termcolor", 234 | ] 235 | 236 | [[package]] 237 | name = "esp-hal" 238 | version = "0.19.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "fe4f8cb6a9dcf0fd4506a856fbb4a0622b92042978c601a23c840c28f621a59f" 241 | dependencies = [ 242 | "basic-toml", 243 | "bitfield", 244 | "bitflags", 245 | "bytemuck", 246 | "cfg-if", 247 | "critical-section", 248 | "delegate", 249 | "document-features", 250 | "embedded-can", 251 | "embedded-dma", 252 | "embedded-hal", 253 | "embedded-hal-nb", 254 | "enumset", 255 | "esp-build", 256 | "esp-hal-procmacros", 257 | "esp-metadata", 258 | "esp-riscv-rt", 259 | "esp32c3", 260 | "fugit", 261 | "nb", 262 | "paste", 263 | "portable-atomic", 264 | "rand_core", 265 | "riscv", 266 | "serde", 267 | "strum 0.26.3", 268 | "void", 269 | "xtensa-lx-rt", 270 | ] 271 | 272 | [[package]] 273 | name = "esp-hal-procmacros" 274 | version = "0.12.0" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "9569ccb286c5a0c39292dbaaa0995bbb2a2a9d671ef3ce807b8b5b3d9a589d35" 277 | dependencies = [ 278 | "darling", 279 | "document-features", 280 | "litrs", 281 | "proc-macro-crate", 282 | "proc-macro-error", 283 | "proc-macro2", 284 | "quote", 285 | "syn 2.0.71", 286 | ] 287 | 288 | [[package]] 289 | name = "esp-metadata" 290 | version = "0.2.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "6013420eb303c3087d82c2d2a38944427662b0b07a9ae79e5b1636fc1442e0ba" 293 | dependencies = [ 294 | "basic-toml", 295 | "lazy_static", 296 | "serde", 297 | "strum 0.26.3", 298 | ] 299 | 300 | [[package]] 301 | name = "esp-println" 302 | version = "0.10.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "58cd4fa834980ba64aad00a5c2c1a630020af984eadef65a125cb99085f6f54c" 305 | dependencies = [ 306 | "critical-section", 307 | "esp-build", 308 | "portable-atomic", 309 | ] 310 | 311 | [[package]] 312 | name = "esp-riscv-rt" 313 | version = "0.9.0" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "bfc32298ed7c263b06c8b031704d8517cc62c819f2a9d5c261d0cb119634d6e9" 316 | dependencies = [ 317 | "document-features", 318 | "riscv", 319 | "riscv-rt-macros", 320 | ] 321 | 322 | [[package]] 323 | name = "esp32c3" 324 | version = "0.24.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "cf6865f32b4936b2c396fd1bed3e935850b130282fdcb935af79c2da192cb638" 327 | dependencies = [ 328 | "critical-section", 329 | "vcell", 330 | ] 331 | 332 | [[package]] 333 | name = "fnv" 334 | version = "1.0.7" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 337 | 338 | [[package]] 339 | name = "fugit" 340 | version = "0.3.7" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" 343 | dependencies = [ 344 | "gcd", 345 | ] 346 | 347 | [[package]] 348 | name = "gcd" 349 | version = "2.3.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 352 | 353 | [[package]] 354 | name = "hashbrown" 355 | version = "0.14.5" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 358 | 359 | [[package]] 360 | name = "heck" 361 | version = "0.4.1" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 364 | 365 | [[package]] 366 | name = "heck" 367 | version = "0.5.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 370 | 371 | [[package]] 372 | name = "ident_case" 373 | version = "1.0.1" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 376 | 377 | [[package]] 378 | name = "indexmap" 379 | version = "2.2.6" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 382 | dependencies = [ 383 | "equivalent", 384 | "hashbrown", 385 | ] 386 | 387 | [[package]] 388 | name = "lazy_static" 389 | version = "1.5.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 392 | 393 | [[package]] 394 | name = "litrs" 395 | version = "0.4.1" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" 398 | dependencies = [ 399 | "proc-macro2", 400 | ] 401 | 402 | [[package]] 403 | name = "memchr" 404 | version = "2.7.4" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 407 | 408 | [[package]] 409 | name = "minijinja" 410 | version = "1.0.21" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "55e877d961d4f96ce13615862322df7c0b6d169d40cab71a7ef3f9b9e594451e" 413 | dependencies = [ 414 | "serde", 415 | ] 416 | 417 | [[package]] 418 | name = "nb" 419 | version = "1.1.0" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" 422 | 423 | [[package]] 424 | name = "paste" 425 | version = "1.0.15" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 428 | 429 | [[package]] 430 | name = "portable-atomic" 431 | version = "1.6.0" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" 434 | 435 | [[package]] 436 | name = "proc-macro-crate" 437 | version = "3.1.0" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" 440 | dependencies = [ 441 | "toml_edit", 442 | ] 443 | 444 | [[package]] 445 | name = "proc-macro-error" 446 | version = "1.0.4" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 449 | dependencies = [ 450 | "proc-macro-error-attr", 451 | "proc-macro2", 452 | "quote", 453 | "syn 1.0.109", 454 | "version_check", 455 | ] 456 | 457 | [[package]] 458 | name = "proc-macro-error-attr" 459 | version = "1.0.4" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 462 | dependencies = [ 463 | "proc-macro2", 464 | "quote", 465 | "version_check", 466 | ] 467 | 468 | [[package]] 469 | name = "proc-macro2" 470 | version = "1.0.86" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 473 | dependencies = [ 474 | "unicode-ident", 475 | ] 476 | 477 | [[package]] 478 | name = "quote" 479 | version = "1.0.36" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 482 | dependencies = [ 483 | "proc-macro2", 484 | ] 485 | 486 | [[package]] 487 | name = "r0" 488 | version = "1.0.0" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" 491 | 492 | [[package]] 493 | name = "rand_core" 494 | version = "0.6.4" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 497 | 498 | [[package]] 499 | name = "regex" 500 | version = "1.10.5" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 503 | dependencies = [ 504 | "aho-corasick", 505 | "memchr", 506 | "regex-automata", 507 | "regex-syntax", 508 | ] 509 | 510 | [[package]] 511 | name = "regex-automata" 512 | version = "0.4.7" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 515 | dependencies = [ 516 | "aho-corasick", 517 | "memchr", 518 | "regex-syntax", 519 | ] 520 | 521 | [[package]] 522 | name = "regex-syntax" 523 | version = "0.8.4" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 526 | 527 | [[package]] 528 | name = "riscv" 529 | version = "0.11.1" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" 532 | dependencies = [ 533 | "critical-section", 534 | "embedded-hal", 535 | ] 536 | 537 | [[package]] 538 | name = "riscv-rt-macros" 539 | version = "0.2.1" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "a8d100d466dbb76681ef6a9386f3da9abc570d57394e86da0ba5af8c4408486d" 542 | dependencies = [ 543 | "proc-macro2", 544 | "quote", 545 | "syn 1.0.109", 546 | ] 547 | 548 | [[package]] 549 | name = "rustversion" 550 | version = "1.0.17" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 553 | 554 | [[package]] 555 | name = "serde" 556 | version = "1.0.204" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" 559 | dependencies = [ 560 | "serde_derive", 561 | ] 562 | 563 | [[package]] 564 | name = "serde_derive" 565 | version = "1.0.204" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" 568 | dependencies = [ 569 | "proc-macro2", 570 | "quote", 571 | "syn 2.0.71", 572 | ] 573 | 574 | [[package]] 575 | name = "stable_deref_trait" 576 | version = "1.2.0" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 579 | 580 | [[package]] 581 | name = "strsim" 582 | version = "0.11.1" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 585 | 586 | [[package]] 587 | name = "strum" 588 | version = "0.24.1" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" 591 | 592 | [[package]] 593 | name = "strum" 594 | version = "0.26.3" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 597 | dependencies = [ 598 | "strum_macros 0.26.4", 599 | ] 600 | 601 | [[package]] 602 | name = "strum_macros" 603 | version = "0.24.3" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" 606 | dependencies = [ 607 | "heck 0.4.1", 608 | "proc-macro2", 609 | "quote", 610 | "rustversion", 611 | "syn 1.0.109", 612 | ] 613 | 614 | [[package]] 615 | name = "strum_macros" 616 | version = "0.26.4" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 619 | dependencies = [ 620 | "heck 0.5.0", 621 | "proc-macro2", 622 | "quote", 623 | "rustversion", 624 | "syn 2.0.71", 625 | ] 626 | 627 | [[package]] 628 | name = "syn" 629 | version = "1.0.109" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 632 | dependencies = [ 633 | "proc-macro2", 634 | "quote", 635 | "unicode-ident", 636 | ] 637 | 638 | [[package]] 639 | name = "syn" 640 | version = "2.0.71" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" 643 | dependencies = [ 644 | "proc-macro2", 645 | "quote", 646 | "unicode-ident", 647 | ] 648 | 649 | [[package]] 650 | name = "termcolor" 651 | version = "1.4.1" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 654 | dependencies = [ 655 | "winapi-util", 656 | ] 657 | 658 | [[package]] 659 | name = "toml_datetime" 660 | version = "0.6.6" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" 663 | 664 | [[package]] 665 | name = "toml_edit" 666 | version = "0.21.1" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" 669 | dependencies = [ 670 | "indexmap", 671 | "toml_datetime", 672 | "winnow", 673 | ] 674 | 675 | [[package]] 676 | name = "unicode-ident" 677 | version = "1.0.12" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 680 | 681 | [[package]] 682 | name = "vcell" 683 | version = "0.1.3" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 686 | 687 | [[package]] 688 | name = "version_check" 689 | version = "0.9.4" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 692 | 693 | [[package]] 694 | name = "void" 695 | version = "1.0.2" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 698 | 699 | [[package]] 700 | name = "winapi-util" 701 | version = "0.1.8" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" 704 | dependencies = [ 705 | "windows-sys", 706 | ] 707 | 708 | [[package]] 709 | name = "windows-sys" 710 | version = "0.52.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 713 | dependencies = [ 714 | "windows-targets", 715 | ] 716 | 717 | [[package]] 718 | name = "windows-targets" 719 | version = "0.52.6" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 722 | dependencies = [ 723 | "windows_aarch64_gnullvm", 724 | "windows_aarch64_msvc", 725 | "windows_i686_gnu", 726 | "windows_i686_gnullvm", 727 | "windows_i686_msvc", 728 | "windows_x86_64_gnu", 729 | "windows_x86_64_gnullvm", 730 | "windows_x86_64_msvc", 731 | ] 732 | 733 | [[package]] 734 | name = "windows_aarch64_gnullvm" 735 | version = "0.52.6" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 738 | 739 | [[package]] 740 | name = "windows_aarch64_msvc" 741 | version = "0.52.6" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 744 | 745 | [[package]] 746 | name = "windows_i686_gnu" 747 | version = "0.52.6" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 750 | 751 | [[package]] 752 | name = "windows_i686_gnullvm" 753 | version = "0.52.6" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 756 | 757 | [[package]] 758 | name = "windows_i686_msvc" 759 | version = "0.52.6" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 762 | 763 | [[package]] 764 | name = "windows_x86_64_gnu" 765 | version = "0.52.6" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 768 | 769 | [[package]] 770 | name = "windows_x86_64_gnullvm" 771 | version = "0.52.6" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 774 | 775 | [[package]] 776 | name = "windows_x86_64_msvc" 777 | version = "0.52.6" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 780 | 781 | [[package]] 782 | name = "winnow" 783 | version = "0.5.40" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 786 | dependencies = [ 787 | "memchr", 788 | ] 789 | 790 | [[package]] 791 | name = "xtensa-lx-rt" 792 | version = "0.16.0" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "904102108b780c9a5e3275c5f3c63dc348ec43ae5da5237868515498b447d51a" 795 | dependencies = [ 796 | "bare-metal", 797 | "core-isa-parser", 798 | "minijinja", 799 | "r0", 800 | "xtensa-lx-rt-proc-macros", 801 | ] 802 | 803 | [[package]] 804 | name = "xtensa-lx-rt-proc-macros" 805 | version = "0.2.1" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "082cdede098bbec9af15b0e74085e5f3d16f2923597de7aed7b8112003af2da7" 808 | dependencies = [ 809 | "darling", 810 | "proc-macro2", 811 | "quote", 812 | "syn 2.0.71", 813 | ] 814 | -------------------------------------------------------------------------------- /intro/blinky/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.86" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 19 | 20 | [[package]] 21 | name = "bare-metal" 22 | version = "1.0.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 25 | 26 | [[package]] 27 | name = "basic-toml" 28 | version = "0.1.9" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" 31 | dependencies = [ 32 | "serde", 33 | ] 34 | 35 | [[package]] 36 | name = "bitfield" 37 | version = "0.15.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1" 40 | 41 | [[package]] 42 | name = "bitflags" 43 | version = "2.6.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 46 | 47 | [[package]] 48 | name = "blinky" 49 | version = "0.1.0" 50 | dependencies = [ 51 | "esp-backtrace", 52 | "esp-hal", 53 | "esp-println", 54 | ] 55 | 56 | [[package]] 57 | name = "bytemuck" 58 | version = "1.16.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" 61 | 62 | [[package]] 63 | name = "cfg-if" 64 | version = "1.0.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 67 | 68 | [[package]] 69 | name = "core-isa-parser" 70 | version = "0.2.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "23ec98e54b735872e54b2335c2e5a5c7fa7d9c3bfd45500f75280f84089a0083" 73 | dependencies = [ 74 | "anyhow", 75 | "enum-as-inner", 76 | "regex", 77 | "strum 0.24.1", 78 | "strum_macros 0.24.3", 79 | ] 80 | 81 | [[package]] 82 | name = "critical-section" 83 | version = "1.1.2" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" 86 | 87 | [[package]] 88 | name = "darling" 89 | version = "0.20.10" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 92 | dependencies = [ 93 | "darling_core", 94 | "darling_macro", 95 | ] 96 | 97 | [[package]] 98 | name = "darling_core" 99 | version = "0.20.10" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 102 | dependencies = [ 103 | "fnv", 104 | "ident_case", 105 | "proc-macro2", 106 | "quote", 107 | "strsim", 108 | "syn 2.0.71", 109 | ] 110 | 111 | [[package]] 112 | name = "darling_macro" 113 | version = "0.20.10" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 116 | dependencies = [ 117 | "darling_core", 118 | "quote", 119 | "syn 2.0.71", 120 | ] 121 | 122 | [[package]] 123 | name = "delegate" 124 | version = "0.12.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" 127 | dependencies = [ 128 | "proc-macro2", 129 | "quote", 130 | "syn 2.0.71", 131 | ] 132 | 133 | [[package]] 134 | name = "document-features" 135 | version = "0.2.10" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" 138 | dependencies = [ 139 | "litrs", 140 | ] 141 | 142 | [[package]] 143 | name = "embedded-can" 144 | version = "0.4.1" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" 147 | dependencies = [ 148 | "nb", 149 | ] 150 | 151 | [[package]] 152 | name = "embedded-dma" 153 | version = "0.2.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" 156 | dependencies = [ 157 | "stable_deref_trait", 158 | ] 159 | 160 | [[package]] 161 | name = "embedded-hal" 162 | version = "1.0.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" 165 | 166 | [[package]] 167 | name = "embedded-hal-nb" 168 | version = "1.0.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" 171 | dependencies = [ 172 | "embedded-hal", 173 | "nb", 174 | ] 175 | 176 | [[package]] 177 | name = "enum-as-inner" 178 | version = "0.4.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" 181 | dependencies = [ 182 | "heck 0.4.1", 183 | "proc-macro2", 184 | "quote", 185 | "syn 1.0.109", 186 | ] 187 | 188 | [[package]] 189 | name = "enumset" 190 | version = "1.1.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" 193 | dependencies = [ 194 | "enumset_derive", 195 | ] 196 | 197 | [[package]] 198 | name = "enumset_derive" 199 | version = "0.8.1" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" 202 | dependencies = [ 203 | "darling", 204 | "proc-macro2", 205 | "quote", 206 | "syn 2.0.71", 207 | ] 208 | 209 | [[package]] 210 | name = "equivalent" 211 | version = "1.0.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 214 | 215 | [[package]] 216 | name = "esp-backtrace" 217 | version = "0.13.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "1a34817530dceba397172d6a9fb660b684a73a3a591fbe7fb0da27bed796f270" 220 | dependencies = [ 221 | "esp-build", 222 | "esp-println", 223 | ] 224 | 225 | [[package]] 226 | name = "esp-build" 227 | version = "0.1.0" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "b94a4b8d74e7cc7baabcca5b2277b41877e039ad9cd49959d48ef94dac7eab4b" 230 | dependencies = [ 231 | "quote", 232 | "syn 2.0.71", 233 | "termcolor", 234 | ] 235 | 236 | [[package]] 237 | name = "esp-hal" 238 | version = "0.19.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "fe4f8cb6a9dcf0fd4506a856fbb4a0622b92042978c601a23c840c28f621a59f" 241 | dependencies = [ 242 | "basic-toml", 243 | "bitfield", 244 | "bitflags", 245 | "bytemuck", 246 | "cfg-if", 247 | "critical-section", 248 | "delegate", 249 | "document-features", 250 | "embedded-can", 251 | "embedded-dma", 252 | "embedded-hal", 253 | "embedded-hal-nb", 254 | "enumset", 255 | "esp-build", 256 | "esp-hal-procmacros", 257 | "esp-metadata", 258 | "esp-riscv-rt", 259 | "esp32c3", 260 | "fugit", 261 | "nb", 262 | "paste", 263 | "portable-atomic", 264 | "rand_core", 265 | "riscv", 266 | "serde", 267 | "strum 0.26.3", 268 | "void", 269 | "xtensa-lx-rt", 270 | ] 271 | 272 | [[package]] 273 | name = "esp-hal-procmacros" 274 | version = "0.12.0" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "9569ccb286c5a0c39292dbaaa0995bbb2a2a9d671ef3ce807b8b5b3d9a589d35" 277 | dependencies = [ 278 | "darling", 279 | "document-features", 280 | "litrs", 281 | "proc-macro-crate", 282 | "proc-macro-error", 283 | "proc-macro2", 284 | "quote", 285 | "syn 2.0.71", 286 | ] 287 | 288 | [[package]] 289 | name = "esp-metadata" 290 | version = "0.2.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "6013420eb303c3087d82c2d2a38944427662b0b07a9ae79e5b1636fc1442e0ba" 293 | dependencies = [ 294 | "basic-toml", 295 | "lazy_static", 296 | "serde", 297 | "strum 0.26.3", 298 | ] 299 | 300 | [[package]] 301 | name = "esp-println" 302 | version = "0.10.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "58cd4fa834980ba64aad00a5c2c1a630020af984eadef65a125cb99085f6f54c" 305 | dependencies = [ 306 | "critical-section", 307 | "esp-build", 308 | "portable-atomic", 309 | ] 310 | 311 | [[package]] 312 | name = "esp-riscv-rt" 313 | version = "0.9.0" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "bfc32298ed7c263b06c8b031704d8517cc62c819f2a9d5c261d0cb119634d6e9" 316 | dependencies = [ 317 | "document-features", 318 | "riscv", 319 | "riscv-rt-macros", 320 | ] 321 | 322 | [[package]] 323 | name = "esp32c3" 324 | version = "0.24.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "cf6865f32b4936b2c396fd1bed3e935850b130282fdcb935af79c2da192cb638" 327 | dependencies = [ 328 | "critical-section", 329 | "vcell", 330 | ] 331 | 332 | [[package]] 333 | name = "fnv" 334 | version = "1.0.7" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 337 | 338 | [[package]] 339 | name = "fugit" 340 | version = "0.3.7" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" 343 | dependencies = [ 344 | "gcd", 345 | ] 346 | 347 | [[package]] 348 | name = "gcd" 349 | version = "2.3.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 352 | 353 | [[package]] 354 | name = "hashbrown" 355 | version = "0.14.5" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 358 | 359 | [[package]] 360 | name = "heck" 361 | version = "0.4.1" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 364 | 365 | [[package]] 366 | name = "heck" 367 | version = "0.5.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 370 | 371 | [[package]] 372 | name = "ident_case" 373 | version = "1.0.1" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 376 | 377 | [[package]] 378 | name = "indexmap" 379 | version = "2.2.6" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 382 | dependencies = [ 383 | "equivalent", 384 | "hashbrown", 385 | ] 386 | 387 | [[package]] 388 | name = "lazy_static" 389 | version = "1.5.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 392 | 393 | [[package]] 394 | name = "litrs" 395 | version = "0.4.1" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" 398 | dependencies = [ 399 | "proc-macro2", 400 | ] 401 | 402 | [[package]] 403 | name = "memchr" 404 | version = "2.7.4" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 407 | 408 | [[package]] 409 | name = "minijinja" 410 | version = "1.0.21" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "55e877d961d4f96ce13615862322df7c0b6d169d40cab71a7ef3f9b9e594451e" 413 | dependencies = [ 414 | "serde", 415 | ] 416 | 417 | [[package]] 418 | name = "nb" 419 | version = "1.1.0" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" 422 | 423 | [[package]] 424 | name = "paste" 425 | version = "1.0.15" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 428 | 429 | [[package]] 430 | name = "portable-atomic" 431 | version = "1.6.0" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" 434 | 435 | [[package]] 436 | name = "proc-macro-crate" 437 | version = "3.1.0" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" 440 | dependencies = [ 441 | "toml_edit", 442 | ] 443 | 444 | [[package]] 445 | name = "proc-macro-error" 446 | version = "1.0.4" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 449 | dependencies = [ 450 | "proc-macro-error-attr", 451 | "proc-macro2", 452 | "quote", 453 | "syn 1.0.109", 454 | "version_check", 455 | ] 456 | 457 | [[package]] 458 | name = "proc-macro-error-attr" 459 | version = "1.0.4" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 462 | dependencies = [ 463 | "proc-macro2", 464 | "quote", 465 | "version_check", 466 | ] 467 | 468 | [[package]] 469 | name = "proc-macro2" 470 | version = "1.0.86" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 473 | dependencies = [ 474 | "unicode-ident", 475 | ] 476 | 477 | [[package]] 478 | name = "quote" 479 | version = "1.0.36" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 482 | dependencies = [ 483 | "proc-macro2", 484 | ] 485 | 486 | [[package]] 487 | name = "r0" 488 | version = "1.0.0" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" 491 | 492 | [[package]] 493 | name = "rand_core" 494 | version = "0.6.4" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 497 | 498 | [[package]] 499 | name = "regex" 500 | version = "1.10.5" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 503 | dependencies = [ 504 | "aho-corasick", 505 | "memchr", 506 | "regex-automata", 507 | "regex-syntax", 508 | ] 509 | 510 | [[package]] 511 | name = "regex-automata" 512 | version = "0.4.7" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 515 | dependencies = [ 516 | "aho-corasick", 517 | "memchr", 518 | "regex-syntax", 519 | ] 520 | 521 | [[package]] 522 | name = "regex-syntax" 523 | version = "0.8.4" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 526 | 527 | [[package]] 528 | name = "riscv" 529 | version = "0.11.1" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" 532 | dependencies = [ 533 | "critical-section", 534 | "embedded-hal", 535 | ] 536 | 537 | [[package]] 538 | name = "riscv-rt-macros" 539 | version = "0.2.1" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "a8d100d466dbb76681ef6a9386f3da9abc570d57394e86da0ba5af8c4408486d" 542 | dependencies = [ 543 | "proc-macro2", 544 | "quote", 545 | "syn 1.0.109", 546 | ] 547 | 548 | [[package]] 549 | name = "rustversion" 550 | version = "1.0.17" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 553 | 554 | [[package]] 555 | name = "serde" 556 | version = "1.0.204" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" 559 | dependencies = [ 560 | "serde_derive", 561 | ] 562 | 563 | [[package]] 564 | name = "serde_derive" 565 | version = "1.0.204" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" 568 | dependencies = [ 569 | "proc-macro2", 570 | "quote", 571 | "syn 2.0.71", 572 | ] 573 | 574 | [[package]] 575 | name = "stable_deref_trait" 576 | version = "1.2.0" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 579 | 580 | [[package]] 581 | name = "strsim" 582 | version = "0.11.1" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 585 | 586 | [[package]] 587 | name = "strum" 588 | version = "0.24.1" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" 591 | 592 | [[package]] 593 | name = "strum" 594 | version = "0.26.3" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 597 | dependencies = [ 598 | "strum_macros 0.26.4", 599 | ] 600 | 601 | [[package]] 602 | name = "strum_macros" 603 | version = "0.24.3" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" 606 | dependencies = [ 607 | "heck 0.4.1", 608 | "proc-macro2", 609 | "quote", 610 | "rustversion", 611 | "syn 1.0.109", 612 | ] 613 | 614 | [[package]] 615 | name = "strum_macros" 616 | version = "0.26.4" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 619 | dependencies = [ 620 | "heck 0.5.0", 621 | "proc-macro2", 622 | "quote", 623 | "rustversion", 624 | "syn 2.0.71", 625 | ] 626 | 627 | [[package]] 628 | name = "syn" 629 | version = "1.0.109" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 632 | dependencies = [ 633 | "proc-macro2", 634 | "quote", 635 | "unicode-ident", 636 | ] 637 | 638 | [[package]] 639 | name = "syn" 640 | version = "2.0.71" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" 643 | dependencies = [ 644 | "proc-macro2", 645 | "quote", 646 | "unicode-ident", 647 | ] 648 | 649 | [[package]] 650 | name = "termcolor" 651 | version = "1.4.1" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 654 | dependencies = [ 655 | "winapi-util", 656 | ] 657 | 658 | [[package]] 659 | name = "toml_datetime" 660 | version = "0.6.6" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" 663 | 664 | [[package]] 665 | name = "toml_edit" 666 | version = "0.21.1" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" 669 | dependencies = [ 670 | "indexmap", 671 | "toml_datetime", 672 | "winnow", 673 | ] 674 | 675 | [[package]] 676 | name = "unicode-ident" 677 | version = "1.0.12" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 680 | 681 | [[package]] 682 | name = "vcell" 683 | version = "0.1.3" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 686 | 687 | [[package]] 688 | name = "version_check" 689 | version = "0.9.4" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 692 | 693 | [[package]] 694 | name = "void" 695 | version = "1.0.2" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 698 | 699 | [[package]] 700 | name = "winapi-util" 701 | version = "0.1.8" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" 704 | dependencies = [ 705 | "windows-sys", 706 | ] 707 | 708 | [[package]] 709 | name = "windows-sys" 710 | version = "0.52.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 713 | dependencies = [ 714 | "windows-targets", 715 | ] 716 | 717 | [[package]] 718 | name = "windows-targets" 719 | version = "0.52.6" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 722 | dependencies = [ 723 | "windows_aarch64_gnullvm", 724 | "windows_aarch64_msvc", 725 | "windows_i686_gnu", 726 | "windows_i686_gnullvm", 727 | "windows_i686_msvc", 728 | "windows_x86_64_gnu", 729 | "windows_x86_64_gnullvm", 730 | "windows_x86_64_msvc", 731 | ] 732 | 733 | [[package]] 734 | name = "windows_aarch64_gnullvm" 735 | version = "0.52.6" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 738 | 739 | [[package]] 740 | name = "windows_aarch64_msvc" 741 | version = "0.52.6" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 744 | 745 | [[package]] 746 | name = "windows_i686_gnu" 747 | version = "0.52.6" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 750 | 751 | [[package]] 752 | name = "windows_i686_gnullvm" 753 | version = "0.52.6" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 756 | 757 | [[package]] 758 | name = "windows_i686_msvc" 759 | version = "0.52.6" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 762 | 763 | [[package]] 764 | name = "windows_x86_64_gnu" 765 | version = "0.52.6" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 768 | 769 | [[package]] 770 | name = "windows_x86_64_gnullvm" 771 | version = "0.52.6" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 774 | 775 | [[package]] 776 | name = "windows_x86_64_msvc" 777 | version = "0.52.6" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 780 | 781 | [[package]] 782 | name = "winnow" 783 | version = "0.5.40" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 786 | dependencies = [ 787 | "memchr", 788 | ] 789 | 790 | [[package]] 791 | name = "xtensa-lx-rt" 792 | version = "0.16.0" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "904102108b780c9a5e3275c5f3c63dc348ec43ae5da5237868515498b447d51a" 795 | dependencies = [ 796 | "bare-metal", 797 | "core-isa-parser", 798 | "minijinja", 799 | "r0", 800 | "xtensa-lx-rt-proc-macros", 801 | ] 802 | 803 | [[package]] 804 | name = "xtensa-lx-rt-proc-macros" 805 | version = "0.2.1" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "082cdede098bbec9af15b0e74085e5f3d16f2923597de7aed7b8112003af2da7" 808 | dependencies = [ 809 | "darling", 810 | "proc-macro2", 811 | "quote", 812 | "syn 2.0.71", 813 | ] 814 | -------------------------------------------------------------------------------- /intro/button/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.86" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 19 | 20 | [[package]] 21 | name = "bare-metal" 22 | version = "1.0.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 25 | 26 | [[package]] 27 | name = "basic-toml" 28 | version = "0.1.9" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" 31 | dependencies = [ 32 | "serde", 33 | ] 34 | 35 | [[package]] 36 | name = "bitfield" 37 | version = "0.15.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "c821a6e124197eb56d907ccc2188eab1038fb919c914f47976e64dd8dbc855d1" 40 | 41 | [[package]] 42 | name = "bitflags" 43 | version = "2.6.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 46 | 47 | [[package]] 48 | name = "button" 49 | version = "0.1.0" 50 | dependencies = [ 51 | "esp-backtrace", 52 | "esp-hal", 53 | "esp-println", 54 | ] 55 | 56 | [[package]] 57 | name = "bytemuck" 58 | version = "1.16.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" 61 | 62 | [[package]] 63 | name = "cfg-if" 64 | version = "1.0.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 67 | 68 | [[package]] 69 | name = "core-isa-parser" 70 | version = "0.2.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "23ec98e54b735872e54b2335c2e5a5c7fa7d9c3bfd45500f75280f84089a0083" 73 | dependencies = [ 74 | "anyhow", 75 | "enum-as-inner", 76 | "regex", 77 | "strum 0.24.1", 78 | "strum_macros 0.24.3", 79 | ] 80 | 81 | [[package]] 82 | name = "critical-section" 83 | version = "1.1.2" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" 86 | 87 | [[package]] 88 | name = "darling" 89 | version = "0.20.10" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 92 | dependencies = [ 93 | "darling_core", 94 | "darling_macro", 95 | ] 96 | 97 | [[package]] 98 | name = "darling_core" 99 | version = "0.20.10" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 102 | dependencies = [ 103 | "fnv", 104 | "ident_case", 105 | "proc-macro2", 106 | "quote", 107 | "strsim", 108 | "syn 2.0.71", 109 | ] 110 | 111 | [[package]] 112 | name = "darling_macro" 113 | version = "0.20.10" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 116 | dependencies = [ 117 | "darling_core", 118 | "quote", 119 | "syn 2.0.71", 120 | ] 121 | 122 | [[package]] 123 | name = "delegate" 124 | version = "0.12.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" 127 | dependencies = [ 128 | "proc-macro2", 129 | "quote", 130 | "syn 2.0.71", 131 | ] 132 | 133 | [[package]] 134 | name = "document-features" 135 | version = "0.2.10" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" 138 | dependencies = [ 139 | "litrs", 140 | ] 141 | 142 | [[package]] 143 | name = "embedded-can" 144 | version = "0.4.1" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" 147 | dependencies = [ 148 | "nb", 149 | ] 150 | 151 | [[package]] 152 | name = "embedded-dma" 153 | version = "0.2.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" 156 | dependencies = [ 157 | "stable_deref_trait", 158 | ] 159 | 160 | [[package]] 161 | name = "embedded-hal" 162 | version = "1.0.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" 165 | 166 | [[package]] 167 | name = "embedded-hal-nb" 168 | version = "1.0.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" 171 | dependencies = [ 172 | "embedded-hal", 173 | "nb", 174 | ] 175 | 176 | [[package]] 177 | name = "enum-as-inner" 178 | version = "0.4.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" 181 | dependencies = [ 182 | "heck 0.4.1", 183 | "proc-macro2", 184 | "quote", 185 | "syn 1.0.109", 186 | ] 187 | 188 | [[package]] 189 | name = "enumset" 190 | version = "1.1.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" 193 | dependencies = [ 194 | "enumset_derive", 195 | ] 196 | 197 | [[package]] 198 | name = "enumset_derive" 199 | version = "0.8.1" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" 202 | dependencies = [ 203 | "darling", 204 | "proc-macro2", 205 | "quote", 206 | "syn 2.0.71", 207 | ] 208 | 209 | [[package]] 210 | name = "equivalent" 211 | version = "1.0.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 214 | 215 | [[package]] 216 | name = "esp-backtrace" 217 | version = "0.13.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "1a34817530dceba397172d6a9fb660b684a73a3a591fbe7fb0da27bed796f270" 220 | dependencies = [ 221 | "esp-build", 222 | "esp-println", 223 | ] 224 | 225 | [[package]] 226 | name = "esp-build" 227 | version = "0.1.0" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "b94a4b8d74e7cc7baabcca5b2277b41877e039ad9cd49959d48ef94dac7eab4b" 230 | dependencies = [ 231 | "quote", 232 | "syn 2.0.71", 233 | "termcolor", 234 | ] 235 | 236 | [[package]] 237 | name = "esp-hal" 238 | version = "0.19.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "fe4f8cb6a9dcf0fd4506a856fbb4a0622b92042978c601a23c840c28f621a59f" 241 | dependencies = [ 242 | "basic-toml", 243 | "bitfield", 244 | "bitflags", 245 | "bytemuck", 246 | "cfg-if", 247 | "critical-section", 248 | "delegate", 249 | "document-features", 250 | "embedded-can", 251 | "embedded-dma", 252 | "embedded-hal", 253 | "embedded-hal-nb", 254 | "enumset", 255 | "esp-build", 256 | "esp-hal-procmacros", 257 | "esp-metadata", 258 | "esp-riscv-rt", 259 | "esp32c3", 260 | "fugit", 261 | "nb", 262 | "paste", 263 | "portable-atomic", 264 | "rand_core", 265 | "riscv", 266 | "serde", 267 | "strum 0.26.3", 268 | "void", 269 | "xtensa-lx-rt", 270 | ] 271 | 272 | [[package]] 273 | name = "esp-hal-procmacros" 274 | version = "0.12.0" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "9569ccb286c5a0c39292dbaaa0995bbb2a2a9d671ef3ce807b8b5b3d9a589d35" 277 | dependencies = [ 278 | "darling", 279 | "document-features", 280 | "litrs", 281 | "proc-macro-crate", 282 | "proc-macro-error", 283 | "proc-macro2", 284 | "quote", 285 | "syn 2.0.71", 286 | ] 287 | 288 | [[package]] 289 | name = "esp-metadata" 290 | version = "0.2.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "6013420eb303c3087d82c2d2a38944427662b0b07a9ae79e5b1636fc1442e0ba" 293 | dependencies = [ 294 | "basic-toml", 295 | "lazy_static", 296 | "serde", 297 | "strum 0.26.3", 298 | ] 299 | 300 | [[package]] 301 | name = "esp-println" 302 | version = "0.10.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "58cd4fa834980ba64aad00a5c2c1a630020af984eadef65a125cb99085f6f54c" 305 | dependencies = [ 306 | "critical-section", 307 | "esp-build", 308 | "portable-atomic", 309 | ] 310 | 311 | [[package]] 312 | name = "esp-riscv-rt" 313 | version = "0.9.0" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "bfc32298ed7c263b06c8b031704d8517cc62c819f2a9d5c261d0cb119634d6e9" 316 | dependencies = [ 317 | "document-features", 318 | "riscv", 319 | "riscv-rt-macros", 320 | ] 321 | 322 | [[package]] 323 | name = "esp32c3" 324 | version = "0.24.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "cf6865f32b4936b2c396fd1bed3e935850b130282fdcb935af79c2da192cb638" 327 | dependencies = [ 328 | "critical-section", 329 | "vcell", 330 | ] 331 | 332 | [[package]] 333 | name = "fnv" 334 | version = "1.0.7" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 337 | 338 | [[package]] 339 | name = "fugit" 340 | version = "0.3.7" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7" 343 | dependencies = [ 344 | "gcd", 345 | ] 346 | 347 | [[package]] 348 | name = "gcd" 349 | version = "2.3.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 352 | 353 | [[package]] 354 | name = "hashbrown" 355 | version = "0.14.5" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 358 | 359 | [[package]] 360 | name = "heck" 361 | version = "0.4.1" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 364 | 365 | [[package]] 366 | name = "heck" 367 | version = "0.5.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 370 | 371 | [[package]] 372 | name = "ident_case" 373 | version = "1.0.1" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 376 | 377 | [[package]] 378 | name = "indexmap" 379 | version = "2.2.6" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 382 | dependencies = [ 383 | "equivalent", 384 | "hashbrown", 385 | ] 386 | 387 | [[package]] 388 | name = "lazy_static" 389 | version = "1.5.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 392 | 393 | [[package]] 394 | name = "litrs" 395 | version = "0.4.1" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" 398 | dependencies = [ 399 | "proc-macro2", 400 | ] 401 | 402 | [[package]] 403 | name = "memchr" 404 | version = "2.7.4" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 407 | 408 | [[package]] 409 | name = "minijinja" 410 | version = "1.0.21" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "55e877d961d4f96ce13615862322df7c0b6d169d40cab71a7ef3f9b9e594451e" 413 | dependencies = [ 414 | "serde", 415 | ] 416 | 417 | [[package]] 418 | name = "nb" 419 | version = "1.1.0" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" 422 | 423 | [[package]] 424 | name = "paste" 425 | version = "1.0.15" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 428 | 429 | [[package]] 430 | name = "portable-atomic" 431 | version = "1.6.0" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" 434 | 435 | [[package]] 436 | name = "proc-macro-crate" 437 | version = "3.1.0" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" 440 | dependencies = [ 441 | "toml_edit", 442 | ] 443 | 444 | [[package]] 445 | name = "proc-macro-error" 446 | version = "1.0.4" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 449 | dependencies = [ 450 | "proc-macro-error-attr", 451 | "proc-macro2", 452 | "quote", 453 | "syn 1.0.109", 454 | "version_check", 455 | ] 456 | 457 | [[package]] 458 | name = "proc-macro-error-attr" 459 | version = "1.0.4" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 462 | dependencies = [ 463 | "proc-macro2", 464 | "quote", 465 | "version_check", 466 | ] 467 | 468 | [[package]] 469 | name = "proc-macro2" 470 | version = "1.0.86" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 473 | dependencies = [ 474 | "unicode-ident", 475 | ] 476 | 477 | [[package]] 478 | name = "quote" 479 | version = "1.0.36" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 482 | dependencies = [ 483 | "proc-macro2", 484 | ] 485 | 486 | [[package]] 487 | name = "r0" 488 | version = "1.0.0" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" 491 | 492 | [[package]] 493 | name = "rand_core" 494 | version = "0.6.4" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 497 | 498 | [[package]] 499 | name = "regex" 500 | version = "1.10.5" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 503 | dependencies = [ 504 | "aho-corasick", 505 | "memchr", 506 | "regex-automata", 507 | "regex-syntax", 508 | ] 509 | 510 | [[package]] 511 | name = "regex-automata" 512 | version = "0.4.7" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 515 | dependencies = [ 516 | "aho-corasick", 517 | "memchr", 518 | "regex-syntax", 519 | ] 520 | 521 | [[package]] 522 | name = "regex-syntax" 523 | version = "0.8.4" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 526 | 527 | [[package]] 528 | name = "riscv" 529 | version = "0.11.1" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" 532 | dependencies = [ 533 | "critical-section", 534 | "embedded-hal", 535 | ] 536 | 537 | [[package]] 538 | name = "riscv-rt-macros" 539 | version = "0.2.1" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "a8d100d466dbb76681ef6a9386f3da9abc570d57394e86da0ba5af8c4408486d" 542 | dependencies = [ 543 | "proc-macro2", 544 | "quote", 545 | "syn 1.0.109", 546 | ] 547 | 548 | [[package]] 549 | name = "rustversion" 550 | version = "1.0.17" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 553 | 554 | [[package]] 555 | name = "serde" 556 | version = "1.0.204" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" 559 | dependencies = [ 560 | "serde_derive", 561 | ] 562 | 563 | [[package]] 564 | name = "serde_derive" 565 | version = "1.0.204" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" 568 | dependencies = [ 569 | "proc-macro2", 570 | "quote", 571 | "syn 2.0.71", 572 | ] 573 | 574 | [[package]] 575 | name = "stable_deref_trait" 576 | version = "1.2.0" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 579 | 580 | [[package]] 581 | name = "strsim" 582 | version = "0.11.1" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 585 | 586 | [[package]] 587 | name = "strum" 588 | version = "0.24.1" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" 591 | 592 | [[package]] 593 | name = "strum" 594 | version = "0.26.3" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 597 | dependencies = [ 598 | "strum_macros 0.26.4", 599 | ] 600 | 601 | [[package]] 602 | name = "strum_macros" 603 | version = "0.24.3" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" 606 | dependencies = [ 607 | "heck 0.4.1", 608 | "proc-macro2", 609 | "quote", 610 | "rustversion", 611 | "syn 1.0.109", 612 | ] 613 | 614 | [[package]] 615 | name = "strum_macros" 616 | version = "0.26.4" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 619 | dependencies = [ 620 | "heck 0.5.0", 621 | "proc-macro2", 622 | "quote", 623 | "rustversion", 624 | "syn 2.0.71", 625 | ] 626 | 627 | [[package]] 628 | name = "syn" 629 | version = "1.0.109" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 632 | dependencies = [ 633 | "proc-macro2", 634 | "quote", 635 | "unicode-ident", 636 | ] 637 | 638 | [[package]] 639 | name = "syn" 640 | version = "2.0.71" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" 643 | dependencies = [ 644 | "proc-macro2", 645 | "quote", 646 | "unicode-ident", 647 | ] 648 | 649 | [[package]] 650 | name = "termcolor" 651 | version = "1.4.1" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 654 | dependencies = [ 655 | "winapi-util", 656 | ] 657 | 658 | [[package]] 659 | name = "toml_datetime" 660 | version = "0.6.6" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" 663 | 664 | [[package]] 665 | name = "toml_edit" 666 | version = "0.21.1" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" 669 | dependencies = [ 670 | "indexmap", 671 | "toml_datetime", 672 | "winnow", 673 | ] 674 | 675 | [[package]] 676 | name = "unicode-ident" 677 | version = "1.0.12" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 680 | 681 | [[package]] 682 | name = "vcell" 683 | version = "0.1.3" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 686 | 687 | [[package]] 688 | name = "version_check" 689 | version = "0.9.4" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 692 | 693 | [[package]] 694 | name = "void" 695 | version = "1.0.2" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 698 | 699 | [[package]] 700 | name = "winapi-util" 701 | version = "0.1.8" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" 704 | dependencies = [ 705 | "windows-sys", 706 | ] 707 | 708 | [[package]] 709 | name = "windows-sys" 710 | version = "0.52.0" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 713 | dependencies = [ 714 | "windows-targets", 715 | ] 716 | 717 | [[package]] 718 | name = "windows-targets" 719 | version = "0.52.6" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 722 | dependencies = [ 723 | "windows_aarch64_gnullvm", 724 | "windows_aarch64_msvc", 725 | "windows_i686_gnu", 726 | "windows_i686_gnullvm", 727 | "windows_i686_msvc", 728 | "windows_x86_64_gnu", 729 | "windows_x86_64_gnullvm", 730 | "windows_x86_64_msvc", 731 | ] 732 | 733 | [[package]] 734 | name = "windows_aarch64_gnullvm" 735 | version = "0.52.6" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 738 | 739 | [[package]] 740 | name = "windows_aarch64_msvc" 741 | version = "0.52.6" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 744 | 745 | [[package]] 746 | name = "windows_i686_gnu" 747 | version = "0.52.6" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 750 | 751 | [[package]] 752 | name = "windows_i686_gnullvm" 753 | version = "0.52.6" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 756 | 757 | [[package]] 758 | name = "windows_i686_msvc" 759 | version = "0.52.6" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 762 | 763 | [[package]] 764 | name = "windows_x86_64_gnu" 765 | version = "0.52.6" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 768 | 769 | [[package]] 770 | name = "windows_x86_64_gnullvm" 771 | version = "0.52.6" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 774 | 775 | [[package]] 776 | name = "windows_x86_64_msvc" 777 | version = "0.52.6" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 780 | 781 | [[package]] 782 | name = "winnow" 783 | version = "0.5.40" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 786 | dependencies = [ 787 | "memchr", 788 | ] 789 | 790 | [[package]] 791 | name = "xtensa-lx-rt" 792 | version = "0.16.0" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "904102108b780c9a5e3275c5f3c63dc348ec43ae5da5237868515498b447d51a" 795 | dependencies = [ 796 | "bare-metal", 797 | "core-isa-parser", 798 | "minijinja", 799 | "r0", 800 | "xtensa-lx-rt-proc-macros", 801 | ] 802 | 803 | [[package]] 804 | name = "xtensa-lx-rt-proc-macros" 805 | version = "0.2.1" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "082cdede098bbec9af15b0e74085e5f3d16f2923597de7aed7b8112003af2da7" 808 | dependencies = [ 809 | "darling", 810 | "proc-macro2", 811 | "quote", 812 | "syn 2.0.71", 813 | ] 814 | --------------------------------------------------------------------------------