diff --git a/esp/README.md b/esp/README.md new file mode 100644 index 0000000..81a2892 --- /dev/null +++ b/esp/README.md @@ -0,0 +1,8 @@ +# esp + +```bash +shaunrd0/klips/esp/ +├── cpp # Examples of ESP32 projects written in C++ +├── rust # Examples of ESP32 projects written in Rust +└── README.md +``` diff --git a/esp/cpp/README.md b/esp/cpp/README.md index b31f094..90b5c18 100644 --- a/esp/cpp/README.md +++ b/esp/cpp/README.md @@ -1,7 +1,7 @@ -# esp +# esp/cpp ```bash -shaunrd0/klips/esp/ +shaunrd0/klips/esp/cpp ├── 01_led-button # Simple LED circuit controlled by an on board button. ├── 02_led-button-web # LED controlled by a button or within a web browser. ├── 03_temp-humidity-web # Temperature and humidity sensor within a web browser. diff --git a/esp/rust/01_esp-idf-std/.cargo/config.toml b/esp/rust/01_esp-idf-std/.cargo/config.toml new file mode 100644 index 0000000..f632639 --- /dev/null +++ b/esp/rust/01_esp-idf-std/.cargo/config.toml @@ -0,0 +1,16 @@ +[build] +target = "xtensa-esp32-espidf" + +[target.xtensa-esp32-espidf] +linker = "ldproxy" +runner = "espflash flash --monitor" +rustflags = [ "--cfg", "espidf_time64"] + +[unstable] +build-std = ["std", "panic_abort"] + +[env] +MCU="esp32" +# Note: this variable is not used by the pio builder (`cargo build --features pio`) +ESP_IDF_VERSION = "v5.2.3" + diff --git a/esp/rust/01_esp-idf-std/.gitignore b/esp/rust/01_esp-idf-std/.gitignore new file mode 100644 index 0000000..44679cf --- /dev/null +++ b/esp/rust/01_esp-idf-std/.gitignore @@ -0,0 +1,5 @@ +/.vscode +/.idea +/.embuild +/target +/Cargo.lock diff --git a/esp/rust/01_esp-idf-std/Cargo.toml b/esp/rust/01_esp-idf-std/Cargo.toml new file mode 100644 index 0000000..8f4af82 --- /dev/null +++ b/esp/rust/01_esp-idf-std/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "esp-idf-std" +version = "0.1.0" +authors = ["Shaun Reed "] +edition = "2021" +resolver = "2" +rust-version = "1.77" + +[[bin]] +name = "esp-idf-std" +harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors + +[profile.release] +opt-level = "s" + +[profile.dev] +debug = true # Symbols are nice and they don't increase the size on Flash +opt-level = "z" + +[features] +default = [] + +experimental = ["esp-idf-svc/experimental"] + +[dependencies] +log = "0.4" +esp-idf-svc = "0.51" +esp-idf-hal = "0.45.2" +anyhow = "1.0.98" + +# --- Optional Embassy Integration --- +# esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } + +# If you enable embassy-time-driver, you MUST also add one of: + +# a) Standalone Embassy libs ( embassy-time, embassy-sync etc) with a foreign async runtime: +# embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } # NOTE: any generic-queue variant will work + +# b) With embassy-executor: +# embassy-executor = { version = "0.7", features = ["executor-thread", "arch-std"] } + +# NOTE: if you use embassy-time with embassy-executor you don't need the generic-queue-8 feature + +# --- Temporary workaround for embassy-executor < 0.8 --- +# esp-idf-svc = { version = "0.51", features = ["embassy-time-driver", "embassy-sync"] } +# critical-section = { version = "1.1", features = ["std"], default-features = false } + +[build-dependencies] +embuild = "0.33" diff --git a/esp/rust/01_esp-idf-std/README.md b/esp/rust/01_esp-idf-std/README.md new file mode 100644 index 0000000..c6bdb62 --- /dev/null +++ b/esp/rust/01_esp-idf-std/README.md @@ -0,0 +1,32 @@ +# esp-idf-std + +This is an example of using ESP-IDF with std enabled in Rust +When flashed to a device, the application just adjusts the intensity of the on-board LED for visual verification that flashing works correctly. + +Steps used to generate this project + +```bash +cargo install cargo-generate +cargo generate --git https://github.com/esp-rs/esp-idf-template.git --name esp-idf-rust-std -d mcu=esp32 -d std=true +``` + +Steps to build and flash this project + +```bash +# Install espflash if you don't have it already +cargo install espflash + +# Export esp-idf build environment +. ~/export-esp.sh + +# Build and flash to the device +cargo build +cargo run + +# Check the serial monitor (optional) +sudo usermod -aG dialout $USER +newgrp dialout +espflash monitor +``` + +For more detailed information on setting up a development environment, see [the esp/rust README](/esp/rust/README.md) diff --git a/esp/rust/01_esp-idf-std/build.rs b/esp/rust/01_esp-idf-std/build.rs new file mode 100644 index 0000000..112ec3f --- /dev/null +++ b/esp/rust/01_esp-idf-std/build.rs @@ -0,0 +1,3 @@ +fn main() { + embuild::espidf::sysenv::output(); +} diff --git a/esp/rust/01_esp-idf-std/rust-toolchain.toml b/esp/rust/01_esp-idf-std/rust-toolchain.toml new file mode 100644 index 0000000..a2f5ab5 --- /dev/null +++ b/esp/rust/01_esp-idf-std/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/esp/rust/01_esp-idf-std/sdkconfig.defaults b/esp/rust/01_esp-idf-std/sdkconfig.defaults new file mode 100644 index 0000000..c25b89d --- /dev/null +++ b/esp/rust/01_esp-idf-std/sdkconfig.defaults @@ -0,0 +1,10 @@ +# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 + +# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). +# This allows to use 1 ms granularity for thread sleeps (10 ms by default). +#CONFIG_FREERTOS_HZ=1000 + +# Workaround for https://github.com/espressif/esp-idf/issues/7631 +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n diff --git a/esp/rust/01_esp-idf-std/src/main.rs b/esp/rust/01_esp-idf-std/src/main.rs new file mode 100644 index 0000000..51219a2 --- /dev/null +++ b/esp/rust/01_esp-idf-std/src/main.rs @@ -0,0 +1,35 @@ +use esp_idf_hal::delay::FreeRtos; +use esp_idf_hal::ledc::*; +use esp_idf_hal::peripherals::Peripherals; +use esp_idf_hal::prelude::*; + +fn main() -> anyhow::Result<()> { + esp_idf_hal::sys::link_patches(); + + println!("Configuring output channel"); + + let peripherals = Peripherals::take()?; + // Channel for on-board LED on ESP32 + let mut channel = LedcDriver::new( + peripherals.ledc.channel0, + LedcTimerDriver::new( + peripherals.ledc.timer0, + &config::TimerConfig::new().frequency(25_u32.kHz().into()), + )?, + peripherals.pins.gpio2, + )?; + + println!("Starting duty-cycle loop"); + let max_duty = channel.get_max_duty(); + // Cycle the channel duty every 2s to visually show that things are working when flashed. + for numerator in [0, 1, 2, 3, 4, 5].iter().cycle() { + println!("Duty {numerator}/5"); + channel.set_duty(max_duty * numerator / 5)?; + FreeRtos::delay_ms(2000); + } + + // We want this to run forever, so don't let the application terminate. + loop { + FreeRtos::delay_ms(1000); + } +} diff --git a/esp/rust/README.md b/esp/rust/README.md new file mode 100644 index 0000000..a5246ec --- /dev/null +++ b/esp/rust/README.md @@ -0,0 +1,13 @@ +# esp/rust + +```bash +shaunrd0/klips/esp/rust +├── 01_es-idf-std # Template project for using ESP-IDF with std enabled. +└── README.md +``` + +## Development Setup + +Some notes I took while setting this up for the first time: [Knoats](https://knoats.com/books/esp32/page/rust) + +[Espressif Rust book](https://docs.espressif.com/projects/rust/book/introduction.html)