diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index eeb32b2b..0eab6c93 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -5,7 +5,7 @@ FROM debian:bullseye-slim ENV DEBIAN_FRONTEND=noninteractive ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 -ARG NIGHTLY_VERSION=nightly-2022-03-10 +ARG NIGHTLY_VERSION=nightly-2023-02-28 ARG ESP_IDF_VERSION=v4.4.1 ARG ESP_BOARD=esp32c3 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5a69d8f3..1cec5183 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ "build": { "dockerfile": "Dockerfile", "args": { - "NIGHTLY_VERSION": "nightly-2022-03-10" + "NIGHTLY_VERSION": "nightly-2023-02-28" } }, "settings": { diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1aca6342..fbbcaccb 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,7 +2,10 @@ name: CI on: - push: {} + push: + paths-ignore: + - "book/" + - "book/**" pull_request: branches: [main] paths-ignore: diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 56354076..3e1080eb 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -4,7 +4,7 @@ ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 ARG CONTAINER_USER=gitpod ARG CONTAINER_GROUP=gitpod -ARG NIGHTLY_VERSION=nightly-2022-03-10 +ARG NIGHTLY_VERSION=nightly-2023-02-28 ARG ESP_IDF_VERSION=v4.4.1 ARG ESP_BOARD=esp32c3 RUN sudo install-packages git curl gcc clang ninja-build libudev-dev \ diff --git a/README.md b/README.md index 4bacb71e..fd6174f0 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ There is: * GPIO/Button Interrupts ([Source](./advanced/button-interrupt)) * Driving an RGB LED * Some useful common crates: - * [`esp32-c3-dkc02-bsc`](./common/lib/esp32-c3-dkc02-bsc) - Board-Support for the ESP32-C3-DKC02 - * [`get-uuid`](./common/lib/get-uuid) - provides a compile-time generated UUID + * [`get-uuid`](./common/lib/get-uuid) - Provides a compile-time generated UUID * [`mqtt-messages`](./common/lib/mqtt-messages) - MQTT helper functions - * [`icm42670p`](./common/lib/icm42670p) - basic sensor driver + * [`rgb-led`](./common/lib/rgb-led) - Provides support for the RGB LED (WS2812) + * [`wifi`](./common/lib/wifi) - Wifi helper functions * Some extra bits: * [`mqtt-python-client`](./extra/mqtt-python-client) A Python MQTT client, for testing diff --git a/advanced/README.md b/advanced/README.md index 276d3f84..0477e194 100644 --- a/advanced/README.md +++ b/advanced/README.md @@ -4,20 +4,21 @@ Folders are listed in alphabetical order, not in the order they are taught in th ## Button Interrupt -`button-interrupt/exercise/src/main.rs` contains the project code skeleton -`button-interrupt/solution/src/main.rs` contains the solution for the first step of the exercise. -`button-interrupt/solution/src/main_led.rs` contains the solution for the second step of the exercise. +[`button-interrupt/exercise/src/main.rs`](button-interrupt/src/main.rs) contains the project code skeleton +[`button-interrupt/examples/solution.rs`](button-interrupt/examples/solution.rs) contains the solution for the first step of the exercise. +[`button-interrupt/examples/solution_led.rs`]((button-interrupt/examples/solution_led.rs) ) contains the solution for the second step of the exercise. ## I2C Driver exercise (WIP) -`i2c-driver/exercise/src/icm42670p.rs` will be gap text of a very basic i2c IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver. The this gap text driver is based on the version of the same name that lives in common, but provides a little bit more functionality. +[`i2c-driver/exercise/src/icm42670p.rs`](i2c-driver/src/icm42670p.rs) will be gap text of a very basic i2c IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver. The this gap text driver is based on the version of the same name that lives in common, but provides a little bit more functionality. -`i2c-driver/exercise/src/main.rs` will contain working code. Running it without modifying the driver file will yield errors. +[`i2c-driver/exercise/src/main.rs`](i2c-driver/src/main.rs) will contain working code. Running it without modifying the driver file will yield errors. -`i2c-driver/solution/src/icm42670p.rs` provides a solution to the task. +[`i2c-driver/exercise/src/icm42670p_solution.rs`](i2c-driver/src/icm42670p_solution.rs) provides a solution to the task. ## I2C Sensor Reading Exercise (WIP) - `i2c-sensor-reading/exercise/src/main.rs` will be an exercise skeleton that will build. The task is to use an existing driver from crates.io to read out the temperature and humidity sensor over i2c. After that, a second sensor will be read out over the same i2c bus using `shared-bus`. The driver for the second sensor is available locally in `common/`. +[`i2c-sensor-reading/src/main.rs`](i2c-sensor-reading/src/main.rs) will be an exercise skeleton that will build. The task is to use an existing driver from crates.io to read out the temperature and humidity sensor over i2c. After that, a second sensor will be read out over the same i2c bus using `shared-bus`. -`i2c-sensor-reading/solution/src/main.rs` contains a working solution. +`i2c-sensor-reading/examples/part_1.rs` contains a working solution for Part 1. +`i2c-sensor-reading/examples/part_2.rs` contains a working solution for Part 2. diff --git a/advanced/button-interrupt/Cargo.toml b/advanced/button-interrupt/Cargo.toml index cf85723d..0a85519b 100644 --- a/advanced/button-interrupt/Cargo.toml +++ b/advanced/button-interrupt/Cargo.toml @@ -1,7 +1,11 @@ [package] name = "button-interrupt" version = "0.1.0" -authors = ["Anatol Ulrich ", "Tanks Transfeld "] +authors = [ + "Anatol Ulrich ", + "Tanks Transfeld ", + "Sergio Gasquez ", +] edition = "2021" resolver = "2" @@ -9,7 +13,7 @@ resolver = "2" opt-level = "s" [profile.dev] -debug = true # Symbols are nice and they don't increase the size on Flash +debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" [features] @@ -17,10 +21,11 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -anyhow = "1" -esp32-c3-dkc02-bsc = { path = "../../common/lib/esp32-c3-dkc02-bsc" } +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +anyhow = "=1.0.69" +rgb-led = { path = "../../common/lib/rgb-led" } +esp-idf-hal = "=0.40.1" [build-dependencies] -embuild = "0.28" -anyhow = "1" +embuild = "=0.31.0" +anyhow = "=1.0.69" diff --git a/advanced/button-interrupt/README.md b/advanced/button-interrupt/README.md deleted file mode 100644 index f3954314..00000000 --- a/advanced/button-interrupt/README.md +++ /dev/null @@ -1 +0,0 @@ -# Readme diff --git a/advanced/button-interrupt/examples/solution.rs b/advanced/button-interrupt/examples/solution.rs index 757fa921..8e074383 100644 --- a/advanced/button-interrupt/examples/solution.rs +++ b/advanced/button-interrupt/examples/solution.rs @@ -1,45 +1,43 @@ -// reference: -// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html - -use std::ptr; +// Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html +use anyhow::Result; use esp_idf_sys::{ - c_types::c_void, esp, gpio_config, gpio_config_t, gpio_install_isr_service, - gpio_int_type_t_GPIO_INTR_POSEDGE, gpio_isr_handler_add, gpio_mode_t_GPIO_MODE_INPUT, - xQueueGenericCreate, xQueueGiveFromISR, xQueueReceive, QueueHandle_t,ESP_INTR_FLAG_IRAM, + esp, gpio_config, gpio_config_t, gpio_install_isr_service, gpio_int_type_t_GPIO_INTR_POSEDGE, + gpio_isr_handler_add, gpio_mode_t_GPIO_MODE_INPUT, xQueueGenericCreate, xQueueGiveFromISR, + xQueueReceive, QueueHandle_t, ESP_INTR_FLAG_IRAM, }; +use std::ptr; // This `static mut` holds the queue handle we are going to get from `xQueueGenericCreate`. // This is unsafe, but we are careful not to enable our GPIO interrupt handler until after this value has been initialised, and then never modify it again static mut EVENT_QUEUE: Option = None; #[link_section = ".iram0.text"] -unsafe extern "C" fn button_interrupt(_: *mut c_void) { +unsafe extern "C" fn button_interrupt(_: *mut core::ffi::c_void) { xQueueGiveFromISR(EVENT_QUEUE.unwrap(), std::ptr::null_mut()); } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { const GPIO_NUM: i32 = 9; - + // Configures the button let io_conf = gpio_config_t { pin_bit_mask: 1 << GPIO_NUM, mode: gpio_mode_t_GPIO_MODE_INPUT, pull_up_en: true.into(), pull_down_en: false.into(), - intr_type: gpio_int_type_t_GPIO_INTR_POSEDGE, // positive edge trigger = button down + intr_type: gpio_int_type_t_GPIO_INTR_POSEDGE, // Positive edge trigger = button down }; // Queue configurations const QUEUE_TYPE_BASE: u8 = 0; - const ITEM_SIZE: u32 = 0; // we're not posting any actual data, just notifying + const ITEM_SIZE: u32 = 0; // We're not posting any actual data, just notifying const QUEUE_SIZE: u32 = 1; unsafe { // Writes the button configuration to the registers esp!(gpio_config(&io_conf))?; - // Installs the generic GPIO interrupt handler esp!(gpio_install_isr_service(ESP_INTR_FLAG_IRAM as i32))?; @@ -57,16 +55,16 @@ fn main() -> anyhow::Result<()> { // Reads the queue in a loop. loop { unsafe { - // maximum delay + // Maximum delay const QUEUE_WAIT_TICKS: u32 = 1000; // Reads the event item out of the queue let res = xQueueReceive(EVENT_QUEUE.unwrap(), ptr::null_mut(), QUEUE_WAIT_TICKS); - - // If the event has the value 0, nothing happens. if it has a different value, the button was pressed. + + // If the event has the value 0, nothing happens. if it has a different value, the button was pressed. match res { - 1 => println!("button pressed!"), - _ => {}, + 1 => println!("Button pressed!"), + _ => {} }; } } diff --git a/advanced/button-interrupt/examples/solution_led.rs b/advanced/button-interrupt/examples/solution_led.rs index e385008e..0e5f7760 100644 --- a/advanced/button-interrupt/examples/solution_led.rs +++ b/advanced/button-interrupt/examples/solution_led.rs @@ -1,49 +1,48 @@ -// reference: -// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html - -use std::ptr; -use esp32_c3_dkc02_bsc as bsc; -use bsc::led::{RGB8, WS2812RMT}; +// Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html +use anyhow::Result; +use esp_idf_hal::prelude::Peripherals; use esp_idf_sys::{ - c_types::c_void, esp, gpio_config, gpio_config_t, gpio_install_isr_service, + esp, esp_random, gpio_config, gpio_config_t, gpio_install_isr_service, gpio_int_type_t_GPIO_INTR_POSEDGE, gpio_isr_handler_add, gpio_mode_t_GPIO_MODE_INPUT, - xQueueGenericCreate, xQueueGiveFromISR, xQueueReceive, QueueHandle_t,ESP_INTR_FLAG_IRAM, esp_random, + xQueueGenericCreate, xQueueGiveFromISR, xQueueReceive, QueueHandle_t, ESP_INTR_FLAG_IRAM, }; +use rgb_led::{RGB8, WS2812RMT}; +use std::ptr; // This `static mut` holds the queue handle we are going to get from `xQueueGenericCreate`. // This is unsafe, but we are careful not to enable our GPIO interrupt handler until after this value has been initialised, and then never modify it again static mut EVENT_QUEUE: Option = None; #[link_section = ".iram0.text"] -unsafe extern "C" fn button_interrupt(_: *mut c_void) { +unsafe extern "C" fn button_interrupt(_: *mut core::ffi::c_void) { xQueueGiveFromISR(EVENT_QUEUE.unwrap(), std::ptr::null_mut()); } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { + let peripherals = Peripherals::take().unwrap(); - let mut led = WS2812RMT::new()?; + let mut led = WS2812RMT::new(peripherals.pins.gpio2, peripherals.rmt.channel0)?; const GPIO_NUM: i32 = 9; - + // Configures the button let io_conf = gpio_config_t { pin_bit_mask: 1 << GPIO_NUM, mode: gpio_mode_t_GPIO_MODE_INPUT, pull_up_en: true.into(), pull_down_en: false.into(), - intr_type: gpio_int_type_t_GPIO_INTR_POSEDGE, // positive edge trigger = button down + intr_type: gpio_int_type_t_GPIO_INTR_POSEDGE, // Positive edge trigger = button down }; // Queue configurations const QUEUE_TYPE_BASE: u8 = 0; - const ITEM_SIZE: u32 = 0; // we're not posting any actual data, just notifying + const ITEM_SIZE: u32 = 0; // We're not posting any actual data, just notifying const QUEUE_SIZE: u32 = 1; unsafe { // Writes the button configuration to the registers esp!(gpio_config(&io_conf))?; - // Installs the generic GPIO interrupt handler esp!(gpio_install_isr_service(ESP_INTR_FLAG_IRAM as i32))?; @@ -60,24 +59,22 @@ fn main() -> anyhow::Result<()> { // Reads the queue in a loop. loop { - - unsafe { - // maximum delay + // Maximum delay const QUEUE_WAIT_TICKS: u32 = 1000; // Reads the event item out of the queue let res = xQueueReceive(EVENT_QUEUE.unwrap(), ptr::null_mut(), QUEUE_WAIT_TICKS); - - // If the event has the value 0, nothing happens. if it has a different value, the button was pressed. - // If the button was pressed, a function that changes the state of the LED is called. - + + // If the event has the value 0, nothing happens. if it has a different value, the button was pressed. + // If the button was pressed, a function that changes the state of the LED is called. + match res { 1 => { // Generates random rgb values and sets them in the led. random_light(&mut led); - }, - _ => {}, + } + _ => {} }; } } @@ -93,6 +90,6 @@ fn random_light(led: &mut WS2812RMT) { color = RGB8::new(r, g, b); } - + led.set_pixel(color).unwrap(); } diff --git a/advanced/button-interrupt/rust-toolchain.toml b/advanced/button-interrupt/rust-toolchain.toml index e744d7f2..a550ad27 100644 --- a/advanced/button-interrupt/rust-toolchain.toml +++ b/advanced/button-interrupt/rust-toolchain.toml @@ -1,5 +1,2 @@ [toolchain] - - -channel = "nightly-2022-03-10" - +channel = "nightly-2023-02-28" diff --git a/advanced/button-interrupt/src/main.rs b/advanced/button-interrupt/src/main.rs index 91fe4787..40261efe 100644 --- a/advanced/button-interrupt/src/main.rs +++ b/advanced/button-interrupt/src/main.rs @@ -1,52 +1,47 @@ -// reference: -// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html -use std::ptr; - +// Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html +use anyhow::Result; use esp_idf_sys::{ - c_types::c_void, esp, gpio_config, gpio_config_t, gpio_install_isr_service, + esp, esp_random, gpio_config, gpio_config_t, gpio_install_isr_service, gpio_int_type_t_GPIO_INTR_POSEDGE, gpio_isr_handler_add, gpio_mode_t_GPIO_MODE_INPUT, - xQueueGenericCreate, xQueueGiveFromISR, xQueueReceive, QueueHandle_t,ESP_INTR_FLAG_IRAM, esp_random, + xQueueGenericCreate, xQueueGiveFromISR, xQueueReceive, QueueHandle_t, ESP_INTR_FLAG_IRAM, }; +use std::ptr; // These imports are needed for part 2. -use esp32_c3_dkc02_bsc as bsc; -use bsc::led::{RGB8, WS2812RMT}; +use rgb_led::{RGB8, WS2812RMT}; // 4. Create a `static mut` that holds the queue handle. static mut EVENT_QUEUE: Option = None; -// 6. Define what the interrupt handler does, once the button is pushed. Button_interrupt sends a message into the queue. +// 6. Define what the interrupt handler does, once the button is pushed. Button_interrupt sends a message into the queue. #[link_section = ".iram0.text"] -unsafe extern "C" fn button_interrupt(_: *mut c_void) { +unsafe extern "C" fn button_interrupt(_: *mut core::ffi::c_void) { xQueueGiveFromISR(EVENT_QUEUE.unwrap(), std::ptr::null_mut()); } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { const GPIO_NUM: i32 = 9; - // 1. Add GPIO configuration c struct + // 1. Add GPIO configuration C struct // let io_conf = gpio_config_t { // ... // }; unsafe { - - // 2. write the GPIO configuration into the register + // 2. Write the GPIO configuration into the register // esp!(...)?; - // 3. Install the global GPIO interrupt handler // esp!(...)?; // Queue configurations const QUEUE_TYPE_BASE: u8 = 0; - const ITEM_SIZE: u32 = 0; + const ITEM_SIZE: u32 = 0; const QUEUE_SIZE: u32 = 1; // 5. Create an event queue // EVENT_QUEUE = Some(...); - - + // 7. Add the button GPIO and the function to the interrupt handler // esp!(...)?; } @@ -54,12 +49,12 @@ fn main() -> anyhow::Result<()> { // The loop in main waits until it gets a message through the rx ("receiver") part of the channel loop { unsafe { - // maximum delay + // Maximum delay const QUEUE_WAIT_TICKS: u32 = 1000;; // 8. Receive the event from the queue. // let res = ...; - + // 9. Handle the value of res. // ... } diff --git a/advanced/i2c-driver/Cargo.toml b/advanced/i2c-driver/Cargo.toml index 229ce4d4..d70f1583 100644 --- a/advanced/i2c-driver/Cargo.toml +++ b/advanced/i2c-driver/Cargo.toml @@ -1,7 +1,10 @@ [package] -name = "i2c-driver-exercise" +name = "i2c-driver" version = "0.1.0" -authors = ["Tanks Transfeld "] +authors = [ + "Tanks Transfeld ", + "Sergio Gasquez ", +] edition = "2021" resolver = "2" @@ -9,7 +12,7 @@ resolver = "2" opt-level = "s" [profile.dev] -debug = true # Symbols are nice and they don't increase the size on Flash +debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" [features] @@ -17,12 +20,11 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -esp-idf-hal = "=0.38" -anyhow = "1" -embedded-hal = "0.2.7" -ignore = "=0.4.11" +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +esp-idf-hal = "=0.40.1" +anyhow = "=1.0.69" +embedded-hal = "=0.2.7" [build-dependencies] -embuild = "0.28" -anyhow = "1" +embuild = "=0.31.0" +anyhow = "=1.0.69" diff --git a/advanced/i2c-driver/rust-toolchain.toml b/advanced/i2c-driver/rust-toolchain.toml index e744d7f2..a550ad27 100644 --- a/advanced/i2c-driver/rust-toolchain.toml +++ b/advanced/i2c-driver/rust-toolchain.toml @@ -1,5 +1,2 @@ [toolchain] - - -channel = "nightly-2022-03-10" - +channel = "nightly-2023-02-28" diff --git a/advanced/i2c-driver/src/icm42670p.rs b/advanced/i2c-driver/src/icm42670p.rs index 132f9940..37ab033f 100644 --- a/advanced/i2c-driver/src/icm42670p.rs +++ b/advanced/i2c-driver/src/icm42670p.rs @@ -1,17 +1,17 @@ #![deny(unsafe_code)] -use embedded_hal::blocking::i2c; use core::marker::PhantomData; +use embedded_hal::blocking::i2c; /// ICM42670P device driver, represented by a struct with 2 fields. -/// Datasheet: https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf +/// Datasheet: https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf #[derive(Debug)] pub struct ICM42670P { // The concrete I²C device implementation. - // TODO! field 1 + // TODO! field 1 // Device address // TODO! field 2 - // remove the following line as soon as the I2C parameter is used. + // Remove the following line as soon as the I2C parameter is used. rec_type: PhantomData, } @@ -19,28 +19,28 @@ pub struct ICM42670P { /// Contains the possible variants of the devices addesses as binary numbers. #[derive(Debug, Clone, Copy, PartialEq)] pub enum DeviceAddr { - AD0, // add address - AD1, // add address + AD0, // Add address + AD1, // Add address } // impl block with methods -implICM42670P +impl ICM42670P where - // this defines which error messages will be used + // This defines which error messages will be used I2C: i2c::WriteRead + i2c::Write, { /// Creates a new instance of the sensor, taking ownership of the i2c peripheral. pub fn new(i2c: I2C, address: DeviceAddr) -> Result { - // instantiates the ICM42670P struct - // returns the struct as Ok value + // Instantiates the ICM42670P struct + // Returns the struct as Ok value todo!(); } - /// Returns the device's ID `0x67 + /// Returns the device's ID `0x67 //(if it doesn't, something is amiss) // Public method that can be accessed from outside this file. pub fn read_device_id_register(&mut self) -> Result { - // reads the Device ID register + // Reads the Device ID register todo!(); } @@ -48,17 +48,17 @@ where // This method is not public as it is only needed inside this file. #[allow(unused)] fn write_register(&mut self, register: Register, value: u8) -> Result<(), E> { - // value that will be written as u8 - // i2c write + // Value that will be written as u8 + // i2c write todo!(); } /// Reads a register using a `write_read` method. // This method is not public as it is only needed inside this file. fn read_register(&mut self, register: Register) -> Result { - // buffer for values + // Buffer for values // i2c write_read - // return u8 from le bytes + // Return u8 from le bytes todo!(); } } diff --git a/advanced/i2c-driver/src/icm42670p_solution.rs b/advanced/i2c-driver/src/icm42670p_solution.rs index 22412c60..0d80849e 100644 --- a/advanced/i2c-driver/src/icm42670p_solution.rs +++ b/advanced/i2c-driver/src/icm42670p_solution.rs @@ -3,7 +3,7 @@ use embedded_hal::blocking::i2c; /// ICM42670P device driver. -/// Datasheet: https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf +/// Datasheet: https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf #[derive(Debug)] pub struct ICM42670P { // The concrete I²C device implementation. @@ -23,7 +23,7 @@ pub enum DeviceAddr { AD1 = 0b110_1001, } -implICM42670P +impl ICM42670P where I2C: i2c::WriteRead + i2c::Write, { @@ -43,7 +43,7 @@ where // This method is not public as it is only needed inside this file. #[allow(unused)] fn write_register(&mut self, register: Register, value: u8) -> Result<(), E> { - let byte = value as u8; + let byte = value; self.i2c .write(self.address as u8, &[register.address(), byte]) } diff --git a/advanced/i2c-driver/src/lib.rs b/advanced/i2c-driver/src/lib.rs index 0fcbf7d4..7c01339a 100644 --- a/advanced/i2c-driver/src/lib.rs +++ b/advanced/i2c-driver/src/lib.rs @@ -1,11 +1,8 @@ #![deny(unsafe_code)] #![no_std] -// pub mod icm42670p; - - -// uncomment the following line to run the solution, check lib.rs for further instructions +// Uncomment the following line to run the solution, check main.rs for further instructions // pub mod icm42670p_solution; -// comment out the following line to run the exercise, check lib.rs for further instructions -pub mod icm42670p; \ No newline at end of file +// Comment out the following line to run the solution, check main.rs for further instructions +pub mod icm42670p; diff --git a/advanced/i2c-driver/src/main.rs b/advanced/i2c-driver/src/main.rs index 7a924516..4a8991e5 100644 --- a/advanced/i2c-driver/src/main.rs +++ b/advanced/i2c-driver/src/main.rs @@ -1,35 +1,32 @@ -use anyhow; +use anyhow::Result; use embedded_hal::blocking::delay::DelayMs; use esp_idf_hal::{ delay::FreeRtos, - i2c::{config::MasterConfig, Master, MasterPins, I2C0}, + i2c::{I2cConfig, I2cDriver}, peripherals::Peripherals, prelude::*, }; -use esp_idf_sys::*; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; -// uncomment the following line to run the solution, check lib.rs for further instructions -// use i2c_driver_exercise::icm42670p_solution::{DeviceAddr, ICM42670P}; - -// comment out the following line to run the exercise, check lib.rs for further instructions -use i2c_driver_exercise::icm42670p::{DeviceAddr, ICM42670P}; +// Uncomment the following line to run the solution, check lib.rs for further instructions +// use i2c_driver::icm42670p_solution::{DeviceAddr, ICM42670P}; +// Comment out the following line to run the solution, check lib.rs for further instructions +use i2c_driver::icm42670p::{DeviceAddr, ICM42670P}; // Dont change this file. Work in the icm42670p.rs and modify it so main.rs runs. -fn main() -> anyhow::Result<()> { - link_patches(); +fn main() -> Result<()> { + esp_idf_sys::link_patches(); let peripherals = Peripherals::take().unwrap(); let sda = peripherals.pins.gpio10; let scl = peripherals.pins.gpio8; - let i2c = Master::::new( - peripherals.i2c0, - MasterPins { sda, scl }, - ::default().baudrate(400.kHz().into()), - )?; + let config = I2cConfig::new().baudrate(400.kHz().into()); + let i2c = I2cDriver::new(peripherals.i2c0, sda, scl, &config)?; let mut sensor = ICM42670P::new(i2c, DeviceAddr::AD0)?; diff --git a/advanced/i2c-sensor-reading/Cargo.toml b/advanced/i2c-sensor-reading/Cargo.toml index eb86827b..98ffcaf8 100644 --- a/advanced/i2c-sensor-reading/Cargo.toml +++ b/advanced/i2c-sensor-reading/Cargo.toml @@ -1,7 +1,10 @@ [package] -name = "i2c-sensor-exercise" +name = "i2c-sensor-reading" version = "0.1.0" -authors = ["Tanks Transfeld "] +authors = [ + "Tanks Transfeld ", + "Sergio Gasquez ", +] edition = "2021" resolver = "2" @@ -9,7 +12,7 @@ resolver = "2" opt-level = "s" [profile.dev] -debug = true # Symbols are nice and they don't increase the size on Flash +debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" [features] @@ -17,16 +20,15 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -esp-idf-hal = "=0.38" -anyhow = "1" -embedded-hal = "0.2.7" -shtcx = "0.10.0" -lis3dh = "0.4.1" -shared-bus = "0.2.4" -icm42670p = { path = "../../common/lib/icm42670p" } -ignore = "=0.4.11" +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +esp-idf-hal = "=0.40.1" +anyhow = "=1.0.69" +embedded-hal = "=0.2.7" +shtcx = "=0.11.0" +lis3dh = "=0.4.2" +shared-bus = "=0.2.5" +icm42670 = "=0.1.1" [build-dependencies] -embuild = "0.28" -anyhow = "1" +embuild = "=0.31.0" +anyhow = "=1.0.69" diff --git a/advanced/i2c-sensor-reading/examples/part_1.rs b/advanced/i2c-sensor-reading/examples/part_1.rs index 473edb0f..e54a3c1f 100644 --- a/advanced/i2c-sensor-reading/examples/part_1.rs +++ b/advanced/i2c-sensor-reading/examples/part_1.rs @@ -1,60 +1,54 @@ -use anyhow; +use anyhow::Result; use embedded_hal::blocking::delay::DelayMs; use esp_idf_hal::{ delay::FreeRtos, - i2c::{config::MasterConfig, Master, MasterPins, I2C0}, + i2c::{I2cConfig, I2cDriver}, peripherals::Peripherals, prelude::*, }; -use esp_idf_sys::*; - use shtcx::{self, PowerMode}; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; -// goals of this exercise: -// instantiate i2c peripheral -// implement one sensor, print sensor values -// implement second sensor on same bus to solve an ownership problem +// Goals of this exercise: +// - Part1: Instantiate i2c peripheral +// - Part1: Implement one sensor, print sensor values +// - Part2: Implement second sensor on same bus to solve an ownership problem -fn main() -> anyhow::Result<()> { - link_patches(); +fn main() -> Result<()> { + esp_idf_sys::link_patches(); let peripherals = Peripherals::take().unwrap(); - // Instanciate the i2c peripheral, correct pins are in the training material. + // 1. Instanciate the SDA and SCL pins, correct pins are in the training material. let sda = peripherals.pins.gpio10; let scl = peripherals.pins.gpio8; + // 2. Instanciate the i2c peripheral + let config = I2cConfig::new().baudrate(400.kHz().into()); + let i2c = I2cDriver::new(peripherals.i2c0, sda, scl, &config)?; - - let i2c = Master::::new( - peripherals.i2c0, - MasterPins { sda, scl }, - ::default().baudrate(400.kHz().into()), - )?; - - - // Create an instance of the SHTC3 sensor. + // 3. Create an instance of the SHTC3 sensor. let mut sht = shtcx::shtc3(i2c); let device_id = sht.device_identifier().unwrap(); - - // Read and print the sensor's device ID. + + // 4. Read and print the sensor's device ID. println!("Device ID SHTC3: {}", device_id); loop { - // This loop initiates measurements, reads values and prints humidity in % and Temperature in °C. + // 5. This loop initiates measurements, reads values and prints humidity in % and Temperature in °C. sht.start_measurement(PowerMode::NormalMode).unwrap(); FreeRtos.delay_ms(100u32); - let measurement = sht.get_measurement_result().unwrap(); - + let measurement = sht.get_measurement_result().unwrap(); println!( "TEMP: {} °C\n HUM: {:?} %\n - \n + \n ", - measurement.temperature.as_degrees_celsius(), measurement.humidity.as_percent(), + measurement.temperature.as_degrees_celsius(), + measurement.humidity.as_percent(), ); FreeRtos.delay_ms(500u32); } } - diff --git a/advanced/i2c-sensor-reading/examples/part_2.rs b/advanced/i2c-sensor-reading/examples/part_2.rs index 6f2f88f3..36371549 100644 --- a/advanced/i2c-sensor-reading/examples/part_2.rs +++ b/advanced/i2c-sensor-reading/examples/part_2.rs @@ -1,83 +1,79 @@ -use anyhow; +use anyhow::Result; use embedded_hal::blocking::delay::DelayMs; use esp_idf_hal::{ delay::FreeRtos, - i2c::{config::MasterConfig, Master, MasterPins, I2C0}, + i2c::{I2cConfig, I2cDriver}, peripherals::Peripherals, prelude::*, }; -use esp_idf_sys::*; -use icm42670p::{ICM42670P, DeviceAddr}; +use icm42670::{Address, Icm42670, PowerMode as imuPowerMode}; +use shared_bus::BusManagerSimple; +use shtcx::{self, PowerMode as shtPowerMode}; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; -use shtcx::{self, PowerMode}; +// Goals of this exercise: +// - Part1: Instantiate i2c peripheral +// - Part1: Implement one sensor, print sensor values +// - Part2: Implement second sensor on same bus to solve an ownership problem -use shared_bus; - -// goals of this exercise: -// instantiate i2c peripheral -// implement one sensor, print sensor values -// implement second sensor on same bus to solve an ownership problem - -fn main() -> anyhow::Result<()> { - link_patches(); +fn main() -> Result<()> { + esp_idf_sys::link_patches(); let peripherals = Peripherals::take().unwrap(); + // 1. Instanciate the SDA and SCL pins, correct pins are in the training material. let sda = peripherals.pins.gpio10; let scl = peripherals.pins.gpio8; + // 2. Instanciate the i2c peripheral + let config = I2cConfig::new().baudrate(400.kHz().into()); + let i2c = I2cDriver::new(peripherals.i2c0, sda, scl, &config)?; - let i2c = Master::::new( - peripherals.i2c0, - MasterPins { sda, scl }, - ::default().baudrate(400.kHz().into()), - )?; + // 3. Instantiate the bus manager, pass the i2c bus. + let bus = BusManagerSimple::new(i2c); - // Instantiate the bus manager, pass the i2c bus. - let bus = shared_bus::BusManagerSimple::new(i2c); + // 4. Create two proxies. Now, each sensor can have their own instance of a proxy i2c, which resolves the ownership problem. + let proxy_1 = bus.acquire_i2c(); + let proxy_2 = bus.acquire_i2c(); - // Create two proxies. Now, each sensor can have their own instance of a proxy i2c, which resolves the ownership problem. - let proxy_1 =bus.acquire_i2c(); - let proxy_2 =bus.acquire_i2c(); - - // Change your previous code, so that one of the proxies is passed to the SHTC3, instead of the original i2c bus. + // 5. Change your previous code, so that one of the proxies is passed to the SHTC3, instead of the original i2c bus. let mut sht = shtcx::shtc3(proxy_1); - // Read and print the device ID. + // 6. Read and print the device ID. let device_id = sht.device_identifier().unwrap(); println!("Device ID SHTC3: {}", device_id); - // Create an instance of ICM42670p sensor. Pass the second proxy and the sensor's address. - let mut imu = ICM42670P::new(proxy_2, DeviceAddr::B110_1000)?; + // 7. Create an instance of ICM42670p sensor. Pass the second proxy and the sensor's address. + let mut imu = Icm42670::new(proxy_2, Address::Primary).unwrap(); - // Read the device's ID register and print the value. - let device_id = imu.read_device_id_register()?; + // 8. Read the device's ID register and print the value. + let device_id = imu.device_id().unwrap(); println!("Device ID ICM42670p: {}", device_id); - - // Start the ICM42670p in low noise mode. - imu.gyro_ln()?; - + // 9. Start the ICM42670p in low noise mode. + imu.set_power_mode(imuPowerMode::GyroLowNoise).unwrap(); loop { - // Read gyro data - let gyro_data =imu.read_gyro()?; - sht.start_measurement(PowerMode::NormalMode).unwrap(); + // 10. Read gyro data + let gyro_data = imu.gyro_norm().unwrap(); + sht.start_measurement(shtPowerMode::NormalMode).unwrap(); FreeRtos.delay_ms(100u32); - let measurement = sht.get_measurement_result().unwrap(); - - // Print all values + let measurement = sht.get_measurement_result().unwrap(); + + // 11. Print all values println!( " GYRO: X: {:.2} Y: {:.2} Z: {:.2}\n TEMP: {} °C\n HUM: {:?} %\n - \n + \n ", - - gyro_data.x, gyro_data.y, gyro_data.z, - measurement.temperature.as_degrees_celsius(), measurement.humidity.as_percent(), + gyro_data.x, + gyro_data.y, + gyro_data.z, + measurement.temperature.as_degrees_celsius(), + measurement.humidity.as_percent(), ); FreeRtos.delay_ms(500u32); } } - diff --git a/advanced/i2c-sensor-reading/rust-toolchain.toml b/advanced/i2c-sensor-reading/rust-toolchain.toml index e744d7f2..a550ad27 100644 --- a/advanced/i2c-sensor-reading/rust-toolchain.toml +++ b/advanced/i2c-sensor-reading/rust-toolchain.toml @@ -1,5 +1,2 @@ [toolchain] - - -channel = "nightly-2022-03-10" - +channel = "nightly-2023-02-28" diff --git a/advanced/i2c-sensor-reading/src/main.rs b/advanced/i2c-sensor-reading/src/main.rs index 2a9fc7ff..2747a919 100644 --- a/advanced/i2c-sensor-reading/src/main.rs +++ b/advanced/i2c-sensor-reading/src/main.rs @@ -1,40 +1,35 @@ -use anyhow; +use anyhow::Result; use embedded_hal::blocking::delay::DelayMs; use esp_idf_hal::{ delay::FreeRtos, - i2c::{config::MasterConfig, Master, MasterPins, I2C0}, + i2c::{I2cConfig, I2cDriver}, peripherals::Peripherals, prelude::*, }; -use esp_idf_sys::*; - use shtcx::{self, PowerMode}; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; -// goals of this exercise: -// instantiate i2c peripheral -// implement one sensor, print sensor values -// implement second sensor on same bus to solve an ownership problem +// Goals of this exercise: +// - Part1: Instantiate i2c peripheral +// - Part1: Implement one sensor, print sensor values +// - Part2: Implement second sensor on same bus to solve an ownership problem -fn main() -> anyhow::Result<()> { - link_patches(); +fn main() -> Result<()> { + esp_idf_sys::link_patches(); let peripherals = Peripherals::take().unwrap(); - // Instanciate the i2c peripheral, correct pins are in the training material. - - - - // Create an instance of the SHTC3 sensor, find help in the documentation. + // 1. Instantiate the SDA and SCL pins, correct pins are in the training material. + // 2. Instantiate the i2c peripheral,I2cDriver, using a I2cConfig of 400kHz + // 3. Create an instance of the SHTC3 sensor. - // Read and print the sensor's device ID, find the methods in the documentation. - + // 4. Read and print the sensor's device ID. loop { - - // This loop initiates measurements, reads values and prints humidity in % and Temperature in °C. + // 5. This loop initiates measurements, reads values and prints humidity in % and Temperature in °C. FreeRtos.delay_ms(500u32); } } - diff --git a/book/book.toml b/book/book.toml index 6b0ac664..2ff75cb4 100644 --- a/book/book.toml +++ b/book/book.toml @@ -1,6 +1,14 @@ [book] -authors = ["Anatol Ulrich"] +authors = ["Anatol Ulrich", "Sergio Gasquez"] +description = "Ferrous Systems' Embedded Rust on Espressif training material" language = "en" multilingual = false src = "src" title = "Embedded Rust on Espressif" + +[rust] +edition = "2021" + + +[output.html] +git-repository-url = "https://github.com/esp-rs/espressif-trainings/" diff --git a/book/src/000 summary scratch.md b/book/src/000 summary scratch.md deleted file mode 100644 index 5cb73569..00000000 --- a/book/src/000 summary scratch.md +++ /dev/null @@ -1,19 +0,0 @@ -- Intro - - Hello, world! - - log msg - - LED: show wifi status - - Hello, template! - - HTTP client - - MQTT client - - Hello, MQTT! - - dispatch commands -- [Advanced](./0x_advanced.md) - - GPIO - - Low level I/O - - I2C - - Interrupts - - RGB LED driver - - Watchdog vs. blocking I/O, threads, ?async? - -no_std: `$ rustup target add riscv32imc-unknown-none-elf` -pin nightly \ No newline at end of file diff --git a/book/src/01_intro.md b/book/src/01_intro.md index f3a46c4b..3f8dab3c 100644 --- a/book/src/01_intro.md +++ b/book/src/01_intro.md @@ -12,18 +12,18 @@ You can join the [esp-rs community](https://matrix.to/#/#esp-rs:matrix.org) on M ## The board -An [Espressif Rust Board](https://github.com/esp-rs/esp-rust-board) is mandatory[^note] for working with this book - emulators like QEMU are not supported. +A [Rust ESP Board](https://github.com/esp-rs/esp-rust-board) is mandatory[^note] for working with this book - emulators like QEMU are not supported. -The board design and images, pin layout and schematics can be also found in this repository. +The board design and images, pin layout and schematics can also be found in this repository. -If you subscribed to one of the trainings, a board will be provided to you directly by Espressif. -Some exercises also require wireless internet access. +If you are subscribed to one of the trainings, a board will be provided to you directly by Espressif. -Our focus lies primarily on the [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) platform, a [RISC-V](https://riscv.org/) based microcontroller with strong IoT capabilities, facilitated by integrated Wi-Fi and Bluetooth 5 (LE) functionality as well as large RAM + flash size for sophisticated applications. A substantial amount of this course is also applicable for Xtensa the other architecture Espressif uses, in particular the [ESP32-S3](https://www.espressif.com/en/products/socs/esp32-s3). For low-level access the general principles apply as well, but actual hardware access will differ in various ways - refer to the technical reference manuals ([C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf), [S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf)) or [other available technical documents](https://www.espressif.com/en/support/documents/technical-documents) as needed. +Our focus lies primarily on the [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) platform, a [RISC-V](https://riscv.org/) based microcontroller with strong IoT capabilities, facilitated by integrated Wi-Fi and Bluetooth 5 (LE) functionality as well as large RAM + flash size for sophisticated applications. A substantial amount of this course is also applicable for Xtensa, the other architecture Espressif uses, in particular the [ESP32-S3](https://www.espressif.com/en/products/socs/esp32-s3). For low-level access the general principles apply as well, but actual hardware access will differ in various ways - refer to the technical reference manuals ([C3](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf), [S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf)) or [other available technical documents](https://www.espressif.com/en/support/documents/technical-documents) as needed. ## Rust knowledge -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. +- 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. +- [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. -[^note]: It is possible to follow the intro part with [ESP32-C3-DevKitC-02](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html) but we do not recommend it. It is inherently easier to follow the training when using the same hardware. +[^note]: It is possible to follow the intro part with [ESP32-C3-DevKitC-02](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html) but, we do not recommend it. It is inherently easier to follow the training when using the same hardware. diff --git a/book/src/02_0_preparations.md b/book/src/02_0_preparations.md index f6b87b30..e08907ca 100644 --- a/book/src/02_0_preparations.md +++ b/book/src/02_0_preparations.md @@ -1,32 +1,32 @@ # Preparations -This chapter contains informations about the course material, the required hardware and an installation guide. +This chapter contains information about the course material, the required hardware and an installation guide. ## Icons and Formatting we use We use Icons to mark different kinds of information in the book: -* ✅ Call for action -* ❗️ Warnings, Details that require special attention -* 🔎 Knowledge that dives deeper into a subject, but which you are not required to understand to proceed. -* 💬 Descriptions for Accessibility +* ✅ Call for action. +* ⚠️ Warnings, details that require special attention. +* 🔎 Knowledge that dives deeper into a subject but which you are not required to understand, proceeding. +* 💡 Hints that might help you during the exercises > Example note: Notes like this one contain helpful information ## Required Hardware -- Rust ESP Board, available on Mouser, Aliexpress. [Full list of vendors](https://github.com/esp-rs/esp-rust-board). -- USB-C cable suitable to connect the board to your development computer -- Wi-Fi access point connected to the Internet +- [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). +- USB-C cable suitable to connect the board to your development computer. +- Wi-Fi access point connected to the Internet. -No additional debugger/probe hardware is required. +> No additional debugger/probe hardware is required. ## Ensuring a working setup -❗️ As of March 2022 we are not providing complete setup instructions for MS Windows. + -❗️ If you are participating in a training led by Ferrous Systems, we urge you to do prepare for the workshop by following the instructions in this chapter least one business day in advance to verify you're ready to go by the time it starts. Please [contact us](training@ferrous-systems.com) should you encounter any issues or require any kind of support. +⚠️ If you are participating in a training led by Ferrous Systems, we urge you to do prepare for the workshop by following the instructions in this chapter, at least, one business day in advance to verify you're ready to go by the time it starts. Please [contact us](https://ferrous-systems.com/contact/) should you encounter any issues or require any kind of support. -❗️ If you are using a [ESP32-C3-DevKitC-02](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html) a few pins and slave adresses are different, since the board is similar but not the same. This is relevant for the solutions in [advanced/i2c-sensor-reading/](/advanced/i2c-sensor-reading/solution/src/) and [advanced/i2c-driver/](/advanced/i2c-driver/solution/src/), where the pins and slave addresses for the ESP32-C3-DevKitC-02 are commented out. +⚠️ If you are using a [ESP32-C3-DevKitC-02](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html) a few pins and slave addresses are different, since the board is similar but not the same. This is relevant for the solutions in [advanced/i2c-sensor-reading/](/advanced/i2c-sensor-reading/examples) and [advanced/i2c-driver/](/advanced/i2c-driver/src/), where the pins and slave addresses for the ESP32-C3-DevKitC-02 are commented out. ## Companion material -- [Official esp-rs book](https://esp-rs.github.io/book/introduction.html) \ No newline at end of file +- [Official esp-rs book](https://esp-rs.github.io/book/introduction.html) diff --git a/book/src/02_1_hardware.md b/book/src/02_1_hardware.md index f1ffc210..6b4680b9 100644 --- a/book/src/02_1_hardware.md +++ b/book/src/02_1_hardware.md @@ -1,12 +1,12 @@ # Checking the hardware -Connect the Espressif Rust Board to your computer. Verify a tiny red control LED lights up. +Connect the Espressif Rust Board to your computer. Verify, a tiny red control LED lights up. The device should also expose its UART serial port over USB: -**Windows**: a USB Serial Device (COM port) in the Device Manager under the Ports section +**Windows**: a USB Serial Device (COM port) in the Device Manager under the Ports section. -**Linux**: a USB device under `lsusb`. +**Linux**: a USB device under `lsusb`. 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`: ``` console @@ -14,13 +14,13 @@ $ lsusb | grep USB Bus 006 Device 035: ID 303a:1001 Espressif USB JTAG/serial debug unit ``` -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: +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: ``` console $ ls -l /dev/serial/by-id lrwxrwxrwx 1 root root .... usb-Espressif_USB_JTAG_serial_debug_unit_60:55:F9:C0:27:18-if00 -> ../../ttyACM0 -(If you are using a ESP32-C3-DevKitC-02 the command is `$ ls /dev/ttyUSB*` ) ``` +> If you are using a ESP32-C3-DevKitC-02 the command is `$ ls /dev/ttyUSB*` **macOS**: The device will show up as part of the USB tree in `system_profiler`: diff --git a/book/src/02_2_software.md b/book/src/02_2_software.md index 82c1c26d..909cad52 100644 --- a/book/src/02_2_software.md +++ b/book/src/02_2_software.md @@ -2,19 +2,18 @@ Follow the steps below for a default installation of the ESP32-C3 platform tooling. -🔎 Should you desire a customized installation (e.g. building parts from source, or add support for Xtensa/ESP32-S3), instructions for doing so can be found in the [Rust on ESP targets](https://esp-rs.github.io/book/installation/index.html) chapter of the *Rust on ESP* Book. +🔎 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 [Rust on ESP targets](https://esp-rs.github.io/book/installation/index.html) chapter of the *Rust on ESP* Book. ## Rust toolchain ✅ If you haven't got Rust on your computer, obtain it via -Furthermore, for ESP32-C3, a specific *nightly* version of the Rust toolchain is currently required. +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-02-28` version. -✅ Install nightly Rust and add support for the target architecture using the following console commands: +✅ Install *nightly* Rust and add support for the target architecture using the following command: ```console -$ rustup install nightly-2022-03-10 -$ rustup component add rust-src --toolchain nightly-2022-03-10 +rustup toolchain install nightly-2023-02-28 --component rust-src ``` 🔎 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. @@ -23,14 +22,14 @@ To build for the Xtensa architecture (*not* part of this material), a fork of th ## Espressif toolchain Several tools are required: -- `cargo-espflash` - upload firmware to the microcontroller and open serial monitor with cargo integration -- `espflash` - upload firmware to the microcontroller and open serial monitor -- `ldproxy` - Espressif build toolchain dependency +- [`cargo-espflash`](https://github.com/esp-rs/espflash/tree/main/cargo-espflash) - upload firmware to the microcontroller and open serial monitor with cargo integration +- [`espflash`](https://github.com/esp-rs/espflash/tree/main/espflash) - upload firmware to the microcontroller and open serial monitor +- [`ldproxy`](https://github.com/esp-rs/embuild/tree/master/ldproxy) - Espressif build toolchain dependency ✅ Install them with the following command: ```console -$ cargo install cargo-espflash espflash ldproxy +cargo install cargo-espflash espflash ldproxy ``` ⚠️ The `espflash` and `cargo-espflash` commands listed in the book assume version is >= 2 @@ -40,70 +39,52 @@ $ cargo install cargo-espflash espflash ldproxy ### Debian/Ubuntu ```console -$ sudo apt install llvm-dev libclang-dev clang +sudo apt install llvm-dev libclang-dev clang ``` ### macOS -(when using the Homebrew package manager, which we recommend) +When using the Homebrew package manager, which we recommend: ```console -$ brew install llvm +brew install llvm ``` ### Troubleshooting - Python 3 is a required dependency. It comes preinstalled on stock macOS and typically on desktop Linux distributions. An existing **Python 2** installation with the `virtualenv` add-on pointing to it is known to potentially cause build problems. -- Error `failed to run custom build command for libudev-sys v0.1.4` or `esp-idf-sys v0.30.X`: +- Error `failed to run custom build command for libudev-sys vX.X.X` or `esp-idf-sys vX.X.X`: - At time of writing, this can be solved by - 1. running [this line](https://github.com/esp-rs/rust-build/blob/f773036483333f3b4618d988f9a1eda051573cb2/support/esp-rs-rust/Containerfile#L13) from the `esp-rs` container: + At time of writing, this can be solved by: + 1. Running this line: `apt-get update \ && apt-get install -y vim nano git curl gcc ninja-build cmake libudev-dev python3 python3-pip libusb-1.0-0 libssl-dev \ pkg-config libtinfo5` - 2. restarting the terminal + 2. Restarting the terminal. - 3. If this is not working, try `cargo clean`, remove the `~/.espressif` folder and reinstall [according to esp instructions]( -https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html). - - ⚠️ In [step 2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html#step-2-get-esp-idf), do not clone the `https://github.com/espressif/esp-idf.git` repository. For this training, we are using a git tag. - - Instead, do the following: - - ```console - git clone --recursive --depth 1 --shallow-submodules git@github.com:espressif/esp-idf.git --branch "v4.4.1" esp-idf-v4.4 - cd esp-idf-v4.4 - ./install.sh esp32c3 - . ./export.sh - ``` - - If you change terminal, you will need to source the `export.sh` file: - - ```console - source ~/esp/esp-idf-v4.4/export.sh - ``` + 3. If this is not working, try `cargo clean`, remove the `~/.espressif` folder (`%USERPROFILE%\.espressif` in Windows) and rebuild your project. 4. On Ubuntu, you might need to change your kernel to `5.19`. Run `uname -r` to obtain your kernel version. ## Docker -> ❗️ Please **note** the Docker container provides an alternative option to **compile** the Rust exercises in. +> ⚠️ Please **note**, the Docker container provides an alternative option to **compile** the Rust exercises in. > It is meant for users that have experience with virtualized environments. > Be aware that we cannot provide help for Docker specific issues during the training. - + An alternative environment to **compile** the Rust exercises in is to use Docker. In this repository there is a `Dockerfile` with instructions to install the Rust toolchain & all required packages. This virtualized environment is designed -to only compile the binaries for the espressif target. Other commands, e.g. using `cargo-espflash`, still need to +to only compile the binaries for the Espressif target. Other commands, e.g., using `cargo-espflash`, still need to be executed on the host system. ✅ Install [`Docker`](https://docs.docker.com/get-docker/) for your operating system. -To build the Docker image run the following command from the root folder: +To build the Docker image, run the following command from the root folder: ```console -$ docker image build --tag esp --file .devcontainer/Dockerfile . +docker image build --tag esp --file .devcontainer/Dockerfile . ``` Building the image takes a while depending on the OS & hardware (20-30 minutes). @@ -111,13 +92,13 @@ Building the image takes a while depending on the OS & hardware (20-30 minutes). To start the new Docker container run: ```console -$ docker run --mount type=bind,source="$(pwd)",target=/workspace,consistency=cached -it esp /bin/bash +docker run --mount type=bind,source="$(pwd)",target=/workspace,consistency=cached -it esp /bin/bash ``` This starts an interactive shell in the Docker container. It also mounts the local repository to a folder named `/workspace` inside the container. Changes to the project on the host system are reflected inside the container & vice versa. -Using this Docker setup requires certain commands to run inside the container, while other have to be executed on the host system. +Using this Docker setup requires certain commands to run inside the container, while others have to be executed on the host system. It's recommended to keep two terminals open, one connected to the Docker container, one on the host system. * in the container: compile the project @@ -128,11 +109,11 @@ It's recommended to keep two terminals open, one connected to the Docker contain ### VS Code -One editor with good Rust support is [VS Code](https://code.visualstudio.com/) which is available for most platforms. -When using VS Code we recommend the following extensions to help during the development. +One editor with good Rust support is [VS Code](https://code.visualstudio.com/), which is available for most platforms. +When using VS Code, we recommend the following extensions to help during the development. -* `Even Better TOML` for editing TOML based configuration files * [`Rust Analyzer`](https://rust-analyzer.github.io/) to provide code completion & navigation +* `Even Better TOML` for editing TOML based configuration files There are a few more useful extensions for advanced usage @@ -143,4 +124,4 @@ There are a few more useful extensions for advanced usage 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). It uses the same `Dockerfile` as the Docker setup, but builds the image and connects to it from within VS Code. -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. +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. diff --git a/book/src/02_3_repository.md b/book/src/02_3_repository.md index 0ddc9eba..06d3fb09 100644 --- a/book/src/02_3_repository.md +++ b/book/src/02_3_repository.md @@ -1,18 +1,18 @@ # Workshop repository -The entire material can be found at . +The entire material can be found at . ✅ Clone and change into the workshop repository: ```console -$ git clone "https://github.com/ferrous-systems/espressif-trainings.git" -$ cd espressif-trainings +git clone "https://github.com/esp-rs/espressif-trainings.git" +cd espressif-trainings ``` ❗ Windows users may have problems with long path names. Follow these steps to substitute the path: ```console -git clone https://github.com/ferrous-systems/espressif-trainings.git +git clone https://github.com/esp-rs/espressif-trainings.git subst r:\ espressif-trainings cd r:\ ``` @@ -23,8 +23,6 @@ cd r:\ - `book/` - markdown sources of this book - `common/` - code shared between both courses - `common/lib/` - support crates -- `common/lib/esp32-c3-dkc02-bsc` - board support crate (bsc) for the `ESP32-C3-DevKitC-02` board -- `common/vendor/` - third party crates that have been forked to add required support, pending upstream merges - `extra/` - tools not required for this training which might still be useful - `intro/` - code examples and exercises for the introduction course @@ -41,4 +39,4 @@ user = "example" password = "h4ckm3" ``` -If you copy a `cfg.toml` to a new project, remember to change the header to `[name-of-new-package]`. +❗ If you copy a `cfg.toml` to a new project, remember to change the header to `[name-of-new-package]`. diff --git a/book/src/02_4_hello_board.md b/book/src/02_4_hello_board.md index b8b249ba..c638fdcc 100644 --- a/book/src/02_4_hello_board.md +++ b/book/src/02_4_hello_board.md @@ -1,18 +1,18 @@ # Hello, board! -You're now ready to do a consistency check. +You're now ready to do a consistency check! -✅ Connect the USB-C port of the board to your computer and enter the hardware check directory in the workshop repository: +✅ Connect the USB-C port of the board to your computer and enter the `hardware-check` directory in the workshop repository: ```console -espressif-trainings$ cd intro/hardware-check +cd intro/hardware-check ``` To test Wi-Fi connectivity, you will have to provide your network name (SSID) and password (PSK). These credentials are stored in a dedicated `cfg.toml` file (which is `.gitignore`d) to prevent accidental disclosure by sharing source code or doing pull requests. An example is provided. ✅ Copy `cfg.toml.example` to `cfg.toml` (in the same directory) and edit it to reflect your actual credentials: -❗️The 5GHz band is not supported according to [ESP32-C3 documentation](https://www.espressif.com/en/news/ESP32-C3_Wi-Fi_Certified#:~:text=ESP32%2DC3%20is%20a%20safe,wide%20range%20of%20IoT%20applications), you need to ensure you are using a WiFi with active 2.4GHz band. +> ⚠️The [5GHz band is not supported in ESP32-C3](https://www.espressif.com/en/news/ESP32-C3_Wi-Fi_Certified#:~:text=ESP32%2DC3%20is%20a%20safe,wide%20range%20of%20IoT%20applications), you need to ensure you are using a WiFi with active 2.4GHz band. ```console $ cp cfg.toml.example cfg.toml @@ -46,29 +46,34 @@ rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT) (...) (...) (...) -I (4427) bsc::wifi: Wifi connected! +I (4427) wifi::wifi: Wifi connected! ``` -The board LED should turn yellow on startup, and then, depending on whether a Wifi connection could be established, either turn red (error) or blink, alternating green and blue. In case of a Wifi error, a diagnostic message will also show up at the bottom, e.g.: +>🔎 If `cargo run` has been successful, you can exit with `ctrl+C`. + +> 🔎 `cargo run` is [configured to use `espflash`](https://github.com/esp-rs/espressif-trainings/blob/main/intro/hardware-check/.cargo/config.toml#L6) as [custom runner](https://doc.rust-lang.org/cargo/reference/config.html#target). The same output can be achieved via: +> - Using `cargo-espflash`: `cargo espflash flash --release --monitor` +> - Building your project and flashing it with `espflash`: `cargo build --release && espflash target/riscv32imc-esp-espidf/release/hardware-check` +> This modification is applied to all the projects in the training for convenience. + +The board LED should turn yellow on startup, and then, depending on whether a Wifi connection could be established, either turn red (error) or blink, alternating green and blue, in case of succeeding. In case of a Wifi error, a diagnostic message will also show up at the bottom, e.g.: ```console Error: could not connect to Wi-Fi network: ESP_ERR_TIMEOUT ``` +> ⚠️ You will get an `ESP_ERR_TIMEOUT` error also in case your network name or password are incorrect, so double-check those. ## Extra information about building, flashing and monitoring If you want to try to build without flashing, you can run: ```console - cargo build --target riscv32imc-esp-espidf + cargo build ``` -This can save a lot of time as you do not need to re-flash the program in its entirety and flashing can take up quit some time. - - -If `cargo run` has been successful, you can exit with `ctrl+C`, and run the monitor the device without flashing anew with the following command: +You can also monitor the device without flashing it with the following command: ```console -cargo espflash monitor +espflash monitor ``` @@ -101,8 +106,10 @@ CMake Error at .../Modules/CMakeDetermineSystem.cmake:129 (message): Your Espressif toolchain installation might be damaged. Delete it and rerun the build to trigger a fresh download: ```console -$ rm -rf ~/.espressif +rm -rf ~/.espressif ``` +On Windows, delete `%USERPROFILE%\.espressif` folder. + --- ```console @@ -127,6 +134,3 @@ Workarounds: 2. use a hub. [Source](https://georgik.rocks/unable-to-flash-esp32-with-these-usb-c-cables/). -## Connecting to Wifi - -- You will get an `ESP_ERR_TIMEOUT` error also in case your network name or password are incorrect, so double-check those. diff --git a/book/src/03_0_intro_workshop.md b/book/src/03_0_intro_workshop.md index ffc1d75d..60c68117 100644 --- a/book/src/03_0_intro_workshop.md +++ b/book/src/03_0_intro_workshop.md @@ -1 +1,19 @@ # Intro Workshop + +This workshop guides you through the basics of embedded development, at the end of +the workshop we will be able to interact with the outside world, including sending and receiving commands to/from the board sensors. The content includes: +- Overview of a project +- Setting up a project with cargo generate. +- Writing an HTTP client. +- Writing an HTTP server. +- Writing an MQTT client that: + - Publishes sensor data + - Receives commands via a subscribed topic. + + ## Preparations + + Please go through the [preparations](./02_0_preparations.md) chapter to prepare for this workshop. + + ## Reference + + If you're new to embedded programming, read our [reference](./05_reference.md), where we explain some terms in a basic manner. diff --git a/book/src/03_1_project_orga.md b/book/src/03_1_project_orga.md index ea3f7cf4..6c053e05 100644 --- a/book/src/03_1_project_orga.md +++ b/book/src/03_1_project_orga.md @@ -2,22 +2,22 @@ ## The esp-rs crates -Unlike most other embedded platforms, Espressif supports the Rust standard library. Most notably this means you'll have arbitrary-sized collections like `Vec` or `HashMap` at your disposal, as well as generic heap storage using `Box`. You're also free to spawn new threads, and use synchronization primitives like `Arc` and `Mutex` to safely share data between them. +Unlike most other embedded platforms, Espressif supports the Rust standard library. Most notably, this means you'll have arbitrary-sized collections like `Vec` or `HashMap` at your disposal, as well as generic heap storage using `Box`. You're also free to spawn new threads, and use synchronization primitives like `Arc` and `Mutex` to safely share data between them. Still, memory is a scarce resource on embedded systems, and so you need to take care not to run out of it - threads in particular can become rather expensive. -Services like WiFi, HTTP client/server, MQTT, OTA updates, logging etc. are exposed via Espressif's open source IoT Development Framework, [esp-idf](https://github.com/espressif/esp-idf). It is mostly written in C and as such is exposed to Rust in the canonical split crate style: +Services like WiFi, HTTP client/server, MQTT, OTA updates, logging etc. are exposed via Espressif's open source IoT Development Framework, [ESP-IDF](https://github.com/espressif/esp-idf). It is mostly written in C and as such is exposed to Rust in the canonical split crate style: - a `sys` crate to provide the actual `unsafe` bindings ([esp-idf-sys](https://github.com/esp-rs/esp-idf-sys)) - a higher level crate offering safe and comfortable Rust abstractions ([esp-idf-svc](https://github.com/esp-rs/esp-idf-svc/)) The final piece of the puzzle is low-level hardware access, which is again provided in a split fashion: -- [esp-idf-hal](https://github.com/esp-rs/esp-idf-hal) implements the hardware-independent [embedded-hal](https://github.com/rust-embedded/embedded-hal) traits like analog/digital conversion, digital I/O pins, or SPI communication - as the name suggests, it also uses `esp-idf` as a foundation -- if direct register manipulation is required, [esp32c3](https://github.com/esp-rs/esp32c3) provides the peripheral access crate generated by svd2rust. +- [esp-idf-hal](https://github.com/esp-rs/esp-idf-hal) implements the hardware-independent [embedded-hal](https://github.com/rust-embedded/embedded-hal) traits like analog/digital conversion, digital I/O pins, or SPI communication - as the name suggests, it also uses ESP-IDF as a foundation +- if direct register manipulation is required, [esp32c3](https://github.com/esp-rs/esp-pacs/tree/main/esp32c3) provides the peripheral access crate generated by [`svd2rust`](https://github.com/rust-embedded/svd2rust). -More information is available in the [ecosystem chapter](https://esp-rs.github.io/book/overview/using-the-standard-library.html) of the `esp-rs` book. +More information is available in the [ecosystem chapter](https://esp-rs.github.io/book/overview/using-the-standard-library.html) of The Rust on ESP Book. ### Build toolchain -🔎 As part of a project build, `esp-idf-sys` will download [esp-idf](https://github.com/espressif/esp-idf), the C-based Espressif toolchain. The download destination is configurable; to save disk space and download time, all examples/exercises in the workshop repository are set to use one single `global` toolchain, installed in `~/.espressif`. See the `ESP_IDF_TOOLS_INSTALL_DIR` parameter in `esp-idf-sys`'s [README](https://github.com/esp-rs/esp-idf-sys#configuration) for other options. +🔎 As part of a project build, `esp-idf-sys` will download [ESP-IDF](https://github.com/espressif/esp-idf), the C-based Espressif toolchain. The download destination is configurable; to save disk space and download time, all examples/exercises in the workshop repository are set to use one single `global` toolchain, installed in `~/.espressif` (`%USERPROFILE%\.espressif` in Windows). See the `ESP_IDF_TOOLS_INSTALL_DIR` parameter in `esp-idf-sys`'s [README](https://github.com/esp-rs/esp-idf-sys#configuration) for other options. ## Package layout @@ -27,7 +27,7 @@ On top of the usual contents of a Rust project created with `cargo new`, a few a ### `Cargo.toml` -This workshop is written around the `native` build system. Alternatively you may use `PlatformIO`/`pio`, however this is currently being deprecated. +This workshop is written around the [`native` build system](https://github.com/esp-rs/esp-idf-sys#native). Alternatively, you may use [`PlatformIO`/`pio`](https://github.com/esp-rs/esp-idf-sys#pio), however this is currently being deprecated. ```toml [features] @@ -35,16 +35,16 @@ default = ["native"] native = ["esp-idf-sys/native"] ``` -Some build dependencies must be set: +Some [build dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#build-dependencies) must be set: ```toml [build-dependencies] -embuild = "0.28" -anyhow = "1" +embuild = "=0.31.0" +anyhow = "=1.0.69" ``` ### Additional configuration files - `build.rs` - [Cargo build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html). Here: sets environment variables required for building. -- `.cargo/config.toml` - sets the target architecture and controls build details. This is the place to override `ESP_IDF_TOOLS_INSTALL_DIR` if you wish to do so. -- `sdkconfig.defaults` - overrides `esp-idf` specific parameters such as stack size or log level. +- `.cargo/config.toml` - sets the target architecture, a custom runner to flash and monitor the device, and controls build details. This is the place to override `ESP_IDF_TOOLS_INSTALL_DIR` if you wish to do so. +- `sdkconfig.defaults` - overrides ESP-IDF specific parameters such as stack size, log level... diff --git a/book/src/03_2_cargo_generate.md b/book/src/03_2_cargo_generate.md index 268d9ce5..ec002c26 100644 --- a/book/src/03_2_cargo_generate.md +++ b/book/src/03_2_cargo_generate.md @@ -3,15 +3,21 @@ We're now going to use [`cargo-generate`](https://github.com/cargo-generate/cargo-generate) (a generic project wizard) to set up our first application. > Most other exercises in this workshop already provide a project skeleton and don't require using `cargo-generate`. +> +✅ Install `cargo-generate`: -✅ Change to the `intro` directory and run `cargo generate` with the `esp-idf` template: +```shell +cargo install cargo-generate +``` + +✅ Change to the `intro` directory and run `cargo generate` with the [`esp-idf` template](https://github.com/esp-rs/esp-idf-template): ```shell -$ cd intro -$ cargo generate --git https://github.com/esp-rs/esp-idf-template cargo +cd intro +cargo generate https://github.com/esp-rs/esp-idf-template cargo ``` -You'll be prompted for details regarding your new project. When given a choice between several options, navigate using cursor up/down and select with the Return key. +[You'll be prompted for details regarding your new project](https://github.com/esp-rs/esp-idf-template#generate-the-project). When given a choice between several options, navigate using cursor up/down and select with the Return key. The first message you see will be: `⚠️Unable to load config file: /home/$USER/.cargo/cargo-generate.toml`. You see this error because you do not have a favorite config file, but you don't need one and you can ignore this warning. @@ -26,26 +32,16 @@ The first message you see will be: (These items may appear in a different order) * Project Name: `hello-world` -* Rust toolchain: `nightly` * MCU: `esp32c3` * ESP-IDF native build version: `4.4` * STD support: `true` - -We're going to build using the `native` variant of the Espressif build system. - -✅ Enable the native build system by opening `Cargo.toml` in your new `hello-world` project and adding `"native"` as default feature: - -```toml -[features] -default = ["native"] # add this line -native = ["esp-idf-sys/native"] -``` +* Dev Containers support: `false` 🔎 `.cargo/config.toml` contains local settings ([list of all settings](https://doc.rust-lang.org/cargo/reference/config.html)) for your package. `Cargo.toml` contains dependencies [import all your dependencies](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html). -Optional, but recommended: To save disk space and download time, set the toolchain directory to global - otherwise each new project/workspace will have its own instance of the toolchain installed on your computer. +Optional, but recommended: To save disk space and download time, set the [toolchain directory to global](https://github.com/esp-rs/esp-idf-sys#esp_idf_tools_install_dir-esp_idf_tools_install_dir) - otherwise each new project/workspace will have its own instance of the toolchain installed on your computer: ✅ Open `hello-world/.cargo/config.toml` and add the following line to the bottom of the `[env]` section. Leave everything else unchanged. @@ -61,14 +57,14 @@ ESP_IDF_TOOLS_INSTALL_DIR = { value = "global" } # add this line ```toml [toolchain] -channel = "nightly-2022-03-10" # change this line +channel = "nightly-2023-02-28" # change this line ``` ✅ Run your project by using the following command out of the `hello-world` directory. ```shell -$ cd hello-world -$ cargo run +cd hello-world +cargo run ``` ✅ The last lines of your output should look like this: @@ -84,9 +80,7 @@ Hello, world! - Can you think of a way to prevent what you're now seeing? (click for hint:[^hint]) ## Troubleshooting -- `⛔ Git Error: authentication required`: your git configuration is probably set to override `https` github URLs to `ssh`. Check your global `~/.git/config` for `insteadOf` sections and disable them. -- `Error: Failed to generate bindings`: add `default = ["native"]` to `Cargo.toml` -- if you're using the deprecated `pio` build system, an [initial git commit of your project](https://github.com/espressif/esp-idf/issues/3920) will be required for a successful build. - if `cargo run` is stuck on `Connecting...`, you might have another monitor process still running (e.g. from the initial `hardware-check` test). Try finding and terminating it. If this doesn't help, disconnect and reconnect the board's USB cable. +- `⛔ Git Error: authentication required`: your git configuration is probably set to override `https` github URLs to `ssh`. Check your global `~/.git/config` for `insteadOf` sections and disable them. [^hint]: yield control back to the underlying operating system by `sleep`ing in a loop instead of busy waiting. (use `use std::thread::sleep`) diff --git a/book/src/03_3_1_http_https_client.md b/book/src/03_3_1_http_https_client.md index 7dc77ad9..acd3371b 100644 --- a/book/src/03_3_1_http_https_client.md +++ b/book/src/03_3_1_http_https_client.md @@ -1,4 +1,4 @@ # HTTP and HTTPS client -In this exercise, we'll write a small client that retrieves data over a HTTP connection to the internet. -Then we will upgrade it into an HTTPS client. \ No newline at end of file +In this exercise, we'll write a small client that retrieves data over an HTTP connection to the internet. +Then we will upgrade it into an HTTPS client. diff --git a/book/src/03_3_2_http_client.md b/book/src/03_3_2_http_client.md index 1221aa8a..375f4355 100644 --- a/book/src/03_3_2_http_client.md +++ b/book/src/03_3_2_http_client.md @@ -12,41 +12,34 @@ The goal of this exercise is to write a small HTTP client that connects to a web ✅ Open the docs for this project with the following command: -``` -$ cargo doc --open +```console +cargo doc --open ``` -`intro/http-client/examples/http_client.rs` contains the solution. you can run it with the following command: +`intro/http-client/examples/http_client.rs` contains the solution. You can run it with the following command: -``` +```console cargo run --example http_client ``` ## Making a connection -By default only unencrypted HTTP is available, which rather limits our options of hosts to connect to. We're going to use `http://neverssl.com/`. - -In `esp-idf`, HTTP client connections are managed by `http::client::EspHttpClient` in the `esp-idf-svc` crate. It implements the `http::client::Client` trait from `embedded-svc`, which defines functions for [HTTP request methods](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods) like `GET` or `POST`. This is a good time to have a look at the documentation you opened with `cargo doc --open` for `http::client::EspHttpClient` and see instantiation methods at your disposal. +By default, only unencrypted HTTP is available, which rather limits our options of hosts to connect to. We're going to use `http://neverssl.com/`. -✅ Add the url `http://neverssl.com/` to the main function. This is the address we will query. +In ESP-IDF, HTTP client connections are managed by `http::client::EspHttpClient` in the `esp-idf-svc` crate. It implements the `http::client::Client` trait from `embedded-svc`, which defines functions for [HTTP request methods](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods) like `GET` or `POST`. This is a good time to have a look at the documentation you opened with `cargo doc --open` for `esp_idf_svc::http::client::EspHttpConnection` and `embedded_svc::http::client::Client`. See instantiation methods at your disposal. -✅ Create a new `EspHttpClient` with default values. Look for a suitable constructor in the documentation. +✅ Create a new `EspHttpConnection` with default configuration. Look for a suitable constructor in the documentation. +✅ Get a client from the connection you just made. -Calling HTTP functions (e.g. `get(url)`) on this client returns an `EspHttpRequest`, which must be turned into a `Writer` to reflect the client's option to send some data alongside its request. +Calling HTTP functions (e.g. `get(url)`) on this client returns an `embedded_svc::http::client::Request`, which must be submitted to reflect the client's option to send some data alongside its request. -After this optional send step the `Writer` can be turned into a `Response` from which the received server output can be read: +The `get` function uses [as_ref()](https://doc.rust-lang.org/std/convert/trait.AsRef.html). This means that instead of being restricted to one specific type like just `String` or just `&str`, the function can accept anything that implements the `AsRef` trait - that is, any type where a call to `.as_ref()` will produce a `&str`. This works for `String` and `&str`, but also the `Cow` enum type which contains either of the previous two. -The `get` function uses [as_ref()](https://doc.rust-lang.org/std/convert/trait.AsRef.html). This means that instead of being restricted to one specific type like just `String` or just `&str`, the function can accept anything that implements the `AsRef` trait - that is, any type where a call to `.as_ref()` will produce an `&str`. This works for `String` and `&str`, but also the `Cow` enum type which contains either of the previous two. - -```Rust +```rust let request = client.get(url.as_ref())?; -// the parameter passed to `into_writer` is the number of bytes -// the client intends to send -let writer = request.into_writer(0)?; -let response = writer.submit()?; +let response = request.submit()?; ``` -The parameter passed to `into_writer` is the number of bytes the client intends to send. Here we are not trying to send anything. A successful response has [a status code in the 2xx range](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). Followed by the raw html of the website. @@ -58,17 +51,18 @@ A successful response has [a status code in the 2xx range](https://en.wikipedia. match status { 200..=299 => { } - _ => anyhow::bail!("unexpected response code: {}", status), + _ => bail!("Unexpected response code: {}", status), } ``` The status error can be returned with the [Anyhow](https://docs.rs/anyhow/latest/anyhow/index.html), crate which contains various functionality to simplify application-level error handling. It supplies a universal `anyhow::Result`, wrapping the success (`Ok`) case in T and removing the need to specify the Err type, as long as every error you return implements `std::error::Error`. -✅ Turn your `response` into a `embedded_svc::io::Read` reader by calling `response.reader()` and read the received data chunk by chunk into a `u8` buffer using `reader.do_read(&mut buf)`. `do_read` returns the number of bytes read - you're done when this value is `0`. +✅ Read the received data chunk by chunk into an `u8` buffer using `Read::read(&mut reader,&mut buf)`. `Read::read` returns the number of bytes read - you're done when this value is `0`. ✅ Report the total number of bytes read. -✅ Log the received data to the console. Hint, the response in the buffer is in bytes, so you might need [a method](https://doc.rust-lang.org/std/str/fn.from_utf8.html) to convert from bytes to `&str`. +✅ Log the received data to the console. +💡 The response in the buffer is in bytes, so you might need [a method](https://doc.rust-lang.org/std/str/fn.from_utf8.html) to convert from bytes to `&str`. ## Extra Tasks @@ -95,4 +89,4 @@ wifi_psk = "..." ``` - `Guru Meditation Error: Core 0 panic'ed (Load access fault). Exception was unhandled.` - This may caused by an `.unwrap()` in your code. Try replacing those by question marks. + This may be caused by an `.unwrap()` in your code. Try replacing those by question marks. diff --git a/book/src/03_3_3_https_client.md b/book/src/03_3_3_https_client.md index b66bab25..433249cc 100644 --- a/book/src/03_3_3_https_client.md +++ b/book/src/03_3_3_https_client.md @@ -1,26 +1,24 @@ -# HTTPS CLIENT +# HTTPS client -You will now make changes to your http client files so that it also works for encrypted connections. +You will now make changes to your HTTP client files so that it also works for encrypted connections. `intro/http-client/examples/http_client.rs` contains the solution. You can run it with the following command: -(It won't build unless you have completed the first step of the exercise.) -``` +```shell cargo run --example https_client ``` -Create a custom client configuration to use an `http::client::EspHttpClientConfiguration` which enables the use of these certificates and uses default values for everything else: +Create a custom client configuration to use an `esp_idf_svc::http::client::EspHttpConnection` which enables the use of these certificates and uses default values for everything else: ```rust let mut client = EspHttpClient::new(&EspHttpClientConfiguration { use_global_ca_store: true, crt_bundle_attach: Some(esp_idf_sys::esp_crt_bundle_attach), - ..Default::default() } ``` -✅ Initialize your HTTP client with this new configuration and verify HTTPS works by downloading from a `https` resource e.g. `https://espressif.com/`. the download will show as raw html in the terminal output. +✅ Initialize your HTTP client with this new configuration and verify HTTPS works by downloading from a `https` resource, e.g. `https://espressif.com/`. the download will show as raw HTML in the terminal output. ## Troubleshooting (repeated from previous section) diff --git a/book/src/03_4_http_server.md b/book/src/03_4_http_server.md index 9e950210..31c62988 100644 --- a/book/src/03_4_http_server.md +++ b/book/src/03_4_http_server.md @@ -8,7 +8,7 @@ You can find a prepared project skeleton in `intro/http-server/`. It includes es `intro/http-server/examples/https-server.rs` contains a solution. You can run it with the following command: -``` +```console cargo run --example http_server ``` @@ -20,32 +20,29 @@ To connect to your board with your browser, you need to know the board's IP addr ✅ Run the skeleton code in `intro/http-server`. The output should yield the board's IP address like this: ```console -I (3862) esp_netif_handlers: sta ip: 192.168.178.54, mask: .. -server awaiting connection +I (3862) esp_netif_handlers: sta ip: 192.168.178.54, mask: ... +... +Server awaiting connection ``` -The `sta ip` is the "station", the WiFi term for an interface connected to an access point. This is the address you'll put in your browser (or other http client like `curl`). +The `sta ip` is the _"station"_, the WiFi term for an interface connected to an access point. This is the address you'll put in your browser (or other HTTP client like `curl`). -> esp-idf tries to register the hostname `espressif` in your local network, so often `http://espressif/` instead of `http:///` will also work. +> 🔎 ESP-IDF tries to register the hostname `espressif` in your local network, so often `http://espressif/` instead of `http:///` will also work. > > You can change the hostname by setting `CONFIG_LWIP_LOCAL_HOSTNAME` in `sdkconfig.defaults`, e.g.: `CONFIG_LWIP_LOCAL_HOSTNAME="esp32c3"` Sending HTTP data to a client involves: -- creating an an instance of `EspHttpServer` -- looping in the main function so it doesn't terminate - termination would result in the server going out of scope and subsequently shutting down -- setting a separate request `handler` function for each requested path you want to serve content. Any unconfigured path will result in a `404` error. These handler functions are realized inline as Rust closures via: +- Creating an instance of `EspHttpServer` +- Looping in the main function, so it doesn't terminate - termination would result in the server going out of scope and subsequently shutting down +- Setting a separate request `handler` function for each requested path you want to serve content. Any unconfigured path will result in a `404` error. These handler functions are realized inline as Rust closures via: ```rust -server.handle_get(path, |request, response| { - // the `response` needs to write data to the client - let mut writer = response.into_writer(request); - +server.fn_handler(path, Method::Get, |request| { + // ... // construct a response - let some_buf = ...; - + let mut response = request.into_ok_response()?; // now you can write your desired data - writer.write_all(&some_buf); - + response.write_all(&some_buf)?; // once you're done the handler expects a `Completion` as result, // this is achieved via: Ok(()) @@ -65,11 +62,10 @@ server.handle_get(path, |request, response| { We can also report dynamic information to a client. The skeleton includes a configured `temp_sensor` that measures the board's internal temperature. ✅ Write a second handler that reports the chip temperature at `http:///temperature`, using the provided `temperature(val: f32)` function to generate the HTML String. -## Hints -- If you want to send a response string, it needs to be converted into a `&[u8]` slice via `a_string.as_bytes()` -- The temperature sensor needs exclusive (mutable) access. Passing it as owned value into the handler will not work (since it would get dropped after the first invocation) - you can fix this by making the handler a `move ||` closure, wrapping the sensor in an `Arc>`, keeping one `clone()` of this `Arc` in your main function and moving the other into the closure. +💡 If you want to send a response string, it needs to be converted into a `&[u8]` slice via `a_string.as_bytes()` +💡 The temperature sensor needs exclusive (mutable) access. Passing it as owned value into the handler will not work (since it would get dropped after the first invocation) - you can fix this by making the handler a `move ||` closure, wrapping the sensor in an `Arc>`, keeping one `clone()` of this `Arc` in your main function and moving the other into the closure. ## Troubleshooting - `httpd_txrx: httpd_resp_send_err` can be solved by restarting, or `cargo clean` if nothing happens. -- Make sure computer and rust board are using the same wifi network. +- Make sure your computer and the Rust ESP Board are using the same Wifi network. diff --git a/book/src/03_5_0_mqtt.md b/book/src/03_5_0_mqtt.md index 99610685..b12b21c5 100644 --- a/book/src/03_5_0_mqtt.md +++ b/book/src/03_5_0_mqtt.md @@ -1 +1,3 @@ # IoT using MQTT + +In this exercise, we will learn how MQTT works and write an application that is able to send and receive data to the Internet using MQTT. diff --git a/book/src/03_5_1_mqtt.md b/book/src/03_5_1_mqtt.md index 2c3edbd6..bb64c5a4 100644 --- a/book/src/03_5_1_mqtt.md +++ b/book/src/03_5_1_mqtt.md @@ -1,31 +1,32 @@ # How does MQTT work -❗️This exercise requires an MQTT server. If you're participating in a Ferrous Systems training, login credentials for a server operated by Espressif will be made available in the workshop, otherwise you can use one listed at or install one locally. +⚠️ This exercise requires an MQTT server. If you're participating in a Ferrous Systems training, login credentials for a server operated by Espressif will be made available in the workshop, otherwise you can use one listed at or install one locally. + +To conclude the introductory course, let's add some [IoT](https://en.wikipedia.org/wiki/Internet_of_things) functionality to the board. +Our goal here is having our boar to send out real-time updates of sensor values without having to poll repeatedly, like we would with an HTTP server, and also receive commands to change the board LED color. -To conclude the introductory course, let's add some [IoT](https://en.wikipedia.org/wiki/Internet_of_things) functionality to the board. -Our goal here is have it send out real-time updates of sensor values without having to poll repeatedly, like we would with an HTTP server, and also receive commands to change the board LED color. - -This can be modeled using a [publish-subscribe architecture](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern), where multiple clients publish messages in certain channels/topics, and can also subscribe to these topics to receive messages sent by others. Dispatching of these messages is coordinated by a message broker - in our case, this is done an MQTT server. +This can be modeled using a [publish-subscribe architecture](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern), where multiple clients publish messages in certain channels/topics, and can also subscribe to these topics to receive messages sent by others. Dispatching of these messages is coordinated by a message broker - in our case, this is done in an MQTT server. ## MQTT messages An MQTT message consists of two parts - topic and payload. -The topic serves the same purpose as an email subject or a label on a filing cabinet, whereas the payload contains the actual data. The payload data format is not specified, although JSON is common. +The topic serves the same purpose as an email subject or a label on a filing cabinet, whereas the payload contains the actual data. The payload data format is not specified, although JSON is common. 🔎 The most recent version of the MQTT standard (MQTT 5) supports content type metadata. -When sending a MQTT message, a Quality of Service (QoS) parameter needs to be defined, indicating delivery guarantees: -- at most once -- at least once -- exactly once. +When sending a MQTT message, a [Quality of Service (QoS)](https://en.wikipedia.org/wiki/MQTT#Quality_of_service) parameter needs to be defined, indicating delivery guarantees: +- At most once. +- At least once. +- Exactly once. + +For the purpose of this exercise, it does not matter which quality you choose. -For the purpose of this exercise it does not matter which quality you choose. ## MQTT topics -MQTT topics are UTF-8 strings representing a hierarchy, with individual levels separated by a `/` slash character. A leading slash is supported but not recommended. Some example topics are: +MQTT topics are UTF-8 strings representing a hierarchy, with individual levels separated by a `/` slash character. A leading slash is supported, but not recommended. Some example topics are: ```code home/garage/temperature @@ -36,9 +37,9 @@ home/front door/lock Here a sensor would periodically publish the garage temperature which then gets broadcast to every subscriber, just as the bicycle beacon publishes its GPS coordinates. The `alarm` and `lock` topics serve as a command sink for specific devices. However, nothing prevents additional subscribers from listening in on these commands, which might provide useful for auditing purposes. -🔎 Topics starting with `$` are reserved for statistics internal to the broker. Typically the topic will begin with `$SYS`. Clients cannot publish to these topics. +🔎 Topics starting with `$` are reserved for statistics internal to the broker. Typically, the topic will begin with `$SYS`. Clients cannot publish to these topics. -❗️Since all workshop participants will be sharing the same MQTT server, some measures are required to prevent crosstalk between different projects. The exercise skeleton will generate a unique, random ID (in the `UUID v4` format) for each repository checkout. You can also [manually generate your own online](https://www.uuidgenerator.net/version4). Your UUID should be used as leading part of the message topics sent between computer and board, roughly resembling this pattern: +⚠️ Since all workshop participants will be sharing the same MQTT server, some measures are required to prevent crosstalk between different projects. The exercise skeleton will generate a unique, random ID (in the `UUID v4` format) for each repository checkout. You can also [manually generate your own online](https://www.uuidgenerator.net/version4). Your UUID should be used as leading part of the message topics sent between computer and board, roughly resembling this pattern: ```code 6188eec9-6d3a-4eac-996f-ac4ab13f312d/sensor_data/temperature diff --git a/book/src/03_5_2_mqtt.md b/book/src/03_5_2_mqtt.md index ab46f167..17772083 100644 --- a/book/src/03_5_2_mqtt.md +++ b/book/src/03_5_2_mqtt.md @@ -2,28 +2,48 @@ ## Setup -✅ You can find a prepared project skeleton in `intro/mqtt/exercise`. +✅ Go to `intro/mqtt/exercise` directory. -✅ In `intro/mqtt/host_client` you can find a host run program that mimics the behavior of a second client. Run it in a separate terminal using the `cargo run` command. Find more information about the host client below. +✅ Open the prepared project skeleton in `intro/mqtt/exercise`. + +✅ In `intro/mqtt/host_client` you can find a host run program that mimics the behavior of a second client. Run it in a separate terminal using the `cargo run` command. Find more information about the host client below. The client also generates random RGB colors and publishes them in a topic. -**This is only relevant for the second part of this exercise**. +**This is only relevant for the second part of this exercise**. -❗️ Similar to the http exercises you need to configure your connection credentials in `cfg.toml` for both programs. Besides WiFi credentials you'll also need to add MQTT server details. Check each `cfg.toml.example` for required settings. Remember the name between brackets in the the `cfg.toml` file is the name of the package in `Cargo.toml`. +⚠️ Similar to the http exercises, you need to configure your connection credentials in `cfg.toml` for **both programs**. Besides WiFi credentials, you'll also need to add MQTT server details. Check each `cfg.toml.example` for required settings. Remember, the name between brackets in the `cfg.toml` file is the name of the package in `Cargo.toml`. The structure of the exercises is as below. In this part, we will focus on the Temperature topic. ![example_client_broker_board](./assets/mqtt_structure.svg) +`intro/mqtt/exercise/solution/solution_publ.rs` contains a solution. You can run it with the following command: + +```console +cargo run --example solution_publ +``` + ## Tasks ✅ Create an `EspMqttClient` with a default configuration and an empty handler closure. ✅ Send an empty message under the `hello_topic` to the broker. Use the `hello_topic(uuid)` utility function to generate a properly scoped topic. -✅ Verify a successful publish by having a client connected that logs these messages. The `host_client` implements this behavior. You should run it in another terminal. +✅ Verify a successful publish by having a client connected that logs these messages. The `host_client` implements this behavior. The `host_client` should be running in another terminal +before you run your program in the ESP Rust Board. `host_client` should print something like: +```console +Setting new color: rgb(1,196,156) +Setting new color: rgb(182,190,128) +Board says hi! +``` -✅ In the loop at the end of your main function, publish the board temperature on `temperature_data_topic(uuid)` every second. Verify this, too. +✅ In the loop at the end of your main function, publish the board temperature on `temperature_data_topic(uuid)` every second. Verify this, using `host_client` too: +```console +Setting new color: rgb(218,157,124) +Board temperature: 33.29°C +Setting new color: rgb(45,88,22) +Board temperature: 33.32°C +``` ## Establishing a connection @@ -35,8 +55,8 @@ It is constructed using ```rust -let mut client = EspMqttClient::new(broker_url, - &mqtt_config, +let mut client = EspMqttClient::new(broker_url, + &mqtt_config, move |message_event| { // ... your handler code here - leave this empty for now // we'll add functionality later in this chapter @@ -48,13 +68,13 @@ let mut client = EspMqttClient::new(broker_url, To log the sensor values sent by the board, a helper client is provided under `intro/mqtt/host_client`. It subscribes to the temperature topic. -The `mqtt_messages` crate (located in `common/lib`) supports handling messages, subscriptions and topics: +The `mqtt_messages` crate (located in `common/lib`) supports handling messages, subscriptions, and topics: ### Functions to generate topic strings - `color_topic(uuid)` - creates a topic to send colors that will be published to the board. - `hello_topic(uuid)` - test topic for initially verifying a successful connection -- `temperature_data_topic(uuid)` - creates a whole "temperature" topic string +- `temperature_data_topic(uuid)` - creates a whole "temperature" topic string ### Encoding and decoding message payloads @@ -70,7 +90,7 @@ let decoded_temperature = f32::from_be_bytes(temperature_data); // workstation ## Publish & Subscribe `EspMqttClient` is also responsible for publishing messages under a given topic. -The `publish` function includes a `retain` parameter indicating whether this message should also be delivered to clients that connect after it has been published. +The `publish` function includes a `retain` parameter indicating whether this message should also be delivered to clients that connect after it has been published. ```rust let publish_topic = /* ... */; diff --git a/book/src/03_5_3_mqtt.md b/book/src/03_5_3_mqtt.md index e1fa0679..7303f0cb 100644 --- a/book/src/03_5_3_mqtt.md +++ b/book/src/03_5_3_mqtt.md @@ -2,17 +2,23 @@ ✅ Subscribe to `color_topic(uuid)` -✅ Run `host_client` in parallel in it's own terminal. The `host_client` publishes board LED `color` roughly every second. +✅ Run `host_client` in parallel in its own terminal. The `host_client` publishes board LED `color` roughly every second. ✅ Verify your subscription is working by logging the information received through the topic. ✅ React to the LED commands by setting the newly received color to the board with `led.set_pixel(/* received color here */)`. +`intro/mqtt/exercise/solution/solution_publ_rcv.rs` contains a solution. You can run it with the following command: + +```console +cargo run --example solution_publ_rcv +``` + ### Encoding and decoding message payloads -The board LED commands are made of three bytes indicating red, green and blue. +The board LED commands are made of three bytes indicating red, green, and blue. - `enum ColorData` contains a topic `color_topic(uuid)` and the `BoardLed` - - it can convert the `data()` field of an `EspMqttMessage` by using `try_from()`. The message needs first to be coerced into a slice, using `let message_data: &[u8] = &message.data();` + - It can convert the `data()` field of an `EspMqttMessage` by using `try_from()`. The message needs first to be coerced into a slice, using `let message_data: &[u8] = &message.data();` ```rust @@ -23,7 +29,7 @@ if let Ok(ColorData::BoardLed(color)) = ColorData::try_from(message_data) { /* s ## Publish & Subscribe -`EspMqttClient` is not only responsible for publishing but also for subscribing to topics. +`EspMqttClient` is not only responsible for publishing, but also for subscribing to topics. ```rust let subscribe_topic = /* ... */; @@ -38,53 +44,52 @@ Since we're only interested in processing successfully received messages, we can ```rust let mut client = - EspMqttClient::new( - broker_url, - &mqtt_config, - move |message_event| match message_event { - Ok(Received(msg)) => process_message(msg, &mut led), - _ => warn!("Received from MQTT: {:?}", message_event), - }, - )?; + EspMqttClient::new( + broker_url, + &mqtt_config, + move |message_event| match message_event { + Ok(Received(msg)) => process_message(msg, &mut led), + _ => warn!("Received from MQTT: {:?}", message_event), + }, + )?; ``` -In the processing function, you will handle `Complete` messages. Use Rust Analyzer to generate the missing match arms or match any other type of response by logging an `info!()`. +In the processing function, you will handle `Complete` messages. + +💡 Use Rust Analyzer to generate the missing match arms or match any other type of response by logging an `info!()`. + ```rust - match message.details() { - // all messages in this exercise will be of type `Complete` - // the other variants of the `Details` enum are for larger message payloads - Complete => { +match message.details() { + // All messages in this exercise will be of type `Complete` + // The other variants of the `Details` enum are for larger message payloads + Complete => { - // Cow<&[u8]> can be coerced into a slice &[u8] or a Vec - // You can coerce it into a slice to be sent to try_from() - let message_data: &[u8] = &message.data(); - if let Ok(ColorData::BoardLed(color)) = ColorData::try_from(message_data) { - // set the LED to the newly received color + // Cow<&[u8]> can be coerced into a slice &[u8] or a Vec + // You can coerce it into a slice to be sent to try_from() + let message_data: &[u8] = &message.data(); + if let Ok(ColorData::BoardLed(color)) = ColorData::try_from(message_data) { + // Set the LED to the newly received color - } } - // Use Rust Analyzer to generate the missing match arms or match an incomplete message with a log message. - } + // Use Rust Analyzer to generate the missing match arms or match an incomplete message with a log message. +} ``` - -## Hints - -- Use a logger to see what you are receiving, for example: `info!("{}", color);` or `dbg!(color)`. +💡 Use a logger to see what you are receiving, for example: `info!("{}", color);` or `dbg!(color)`. ## Extra tasks ### Implement MQTT with hierarchical topics -- work on this if you have finished everything else. We don't provide a full solution for this, as this is to test how far you get on your own. +✅ Work on this if you have finished everything else. We don't provide a full solution for this, as this is to test how far you get on your own. Check `common/lib/mqtt-messages`: -- Implement the same procedure but by using MQTT hierarchy. Subscribe subscribing to all "command" messages, combining `cmd_topic_fragment(uuid)` with a trailing `#` wildcard. +✅ Implement the same procedure, but by using MQTT hierarchy. Subscribe subscribing to all "command" messages, combining `cmd_topic_fragment(uuid)` with a trailing `#` wildcard. -- Use `enum Command` instead of `enum ColorData`. `enum Command` represents all possible commands (here: just `BoardLed`). +✅ Use `enum Command` instead of `enum ColorData`. `enum Command` represents all possible commands (here: just `BoardLed`). -- `RawCommandData` stores the last part of a message topic (e.g. `board_led` in `a-uuid/command/board_led`). It can be converted into a `Command` using `try_from`. +✅ `RawCommandData` stores the last part of a message topic (e.g. `board_led` in `a-uuid/command/board_led`). It can be converted into a `Command` using `try_from`. ```rust // RGB LED command @@ -97,57 +102,56 @@ let raw = RawCommandData { Check the `host-client`: -- you will need to replace `color` with `command`. For example like this +✅ you will need to replace `color` with `command`. For example, like this: -``` +```rust let command = Command::BoardLed(color) ``` -- in the `process_message()` function you will need to parse the topic. +✅ in the `process_message()` function, you will need to parse the topic. ```rust match message.details() { Complete => { - // all messages in this exercise will be of type `Complete` + // All messages in this exercise will be of type `Complete` // the other variants of the `Details` enum // are for larger message payloads // Cow behaves a lot like other Rust strings (&str, String) let topic: Cow = message.topic(token); - // determine if we're interested in this topic and - // dispatch based on its content + // Determine if we're interested in this topic and + // Dispatch based on its content let is_command_topic: bool = /* ... */; if is_command_topic { let raw = RawCommandData { /* ... */ }; if let Ok(Command::BoardLed(color)) = Command::try_from(raw) { - // set the LED to the newly received color + // Set the LED to the newly received color } }, _ => {} - } } } ``` -#### Hints! - -- Since you will be iterating over a MQTT topic, you will need to `split()` on a string returns an iterator. You can access a specific item from an iterator using [`nth()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.nth). -- The solution implementing hierarchy can be run with `cargo run --example solution2`, while the solution without can be run with `cargo run` or `cargo run --example solution1` +💡 Since you will be iterating over a MQTT topic, you will need to `split()` on a string returns an iterator. You can access a specific item from an iterator using [`nth()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.nth). +💡 The solution implementing hierarchy can be run with `cargo run --example solution2`, while the solution without can be run with `cargo run` or `cargo run --example solution1` ### Other tasks -- leverage [`serde_json`](https://docs.serde.rs/serde_json/) to encode/decode your message data as JSON. -- Send some messages with a large payload from the host client and process them on the microcontroller. Large messages will be delivered in parts instead of `Details::Complete`: +✅ Leverage [`serde_json`](https://docs.serde.rs/serde_json/) to encode/decode your message data as JSON. + +✅ Send some messages with a large payload from the host client and process them on the microcontroller. Large messages will be delivered in parts instead of `Details::Complete`: ```rust InitialChunk(chunk_info) => { /* first chunk */}, SubsequentChunk(chunk_data) => { /* all subsequent chunks */ } ``` -You do not need to differentiate incoming chunks based on message ID, since at most one message will be in flight at any given time. -## Troubleshooting +💡 You do not need to differentiate incoming chunks based on message ID, since at most one message will be in flight at any given time. +## Troubleshooting + - `error: expected expression, found .` When building host client: update your stable Rust installation to 1.58 or newer - MQTT messages not showing up? make sure all clients (board and workstation) use the same UUID (you can see it in the log output) diff --git a/book/src/04_0_advanced_workshop.md b/book/src/04_0_advanced_workshop.md index fd8ecbd0..7b17cab3 100644 --- a/book/src/04_0_advanced_workshop.md +++ b/book/src/04_0_advanced_workshop.md @@ -1,15 +1,13 @@ # Advanced Workshop -In this course we're going to dive deeper into topics that are embedded-only and/or close to the hardware, especially focussing on lower level i/o. Unlike in the first part, we'll not just use the higher level abstractions where for example something like pin configurations are hidden away. Instead you'll learn how to configure them yourself. You're also going to learn how to write directly into registers and how to find out which register is needed in the first place. We'll talk about ownership issues and memory safety issues in the context of exercises. +In this course, we're going to dive deeper into topics that are embedded-only and/or close to the hardware, especially focussing on lower level I/O. Unlike in the first part, we'll not just use the higher level abstractions where for example something like pin configurations are hidden away. Instead, you'll learn how to configure them yourself. You're also going to learn how to write directly into registers and how to find out which register is needed in the first place. We'll talk about ownership issues and memory safety issues in the context of exercises. - This part consists of three exercises: +This part consists of three exercises: - In the first one you'll learn how to handle a button interrupt, in the second you'll read sensor values from sensors via the I²C bus. Once you have used the drivers we have prepared, you'll learn how to get started writing your own. This is a necessary skill as Rust drivers are usually not provided by manufacturers. +In the first one you'll learn how to handle a button interrupt, in the second you'll read sensor values from sensors via the I²C bus. Once you have used the drivers we have prepared, you'll learn how to get started writing your own. This is a necessary skill as Rust drivers are usually not provided by manufacturers. - ## Preparations - - Please go through the [preparations](./02_0_preparations.md) chapter to prepare for this workshop. +## Preparations +Please go through the [preparations](./02_0_preparations.md) chapter to prepare for this workshop. - ## Reference - - If you're new to embedded programming read our [reference](./04_7_reference.md) where we explain some terms in a basic manner. \ No newline at end of file +## Reference +If you're new to embedded programming, read our [reference](./05_reference.md) where we explain some terms in a basic manner. diff --git a/book/src/04_2_low_level_io.md b/book/src/04_2_low_level_io.md index ab80ea3e..f43df4c4 100644 --- a/book/src/04_2_low_level_io.md +++ b/book/src/04_2_low_level_io.md @@ -1,39 +1,42 @@ # Lower level I/O: How to manipulate Registers -In general there are two ways to write firmware for the ESP32-C3. One is the bare-metal using only `[no_std]` Rust, and the other using `[std]` Rust and C-Bindings to the esp-idf. -`[no_std]` Rust refers to Rust not using the standard library, only the core library, which is a subset of the standard library that does not depend on the existence of an operating system. +There are [two ways to write firmware for the ESP32-C3](https://esp-rs.github.io/book/overview/index.html): + - One is the bare-metal using only `[no_std]` Rust. + - The other using `[std]` Rust and C-Bindings to ESP-IDF. + +> [`[no_std]` Rust](https://docs.rust-embedded.org/book/intro/no-std.html) refers to Rust not using the standard library, only the [core library](https://doc.rust-lang.org/core/), which is a subset of the [standard library](https://doc.rust-lang.org/std/) that does not depend on the existence of an operating system. ## What do the ecosystems look like? -### `[std]` Rust and the esp-idf +### `[std]` Rust and the ESP-IDF -The most established way to use Rust on ESP32-C3 is using C bindings to the esp-idf. We can use Rust's standard library when going this route, as we can use an operating system: FreeRTOS. Being able to use the standard library comes with benefits: We can use all types no matter if they are stack or heap allocated. We can use threads, Mutexes and other synchronization primitives. +This way relies on using C bindings to ESP-IDF. We can use Rust's standard library when going this route, as we can use an operating system: ESP-IDF, which is based on [FreeRTOS](https://www.freertos.org/). Being able to use the standard library comes with benefits: We can use all types, no matter if they are stack or heap allocated. We can use threads, Mutexes and other synchronization primitives. - The esp-idf is mostly written in C and as such is exposed to Rust in the canonical split crate style: -- a `sys` crate to provide the actual `unsafe` bindings ([esp-idf-sys](https://github.com/esp-rs/esp-idf-sys)) -- a higher level crate offering safe and comfortable Rust abstractions ([esp-idf-svc](https://github.com/esp-rs/esp-idf-svc/)) + The ESP-IDF is mostly written in C and as such is exposed to Rust in the canonical split crate style: +- A `sys` crate to provide the actual `unsafe` bindings ([esp-idf-sys](https://github.com/esp-rs/esp-idf-sys)) +- A higher level crate offering safe and comfortable Rust abstractions ([esp-idf-svc](https://github.com/esp-rs/esp-idf-svc/)) The final piece of the puzzle is low-level hardware access, which is again provided in a split fashion: -- [esp-idf-hal](https://github.com/esp-rs/esp-idf-hal) implements the hardware-independent [embedded-hal](https://github.com/rust-embedded/embedded-hal) traits like analog/digital conversion, digital I/O pins, or SPI communication - as the name suggests, it also uses `esp-idf` as a foundation +- [esp-idf-hal](https://github.com/esp-rs/esp-idf-hal) implements the hardware-independent [embedded-hal](https://github.com/rust-embedded/embedded-hal) traits like analog/digital conversion, digital I/O pins, or SPI communication - as the name suggests, it also uses ESP-IDF as a foundation -More information is available in the [ecosystem chapter](https://esp-rs.github.io/book/overview/using-the-standard-library.html) of the `esp-rs` book. +More information is available in the [ecosystem chapter](https://esp-rs.github.io/book/overview/using-the-standard-library.html) of _The Rust on ESP Book_. -This is the way that currently allows the most possibilities on Espressif chips if you want to use Rust. Everything in this course is based on this approach. +This is the way that currently allows the most possibilities on Espressif chips if you want to use Rust. **Everything in this course is based on this approach.** -We're going to look at how to write values into Registers in this ecosystem in the context of the Interrupt exercise. +We're going to look at how to write values into Registers in this ecosystem in the context of the Interrupts exercise. ### Bare metal Rust with `[no_std]` As the name bare metal implies, we don't use an operating system. Because of this, we can't use language features that rely on one. The core library is a subset of the standard library that excludes features like heap allocated types and threads. Code that uses only the core library is labelled with `#[no_std]`. `#[no_std]` code can always run in a `std` environment, but the reverse is not true. -In Rust the mapping from Registers to Code works like this: +In Rust, the mapping from Registers to Code works like this: -Registers and their fields on a device are described in _System View Description_ (SVD) files. `svd2rust` is used to generate _Peripheral Access Crates_ (PACs) from these SVD files. The PACs provide a thin wrapper over the various memory-mapped registers defined for the particular model of micro-controller you are using. +Registers and their fields on a device are described in [_System View Description_ (SVD) files](http://www.disca.upv.es/aperles/arm_cortex_m3/curset/CMSIS/Documentation/SVD/html/index.html). [`svd2rust`](https://docs.rs/svd2rust/latest/svd2rust/) is used to generate _Peripheral Access Crates_ (PACs) from these SVD files. The PACs provide a thin wrapper over the various memory-mapped registers defined for the particular model of microcontroller you are using. -Whilst it is possible to write firmware with a PAC alone, some of it would prove unsafe or otherwise inconvenient as it only provides the most basic access to the peripherals of the microcontroller. So there is another layer, the _Hardware Abstraction Layer_ (HAL). HALs provide a more user friendly API for the chip, and often implement common traits defined in the generic [`embedded-hal`](https://github.com/rust-embedded/embedded-hal). +Whilst it is possible to write firmware with a PAC alone, some of it would prove unsafe or otherwise inconvenient as it only provides the most basic access to the peripherals of the microcontroller. So there is another layer, the _Hardware Abstraction Layer_ (HAL). HALs provide a more user-friendly API for the chip, and often implement common traits defined in the generic [`embedded-hal`](https://github.com/rust-embedded/embedded-hal). Microcontrollers are usually soldered to some _Printed Circuit Board_ (or just _Board_), which defines the connections that are made to each pin. A _Board Support Crate_ (BSC, also known as a _Board Support Package_ or BSP) may be written for a given board. This provides yet another layer of abstraction and might, for example, provide an API to the various sensors and LEDs on that board - without the user necessarily needing to know which pins on your microcontroller are connected to those sensors or LEDs. -Although a [PAC](https://github.com/esp-rs/esp-pacs/tree/main/esp32c3) for the ESP32-C3 exists, bare-metal Rust is highly experimental on ESP32-C3 chips, so for now we will not work with it on the microcontroller directly. We will write a partial sensor driver in this approach as driver's should be platform agnostic. +We will write a partial sensor driver in this approach, as driver's should be platform-agnostic. diff --git a/book/src/04_3_0_i2c.md b/book/src/04_3_0_i2c.md index 0d0ef3cc..7272eae7 100644 --- a/book/src/04_3_0_i2c.md +++ b/book/src/04_3_0_i2c.md @@ -2,13 +2,13 @@ ## Introduction -The Inter-Integrated Circuit is a serial protocol (usually shortened to I²C or I2C), which allows multiple peripheral (or slave) chips to communicate with one or more controller (or master) chips. Many devices can be connected to the same I²C bus and messages can be sent to a particular device by specifying its I²C address. The protocol requires two signal wires and can only be used for short-distance communications within one device. +The Inter-Integrated Circuit, usually shortened to I²C or I2C, is a serial protocol which allows multiple peripheral (or slave) chips to communicate with one or more controller (or master) chips. Many devices can be connected to the same I²C bus, and messages can be sent to a particular device by specifying its I²C address. The protocol requires two signal wires and can only be used for short-distance communications within one device. -One of the signal lines is for data (SDA) and the other is for the clock signal (SCL). The lines are pulled-high by default with some resistors fitted somewhere on the bus. Any device on the bus (or even multiple devices simultaneously) can 'pull' either or both of the signal lines low. This means that no damage occurs if two devices try and talk on the bus at the same time - the messages are merely corrupted (and detectably so). +One of the signal lines is for data (SDA) and the other is for the clock signal (SCL). The lines are pulled-high by default, with some resistors fitted somewhere on the bus. Any device on the bus (or even multiple devices simultaneously) can 'pull' either or both of the signal lines low. This means that no damage occurs if two devices try to talk on the bus at the same time - the messages are merely corrupted (and this is detectable). -An I²C _transaction_ consists of one or more _messages_. Each _message_ is comprised of a _start symbol_, some _words_, and finally a _stop symbol_ (or another _start symbol_ if there is a follow-on message). Each word is eight bits, followed by an ACK (0) or NACK (1) bit which is sent by the recipient to indicate whether the word was received and understood correctly. The first word indicates both the 7-bit address of the device the message is intended for, plus a bit to indicate if the device is being _read from_ or being _written to_. If there is no device of that address on the bus, the first word will naturally have a 'NACK' after it (because there is no device driving the SDA line low to generate an 'ACK' bit) and so you know there is no device present. +An I²C _transaction_ consists of one or more _messages_. Each _message_ is consists of a _start symbol_, some _words_, and finally a _stop symbol_ (or another _start symbol_ if there is a follow-on message). Each word is eight bits, followed by an ACK (0) or NACK (1) bit which is sent by the recipient to indicate whether the word was received and understood correctly. The first word indicates both the 7-bit address of the device the message is intended for, plus a bit to indicate if the device is being _read from_ or being _written to_. If there is no device of that address on the bus, the first word will naturally have a NACK after it, because there is no device driving the SDA line low to generate an ACK bit, and so you know there is no device present. -The clock frequency of the SCL line is usually 400 kHz but slower and faster speed are supported (standard speed are 100kHz-400kHz-1MHz).In our exercise, the configuration will be 400 kHz (` ::default().baudrate(400.kHz().into())`). +The clock frequency of the SCL line is usually 400 kHz but slower and faster speed are supported (standard speeds are 100kHz-400kHz-1MHz).In our exercise, the configuration will be 400 kHz (` ::default().baudrate(400.kHz().into())`). @@ -41,7 +41,7 @@ To read three bytes from an EEPROM device, the sequence will be something like: A sequence diagram of data transfer on the I²C bus: - S - Start condition - P - Stop condition -- B1 to BN - transferring of one bit -- SDA changes are allowed when SCL is low (blue), otherwise there will be a start or stop condition generated. +- B1 to BN - Transferring of one bit +- SDA changes are allowed when SCL is low (blue), otherwise there will be a start or stop condition generated. -[Source & more details: Wikipedia](https://en.wikipedia.org/wiki/I%C2%B2C). \ No newline at end of file +[Source & more details: Wikipedia](https://en.wikipedia.org/wiki/I%C2%B2C). diff --git a/book/src/04_3_1_i2c.md b/book/src/04_3_1_i2c.md index 0afa9b2f..cdbfef64 100644 --- a/book/src/04_3_1_i2c.md +++ b/book/src/04_3_1_i2c.md @@ -1,29 +1,27 @@ ## I²C Sensor Reading Exercise -In this exercise you will learn how to read out sensors on the I²C bus. +In this exercise, you will learn how to read out sensors on the I²C bus. -The board has two sensors that can be read via the I²C bus: +The Rust ESP Board has [two sensors that can be read via the I²C bus](https://github.com/esp-rs/esp-rust-board#i2c-peripherals): -| Peripheral | Part number | Reference | Crate | Address | -| ------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------- | -| IMU | ICM-42670-P | [Datasheet](https://invensense.tdk.com/download-pdf/icm-42670-p-datasheet/) | [Link](https://crates.io/crates/icm42670) | 0x68 | -| Temperature and Humidity | SHTC3 | [Datasheet](https://www.sensirion.com/en/environmental-sensors/humidity-sensors/digital-humidity-sensor-shtc3-our-new-standard-for-consumer-electronics/) | [Link](https://crates.io/crates/shtcx) | 0x70 | +| Peripheral | Part number | Reference | Crate | Address | +| ------------------------ | ----------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------- | +| IMU | ICM-42670-P | [Datasheet](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) | [Link](https://crates.io/crates/icm42670) | 0x68 | +| Temperature and Humidity | SHTC3 | [Datasheet](https://datasheetspdf.com/pdf-file/1372109/Sensirion/SHTC3/1) | [Link](https://crates.io/crates/shtcx) | 0x70 | -The task is to use an existing driver from crates.io to read out the temperature and humidity sensor over I²C. After that, a second sensor will be read out over the same I²C bus using `shared-bus`. The driver for the second sensor is available locally in `common/`. +The task is to use an existing driver from [crates.io](https://crates.io/) to read out the temperature and humidity sensor over I²C. After that, a second sensor will be read out over the same I²C bus using [`shared-bus`](https://crates.io/crates/shared-bus). ### Part 1: Reading Temperature & Humidity -Create an instance of the of the Humidity sensor SHTC3 and read and print the values for humidity and temperature every 600 ms. +Create an instance of the Humidity sensor SHTC3 and read and print the values for humidity and temperature every 600 ms. - - -`i2c-sensor-reading/examples/part_1.rs` contains a working solution of Part 1. To run the solution add `--example part_1` to your run command: +`i2c-sensor-reading/examples/part_1.rs` contains a working solution of Part 1. To run the solution for Part 1: ```console -$ cargo run --example part_1 +cargo run --example part_1 ``` `i2c-sensor-reading/src/main.rs` contains skeleton code, that already contains necessary imports for this part. @@ -32,8 +30,8 @@ $ cargo run --example part_1 ✅ Go to the `i2c-sensor-reading/` folder and open the relevant documentation with the following command: -``` -$ cargo doc --open +```console +cargo doc --open ``` ✅ Define two pins, one as SDA and one as SCL. @@ -43,22 +41,22 @@ $ cargo doc --open | SDA | GPIO10 | | SCL | GPIO8 | -✅ Create an Instance of the I²C peripheral with the help of the documentation you generated. This requires a baud rate: You can use 400kHz, a default value. +✅ Create an instance of the I²C peripheral with the help of the documentation you generated. Use 400kHz as frequency. -✅ Use the `shtcx` driver crate, make an instance of the SHTC3 sensor passing the I²C instance into them. Check the documentation for guidance. +✅ Use the `shtcx` driver crate, make an instance of the SHTC3 sensor, passing the I²C instance into them. Check the documentation for guidance. -✅ To check if the sensor is addressed correctly, read it's device ID and print the value. +✅ To check if the sensor is addressed correctly, read its device ID and print the value. #### Expected Output: -``` -Device ID: 71 +```console +Device ID SHTC3: 71 ``` ✅ Make a measurement, and read the sensor values and print them. Check the documentation for guidance on sensor methods. #### Expected Output: -``` +```console TEMP: [local temperature] °C HUM: [local humidity] % ``` @@ -66,13 +64,7 @@ HUM: [local humidity] % ❗ Some sensors need some time to pass between measurement and reading value. ❗ Watch out for the expected units! - - - - -## Hints - -* There are methods that turn the sensor values into the desired unit. +💡 There are methods that turn the sensor values into the desired unit. ### Part 2: Reading Accelerometer data. @@ -81,22 +73,23 @@ Using a bus manager, implement the second sensor. Read out its values and print Continue with your own solution from part one. Alternatively you can start with the provided partial solution of Part 1: `i2c-sensor-reading/examples/part_1.rs`. -`i2c-sensor-reading/examples/part_2.rs` contains a working solution of Part 2. You can consult it if you need help. +`i2c-sensor-reading/examples/part_2.rs` contains a working solution of Part 2. You can consult it if you need help, to run it: +```console +cargo run --example part_2 +``` #### Steps ✅ Import the driver crate for the ICM42670p. ```rust -use imc42670p; +use icm42670::{Address, Icm42670, PowerMode as imuPowerMode}; ``` ✅ Create an instance of the sensor. - - ✅ Why does passing the same I²C instance to two sensors not work, despite both being on the same I²C bus?
@@ -108,7 +101,7 @@ This is an ownership issue. Every place in memory needs to be owned by something ✅ Import the bus manager crate. ```rust -use shared_bus; +use shared_bus::BusManagerSimple; ``` ✅ Create an instance of a simple bus manager. Make two proxies and use them instead of the original I²C instance to pass to the sensors. @@ -116,20 +109,18 @@ use shared_bus; ✅ Read & print the device ID from both sensors. #### Expected Output: -``` +```console Device ID SHTC3: 71 Device ID ICM42670p: 96 ``` - ✅ Start the ICM42670p in low noise mode. - ✅ Read the gyroscope sensor values and print them with 2 decimal places alongside the temperature and humidity values. #### Expected Output: -``` +```console GYRO: X: 0.00 Y: 0.00 Z: 0:00 TEMP: [local temperature] °C HUM: [local humidity] % diff --git a/book/src/04_3_2_i2c.md b/book/src/04_3_2_i2c.md index 7cf24a28..a6b67517 100644 --- a/book/src/04_3_2_i2c.md +++ b/book/src/04_3_2_i2c.md @@ -1,18 +1,18 @@ -# I²C Driver Exercise - Easy Version +# I²C Driver Exercise - Easy Version We're not going to write an entire driver, merely the first step: the `hello world` of driver writing: reading the device ID of the sensor. This version is labelled easy, because we explain the code fragments, and you only have to copy and paste the fragments into the right place. Use this version if you have very little previous experience with Rust, if these workshops are your first in the embedded domain, or if you found the hard version too hard. You can work in the same file with either version. -`i2c-driver/src/icm42670p.rs` is a gap text of a very basic I²C IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver. This gap text driver is based on the version of the same name that lives in common, but provides a little bit more functionality. +`i2c-driver/src/icm42670p.rs` is a gap text of a very basic I²C IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver. -`i2c-driver/src/icm42670p_solution.rs` provides the solution to this exercise. If you want to run it, the imports need to be changed in `main.rs` and `lib.rs`. The imports are already there, you only need to comment the current imports out and uncomment the solutions as marked in the line comments. +`i2c-driver/src/icm42670p_solution.rs` provides the solution to this exercise. If you want to run it, the imports need to be changed in `main.rs` and `lib.rs`. The imports are already there, you only need to comment the current imports out and uncomment the solutions as marked in the line comments. -## Driver +## Driver API ### Instance of the Sensor -To use a peripheral sensor first you must get an instance of it. The sensor is represented as a struct that contains both its device address, and an object representing the I²C bus itself. This is done using traits defined in the `embedded-hal` crate. The struct is public as it needs to be accessible from outside this crate, but its fields are private. +To use a peripheral sensor first you must get an instance of it. The sensor is represented as a struct that contains both its device address, and an object representing the I²C bus itself. This is done using traits defined in the [`embedded-hal`](https://docs.rs/embedded-hal/latest/embedded_hal/) crate. The struct is public as it needs to be accessible from outside this crate, but its fields are private. -```rust +```rust #[derive(Debug)] pub struct ICM42670P { /// The concrete I²C device implementation. @@ -25,7 +25,7 @@ pub struct ICM42670P { // ... ``` -We add an `impl` block that will contain all the methods that can be used on the sensor instance. It also defines the Error Handling. In this block we also implement an instantiating method. Methods can also be public or private. This method needs to be accessible from outside, so it's labelled `pub`. Note that written this way, the sensor instance takes ownership of the I²C bus. +We add an `impl` block that will contain all the methods that can be used on the sensor instance. It also defines the Error Handling. In this block, we also implement an instantiating method. Methods can also be public or private. This method needs to be accessible from outside, so it's labelled `pub`. Note that written this way, the sensor instance takes ownership of the I²C bus. ```rust implICM42670P @@ -40,21 +40,22 @@ where ``` ### Device address -- the device's addresses are available in the code: +- The device's addresses are available in the code: ```rust AD0 = 0b110_1000, // or 0x68 AD1 = 0b110_1001, // or 0x69 ``` -- This I²C device has two possible addresses - 0x68 and 0x69. -We tell the device which one we want it to use by applying either 0V or 3.3V to the AP_AD0 pin on the device. If we apply 0V, it listens to address 0x68. If we apply 3.3V it listens to address 0x69. You can therefore think of pin AD_AD0 as being a one-bit input which sets the least-significant bit of the device address. -More information is available in the [data sheet, section 9.3](https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) -### Representation of Registers +- This I²C device has two possible addresses - `0x68` and `0x69`. +We tell the device which one we want it to use by applying either `0V` or `3.3V` to the `AP_AD0` pin on the device. If we apply 0V, it listens to address 0x68. If we apply `3.3V` it listens to address `0x69`. You can therefore think of pin `AD_AD0` as being a one-bit input which sets the least-significant bit of the device address. +More information is available in the [datasheet, section 9.3](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) + +### Representation of Registers The sensor's registers are represented as enums. Each variant has the register's address as value. The type `Register` implements a method that exposes the variant's address. -```Rust +```rust #[derive(Clone, Copy)] pub enum Register { WhoAmI = 0x75, @@ -68,15 +69,15 @@ impl Register { ``` -### read_register() and write_register() +### `read_register()` and `write_register()` -We define a read and a write method, based on methods provided by the `embedded-hal` crate. They serve as helpers for more specific methods and as an abstraction that is adapted to a sensor with 8-bit registers. Note how the `read_register()` method is based on a `write_read()` method. The reason for this lies in the characteristics of the I²C protocol: We first need to write a command over the I²C bus to specify which register we want to read from. Helper methods can remain private as they don't need to be accessible from outside this crate. +We define a _read_ and a _write_ method, based on methods provided by the `embedded-hal` crate. They serve as helpers for more specific methods and as an abstraction that is adapted to a sensor with 8-bit registers. Note how the `read_register()` method is based on a `write_read()` method. The reason for this lies in the characteristics of the I²C protocol: We first need to write a command over the I²C bus to specify which register we want to read from. Helper methods can remain private as they don't need to be accessible from outside this crate. ```rust implICM42670P where I2C: i2c::WriteRead + i2c::Write, -{ +{ //... fn write_register(&mut self, register: Register, value: u8) -> Result<(), E> { let byte = value as u8; @@ -93,20 +94,19 @@ where } ``` -✅ Implement a public method that reads the `WHOAMI` register with the address `0x0F`. Make use of the the above `read_register()` method. - +✅ Implement a public method that reads the `WhoAmI` register with the address `0x0F`. Make use of the above `read_register()` method. -✅ Optional: Implement further methods that add features to the driver. Check the [documentation](https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) for the respective registers and their addresses. Some ideas: - * switching the the gyroscope sensor or the accelerometer on - * starting measurements - * reading measurements +✅ Optional: Implement further methods that add features to the driver. Check the [documentation](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) for the respective registers and their addresses. 💡 Some ideas: +* Switching the gyroscope sensor or the accelerometer on +* Starting measurements +* Reading measurements ### 🔎 General info about peripheral registers -Registers can have different meanings; in essence they are **a location that can store a value**. +Registers can have different meanings; in essence, they are **a location that can store a value**. -In this specific context we are using an external device (since it is a sensor, even if it is on the same PCB). It is addressable by I2C and we are reading and writing to its register addresses. The addresses each identify a unique location that contains some information. In this case, we want the address for the location that contains the current temperature, as read by the sensor. +In this specific context, we are using an external device (since it is a sensor, even if it is on the same PCB). It is addressable by I2C, and we are reading and writing to its register addresses. The addresses each identify a unique location that contains some information. In this case, we want the address for the location that contains the current temperature, as read by the sensor. -You can find the register map of the ICM-42670 in [section 14](https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) should you want to try to get other interesting data from this sensor. +You can find the register map of the ICM-42670 in [section 14](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) should you want to try to get other interesting data from this sensor. diff --git a/book/src/04_3_3_i2c.md b/book/src/04_3_3_i2c.md index 4b8951ed..5f212bd1 100644 --- a/book/src/04_3_3_i2c.md +++ b/book/src/04_3_3_i2c.md @@ -1,69 +1,59 @@ -# Writing an I²C Driver - Hard +# Writing an I²C Driver - Hard Version -We're not going to write an entire driver, merely the first step: the `hello world` of driver writing: reading the device ID of the sensor. This version is labelled hard, because you have to come up with the content of the methods and research information in the `embedded-hal` and data-sheets yourself. You can work in the same file with either version. +We're not going to write an entire driver, merely the first step: the `hello world` of driver writing: reading the device ID of the sensor. This version is labelled hard, because you have to come up with the content of the methods and research information in the [`embedded-hal`](https://docs.rs/embedded-hal/latest/embedded_hal/) and datasheets yourself. You can work in the same file with either version. -`i2c-driver/src/icm42670p.rs` is a gap text of a very basic I²C IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver. The this gap text driver is based on the version of the same name that lives in common, but provides a little bit more functionality. +`i2c-driver/src/icm42670p.rs` is a gap text of a very basic I²C IMU sensor driver. The task is to complete the file, so that running `main.rs` will log the device ID of the driver. -`i2c-driver/src/icm42670p_solution.rs` provides the solution to this exercise. If you want to run it, the imports need to be changed in `main.rs` and `lib.rs`. The imports are already there, you only need to comment the current imports out and uncomment the solutions as marked in the line comments. +`i2c-driver/src/icm42670p_solution.rs` provides the solution to this exercise. If you want to run it, the imports need to be changed in `main.rs` and `lib.rs`. The imports are already there, you only need to comment the current imports out and uncomment the solutions as marked in the line comments. ## Driver API ### Instance of the Sensor - ✅ Create a struct that represents the sensor. It has two fields, one that represents the sensor's device address and one that represents the `I²C` bus itself. This is done using traits defined in the `embedded-hal` crate. The struct is public as it needs to be accessible from outside this crate, but its fields are private. + ✅ Create a struct that represents the sensor. It has two fields, one that represents the sensor's device address and one that represents the `I²C` bus itself. This is done using traits defined in the `embedded-hal` crate. The struct is public as it needs to be accessible from outside this crate, but its fields are private. ✅ Implement an instantiating method in the `impl` block. This method needs to be accessible from outside, so it's labelled `pub`. The method takes ownership of the I²C bus and creates an instance of the struct you defined earlier. #### Device address - ✅ This I²C device has two possible addresses, find them in the [data sheet, section 9.3](https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf). + ✅ This I²C device has two possible addresses, find them in the [datasheet, section 9.3](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf). -🔎 We tell the device which one we want it to use by applying either 0V or 3.3V to the AP_AD0 pin on the device. If we apply 0V, it listens to address 0x68. If we apply 3.3V it listens to address 0x69. You can therefore think of pin AD_AD0 as being a one-bit input which sets the least-significant bit of the device address. - - - ✅ Create an enum that represents both address variants. The values of the variants need to be in binary representation. +🔎 We tell the device which one we want it to use by applying either `0V` or `3.3V` to the `AP_AD0` pin on the device. If we apply `0V`, it listens to address `0x68`. If we apply `3.3V` it listens to address `0x69`. You can therefore think of pin `AD_AD0` as being a one-bit input which sets the least-significant bit of the device address. +✅ Create an enum that represents both address variants. The values of the variants need to be in binary representation. ### Representation of Registers -✅ Create an enum that represents the sensor's registers. Each variant has the register's address as value. For now you only need the WhoAmI register. Find its address in the data sheet. - +✅ Create an enum that represents the sensor's registers. Each variant has the register's address as value. For now, you only need the `WhoAmI` register. Find its address in the datasheet. ✅ Implement a method that exposes the variant's address as `u8`. +### `read_register()` and `write_register()` -### read_register() and write_register() - -✅ Check out the write and write_read function in the embedded-hal. Why is it `write_read` and not just `read`? +✅ Check out the write and `write_read` function in the `embedded-hal`. Why is it `write_read` and not just `read`?
Answer -The reason for this lies in the characteristics of the I²C protocol: We first need to write a command over the I²C bus to specify which register we want to read from. +The reason for this lies in the characteristics of the I²C protocol: We first need to write a command over the I²C bus to specify which register we want to read from.
+✅ Define a `read_register` and a `write_register` method for the sensor instance. Use methods provided by the `embedded-hal` crate. They serve as helpers for more specific methods and as an abstraction that is adapted to a sensor with 8-bit registers. This means that the data that is written, as well as the data that is read is an unsigned 8-bit integer. Helper methods can remain private as they don't need to be accessible from outside this crate. -✅ Define a `read_register` and a `write_register` method for the sensor instance. Use methods provided by the `embedded-hal` crate. They serve as helpers for more specific methods and as an abstraction that is adapted to a sensor with 8-bit registers. This means that the data that is written, as well as the data that is read is an unsigned 8-bit integer. Helper methods can remain private as they don't need to be accessible from outside this crate. - +✅ Implement a public method that reads the `WhoAmI` register with the address `0x75`. Make use of the above `read_register()` method. -✅ Implement a public method that reads the `WHOAMI` register with the address `0x0F`. Make use of the the above `read_register()` method. +✅ Optional: Implement further methods that add features to the driver. Check the [documentation](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) for the respective registers and their addresses. 💡 Some ideas: + * Switching the gyroscope sensor or the accelerometer on + * Starting measurements + * Reading measurements - -✅ Optional: Implement further methods that add features to the driver. Check the [documentation](https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) for the respective registers and their addresses. Some ideas: - * switching the the gyroscope sensor or the accelerometer on - * starting measurements - * reading measurements - -### General info about how registers work +### 🔎 General info about peripheral registers - Registers are small amounts of storage, immediately accessible by the processor. The registers on the sensor are 8 bits. - They can be accessed by their address -- You can find [register maps](https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) in the section 14. +- You can find [register maps](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf) in the section 14. - Returning a value with MSB and LSB (most significant byte and least significant byte) is done by shifting MSB values, and OR LSB values. ```rust let GYRO_DATA_X: i16 = ((GYRO_DATA_X1 as i16) << 8) | GYRO_DATA_X0 as i16; ``` - -If you need hints and inspiration on what to implement, you can check the icm42670p in the common/lib folder. - diff --git a/book/src/04_4_0_interrupts.md b/book/src/04_4_0_interrupts.md index 24542501..bb829d1f 100644 --- a/book/src/04_4_0_interrupts.md +++ b/book/src/04_4_0_interrupts.md @@ -1,23 +1,23 @@ # Interrupts -An interrupt is a request for the processor to interrupt currently executing code, so that the event can be processed in a timely manner. If the request is accepted, the processor will suspend its current activities, save its state, and execute a function called an interrupt handler to deal with the event. Interrupts are commonly used by hardware devices to indicate electronic or physical state changes that require time-sensitive attention, for example pushing a button. +An interrupt is a request for the processor to interrupt currently executing code, so that the event can be processed in a timely manner. If the request is accepted, the processor will suspend its current activities, save its state, and execute a function called an interrupt handler to deal with the event. Interrupts are commonly used by hardware devices to indicate electronic or physical state changes that require time-sensitive attention, for example, pushing a button. -The fact that interrupt handlers can be called at any time provides a challenge in embedded Rust: It requires the existence of statically allocated mutable memory that both the interrupt handler and the main code can refer to and it also requires that this memory is always accessible. +The fact that interrupt handlers can be called at any time provides a challenge in embedded Rust: It requires the existence of statically allocated mutable memory that both the interrupt handler and the main code can refer to, and it also requires that this memory is always accessible. ## Challenges ### Flash Memory -Flash memory does not fulfill this requirement as it is out of action for example during write operations. Interrupts that occur during this time will go unnoticed. In our example this would result in no reaction when the button is pushed. We solve this by moving the the interrupt handler into RAM. -### Statically Mutable Memory +Flash memory does not fulfill this requirement as it is out of action for example during write operations. Interrupts that occur during this time will go unnoticed. In our example, this would result in no reaction when the button is pushed. We solve this by moving the interrupt handler into RAM. +### Statically Mutable Memory -In Rust such memory can be declared by defining a `static mut`. But reading and writing to such variables is always unsafe, as without precautions race conditions can be triggered. +In Rust, such memory can be declared by defining a `static mut`. But reading and writing to such variables is always unsafe, as without precautions race conditions can be triggered. How do we handle this problem? In our example, the ESP-IDF framework provides a `Queue` type which handles the shared-mutable state for us. We simply get a `QueueHandle` which unique identifies the particular `Queue` being used. However, the main thread is given this `QueueHandle_t` at run-time, and so we still need a small amount of shared-mutable state in order to share the `QueueHandle_t` with the interrupt routine. We use an `Option`, which we statically initialize to `None`, and later replace with `Some(queue_handle)` when the queue has been created by ESP-IDF. -In the interrupt routine Rust forces us to handle the case where the `static mut` is still `None`. If this happens we can either return early, or we can `unwrap()` the value, which will exit the program with an error if the value was not previously set to `Some(queue_handle)`. +In the interrupt routine, Rust forces us to handle the case where the `static mut` is still `None`. If this happens, we can either return early, or we can `unwrap()` the value, which will exit the program with an error if the value was not previously set to `Some(queue_handle)`. There is still a risk that `main()` might be in the processing of changing the value of the variable (i.e. changing the `QueueHandle_t` value) just as the interrupt routine fires, leaving it in an inconsistent or invalid state. We mitigate this by making sure we only set the value once, and we do so before the interrupt is enabled. The compiler cannot check that this is safe, and so we must use the `unsafe` keyword when we read or write the value. @@ -28,7 +28,7 @@ Read more about this in the [Embedded Rust Book](https://docs.rust-embedded.org/ ## `unsafe {}` blocks: -This code contains a lot of `unsafe {}` blocks. As a general rule, `unsafe` does not mean that the contained code is not memory safe, it means, that Rust can't make safety guarantees in this place and that it is in the responsibility of the programmer to ensure memory safety. For example Calling C Bindings is per se unsafe, as Rust can't make any safety guarantees for the underlaying C Code. +This code contains a lot of `unsafe {}` blocks. As a general rule, `unsafe` does not mean that the contained code is not memory safe, it means, that Rust can't make safety guarantees in this place and that it is in the responsibility of the programmer to ensure memory safety. For example, Calling C Bindings is per se unsafe, as Rust can't make any safety guarantees for the underlying C Code. diff --git a/book/src/04_4_1_interrupts.md b/book/src/04_4_1_interrupts.md index 960d28e5..09476ee9 100644 --- a/book/src/04_4_1_interrupts.md +++ b/book/src/04_4_1_interrupts.md @@ -1,84 +1,85 @@ # Building the Interrupt Handler -The goal of this exercise is to handle the interrupt that fires if the `BOOT` button is pushed. -This exercise involves working with C bindings to the ESP-IDF and other unsafe operations, as well as non-typical rust documentation. In a first step we will go line by line to build this interrupt handler. +The goal of this exercise is to handle the interrupt that fires if the `BOOT` button is pushed. +This exercise involves working with C bindings to the ESP-IDF and other unsafe operations, as well as non-typical Rust documentation. In a first step we will go line by line to build this interrupt handler. -You can find a skeleton code for this exercise in `advanced/button-interrupt/src/main.rs.` -You can find the solution for this exercise in `advanced/button-interrupt/examples/solution.rs` +You can find a skeleton code for this exercise in `advanced/button-interrupt/src/main.rs`. -## Tasks +You can find the solution for this exercise in `advanced/button-interrupt/examples/solution.rs`. You can run it with the following command: -1. Configure the button (GPIO 9) with a c struct [`gpio_config_t`](https://esp-rs.github.io/esp-idf-sys/esp_idf_sys/struct.gpio_config_t.html)the following settings: - - input mode - - pull up - - interrupt on positive edge - -The struct has the following fields: - - * `pin_bit_mask`: represents the Pin number, the value 1 shifted by the number of the pin. - * `mode`: sets the mode of the pin, it can have the following settings: - * `gpio_mode_t_GPIO_MODE_INPUT` - * `gpio_mode_t_GPIO_MODE_OUTPUT` - * `gpio_mode_t_GPIO_MODE_DISABLE` // disable gpio - * `gpio_mode_t_GPIO_MODE_OUTPUT_OD` // open drain output - * `gpio_mode_t_GPIO_MODE_INPUT_OUTPUT` // input and output - * `gpio_mode_t_GPIO_MODE_INPUT_OUTPUT_OD` // open drain input and output - - * `pull_up_en`: true.into(), if the GPIO is pulled up, - * `pull_down_en`: true.into(), if the GPIO is pulled down, - * `intr_type`: sets the interrupt type, it can have the following settings: - * `gpio_int_type_t_GPIO_INTR_ANYEDGE` // interrupt at any edge - * `gpio_int_type_t_GPIO_INTR_DISABLE` // interrupt disabled - * `gpio_int_type_t_GPIO_INTR_NEGEDGE` // interrupt at negative edge - * `gpio_int_type_t_GPIO_INTR_POSEDGE` // interrupt at positive edge - -They are constants with numbers representing the bit that must be set in the corresponding register. +```console +cargo run --example solution +``` +## ✅ Tasks +1. Configure the [BOOT button](https://github.com/esp-rs/esp-rust-board#ios) (GPIO9) with a C struct [`gpio_config_t`](https://esp-rs.github.io/esp-idf-sys/esp_idf_sys/struct.gpio_config_t.html) and the following settings: + - Input mode + - Pull up + - Interrupt on positive edge -2. Write the configuration into the register with [`unsafe extern "C" fn gpio_config`](https://esp-rs.github.io/esp-idf-sys/esp_idf_sys/fn.gpio_config.html). This needs to happen in the unsafe block. To make these FFI calls we can use the macro `esp!($Cfunktion)`. +The struct has the following fields: + * `pin_bit_mask`: Represents the Pin number, the value 1 shifted by the number of the pin. + * `mode`: Sets the mode of the pin, it can have the following settings: + * `gpio_mode_t_GPIO_MODE_INPUT` + * `gpio_mode_t_GPIO_MODE_OUTPUT` + * `gpio_mode_t_GPIO_MODE_DISABLE` // Disable GPIO + * `gpio_mode_t_GPIO_MODE_OUTPUT_OD` // Open drain output + * `gpio_mode_t_GPIO_MODE_INPUT_OUTPUT` // Input and output + * `gpio_mode_t_GPIO_MODE_INPUT_OUTPUT_OD` // Open drain input and output + * `pull_up_en`: `true.into()`, if the GPIO is pulled up, + * `pull_down_en`: `true.into()`, if the GPIO is pulled down, + * `intr_type`: Sets the interrupt type, it can have the following settings: + * `gpio_int_type_t_GPIO_INTR_ANYEDGE` // Interrupt at any edge + * `gpio_int_type_t_GPIO_INTR_DISABLE` // Interrupt disabled + * `gpio_int_type_t_GPIO_INTR_NEGEDGE` // Interrupt at negative edge + * `gpio_int_type_t_GPIO_INTR_POSEDGE` // Interrupt at positive edge + +They are constants with numbers representing the bit that must be set in the corresponding register. + +2. Write the configuration into the register with [`unsafe extern "C" fn gpio_config`](https://esp-rs.github.io/esp-idf-sys/esp_idf_sys/fn.gpio_config.html). This needs to happen in the unsafe block. To make these FFI calls, we can use the macro `esp!($Cfunktion)`. 3. Install a generic GPIO interrupt handler with [`unsafe extern "C" fn gpio_install_isr_service`](https://esp-rs.github.io/esp-idf-sys/esp_idf_sys/fn.gpio_install_isr_service.html). This function takes `ESP_INTR_FLAG_IRAM` as argument. - 4. Create a `static mut` that holds the queue handle we are going to get from `xQueueGenericCreate`. This is a number that uniquely identifies one particular queue, as opposed to any of the other queues in our program. The queue storage itself if managed by the Operating System. -```rust -static mut EVENT_QUEUE: Option = None; -``` + ```rust + static mut EVENT_QUEUE: Option = None; + ``` 5. Create the event queue using [`pub unsafe extern "C" fn xQueueGenericCreate`](https://esp-rs.github.io/esp-idf-sys/esp_idf_sys/fn.xQueueGenericCreate.html). This lets us safely pass events from an interrupt routine to our main thread. -```rust -EVENT_QUEUE = Some(xQueueGenericCreate(QUEUE_SIZE, ITEM_SIZE, QUEUE_TYPE_BASE)); -``` + ```rust + EVENT_QUEUE = Some(xQueueGenericCreate(QUEUE_SIZE, ITEM_SIZE, QUEUE_TYPE_BASE)); + ``` 6. Add a function which that will be called whenever there is a GPIO interrupt on our button pin. We put this function in a special block of RAM (`iram0`), so it will still be available even if the external flash is busy doing something else (like filesystem work). The function needs to get the queue handle from `EVENT_QUEUE` and call the `xQueueGiveFromISR` function with a `std::ptr::null_mut()` - the objects in our queue are of size zero, so we don't actually need a 'thing' to put on the queue. Instead, the act of pushing a 'nothing' is enough to wake up the other end! -```rust -#[link_section = ".iram0.text"] -unsafe extern "C" fn button_interrupt(_: *mut c_void) { - xQueueGiveFromISR(EVENT_QUEUE.unwrap(), std::ptr::null_mut()); -} -``` -If the interrupt fires, an event is added to the queue. + ```rust + #[link_section = ".iram0.text"] + unsafe extern "C" fn button_interrupt(_: *mut c_void) { + xQueueGiveFromISR(EVENT_QUEUE.unwrap(), std::ptr::null_mut()); + } + ``` + +If the interrupt fires, an event is added to the queue. 7. Pass the function we just wrote to the generic GPIO interrupt handler we registered earlier, along with the number of the GPIO pin that should cause this function to be executed. -```rust -esp!(gpio_isr_handler_add( - GPIO_NUM, - Some(button_interrupt), - std::ptr::null_mut() -))?; -``` + ```rust + esp!(gpio_isr_handler_add( + GPIO_NUM, + Some(button_interrupt), + std::ptr::null_mut() + ))?; + ``` 8. Inside a loop, wait until the queue has an item in it. That is, until the `button_interrupt` function puts something in the queue. -```rust -let res = xQueueReceive(EVENT_QUEUE.unwrap(), ptr::null_mut(), QUEUE_WAIT_TICKS); -``` + ```rust + let res = xQueueReceive(EVENT_QUEUE.unwrap(), ptr::null_mut(), QUEUE_WAIT_TICKS); + ``` + +9. Handle the value of `res`, so that "Button pushed!" is logged, if the button is pushed. -9. Handle the value of `res`, so that "Button pushed!" is logged, if the button is pushed. - -10. Run the program and push the `BOOT` button, so see how it works! \ No newline at end of file +10. Run the program and push the `BOOT` button, so see how it works! diff --git a/book/src/04_4_2_interrupts.md b/book/src/04_4_2_interrupts.md index cbba7ecb..54b6cb5d 100644 --- a/book/src/04_4_2_interrupts.md +++ b/book/src/04_4_2_interrupts.md @@ -1,15 +1,20 @@ # Random LED color on pushing a button -✅ Modify the code so the RGB LED light changes to different random color upon each button press. The LED should not go out or change color if the button is not pressed for some time. +✅ Modify the code so the RGB LED light changes to a different random color upon each button press. The LED should not go out or change color if the button is not pressed for some time. -Continue by adding to your previous solution or the code from `advanced/button-interrupt/src/main.rs` -You can find the solution for this exercise in `advanced/button-interrupt/examples/solution_led.rs` +Continue by adding to your previous solution or the code from `advanced/button-interrupt/src/main.rs`. -## Solving Help +You can find the solution for this exercise in `advanced/button-interrupt/examples/solution.rs`. You can run it with the following command: + +```console +cargo run --example solution_led +``` + +## 💡 Solving Help * The necessary imports are already made, if you enter `cargo --doc --open` you will get helping documentation regarding the LED. -* The LED's part number is WS2812RMT. +* The LED's part number is WS2812RMT. * It's a programmable RGB LED. This means there aren't single pins to set for red, green and blue, but that we need to instantiate it to be able to send `RGB8` type values to it with a method. * The board has a hardware random number generator. It can be called with `esp_random()`. -* Calling functions from the `esp-idf-sys` is unsafe in Rust terms and requires an `unsafe()` block. You can assume that these functions are safe to use, so no other measures are required. +* Calling functions from the `esp-idf-sys` is unsafe in Rust terms and requires an `unsafe()` block. You can assume that these functions are safe to use, so no other measures are required. diff --git a/book/src/04_4_3_interrupts.md b/book/src/04_4_3_interrupts.md index 6b380eb1..367e8787 100644 --- a/book/src/04_4_3_interrupts.md +++ b/book/src/04_4_3_interrupts.md @@ -2,22 +2,21 @@ 1. Initialize the LED peripheral and switch the LED on with an arbitrary value just to see that it works. ```rust - let mut led = WS2812RMT::new()?; - - let arbitrary_color = RGB8::new(20, 0, 20); - led.set_pixel(arbitrary_color).unwrap(); // remove this line after you tried it once + let mut led = WS2812RMT::new(peripherals.pins.gpio2, peripherals.rmt.channel0)?; + + led.set_pixel(RGB8::new(20, 0, 20)).unwrap(); // Remove this line after you tried it once ``` -2. Light up the LED only when the button is pressed. You can do this for now by exchanging the print statement. +2. Light up the LED only when the button is pressed. You can do this for now by exchanging the print statement. ```rust 1 => { led.set_pixel(arbitrary_color)?; - + }, _ => {}, ``` -3. Create random RGB values by calling `esp_random()`. - * This function is unsafe. - * It yields u32, so it needs to be cast as u8. +3. Create random RGB values by calling `esp_random()`. + * This function is `unsafe`. + * It yields `u32`, so it needs to be cast as `u8`. ```rust unsafe { @@ -29,16 +28,30 @@ let color = RGB8::new(r, g, b); led.set_pixel(color)?; - + }, _ => {}, ``` -4. Optional: If you intend to reuse this code in another place, it makes sense to put it into its own function. This lets us explore in detail, which parts of the code need to be in `unsafe` blocks. +4. **Optional**: If you intend to reuse this code in another place, it makes sense to put it into its own function. This lets us explore, in detail, which parts of the code need to be in `unsafe` blocks. -```rust - fn random_light(led: &mut WS2812RMT) { + ```rust + // ... + + unsafe { + // ... + match res { + 1 => { + // Generates random rgb values + random_light(&mut led); + }, + _ => {}, + }; + } + } + // ... + fn random_light(led: &mut WS2812RMT) { let mut color = RGB8::new(0, 0, 0); unsafe { let r = esp_random() as u8; @@ -47,22 +60,8 @@ color = RGB8::new(r, g, b); } - - led.set_pixel(color).unwrap(); - } - unsafe { - // ... - match res { - 1 => { - // Generates random rgb values - random_light(&mut led); - - }, - _ => {}, - }; - } + led.set_pixel(color).unwrap(); } -} -``` + ``` diff --git a/book/src/04_7_reference.md b/book/src/05_reference.md similarity index 76% rename from book/src/04_7_reference.md rename to book/src/05_reference.md index d4f4914a..4344dd77 100644 --- a/book/src/04_7_reference.md +++ b/book/src/05_reference.md @@ -8,7 +8,7 @@ We'll introduce a couple of concepts related to GPIOs: ### Pin Configurations -GPIOs can be configured one of several different ways. The options available can vary depending in the design of the chip, but will usually include: +GPIOs can be configured one of several ways. The options available can vary depending on the design of the chip, but will usually include: Floating: A floating pin is neither connected VCC nor Ground. It just floats around at whatever voltage is applied. Note though, that your circuit should externally pull the pin either low or high, as CMOS silicon devices (such as microcontrollers) can be fail to work correctly if you leave a pin higher than the 'low voltage threshold' or `Vtl`, but lower than the 'high voltage threshold' or `Vth` for more than a few microseconds. @@ -16,24 +16,24 @@ Push-Pull-Output: A pin that is configured as push–pull output can then be set Open-Drain-Output: Open Drain outputs switch between "disconnected" and "connected to ground". It is expected that some external resistor will weakly pull the line up to VCC. This type of output is designed to allow multiple devices to be connected together - the line is 'low' if any of the devices connected to the line drive it low. If two or more devices drive it low at the same time, no damage occurs (connecting Ground to Ground is safe). If none of them drive it low, the resistor will pull it high by default. -Floating-Input: A pin where the external voltage applied can be read in software, as either a `1` (usually if the voltage is above some threshold voltage) or a `0` (if it isn't). The same warnings apply as per the 'Floating' state. +Floating-Input: A pin where the external voltage applied can be read, in software, as either a `1` (usually if the voltage is above some threshold voltage) or a `0` (if it isn't). The same warnings apply as per the 'Floating' state. Pull-Up-Input: Like a Floating-Input, except an internal 'pull-up' resistor weakly pulls the line up to VCC when nothing external is driving it down to Ground. Useful for reading buttons and other switches, as it saves you from needing an external resistor. -### Active high/low +### Active high/low -A digital signal can be in two states: `high` and `low`. This is usually represented by the voltage difference between the signal and ground. It is arbitrary which of these voltage levels represents which logic states: So both `high` and `low` can be defined as an active state. +A digital signal can be in two states: `high` and `low`. This is usually represented by the voltage difference between the signal and ground. It is arbitrary which of these voltage levels represents which logic states: So both `high` and `low` can be defined as an active state. -For example: An active high pin has voltage when the logic level is active. And active low pin has voltage when the logic level is set to inactive. +For example: An active high pin has voltage when the logic level is active. And active low pin has voltage when the logic level is set to inactive. -In embedded Rust abstractions show the logic level and not the voltage level. So if you have an active low pin connected to an LED, you need to set it to inactive in order for the LED to light up. +In embedded Rust, abstractions show the logic level and not the voltage level. So if you have an active low pin connected to an LED, you need to set it to inactive in order for the LED to light up. -### Chip Select +### Chip Select -Chip Select is a binary signal to another device that can switch that device on or off, either partially or entirely. It is usually a signal line connected to a GPIO, and commonly used to allow multiple devices to be connected to the same SPI bus - each device only listens when its Chip Select line is active. +Chip Select is a binary signal to another device that can switch that device on or off, either partially or entirely. It is frequently a signal line connected to a GPIO, and commonly used to allow multiple devices to be connected to the same SPI bus - each device only listens when its Chip Select line is active. ### Bit Banging -For protocols such as I2C or SPI we usually use peripherals within the MCU to convert the data we want to transmit into signals. In some cases, for example if the MCU does not support the protocol or if a non-standard form of the protocol is used, you need to write a program that turns the data into signals manually. This is called bit-banging. +For protocols such as I2C or SPI we usually use peripherals within the MCU to convert the data we want to transmit into signals. In some cases, for example if the MCU does not support the protocol or if a non-standard form of the protocol is used, you need to write a program that turns the data into signals manually. This is called bit-banging. diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 58dfd8a2..1e49b4eb 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -6,26 +6,25 @@ - [Software](./02_2_software.md) - [Workshop repository](./02_3_repository.md) - [Hello, board!](./02_4_hello_board.md) -- [Intro Workshop](./03_0_intro_workshop.md) +- [Intro workshop](./03_0_intro_workshop.md) - [Project organization](./03_1_project_orga.md) - [Generating new projects](./03_2_cargo_generate.md) - [HTTP and HTTPS client](./03_3_1_http_https_client.md) - - [Http Client](./03_3_2_http_client.md) - - [Https Client](./03_3_3_https_client.md) + - [Http client](./03_3_2_http_client.md) + - [Https client](./03_3_3_https_client.md) - [A simple HTTP server](./03_4_http_server.md) - [IoT using MQTT](./03_5_0_mqtt.md) - [How MQTT works](./03_5_1_mqtt.md) - - [MQTT Exercise: Sending Messages](./03_5_2_mqtt.md) - - [MQTT Exercise: Receiving LED Commands](./03_5_3_mqtt.md) -- [Advanced Workshop](./04_0_advanced_workshop.md) + - [MQTT Exercise: Sending messages](./03_5_2_mqtt.md) + - [MQTT Exercise: Receiving LED commands](./03_5_3_mqtt.md) +- [Advanced workshop](./04_0_advanced_workshop.md) - [Low level I/O](./04_2_low_level_io.md) - [I2C](./04_3_0_i2c.md) - [Reading Sensors](./04_3_1_i2c.md) - - [Writing a Driver - Easy Version](./04_3_2_i2c.md) - - [Writing a Driver - Hard Version](./04_3_3_i2c.md) + - [Writing a Driver - Easy version](./04_3_2_i2c.md) + - [Writing a Driver - Hard version](./04_3_3_i2c.md) - [Interrupts](./04_4_0_interrupts.md) - - [Basic Interrupt Handler](./04_4_1_interrupts.md) - - [Random LED Color](./04_4_2_interrupts.md) + - [Basic Interrupt handler](./04_4_1_interrupts.md) + - [Random LED color](./04_4_2_interrupts.md) - [Solution](./04_4_3_interrupts.md) - - [Reference](./04_7_reference.md) - \ No newline at end of file +- [Reference](./05_reference.md) diff --git a/common/lib/esp32-c3-dkc02-bsc/Cargo.toml b/common/lib/esp32-c3-dkc02-bsc/Cargo.toml deleted file mode 100644 index 2dd7c383..00000000 --- a/common/lib/esp32-c3-dkc02-bsc/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "esp32-c3-dkc02-bsc" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - - -[dependencies] -esp32c3 = "=0.4" -esp-idf-sys = { version = "=0.31.5" } -esp-idf-svc = { version= "=0.41.4", features = ["experimental", "alloc"] } -esp-idf-hal = "=0.38" -embedded-svc = "=0.21" -rgb = "0.8" -log = "0.4" -anyhow = "1" -toml-cfg = "0.1" -riscv = { version = "0.8" } -ignore = "=0.4.11" diff --git a/common/lib/esp32-c3-dkc02-bsc/rust-toolchain.toml b/common/lib/esp32-c3-dkc02-bsc/rust-toolchain.toml deleted file mode 100644 index e8085426..00000000 --- a/common/lib/esp32-c3-dkc02-bsc/rust-toolchain.toml +++ /dev/null @@ -1,3 +0,0 @@ -[toolchain] -channel = "nightly-2022-03-10" - diff --git a/common/lib/esp32-c3-dkc02-bsc/src/led.rs b/common/lib/esp32-c3-dkc02-bsc/src/led.rs deleted file mode 100644 index ac8504ba..00000000 --- a/common/lib/esp32-c3-dkc02-bsc/src/led.rs +++ /dev/null @@ -1,156 +0,0 @@ -use std::ptr::{null, null_mut}; - -use esp_idf_sys::{ - c_types::c_void, esp, rmt_config, rmt_config_t, rmt_config_t__bindgen_ty_1, rmt_driver_install, - rmt_get_counter_clock, rmt_item32_t, rmt_item32_t__bindgen_ty_1, - rmt_item32_t__bindgen_ty_1__bindgen_ty_1, rmt_mode_t_RMT_MODE_TX, rmt_translator_init, - rmt_tx_config_t, rmt_wait_tx_done, rmt_write_sample, size_t, u_int8_t, -}; -pub use rgb::RGB8; - -const WS2812_T0H_NS: u32 = 350; -const WS2812_T0L_NS: u32 = 1000; -const WS2812_T1H_NS: u32 = 1000; -const WS2812_T1L_NS: u32 = 350; - -#[derive(Debug, Default, Clone, Copy)] -struct Ws2812Config { - t0h_ticks: u32, - t0l_ticks: u32, - t1h_ticks: u32, - t1l_ticks: u32, -} - -const FREERTOS_HZ: u32 = 1000; - -static mut WS_CONFIG: Option = None; - -unsafe extern "C" fn ws2812_to_rmt( - src: *const c_void, - dest: *mut rmt_item32_t, - src_size: size_t, - wanted_num: size_t, - translated_size: *mut size_t, - item_num: *mut size_t, -) { - if src == null() || dest == null_mut() { - *translated_size = 0; - *item_num = 0; - return; - } - - let config = WS_CONFIG.unwrap(); - let mut bit0: rmt_item32_t__bindgen_ty_1__bindgen_ty_1 = Default::default(); - bit0.set_duration0(config.t0h_ticks); - bit0.set_level0(1); - bit0.set_duration1(config.t0l_ticks); - bit0.set_level1(0); - - let bit0 = rmt_item32_t { - __bindgen_anon_1: rmt_item32_t__bindgen_ty_1 { - __bindgen_anon_1: bit0, - }, - }; - - let mut bit1: rmt_item32_t__bindgen_ty_1__bindgen_ty_1 = Default::default(); - bit1.set_duration0(config.t1h_ticks); - bit1.set_level0(1); - bit1.set_duration1(config.t1l_ticks); - bit1.set_level1(0); - - let bit1 = rmt_item32_t { - __bindgen_anon_1: rmt_item32_t__bindgen_ty_1 { - __bindgen_anon_1: bit1, - }, - }; - - let mut size: size_t = 0; - let mut num = 0; - - let mut psrc = src as *const u_int8_t; - let mut pdest: *mut rmt_item32_t = dest as _; - - while size < src_size && num < wanted_num { - for i in 0..8 { - if *psrc & (1 << (7 - i)) != 0 { - *pdest = bit1; - } else { - *pdest = bit0; - } - num += 1; - pdest = pdest.add(1); - } - size += 1; - psrc = psrc.add(1); - } - *translated_size = size; - *item_num = num; -} - -pub struct WS2812RMT { - config: rmt_config_t, -} -impl WS2812RMT { - pub fn new() -> anyhow::Result { - let rmt_tx_config = rmt_tx_config_t { - carrier_freq_hz: 38000, - carrier_level: 1, - idle_level: 0, - carrier_duty_percent: 33, - loop_count: 1, - carrier_en: false, - loop_en: false, - idle_output_en: true, - }; - - let config = rmt_config_t { - rmt_mode: rmt_mode_t_RMT_MODE_TX, - channel: 0, - gpio_num: 2, - clk_div: 2, - mem_block_num: 1, - flags: 0, - __bindgen_anon_1: rmt_config_t__bindgen_ty_1 { - tx_config: rmt_tx_config, - }, - }; - - unsafe { - esp!(rmt_config(&config))?; - esp!(rmt_driver_install(config.channel, 0, 0))?; - let mut rmt_clock = 0u32; - esp!(rmt_get_counter_clock(config.channel, &mut rmt_clock))?; - - let ratio = rmt_clock as f64 / 1e9; - - WS_CONFIG = Some(Ws2812Config { - t0h_ticks: (ratio * WS2812_T0H_NS as f64) as _, - t0l_ticks: (ratio * WS2812_T0L_NS as f64) as _, - t1h_ticks: (ratio * WS2812_T1H_NS as f64) as _, - t1l_ticks: (ratio * WS2812_T1L_NS as f64) as _, - }); - - esp!(rmt_translator_init(config.channel, Some(ws2812_to_rmt)))?; - } - - Ok(Self { config }) - } - - pub fn set_pixel(&mut self, color: RGB8) -> anyhow::Result<()> { - let timeout_ms = 1; - unsafe { - esp!(rmt_write_sample( - self.config.channel, - &[color.g, color.r, color.b] as *const u8, // WS2812 expects GRB, not RGB - 3, - true, - ))?; - esp!(rmt_wait_tx_done( - self.config.channel, - (timeout_ms as u32 * FREERTOS_HZ) / 1000, - ))?; - } - - Ok(()) - } -} diff --git a/common/lib/esp32-c3-dkc02-bsc/src/lib.rs b/common/lib/esp32-c3-dkc02-bsc/src/lib.rs deleted file mode 100644 index ef1cfb2e..00000000 --- a/common/lib/esp32-c3-dkc02-bsc/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod led; -pub mod temp_sensor; -pub mod wifi; diff --git a/common/lib/esp32-c3-dkc02-bsc/src/temp_sensor.rs b/common/lib/esp32-c3-dkc02-bsc/src/temp_sensor.rs deleted file mode 100644 index ee7d6f08..00000000 --- a/common/lib/esp32-c3-dkc02-bsc/src/temp_sensor.rs +++ /dev/null @@ -1,174 +0,0 @@ -use esp32c3::{Peripherals, APB_SARADC}; -use log::info; - -const _XPD_WAIT_DEFAULT: u16 = 0xFF; /* Set wait cycle time(8MHz) from power up to reset enable. */ -const ADC_FACTOR: f32 = 0.4386; -const DAC_FACTOR: f32 = 27.88; -const _SYS_OFFSET: f32 = 20.52; - -#[allow(unused)] -enum DacOffset { - L0 = 5, /*< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */ - L1 = 7, /*< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */ - L2 = 15, /*< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */ - L3 = 11, /*< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */ - L4 = 10, /*< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */ -} - -impl Default for DacOffset { - fn default() -> Self { - DacOffset::L2 - } -} - -impl DacOffset { - fn offset(&self) -> i8 { - match self { - DacOffset::L0 => -2, - DacOffset::L1 => -1, - DacOffset::L2 => 0, - DacOffset::L3 => 1, - DacOffset::L4 => 2, - } - } -} - -#[allow(unused)] -struct SensorConfig { - dac_offset: DacOffset, - clock_divider: u8, -} - -#[allow(unused)] -impl SensorConfig { - fn new(dac_offset: DacOffset, clock_divider: u8) -> Self { - Self { - dac_offset, - clock_divider, - } - } -} - -impl Default for SensorConfig { - fn default() -> Self { - Self { - clock_divider: 6, - dac_offset: Default::default(), - } - } -} - -pub struct BoardTempSensor { - config: SensorConfig, - efuse_calibration: f32, - peripherals: Option, -} - -impl BoardTempSensor { - pub fn new_taking_peripherals() -> Self { - let mut peripherals = Peripherals::take().unwrap(); - let efuse_calibration = Self::common_init(&mut peripherals); - Self { - config: Default::default(), - efuse_calibration, - peripherals: Some(peripherals), - } - } - pub fn new(peripherals: &mut Peripherals) -> Self { - let efuse_calibration = Self::common_init(peripherals); - Self { - config: Default::default(), - efuse_calibration, - peripherals: None, - } - } - fn common_init(peripherals: &mut Peripherals) -> f32 { - // enable TSENS clock - peripherals - .SYSTEM - .perip_clk_en1 - .modify(|_r, w| w.tsens_clk_en().set_bit()); - - // select XTAL clock for TSENS: - /* - APB_SARADC_TSENS_CLK_SEL - Choose working clock for temperature sensor. 0: FOSC_CLK. 1: XTAL_CLK. (R/W) - */ - peripherals - .APB_SARADC - .tsens_ctrl2 - .modify(|_r, w| w.tsens_clk_sel().set_bit()); - - // power up tsens - peripherals - .APB_SARADC - .apb_tsens_ctrl - .modify(|_r, w| w.tsens_pu().set_bit()); - - // TODO conflicting information - on the one hand, - /* - esp_efuse_table.c - static const esp_efuse_desc_t TEMP_CALIB[] = { - {EFUSE_BLK2, 131, 9}, // Temperature calibration data, - }; - */ - // register is 128..160 - // we want 131 .. 131+9 - // -> offset 3, but python definition disagrees: - - // from esptool/blob/master/espressif/efuse/esp32c3/mem_definition.py: - // # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - // ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "Temperature calibration", None), - // - // a "word" is 32 bit it seems, so that's base = 32*4 + 7 = 135, not 131 - - let register_contents = peripherals.EFUSE.rd_sys_part1_data4.read().bits(); - info!("raw data: {:b}", register_contents); - - // `as u8` truncates accordingly, otherwise we'd need e.g. & 0xff - let efuse_calibration_raw = (register_contents >> 7) as u8; - - // TODO this is what the IDF C source does, but is it correct? - // TODO why does `mem_definition.py` say the length is 9? - let sign = if efuse_calibration_raw & 0b1000_0000 > 0 { - -1. - } else { - 1. - }; - - let efuse_calibration = efuse_calibration_raw as f32 / 10. * sign; - - info!("efuse calibration: {}", efuse_calibration); - - efuse_calibration - } - - fn read_impl(&self, adc: &mut APB_SARADC) -> f32 { - let register = adc.apb_tsens_ctrl.read(); - let raw_value = register.tsens_out().bits(); - let value = ADC_FACTOR * (raw_value as f32) - - DAC_FACTOR * self.config.dac_offset.offset() as f32 - - self.efuse_calibration; - - value - } - - pub fn read(&self, adc: &mut APB_SARADC) -> f32 { - self.read_impl(adc) - } - - pub fn read_owning_peripherals(&mut self) -> f32 { - let adc = &mut self.peripherals.as_mut().unwrap().APB_SARADC; - let register = adc.apb_tsens_ctrl.read(); - let raw_value = register.tsens_out().bits(); - let value = ADC_FACTOR * (raw_value as f32) - - DAC_FACTOR * self.config.dac_offset.offset() as f32 - - self.efuse_calibration; - - value - } - - pub fn free(self) -> Option { - self.peripherals - } -} diff --git a/common/lib/esp32-c3-dkc02-bsc/src/wifi.rs b/common/lib/esp32-c3-dkc02-bsc/src/wifi.rs deleted file mode 100644 index b5accc5b..00000000 --- a/common/lib/esp32-c3-dkc02-bsc/src/wifi.rs +++ /dev/null @@ -1,103 +0,0 @@ -// based on https://github.com/ivmarkov/rust-esp32-std-demo/blob/main/src/main.rs - -use std::sync::Arc; - -use anyhow::bail; -use embedded_svc::wifi::{ - self, AuthMethod, ClientConfiguration, ClientConnectionStatus, ClientIpStatus, ClientStatus, - Wifi as _, -}; -use esp_idf_svc::{ - netif::EspNetifStack, nvs::EspDefaultNvs, sysloop::EspSysLoopStack, wifi::EspWifi, -}; -use log::info; -use std::time::Duration; - -#[allow(unused)] -pub struct Wifi { - esp_wifi: EspWifi, - netif_stack: Arc, - sys_loop_stack: Arc, - default_nvs: Arc, -} - -pub fn wifi(ssid: &str, psk: &str) -> anyhow::Result { - let mut auth_method = AuthMethod::WPA2Personal; // Todo: add this setting - router dependent - if ssid.is_empty() { - anyhow::bail!("missing WiFi name") - } - if psk.is_empty() { - auth_method = AuthMethod::None; - info!("Wifi password is empty"); - } - let netif_stack = Arc::new(EspNetifStack::new()?); - let sys_loop_stack = Arc::new(EspSysLoopStack::new()?); - let default_nvs = Arc::new(EspDefaultNvs::new()?); - let mut wifi = EspWifi::new( - netif_stack.clone(), - sys_loop_stack.clone(), - default_nvs.clone(), - )?; - - info!("Searching for Wifi network {}", ssid); - - let ap_infos = wifi.scan()?; - - let ours = ap_infos.into_iter().find(|a| a.ssid == ssid); - - let channel = if let Some(ours) = ours { - info!( - "Found configured access point {} on channel {}", - ssid, ours.channel - ); - Some(ours.channel) - } else { - info!( - "Configured access point {} not found during scanning, will go with unknown channel", - ssid - ); - None - }; - - info!("setting Wifi configuration"); - wifi.set_configuration(&wifi::Configuration::Client(ClientConfiguration { - ssid: ssid.into(), - password: psk.into(), - channel, - auth_method, - ..Default::default() - }))?; - - info!("getting Wifi status"); - - wifi.wait_status_with_timeout(Duration::from_secs(2100), |status| { - !status.is_transitional() - }) - .map_err(|err| anyhow::anyhow!("Unexpected Wifi status (Transitional state): {:?}", err))?; - - let status = wifi.get_status(); - - if let wifi::Status( - ClientStatus::Started(ClientConnectionStatus::Connected(ClientIpStatus::Done( - _ip_settings, - ))), - _, - ) = status - { - info!("Wifi connected"); - } else { - bail!( - "Could not connect to Wifi - Unexpected Wifi status: {:?}", - status - ); - } - - let wifi = Wifi { - esp_wifi: wifi, - netif_stack, - sys_loop_stack, - default_nvs, - }; - - Ok(wifi) -} diff --git a/common/lib/get-uuid/Cargo.lock b/common/lib/get-uuid/Cargo.lock index e9ff55b1..25c200d3 100644 --- a/common/lib/get-uuid/Cargo.lock +++ b/common/lib/get-uuid/Cargo.lock @@ -4,9 +4,15 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.53" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "cfg-if" @@ -34,32 +40,88 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "libc" version = "0.2.116" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "serde" -version = "1.0.136" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" + +[[package]] +name = "serde_spanned" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +dependencies = [ + "serde", +] [[package]] name = "toml" -version = "0.5.8" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" dependencies = [ + "indexmap", "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] name = "uuid" -version = "0.8.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ "getrandom", ] @@ -69,3 +131,12 @@ name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winnow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +dependencies = [ + "memchr", +] diff --git a/common/lib/get-uuid/Cargo.toml b/common/lib/get-uuid/Cargo.toml index 7eeb57e7..94a656a6 100644 --- a/common/lib/get-uuid/Cargo.toml +++ b/common/lib/get-uuid/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -toml = "0.5.8" -anyhow = "1" +toml = "=0.5.11" +anyhow = "=1.0.69" [build-dependencies] -anyhow = "1" -uuid = { version = "0.8", features = ["v4"] } -toml = "0.5" \ No newline at end of file +anyhow = "=1.0.69" +uuid = { version = "=1.3.0", features = ["v4"] } +toml = "=0.5.11" diff --git a/common/lib/icm42670p/Cargo.toml b/common/lib/icm42670p/Cargo.toml deleted file mode 100644 index b81bcf02..00000000 --- a/common/lib/icm42670p/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "icm42670p" -version = "0.1.0" -authors = ["Tanks Transfeld "] -edition = "2021" - - - - -[dependencies] -embedded-hal = "0.2.7" diff --git a/common/lib/icm42670p/src/lib.rs b/common/lib/icm42670p/src/lib.rs deleted file mode 100644 index 9c606466..00000000 --- a/common/lib/icm42670p/src/lib.rs +++ /dev/null @@ -1,125 +0,0 @@ -#![deny(unsafe_code)] -#![no_std] - -use embedded_hal::blocking::i2c; - -/// ICM42670P device driver. -/// Datasheet: https://3cfeqx1hf82y3xcoull08ihx-wpengine.netdna-ssl.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf -/// -#[derive(Debug)] -pub struct ICM42670P { - /// The concrete I²C device implementation. - i2c: I2C, - - /// Device address - address: DeviceAddr, -} - -/// see Table 3.3.2 -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum DeviceAddr { - /// ADP_AD0 = 0 - B110_1000 = 0b110_1000, - /// ADP_AD0 = 1 - B110_1001 = 0b110_1001, -} - -implICM42670P -where - I2C: i2c::WriteRead + i2c::Write, -{ - /// Create a new instance of the ICM42670P. - pub fn new(i2c: I2C, address: DeviceAddr) -> Result { - - let icm42670p = ICM42670P { i2c, address }; - - Ok(icm42670p) - } - - /// Reads device ID. - /// Should return `0x67`. (if it doesn't, something is amiss) - pub fn read_device_id_register(&mut self) -> Result { - self.read_register(Register::WhoAmI) - } - - /// Starts gyroscope sensor in low noise mode. - pub fn gyro_ln(&mut self) -> Result<(), E> { - let value: u8 = 0b11 << 2; - self. write_pwr_mgmt(value) - } - - /// Reads gyroscope sensor values. - /// This may need some rework. - pub fn read_gyro(&mut self) -> Result { - - - let x0 = self.read_register(Register::GyroDataX0)?; - let x1 = self.read_register(Register::GyroDataX1)?; - let y0 = self.read_register(Register::GyroDataY0)?; - let y1 = self.read_register(Register::GyroDataY1)?; - let z0 = self.read_register(Register::GyroDataZ0)?; - let z1 = self.read_register(Register::GyroDataZ1)?; - - let gyro_data = Data { - x: i16::from_be_bytes([x1, x0]), - y: i16::from_be_bytes([y1, y0]), - z: i16::from_be_bytes([z1, z0]), - }; - - Ok(gyro_data) - - } - - /// Read PwrMgmt0 configuration - pub fn read_pwr_configuration(&mut self) -> Result { - let bits = self.read_register(Register::PwrMgmt0)?; - Ok(PowerManagement { bits }) - } - - /// Write in PwrMgmt0 Register - fn write_pwr_mgmt(&mut self, value: u8) -> Result<(), E> { - self.write_register(Register::PwrMgmt0, value) - } - - fn write_register(&mut self, register: Register, value: u8) -> Result<(), E> { - let byte = value as u8; - self.i2c - .write(self.address as u8, &[register.address(), byte]) - } - - fn read_register(&mut self, register: Register) -> Result { - let mut data = [0]; - self.i2c - .write_read(self.address as u8, &[register.address()], &mut data)?; - Ok(u8::from_le_bytes(data)) - } -} - -pub struct PowerManagement { - pub bits: u8, -} - -pub struct Data { - pub x: i16, - pub y: i16, - pub z: i16, -} - -// Table 14.1 -#[derive(Clone, Copy)] -pub enum Register { - GyroDataX1 = 0x11, - GyroDataX0 = 0x12, - GyroDataY1 = 0x13, - GyroDataY0 = 0x14, - GyroDataZ1 = 0x15, - GyroDataZ0 = 0x16, - PwrMgmt0 = 0x1F, - WhoAmI = 0x75, -} - -impl Register { - fn address(&self) -> u8 { - *self as u8 - } -} diff --git a/common/lib/mqtt-messages/Cargo.lock b/common/lib/mqtt-messages/Cargo.lock index 9f23cfdd..cda69d7a 100644 --- a/common/lib/mqtt-messages/Cargo.lock +++ b/common/lib/mqtt-messages/Cargo.lock @@ -17,9 +17,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.31" +version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a374af9a0e5fdcdd98c1c7b64f05004f9ea2555b6c75f211daa81268a3c50f1" +checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" dependencies = [ "bytemuck", ] diff --git a/common/lib/mqtt-messages/Cargo.toml b/common/lib/mqtt-messages/Cargo.toml index 1ac7bc51..430bb578 100644 --- a/common/lib/mqtt-messages/Cargo.toml +++ b/common/lib/mqtt-messages/Cargo.toml @@ -6,5 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rgb = "0.8" - +rgb = "0.8.36" diff --git a/common/lib/esp32-c3-dkc02-bsc/.cargo/config.toml b/common/lib/rgb-led/.cargo/config.toml similarity index 97% rename from common/lib/esp32-c3-dkc02-bsc/.cargo/config.toml rename to common/lib/rgb-led/.cargo/config.toml index 7bcdbc9a..41361c1e 100644 --- a/common/lib/esp32-c3-dkc02-bsc/.cargo/config.toml +++ b/common/lib/rgb-led/.cargo/config.toml @@ -3,6 +3,7 @@ target = "riscv32imc-esp-espidf" [target.riscv32imc-esp-espidf] linker = "ldproxy" +runner = "espflash flash --monitor" # Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3 # See also https://github.com/ivmarkov/embuild/issues/16 rustflags = ["-C", "default-linker-libraries"] diff --git a/common/lib/esp32-c3-dkc02-bsc/.gitignore b/common/lib/rgb-led/.gitignore similarity index 100% rename from common/lib/esp32-c3-dkc02-bsc/.gitignore rename to common/lib/rgb-led/.gitignore diff --git a/common/lib/rgb-led/Cargo.lock b/common/lib/rgb-led/Cargo.lock new file mode 100644 index 00000000..64550ab6 --- /dev/null +++ b/common/lib/rgb-led/Cargo.lock @@ -0,0 +1,1763 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "atomic-polyfill" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "build-time" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b516fccffbcd4c007256d0d620522ea9fcc6f008c9ebb7173eeb349dfcf99786" +dependencies = [ + "chrono", + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "camino" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "clang-sys" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" +dependencies = [ + "cc", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "const_format" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" + +[[package]] +name = "crossbeam-channel" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cxx" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "defmt" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a0ae7494d9bff013d7b89471f4c424356a71e9752e0c78abe7e6c608a16bb3" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8500cbe4cca056412efce4215a63d0bc20492942aeee695f23b624a53e0a6854" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "defmt-parser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db23d29972d99baa3de2ee2ae3f104c10564a6d05a346eb3f4c4f2c0525a06e" + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "edge-executor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1d66feda51959c8bb07b752c20f1d061eceb178bc91b793a0b32c792c631cf" +dependencies = [ + "async-task", + "heapless", + "log", + "waker-fn", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129b101ddfee640565f7c07b301a31d95aa21e5acef21a491c307139f5fa4c91" + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0760ec0a3bf76859d5e33f39542af103f157d5b2ecfb00ace56dd461472e3a" +dependencies = [ + "embedded-hal 1.0.0-alpha.9", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dfba9e6c113f2fd8537c943780a7345945e66c86972e356b1152e19481bcf5" +dependencies = [ + "futures", +] + +[[package]] +name = "embedded-svc" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079f8182848872fb6e8eed2c1ba3aea409fc71984a9e8090733c08c404e7864" +dependencies = [ + "anyhow", + "defmt", + "embedded-io", + "enumset", + "futures", + "heapless", + "no-std-net", + "num_enum", + "serde", + "strum 0.23.0", +] + +[[package]] +name = "embuild" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65388407a519276cd9aa94291380649d4cedbe8cf566d40f436f7a1ea9b5f8fe" +dependencies = [ + "anyhow", + "bindgen", + "bitflags", + "cmake", + "dirs", + "filetime", + "globwalk", + "log", + "remove_dir_all", + "serde", + "serde_json", + "shlex", + "strum 0.24.1", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "enumset" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "esp-idf-hal" +version = "0.40.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4354dcc4d157de675c55eb2e98f4985a526ea56fff316aa0939a63636c4952b" +dependencies = [ + "anyhow", + "edge-executor", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0-alpha.9", + "embedded-hal-nb", + "embuild", + "esp-idf-sys", + "heapless", + "nb 1.1.0", +] + +[[package]] +name = "esp-idf-svc" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6035126eeaf81d19ca5342fa8f36e85489c6fba1148ec8af167a6b9bff39e0f" +dependencies = [ + "anyhow", + "embedded-svc", + "embuild", + "enumset", + "esp-idf-hal", + "esp-idf-sys", + "heapless", + "log", + "uncased", +] + +[[package]] +name = "esp-idf-sys" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3458faf5c04761cb9a122ba30714afda5e88848e2f99c6e6c05c77ecf626d8" +dependencies = [ + "anyhow", + "bindgen", + "build-time", + "cargo_metadata", + "const_format", + "embuild", + "envy", + "libc", + "regex", + "serde", + "strum 0.24.1", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.45.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-io" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + +[[package]] +name = "futures-task" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" + +[[package]] +name = "futures-util" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heapless" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "no-std-net" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bcece43b12349917e096cddfa66107277f123e6c96a5aea78711dc601a47152" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50686e0021c4136d1d453b2dfe059902278681512a34d4248435dc34b6b5c8ec" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882f368737489ea543bc5c340e6f3d34a28c39980bd9a979e47322b26f60ac40" +dependencies = [ + "libc", + "log", + "num_cpus", + "rayon", + "winapi", +] + +[[package]] +name = "rgb" +version = "0.8.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "rgb-led" +version = "0.1.0" +dependencies = [ + "anyhow", + "embuild", + "esp-idf-hal", + "esp-idf-svc", + "esp-idf-sys", + "log", + "rgb", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.36.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" + +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f2b4817415c6d4210bfe1c7bfcf4801b2d904cb4d0e1a8fdb651013c9e86b8" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d071a94a3fac4aff69d023a7f411e33f40f3483f8c5190b1953822b6b76d7630" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "spin" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" +dependencies = [ + "strum_macros 0.23.1", +] + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros 0.24.3", +] + +[[package]] +name = "strum_macros" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.42.0", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" + +[[package]] +name = "toml_edit" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7082a95d48029677a28f181e5f6422d0c8339ad8396a39d3f33d62a90c1f6c30" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "winnow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +dependencies = [ + "memchr", +] diff --git a/common/lib/rgb-led/Cargo.toml b/common/lib/rgb-led/Cargo.toml new file mode 100644 index 00000000..0b1e4937 --- /dev/null +++ b/common/lib/rgb-led/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "rgb-led" +version = "0.1.0" +edition = "2021" +authors = ["Sergio Gasquez "] + +[dependencies] +esp-idf-sys = { version = "=0.32.1" } +esp-idf-hal = "=0.40.1" +rgb = "=0.8.36" +log = "=0.4.17" +anyhow = "=1.0.69" + +[build-dependencies] +embuild = "0.31.0" +anyhow = "=1.0.69" + +[dev-dependencies] +anyhow = "=1.0.69" +esp-idf-sys = { version = "=0.32.1", features = ["native", "binstart"] } +esp-idf-svc = { version = "=0.45.0", features = ["experimental", "alloc"] } diff --git a/common/lib/rgb-led/build.rs b/common/lib/rgb-led/build.rs new file mode 100644 index 00000000..ccb6e757 --- /dev/null +++ b/common/lib/rgb-led/build.rs @@ -0,0 +1,6 @@ +// Necessary because of this issue: https://github.com/rust-lang/cargo/issues/9641 +fn main() -> Result<(), Box> { + embuild::build::CfgArgs::output_propagated("ESP_IDF")?; + embuild::build::LinkArgs::output_propagated("ESP_IDF")?; + Ok(()) +} diff --git a/common/lib/rgb-led/examples/ws2812.rs b/common/lib/rgb-led/examples/ws2812.rs new file mode 100644 index 00000000..a57e607a --- /dev/null +++ b/common/lib/rgb-led/examples/ws2812.rs @@ -0,0 +1,30 @@ +use anyhow::Result; +use esp_idf_hal::delay::FreeRtos; +use esp_idf_hal::peripherals::Peripherals; +use log::info; +use rgb_led::WS2812RMT; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; + +fn main() -> Result<()> { + esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); + + let peripherals = Peripherals::take().unwrap(); + // Onboard RGB LED pin + // Rust ESP Board gpio2, ESP32-C3-DevKitC-02 gpio8 + let led = peripherals.pins.gpio2; + let channel = peripherals.rmt.channel0; + let mut ws2812 = WS2812RMT::new(led, channel)?; + loop { + info!("Red!"); + ws2812.set_pixel(rgb::RGB8::new(255, 0, 0))?; + FreeRtos::delay_ms(1000); + info!("Green!"); + ws2812.set_pixel(rgb::RGB8::new(0, 255, 0))?; + FreeRtos::delay_ms(1000); + info!("Blue!"); + ws2812.set_pixel(rgb::RGB8::new(0, 0, 255))?; + FreeRtos::delay_ms(1000); + } +} diff --git a/common/lib/rgb-led/rust-toolchain.toml b/common/lib/rgb-led/rust-toolchain.toml new file mode 100644 index 00000000..a550ad27 --- /dev/null +++ b/common/lib/rgb-led/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2023-02-28" diff --git a/common/lib/rgb-led/src/lib.rs b/common/lib/rgb-led/src/lib.rs new file mode 100644 index 00000000..e0cfb26a --- /dev/null +++ b/common/lib/rgb-led/src/lib.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use core::time::Duration; +use esp_idf_hal::{ + gpio, + rmt::{config::TransmitConfig, FixedLengthSignal, PinState, Pulse, TxRmtDriver, CHANNEL0}, +}; + +pub use rgb::RGB8; + +pub struct WS2812RMT<'a> { + tx_rtm_driver: TxRmtDriver<'a>, +} + +impl WS2812RMT<'_> { + // Rust ESP Board gpio2, ESP32-C3-DevKitC-02 gpio8 + pub fn new(led: gpio::Gpio2, channel: CHANNEL0) -> Result { + let config = TransmitConfig::new().clock_divider(2); + let tx = TxRmtDriver::new(channel, led, &config)?; + Ok(Self { tx_rtm_driver: tx }) + } + + pub fn set_pixel(&mut self, rgb: RGB8) -> Result<()> { + let color: u32 = ((rgb.g as u32) << 16) | ((rgb.r as u32) << 8) | rgb.b as u32; + let ticks_hz = self.tx_rtm_driver.counter_clock()?; + let t0h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(350))?; + let t0l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(800))?; + let t1h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(700))?; + let t1l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(600))?; + let mut signal = FixedLengthSignal::<24>::new(); + for i in (0..24).rev() { + let p = 2_u32.pow(i); + let bit = p & color != 0; + let (high_pulse, low_pulse) = if bit { (t1h, t1l) } else { (t0h, t0l) }; + signal.set(23 - i as usize, &(high_pulse, low_pulse))?; + } + self.tx_rtm_driver.start_blocking(&signal)?; + + Ok(()) + } +} + +fn ns(nanos: u64) -> Duration { + Duration::from_nanos(nanos) +} diff --git a/common/lib/wifi/.cargo/config.toml b/common/lib/wifi/.cargo/config.toml new file mode 100644 index 00000000..41361c1e --- /dev/null +++ b/common/lib/wifi/.cargo/config.toml @@ -0,0 +1,28 @@ +[build] +target = "riscv32imc-esp-espidf" + +[target.riscv32imc-esp-espidf] +linker = "ldproxy" +runner = "espflash flash --monitor" +# Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3 +# See also https://github.com/ivmarkov/embuild/issues/16 +rustflags = ["-C", "default-linker-libraries"] + +[unstable] +build-std = ["std", "panic_abort"] +build-std-features = ["panic_immediate_abort"] + +[env] +# Enables the esp-idf-sys "native" build feature (`cargo build --features native`) to build against ESP-IDF (v4.4.1) +ESP_IDF_VERSION = { value = "tag:v4.4.1" } + +# These configurations will pick up your custom "sdkconfig.release", "sdkconfig.debug" or "sdkconfig.defaults[.*]" files +# that you might put in the root of the project +# The easiest way to generate a full "sdkconfig[.release|debug]" configuration (as opposed to manually enabling only the necessary flags via "sdkconfig.defaults[.*]" +# is by running "cargo pio espidf menuconfig" (that is, if using the pio builder) +#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.release", relative = true } +#ESP_IDF_SDKCONFIG = { value = "./sdkconfig.debug", relative = true } +ESP_IDF_SDKCONFIG_DEFAULTS = { value = "./sdkconfig.defaults", relative = true } +# ESP-IDF will be installed in ~/.espressif so it can be reused across the different examples. +# See also https://github.com/esp-rs/esp-idf-sys#esp_idf_tools_install_dir-esp_idf_tools_install_dir +ESP_IDF_TOOLS_INSTALL_DIR = { value = "global" } diff --git a/common/lib/wifi/.gitignore b/common/lib/wifi/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/common/lib/wifi/.gitignore @@ -0,0 +1 @@ +/target diff --git a/common/lib/esp32-c3-dkc02-bsc/Cargo.lock b/common/lib/wifi/Cargo.lock similarity index 57% rename from common/lib/esp32-c3-dkc02-bsc/Cargo.lock rename to common/lib/wifi/Cargo.lock index a3a65fe2..fda33766 100644 --- a/common/lib/esp32-c3-dkc02-bsc/Cargo.lock +++ b/common/lib/wifi/Cargo.lock @@ -4,86 +4,58 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "winapi", + "libc", ] [[package]] name = "anyhow" -version = "1.0.53" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] -name = "atomic-polyfill" -version = "0.1.8" +name = "async-task" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14bf7b4f565e5e717d7a7a65b2a05c0b8c96e4db636d6f780f03b15108cdd1b" -dependencies = [ - "critical-section", -] +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] -name = "atty" -version = "0.2.14" +name = "atomic-polyfill" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "critical-section", ] [[package]] name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bare-metal" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" -dependencies = [ - "rustc_version 0.2.3", -] - -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - -[[package]] -name = "base64" -version = "0.12.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bindgen" -version = "0.59.2" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", - "env_logger", "lazy_static", "lazycell", "log", @@ -93,21 +65,10 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", "which", ] -[[package]] -name = "bit_field" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" - -[[package]] -name = "bitfield" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" - [[package]] name = "bitflags" version = "1.3.2" @@ -116,18 +77,32 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" -version = "0.2.17" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" dependencies = [ "memchr", + "serde", +] + +[[package]] +name = "build-time" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b516fccffbcd4c007256d0d620522ea9fcc6f008c9ebb7173eeb349dfcf99786" +dependencies = [ + "chrono", + "once_cell", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "bytemuck" -version = "1.7.3" +name = "bumpalo" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byteorder" @@ -135,11 +110,43 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "camino" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6031a462f977dd38968b6f23378356512feeace69cef817e1a4475108093cec3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cc" -version = "1.0.72" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cexpr" @@ -152,21 +159,30 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "chrono" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] [[package]] name = "clang-sys" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" +checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" dependencies = [ "glob", "libc", @@ -174,140 +190,148 @@ dependencies = [ ] [[package]] -name = "clap" -version = "2.34.0" +name = "cmake" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", + "cc", ] [[package]] -name = "cmake" -version = "0.1.48" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ - "cc", + "termcolor", + "unicode-width", ] [[package]] -name = "cortex-m" -version = "0.7.5" +name = "const_format" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" dependencies = [ - "bare-metal 0.2.5", - "bitfield", - "embedded-hal 0.2.7", - "volatile-register", + "const_format_proc_macros", ] [[package]] -name = "critical-section" -version = "0.2.7" +name = "const_format_proc_macros" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" dependencies = [ - "bare-metal 1.0.0", - "cfg-if 1.0.0", - "cortex-m", - "riscv 0.7.0", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "crossbeam-channel" -version = "0.4.4" +name = "core-foundation-sys" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" -dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", -] +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" [[package]] name = "crossbeam-channel" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.6", + "cfg-if", + "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", - "crossbeam-utils 0.8.6", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.9" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils 0.8.6", + "cfg-if", + "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.7.2" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "cfg-if", ] [[package]] -name = "crossbeam-utils" -version = "0.8.6" +name = "cxx" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72" dependencies = [ - "cfg-if 1.0.0", - "lazy_static", + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", ] [[package]] -name = "cstr_core" -version = "0.2.6" +name = "cxx-build" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd98742e4fdca832d40cab219dc2e3048de17d873248f83f17df47c1bea70956" +checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613" dependencies = [ - "cty", - "memchr", + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", ] [[package]] -name = "cty" -version = "0.2.2" +name = "cxxbridge-flags" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "darling" -version = "0.13.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8" dependencies = [ "darling_core", "darling_macro", @@ -315,29 +339,57 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", "syn", ] [[package]] name = "darling_macro" -version = "0.13.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" dependencies = [ "darling_core", "quote", "syn", ] +[[package]] +name = "defmt" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a0ae7494d9bff013d7b89471f4c424356a71e9752e0c78abe7e6c608a16bb3" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8500cbe4cca056412efce4215a63d0bc20492942aeee695f23b624a53e0a6854" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "defmt-parser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db23d29972d99baa3de2ee2ae3f104c10564a6d05a346eb3f4c4f2c0525a06e" + [[package]] name = "dirs" version = "4.0.0" @@ -349,20 +401,41 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", "winapi", ] +[[package]] +name = "edge-executor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1d66feda51959c8bb07b752c20f1d061eceb178bc91b793a0b32c792c631cf" +dependencies = [ + "async-task", + "heapless", + "log", + "waker-fn", +] + [[package]] name = "either" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.0.0", +] [[package]] name = "embedded-hal" @@ -376,64 +449,54 @@ dependencies = [ [[package]] name = "embedded-hal" -version = "1.0.0-alpha.8" +version = "1.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3babfc7fd332142a0b11aebf592992f211f4e01b6222fb04b03aba1bd80018d" -dependencies = [ - "nb 1.0.0", -] +checksum = "129b101ddfee640565f7c07b301a31d95aa21e5acef21a491c307139f5fa4c91" [[package]] -name = "embedded-io" -version = "0.3.0" +name = "embedded-hal-nb" +version = "1.0.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36673b79844ff4ec0e3f00aeca0b2cfff564ff6739ab9801d13f45a8ec6cc1c7" +checksum = "7e0760ec0a3bf76859d5e33f39542af103f157d5b2ecfb00ace56dd461472e3a" dependencies = [ - "futures", + "embedded-hal 1.0.0-alpha.9", + "nb 1.0.0", ] [[package]] -name = "embedded-svc" -version = "0.21.3" +name = "embedded-io" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d915ef251b4b19f51943e306f9cf3b8d61f79cd790624f6a8982cfa85aca3622" +checksum = "33dfba9e6c113f2fd8537c943780a7345945e66c86972e356b1152e19481bcf5" dependencies = [ - "anyhow", - "enumset", "futures", - "http-auth-basic", - "log", - "no-std-net", - "num_enum", - "serde", - "serde_json", - "strum 0.23.0", - "strum_macros 0.23.1", ] [[package]] name = "embedded-svc" -version = "0.22.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b52805b9b97351bb74d61d513e226bddb81e6e5117bca61d1d4371d4c795d7cc" +checksum = "2079f8182848872fb6e8eed2c1ba3aea409fc71984a9e8090733c08c404e7864" dependencies = [ "anyhow", + "defmt", "embedded-io", "enumset", + "futures", "heapless", "log", "no-std-net", "num_enum", "serde", - "serde_json", "strum 0.23.0", + "strum_macros 0.23.1", ] [[package]] name = "embuild" -version = "0.29.3" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1dd6c90e28cfc361281a692320fcd820bcae71d327215e87c7d749bf8ddd26" +checksum = "65388407a519276cd9aa94291380649d4cedbe8cf566d40f436f7a1ea9b5f8fe" dependencies = [ "anyhow", "bindgen", @@ -443,23 +506,21 @@ dependencies = [ "filetime", "globwalk", "log", - "remove_dir_all 0.7.0", + "remove_dir_all", "serde", "serde_json", "shlex", "strum 0.24.1", "tempfile", "thiserror", - "toml", "which", - "xmas-elf", ] [[package]] name = "enumset" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6216d2c19a6fb5f29d1ada1dc7bc4367a8cbf0fa4af5cf12e07b5bbdde6b5b2c" +checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753" dependencies = [ "enumset_derive", "serde", @@ -467,9 +528,9 @@ dependencies = [ [[package]] name = "enumset_derive" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6451128aa6655d880755345d085494cf7561a6bee7c8dc821e5d77e6d267ecd4" +checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0" dependencies = [ "darling", "proc-macro2", @@ -478,126 +539,108 @@ dependencies = [ ] [[package]] -name = "env_logger" -version = "0.9.0" +name = "envy" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "serde", ] [[package]] -name = "esp-idf-hal" -version = "0.37.4" +name = "errno" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930c77401c2cf14e6509a1af751df2545256cc229e9ec19b342ce75a3faf55d0" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ - "anyhow", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0-alpha.8", - "embedded-svc 0.21.3", - "embuild", - "esp-idf-sys", - "nb 0.1.3", + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", ] [[package]] name = "esp-idf-hal" -version = "0.38.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc998eadd4eb0b3da435b72b5f4ac29b16b8937224bc08d49e5701038a1ab2d6" +checksum = "c4354dcc4d157de675c55eb2e98f4985a526ea56fff316aa0939a63636c4952b" dependencies = [ "anyhow", + "edge-executor", + "embedded-can", "embedded-hal 0.2.7", - "embedded-hal 1.0.0-alpha.8", - "embedded-svc 0.22.0", + "embedded-hal 1.0.0-alpha.9", + "embedded-hal-nb", "embuild", "esp-idf-sys", - "nb 0.1.3", + "heapless", + "nb 1.0.0", ] [[package]] name = "esp-idf-svc" -version = "0.41.4" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bd726ec2881797a91c2717da67befc00d01cb8d1f635435fc4ac6a6968b764" +checksum = "f6035126eeaf81d19ca5342fa8f36e85489c6fba1148ec8af167a6b9bff39e0f" dependencies = [ "anyhow", - "cstr_core", - "embedded-svc 0.21.3", + "embedded-svc", "embuild", "enumset", - "esp-idf-hal 0.37.4", + "esp-idf-hal", "esp-idf-sys", + "heapless", "log", "uncased", ] [[package]] name = "esp-idf-sys" -version = "0.31.5" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b239e46fe930f21ed36a25de1b6d29a0e22b65166f3a8e44624095a671f2f56c" +checksum = "7b3458faf5c04761cb9a122ba30714afda5e88848e2f99c6e6c05c77ecf626d8" dependencies = [ "anyhow", "bindgen", + "build-time", + "cargo_metadata", + "const_format", "embuild", - "paste", + "envy", + "libc", "regex", + "serde", "strum 0.24.1", ] -[[package]] -name = "esp32-c3-dkc02-bsc" -version = "0.1.0" -dependencies = [ - "anyhow", - "embedded-svc 0.21.3", - "esp-idf-hal 0.38.0", - "esp-idf-svc", - "esp-idf-sys", - "esp32c3", - "ignore", - "log", - "rgb", - "riscv 0.8.0", - "toml-cfg", -] - -[[package]] -name = "esp32c3" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcac1b9f97b99652ed00d2570e3cb5c7729858d0a70b2e2b9c999a7ca087f07" -dependencies = [ - "bare-metal 1.0.0", - "riscv 0.8.0", - "vcell", -] - [[package]] name = "fastrand" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -608,9 +651,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -622,9 +665,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -632,33 +675,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -673,26 +716,26 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -721,15 +764,22 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heapless" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f6733da246dc2af610133c8be0667170fd68e8ca5630936b520300eee8846f9" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" dependencies = [ "atomic-polyfill", "hash32", - "rustc_version 0.4.0", + "rustc_version", + "serde", "spin", "stable_deref_trait", ] @@ -745,33 +795,42 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "libc", ] [[package]] -name = "http-auth-basic" -version = "0.1.3" +name = "iana-time-zone" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df69b6a68474b935f436fb9c84139f32de4f7759810090d1a3a5e592553f7ee0" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ - "base64", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", ] [[package]] -name = "humantime" -version = "2.1.0" +name = "iana-time-zone-haiku" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] [[package]] name = "ident_case" @@ -781,11 +840,10 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "ignore" -version = "0.4.11" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" dependencies = [ - "crossbeam-channel 0.4.4", "globset", "lazy_static", "log", @@ -797,20 +855,49 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +dependencies = [ + "libc", + "windows-sys 0.45.0", ] [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] [[package]] name = "lazy_static" @@ -826,55 +913,65 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.116" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "winapi", ] [[package]] -name = "lock_api" -version = "0.4.6" +name = "link-cplusplus" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ - "scopeguard", + "cc", ] [[package]] -name = "log" -version = "0.4.14" +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ - "cfg-if 1.0.0", + "autocfg", + "scopeguard", ] [[package]] -name = "maybe-uninit" -version = "2.0.0" +name = "log" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -911,20 +1008,38 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.0" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", - "version_check", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ "hermit-abi", "libc", @@ -932,18 +1047,18 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.6" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.6" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -953,15 +1068,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" - -[[package]] -name = "paste" -version = "1.0.6" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "peeking_take_while" @@ -983,80 +1092,103 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "thiserror", - "toml", + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", ] [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.15" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" -version = "1.5.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ - "crossbeam-channel 0.5.5", + "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.6", + "crossbeam-utils", "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -1065,18 +1197,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -1091,47 +1214,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rgb" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a374af9a0e5fdcdd98c1c7b64f05004f9ea2555b6c75f211daa81268a3c50f1" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "riscv" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" -dependencies = [ - "bare-metal 1.0.0", - "bit_field", - "riscv-target", -] - -[[package]] -name = "riscv" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2856a701069e2d262b264750d382407d272d5527f7a51d3777d1805b4e2d3c" -dependencies = [ - "bare-metal 1.0.0", - "bit_field", - "embedded-hal 0.2.7", -] - -[[package]] -name = "riscv-target" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "rustc-hash" version = "1.1.0" @@ -1140,33 +1222,38 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 0.9.0", + "semver", ] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "rustix" +version = "0.36.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" dependencies = [ - "semver 1.0.12", + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", ] [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -1184,40 +1271,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "semver" -version = "0.9.0" +name = "scratch" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] name = "semver" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" - -[[package]] -name = "semver-parser" -version = "0.7.0" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.136" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "3a382c72b4ba118526e187430bb4963cd6d55051ebf13d9b25574d379cc98d20" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1ef476a5790f0f6decbc66726b6e5d63680ed518283e64c7df415989d880954f" dependencies = [ "proc-macro2", "quote", @@ -1226,9 +1307,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.78" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa", "ryu", @@ -1243,18 +1324,18 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] [[package]] name = "spin" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc" dependencies = [ "lock_api", ] @@ -1265,18 +1346,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strum" version = "0.23.0" @@ -1292,7 +1361,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros 0.24.2", + "strum_macros 0.24.3", ] [[package]] @@ -1310,11 +1379,11 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -1323,61 +1392,51 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.86" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "tempfile" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", - "libc", "redox_syscall", - "remove_dir_all 0.5.3", - "winapi", + "rustix", + "windows-sys 0.42.0", ] [[package]] name = "termcolor" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", @@ -1386,18 +1445,30 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "toml" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -1408,7 +1479,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91dbf509587452b781d208257bfe9923808873290d99505ee0eb0e6599540bdf" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro2", "quote", "serde", @@ -1416,6 +1487,23 @@ dependencies = [ "toml", ] +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" + +[[package]] +name = "toml_edit" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "uncased" version = "0.9.7" @@ -1426,34 +1514,28 @@ dependencies = [ ] [[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-width" -version = "0.1.9" +name = "unicode-ident" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "unicode-segmentation" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] -name = "vcell" -version = "0.1.3" +name = "unicode-width" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] -name = "vec_map" -version = "0.8.2" +name = "unicode-xid" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "version_check" @@ -1468,13 +1550,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] -name = "volatile-register" -version = "0.2.1" +name = "waker-fn" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" -dependencies = [ - "vcell", -] +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "walkdir" @@ -1489,19 +1568,93 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "which" -version = "4.2.4" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", +] + +[[package]] +name = "wifi" +version = "0.1.0" +dependencies = [ + "anyhow", + "embedded-svc", + "embuild", + "esp-idf-hal", + "esp-idf-svc", + "esp-idf-sys", + "log", + "toml-cfg", ] [[package]] @@ -1537,58 +1690,90 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" +name = "windows_x86_64_gnullvm" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] -name = "xmas-elf" -version = "0.8.0" +name = "windows_x86_64_msvc" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d29b4d8e7beaceb4e77447ba941a7600d23d0319ab52da0461abea214832d5a" -dependencies = [ - "zero", -] +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] -name = "zero" -version = "0.1.2" +name = "winnow" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" +checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +dependencies = [ + "memchr", +] diff --git a/common/lib/wifi/Cargo.toml b/common/lib/wifi/Cargo.toml new file mode 100644 index 00000000..4e6661b5 --- /dev/null +++ b/common/lib/wifi/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "wifi" +version = "0.1.0" +edition = "2021" +authors = ["Sergio Gasquez "] + +[dependencies] +esp-idf-sys = { version = "=0.32.1" } +esp-idf-svc = { version = "=0.45.0", features = ["experimental", "alloc"] } +esp-idf-hal = "=0.40.1" +embedded-svc = "=0.24.0" +log = "=0.4.17" +anyhow = "=1.0.69" + +[build-dependencies] +embuild = "0.31.0" +anyhow = "1" + +[dev-dependencies] +anyhow = "1" +esp-idf-sys = { version = "0.32", features = ["native", "binstart"] } +toml-cfg = "=0.1.3" diff --git a/common/lib/wifi/build.rs b/common/lib/wifi/build.rs new file mode 100644 index 00000000..ccb6e757 --- /dev/null +++ b/common/lib/wifi/build.rs @@ -0,0 +1,6 @@ +// Necessary because of this issue: https://github.com/rust-lang/cargo/issues/9641 +fn main() -> Result<(), Box> { + embuild::build::CfgArgs::output_propagated("ESP_IDF")?; + embuild::build::LinkArgs::output_propagated("ESP_IDF")?; + Ok(()) +} diff --git a/common/lib/wifi/cfg.toml.example b/common/lib/wifi/cfg.toml.example new file mode 100644 index 00000000..a5ea911b --- /dev/null +++ b/common/lib/wifi/cfg.toml.example @@ -0,0 +1,3 @@ +[wifi] +wifi_ssid = "FBI Surveillance Van" +wifi_psk = "hunter2" diff --git a/common/lib/wifi/examples/wifi.rs b/common/lib/wifi/examples/wifi.rs new file mode 100644 index 00000000..616a248e --- /dev/null +++ b/common/lib/wifi/examples/wifi.rs @@ -0,0 +1,44 @@ +use anyhow::{bail, Result}; +use esp_idf_hal::prelude::Peripherals; +use esp_idf_svc::eventloop::EspSystemEventLoop; +use log::info; +use wifi::wifi; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; + +/// This configuration is picked up at compile time by `build.rs` from the +/// file `cfg.toml`. +#[toml_cfg::toml_config] +pub struct Config { + #[default("")] + wifi_ssid: &'static str, + #[default("")] + wifi_psk: &'static str, +} + +fn main() -> Result<()> { + esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); + + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + + let app_config = CONFIG; + // Connect to the Wi-Fi network + let _wifi = match wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + ) { + Ok(inner) => { + println!("Connected to Wi-Fi network!"); + inner + } + Err(err) => { + // Red! + bail!("Could not connect to Wi-Fi network: {:?}", err) + } + }; + Ok(()) +} diff --git a/common/lib/wifi/rust-toolchain.toml b/common/lib/wifi/rust-toolchain.toml new file mode 100644 index 00000000..a550ad27 --- /dev/null +++ b/common/lib/wifi/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2023-02-28" diff --git a/common/lib/wifi/src/lib.rs b/common/lib/wifi/src/lib.rs new file mode 100644 index 00000000..7cac1a19 --- /dev/null +++ b/common/lib/wifi/src/lib.rs @@ -0,0 +1,94 @@ +use anyhow::{bail, Result}; +use embedded_svc::wifi::{ + AccessPointConfiguration, AuthMethod, ClientConfiguration, Configuration, Wifi, +}; +use esp_idf_hal::peripheral; +use esp_idf_svc::{ + eventloop::EspSystemEventLoop, + netif::{EspNetif, EspNetifWait}, + wifi::{EspWifi, WifiWait}, +}; +use log::info; +use std::{net::Ipv4Addr, time::Duration}; + +pub fn wifi( + ssid: &str, + pass: &str, + modem: impl peripheral::Peripheral

+ 'static, + sysloop: EspSystemEventLoop, +) -> Result>> { + let mut auth_method = AuthMethod::WPA2Personal; + if ssid.is_empty() { + bail!("Missing WiFi name") + } + if pass.is_empty() { + auth_method = AuthMethod::None; + info!("Wifi password is empty"); + } + let mut wifi = Box::new(EspWifi::new(modem, sysloop.clone(), None)?); + + info!("Wifi created, about to scan"); + + let ap_infos = wifi.scan()?; + + let ours = ap_infos.into_iter().find(|a| a.ssid == ssid); + + let channel = if let Some(ours) = ours { + info!( + "Found configured access point {} on channel {}", + ssid, ours.channel + ); + Some(ours.channel) + } else { + info!( + "Configured access point {} not found during scanning, will go with unknown channel", + ssid + ); + None + }; + + wifi.set_configuration(&Configuration::Mixed( + ClientConfiguration { + ssid: ssid.into(), + password: pass.into(), + channel, + auth_method, + ..Default::default() + }, + AccessPointConfiguration { + ssid: "aptest".into(), + channel: channel.unwrap_or(1), + ..Default::default() + }, + ))?; + + wifi.start()?; + + info!("Starting wifi..."); + + if !WifiWait::new(&sysloop)? + .wait_with_timeout(Duration::from_secs(20), || wifi.is_started().unwrap()) + { + bail!("Wifi did not start"); + } + + info!("Connecting wifi..."); + + wifi.connect()?; + + if !EspNetifWait::new::(wifi.sta_netif(), &sysloop)?.wait_with_timeout( + Duration::from_secs(20), + || { + wifi.is_connected().unwrap() + && wifi.sta_netif().get_ip_info().unwrap().ip != Ipv4Addr::new(0, 0, 0, 0) + }, + ) { + bail!("Wifi did not connect or did not receive a DHCP lease"); + } + + let ip_info = wifi.sta_netif().get_ip_info()?; + + info!("Wifi DHCP info: {:?}", ip_info); + + Ok(wifi) +} diff --git a/common/vendor/.sentinel b/common/vendor/.sentinel deleted file mode 100644 index e69de29b..00000000 diff --git a/extra/mqtt-python-client/README.md b/extra/mqtt-python-client/README.md index ae558368..faf60305 100644 --- a/extra/mqtt-python-client/README.md +++ b/extra/mqtt-python-client/README.md @@ -4,7 +4,7 @@ - logs temperature values sent by MCU ## Setup -- Configure MQTT credentials in `../../intro/mqtt/exercise` according to instructions provided in the workshop +- Configure MQTT credentials in `../../intro/mqtt/exercise` according to instructions provided in the workshop - set up a Python environment: ```shell diff --git a/intro/hardware-check/Cargo.toml b/intro/hardware-check/Cargo.toml index cf68e39e..995f581f 100644 --- a/intro/hardware-check/Cargo.toml +++ b/intro/hardware-check/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "hardware-check" version = "0.1.0" -authors = ["Anatol Ulrich "] +authors = [ + "Anatol Ulrich ", + "Sergio Gasquez ", +] edition = "2021" resolver = "2" @@ -17,15 +20,16 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -esp-idf-svc = { version = "=0.41.4", features = ["experimental", "alloc"] } -esp32-c3-dkc02-bsc = { path = "../../common/lib/esp32-c3-dkc02-bsc" } -log = "0.4" -anyhow = "1" -toml-cfg = "0.1" -ignore = "=0.4.11" +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +esp-idf-svc = { version = "=0.45.0", features = ["experimental", "alloc"] } +esp-idf-hal = "=0.40.1" +rgb-led = { path = "../../common/lib/rgb-led" } +wifi = { path = "../../common/lib/wifi" } +log = "=0.4.17" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" [build-dependencies] -embuild = "0.28" -anyhow = "1" -toml-cfg = "0.1" +embuild = "=0.31.0" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" diff --git a/intro/hardware-check/README.md b/intro/hardware-check/README.md deleted file mode 100644 index b52bc04f..00000000 --- a/intro/hardware-check/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# hardware-check - -This program is for the Espressif [ESP32-C3-DevKitC-02 board]. It performs a basic check to ensure your hardware is working and that your PC can program it successfully. - -[ESP32-C3-DevKitC-02 board]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitc-02.html - -## Prerequisites - -1. For the required SDK & tools, follow the the set-up instructions in [Book Section 2.2]( - https://espressif-trainings.ferrous-systems.com/02_2_software.html#espressif-toolchain). - -2. Copy `cfg.toml.example` to `cfg.toml` and edit according to your setup. Do - not add the `uuid` field, that will be generated by `build.rs`. - -## Running - -Run: - -```console -$ cargo run -``` - -See [Book Section 2.4](https://espressif-trainings.ferrous-systems.com/02_4_hello_board.html) -for more details. - -## License - -This source code is made available under either the [MIT](./LICENSE-MIT.txt) -or [Apache-2.0](./LICENSE_APACHE.txt) licenses, at your option. diff --git a/intro/hardware-check/rust-toolchain.toml b/intro/hardware-check/rust-toolchain.toml index d32a6a20..a550ad27 100644 --- a/intro/hardware-check/rust-toolchain.toml +++ b/intro/hardware-check/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly-2022-03-10" +channel = "nightly-2023-02-28" diff --git a/intro/hardware-check/src/main.rs b/intro/hardware-check/src/main.rs index 3e4a177e..03bcd13d 100644 --- a/intro/hardware-check/src/main.rs +++ b/intro/hardware-check/src/main.rs @@ -1,14 +1,11 @@ //! # Hardware Check -//! -//! This `libstd` program is for the ESP32-C3-DevKitC-02 board. - -// Logging macros - -use log::*; - -// And alias for our Board Support Crate -use esp32_c3_dkc02_bsc as bsc; +use anyhow::{bail, Result}; +use esp_idf_hal::prelude::Peripherals; +use esp_idf_svc::eventloop::EspSystemEventLoop; +use log::info; +use rgb_led::{RGB8, WS2812RMT}; +use wifi::wifi; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use esp_idf_sys as _; @@ -29,28 +26,34 @@ pub struct Config { /// /// If the LED goes solid red, then it was unable to connect to your Wi-Fi /// network. -fn main() -> anyhow::Result<()> { - use bsc::led::RGB8; - +fn main() -> Result<()> { esp_idf_sys::link_patches(); esp_idf_svc::log::EspLogger::initialize_default(); + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + info!("Hello, world!"); // Start the LED off yellow - let mut led = bsc::led::WS2812RMT::new()?; + let mut led = WS2812RMT::new(peripherals.pins.gpio2, peripherals.rmt.channel0)?; led.set_pixel(RGB8::new(50, 50, 0))?; // The constant `CONFIG` is auto-generated by `toml_config`. let app_config = CONFIG; // Connect to the Wi-Fi network - let _wifi = match bsc::wifi::wifi(app_config.wifi_ssid, app_config.wifi_psk) { + let _wifi = match wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + ) { Ok(inner) => inner, Err(err) => { // Red! led.set_pixel(RGB8::new(50, 0, 0))?; - anyhow::bail!("could not connect to Wi-Fi network: {:?}", err) + bail!("Could not connect to Wi-Fi network: {:?}", err) } }; diff --git a/intro/http-client/Cargo.toml b/intro/http-client/Cargo.toml index aa6a898c..869dbced 100644 --- a/intro/http-client/Cargo.toml +++ b/intro/http-client/Cargo.toml @@ -1,8 +1,11 @@ [package] name = "http-client" version = "0.1.0" -authors = ["Anatol Ulrich "] -edition = "2018" +authors = [ + "Anatol Ulrich ", + "Sergio Gasquez ", +] +edition = "2021" resolver = "2" [profile.release] @@ -17,15 +20,15 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-svc = "=0.41.4" -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -esp32-c3-dkc02-bsc = { path = "../../common/lib/esp32-c3-dkc02-bsc" } -embedded-svc = "=0.21" -anyhow = "1.0" -toml-cfg = "0.1" -ignore = "=0.4.11" +esp-idf-svc = { version = "0.45.0", features = ["experimental", "alloc"] } +esp-idf-hal = "=0.40.1" +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +wifi = { path = "../../common/lib/wifi" } +embedded-svc = "=0.24.0" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" [build-dependencies] -embuild = "0.28" -anyhow = "1" -toml-cfg = "0.1" +embuild = "=0.31.0" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" diff --git a/intro/http-client/examples/http_client.rs b/intro/http-client/examples/http_client.rs index 30a1aa16..a52dcc1f 100644 --- a/intro/http-client/examples/http_client.rs +++ b/intro/http-client/examples/http_client.rs @@ -1,15 +1,16 @@ +use anyhow::{bail, Result}; use core::str; - -use bsc::wifi::wifi; use embedded_svc::{ - http::{ - client::{Client, Response, Request, RequestWrite}, - Status, - }, io::Read, + http::{client::Client, Status}, + io::Read, }; - -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::http::client::EspHttpClient; +use esp_idf_hal::prelude::Peripherals; +use esp_idf_svc::{ + eventloop::EspSystemEventLoop, + http::client::{Configuration, EspHttpConnection}, +}; +use wifi::wifi; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use esp_idf_sys as _; #[toml_cfg::toml_config] @@ -20,57 +21,61 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - let _wifi = wifi(CONFIG.wifi_ssid, CONFIG.wifi_psk)?; + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + + // The constant `CONFIG` is auto-generated by `toml_config`. + let app_config = CONFIG; + + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; get("http://neverssl.com/")?; Ok(()) } -fn get(url: impl AsRef) -> anyhow::Result<()> { - // 1. Create a new EspHttpClient. (Check documentation) - let mut client = EspHttpClient::new_default()?; +fn get(url: impl AsRef) -> Result<()> { + // 1. Create a new EspHttpConnection with default Configuration. (Check documentation) + let connection = EspHttpConnection::new(&Configuration::default())?; + // 2. Get a client using the Client::wrap method. (Check documentation) + let mut client = Client::wrap(connection); - // 2. Open a GET request to `url` + // 3. Open a GET request to `url` let request = client.get(url.as_ref())?; - // 3. Requests *may* send data to the server. Turn the request into a writer, specifying 0 bytes as write length - // (since we don't send anything - but have to do the writer step anyway) - // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_client.html - // If this were a POST request, you'd set a write length > 0 and then writer.do_write(&some_buf); - - let writer = request.into_writer(0)?; - - // 4. Submit our write request and check the status code of the response. + // 4. Submit the request and check the status code of the response. // Successful http status codes are in the 200..=299 range. - - let response = writer.into_response()?; + let response = request.submit()?; let status = response.status(); - let mut total_size = 0; - - println!("response code: {}\n", status); - + println!("Response code: {}\n", status); match status { 200..=299 => { - // 5. if the status is OK, read response data chunk by chunk into a buffer and print it until done - let mut buf = [0_u8;256]; - let mut reader = response.reader(); + // 5. If the status is OK, read response data chunk by chunk into a buffer and print it until done. + let mut buf = [0_u8; 256]; + let mut reader = response; loop { - if let Ok(size) = reader.do_read(&mut buf) { - if size == 0 { break; } - total_size += size; - // 6. try converting the bytes into a Rust (UTF-8) string and print it + if let Ok(size) = Read::read(&mut reader, &mut buf) { + if size == 0 { + break; + } + // 6. Try converting the bytes into a Rust (UTF-8) string and print it. let response_text = str::from_utf8(&buf[..size])?; println!("{}", response_text); } } } - _ => anyhow::bail!("unexpected response code: {}", status), + _ => bail!("Unexpected response code: {}", status), } - Ok(()) } diff --git a/intro/http-client/examples/https_client.rs b/intro/http-client/examples/https_client.rs index 730e5e42..87b8b6de 100644 --- a/intro/http-client/examples/https_client.rs +++ b/intro/http-client/examples/https_client.rs @@ -1,17 +1,17 @@ +use anyhow::{bail, Result}; use core::str; - -use bsc::wifi::wifi; use embedded_svc::{ - http::{ - client::{Client, Request, RequestWrite, Response}, - Status, - }, + http::{client::Client, Status}, io::Read, }; -use esp_idf_svc::http::client::{EspHttpClient, EspHttpClientConfiguration}; - -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_hal::prelude::Peripherals; +use esp_idf_svc::{ + eventloop::EspSystemEventLoop, + http::client::{Configuration, EspHttpConnection}, +}; +use wifi::wifi; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; #[toml_cfg::toml_config] pub struct Config { @@ -21,63 +21,65 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - let _wifi = wifi(CONFIG.wifi_ssid, CONFIG.wifi_psk)?; + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; - get("http://neverssl.com")?; + // The constant `CONFIG` is auto-generated by `toml_config`. + let app_config = CONFIG; - get("https://espressif.com")?; + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; + + get("https://espressif.com/")?; Ok(()) } -fn get(url: impl AsRef) -> anyhow::Result<()> { - // 1. create a new EspHttpClient with SSL certificates enabled - let mut client = EspHttpClient::new(&EspHttpClientConfiguration { +fn get(url: impl AsRef) -> Result<()> { + // 1. Create a new EspHttpClient. (Check documentation) + let connection = EspHttpConnection::new(&Configuration { use_global_ca_store: true, crt_bundle_attach: Some(esp_idf_sys::esp_crt_bundle_attach), - ..Default::default() })?; + let mut client = Client::wrap(connection); - // 2. open a GET request to `url` + // 2. Open a GET request to `url` let request = client.get(url.as_ref())?; - // 3. requests *may* send data to the server. Turn the request into a writer, specifying 0 bytes as write length - // (since we don't send anything - but have to do the writer step anyway) - // - // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_client.html - // if this were a POST request, you'd set a write length > 0 and then writer.do_write(&some_buf); - let writer = request.into_writer(0)?; - // 4. submit our write request and check the status code of the response. + // 3. Submit write request and check the status code of the response. // Successful http status codes are in the 200..=299 range. - let response = writer.into_response()?; + let response = request.submit()?; let status = response.status(); - println!("response code: {}\n", status); + + println!("Response code: {}\n", status); + match status { 200..=299 => { - // 5. if the status is OK, read response data chunk by chunk into a buffer and print it until done - let mut buf = [0u8; 256]; - let mut total_size = 0; - let mut reader = response.reader(); + // 4. if the status is OK, read response data chunk by chunk into a buffer and print it until done + let mut buf = [0_u8; 256]; + let mut reader = response; loop { - let size = reader.do_read(&mut buf)?; - if size == 0 { - break; + if let Ok(size) = Read::read(&mut reader, &mut buf) { + if size == 0 { + break; + } + // 5. try converting the bytes into a Rust (UTF-8) string and print it + let response_text = str::from_utf8(&buf[..size])?; + println!("{}", response_text); } - total_size += size; - // strictly speaking, we should check the response's encoding... - - // 6. try converting the bytes into a Rust (UTF-8) string and print it - let response_text = str::from_utf8(&buf)?; - print!("{}", response_text); } - - println!("\n\nDone! read {} bytes:", total_size); } - _ => anyhow::bail!("unexpected response code: {}", status), + _ => bail!("Unexpected response code: {}", status), } Ok(()) diff --git a/intro/http-client/rust-toolchain.toml b/intro/http-client/rust-toolchain.toml index d32a6a20..a550ad27 100644 --- a/intro/http-client/rust-toolchain.toml +++ b/intro/http-client/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly-2022-03-10" +channel = "nightly-2023-02-28" diff --git a/intro/http-client/src/main.rs b/intro/http-client/src/main.rs index 1b8e37ce..abc94f7a 100644 --- a/intro/http-client/src/main.rs +++ b/intro/http-client/src/main.rs @@ -1,16 +1,18 @@ +use anyhow::{bail, Result}; use core::str; - -use bsc::wifi::wifi; use embedded_svc::{ - http::{ - client::{Client, Request, RequestWrite, Response}, - Headers, Status, - }, + http::{client::Client, Status}, io::Read, }; -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::http::client::{EspHttpClient, EspHttpClientConfiguration}; -use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_hal::prelude::Peripherals; +use esp_idf_svc::{ + eventloop::EspSystemEventLoop, + http::client::{Configuration, EspHttpConnection}, +}; +use wifi::wifi; + +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; #[toml_cfg::toml_config] pub struct Config { @@ -20,38 +22,47 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - let _wifi = wifi(CONFIG.wifi_ssid, CONFIG.wifi_psk)?; + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; - // TODO your code here - //get(...)?; + // The constant `CONFIG` is auto-generated by `toml_config`. + let app_config = CONFIG; - Ok(()) -} + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; -fn get(url: impl AsRef) -> anyhow::Result<()> { - // 1. Create a new EspHttpClient. (Check documentation) + get("http://neverssl.com/")?; - // 2. Open a GET request to `url` + Ok(()) +} - // 3. Requests *may* send data to the server. Turn the request into a writer, specifying 0 bytes as write length - // (since we don't send anything - but have to do the writer step anyway) - // - // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_http_client.html - // If this were a POST request, you'd set a write length > 0 and then writer.do_write(&some_buf); +fn get(url: impl AsRef) -> Result<()> { + // 1. Create a new EspHttpConnection with default Configuration. (Check documentation) - // let writer = request...; + // 2. Get a client using the Client::wrap method. (Check documentation) - // 4. Turn the writer into a response and check its status. Successful http status codes are in the 200..=299 range. + // 3. Open a GET request to `url` - // let response = writer...; + // 4. Submit the request and check the status code of the response. + // let response = request...; // let status = ...; - // println!("response code: {}\n", status); + // println!("Response code: {}\n", status); + // match status { + // Successful http status codes are in the 200..=299 range. // 5. If the status is OK, read response data chunk by chunk into a buffer and print it until done. + // 6. Try converting the bytes into a Rust (UTF-8) string and print it. + // } Ok(()) } diff --git a/intro/http-server/Cargo.toml b/intro/http-server/Cargo.toml index d914d021..0c154f18 100644 --- a/intro/http-server/Cargo.toml +++ b/intro/http-server/Cargo.toml @@ -1,8 +1,11 @@ [package] name = "http-server" version = "0.1.0" -authors = ["Anatol Ulrich "] -edition = "2018" +authors = [ + "Anatol Ulrich ", + "Sergio Gasquez ", +] +edition = "2021" resolver = "2" [profile.release] @@ -17,16 +20,17 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -esp-idf-svc = "=0.41.4" -esp32-c3-dkc02-bsc = { path = "../../common/lib/esp32-c3-dkc02-bsc" } -esp32c3 = "=0.4" -embedded-svc = "=0.21" -anyhow = "1.0" -toml-cfg = "0.1" -ignore = "=0.4.11" +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +esp-idf-hal = "=0.40.1" +esp-idf-svc = { version = "0.45.0", features = ["experimental", "alloc"] } +wifi = { path = "../../common/lib/wifi" } +embedded-svc = "=0.24.0" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" +shtcx = "=0.11.0" + [build-dependencies] -embuild = "0.28" -anyhow = "1" -toml-cfg = "0.1" +embuild = "=0.31.0" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" diff --git a/intro/http-server/examples/http_server.rs b/intro/http-server/examples/http_server.rs index d16c3cc2..59924eda 100644 --- a/intro/http-server/examples/http_server.rs +++ b/intro/http-server/examples/http_server.rs @@ -1,18 +1,23 @@ +use anyhow::Result; use core::str; +use embedded_svc::{http::Method, io::Write}; +use esp_idf_hal::{ + i2c::{I2cConfig, I2cDriver}, + prelude::*, +}; +use esp_idf_svc::{ + eventloop::EspSystemEventLoop, + http::server::{Configuration, EspHttpServer}, +}; +use shtcx::{self, shtc3, PowerMode}; use std::{ sync::{Arc, Mutex}, thread::sleep, time::Duration, }; - -use bsc::{temp_sensor::BoardTempSensor, wifi::wifi}; -use embedded_svc::{ - http::{server::{registry::Registry, Response, ResponseWrite}, Method}, - io::Write, -}; -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::http::server::{Configuration, EspHttpServer}; -use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use wifi::wifi; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; #[toml_cfg::toml_config] pub struct Config { @@ -21,35 +26,73 @@ pub struct Config { #[default("")] wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - let _wifi = wifi(CONFIG.wifi_ssid, CONFIG.wifi_psk)?; + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; - let server_config = Configuration::default(); - let mut server = EspHttpServer::new(&server_config)?; - server.set_inline_handler("/", Method::Get, |request, response| { - let html = index_html(); - let mut writer = response.into_writer(request)?; - writer.do_write_all(html.as_bytes())?; - writer.complete() - })?; + // The constant `CONFIG` is auto-generated by `toml_config`. + let app_config = CONFIG; + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; - let temp_sensor_main = Arc::new(Mutex::new(BoardTempSensor::new_taking_peripherals())); + // Initialize temperature sensor + let pins = peripherals.pins; + let sda = pins.gpio10; + let scl = pins.gpio8; + let i2c = peripherals.i2c0; + let config = I2cConfig::new().baudrate(100.kHz().into()); + let i2c = I2cDriver::new(i2c, sda, scl, &config)?; + let temp_sensor_main = Arc::new(Mutex::new(shtc3(i2c))); let temp_sensor = temp_sensor_main.clone(); - server.set_inline_handler("/temperature", Method::Get, move |request, response| { - let temp_val = temp_sensor.lock().unwrap().read_owning_peripherals(); - let html = temperature(temp_val); - let mut writer = response.into_writer(request)?; - writer.do_write_all(html.as_bytes())?; - writer.complete() + temp_sensor + .lock() + .unwrap() + .start_measurement(PowerMode::NormalMode) + .unwrap(); + + // Set the HTTP server + let mut server = EspHttpServer::new(&Configuration::default())?; + // http:/// handler + server.fn_handler("/", Method::Get, |request| { + let html = index_html(); + let mut response = request.into_ok_response()?; + response.write_all(html.as_bytes())?; + Ok(()) })?; + // http:///temperature handler + server.fn_handler("/temperature", Method::Get, move |request| { + let temp_val = temp_sensor + .lock() + .unwrap() + .get_measurement_result() + .unwrap() + .temperature + .as_degrees_celsius(); + let html = temperature(temp_val); + let mut response = request.into_ok_response()?; + response.write_all(html.as_bytes())?; + Ok(()) + })?; - println!("server awaiting connection"); + println!("Server awaiting connection"); + // Prevent program from exiting loop { + temp_sensor_main + .lock() + .unwrap() + .start_measurement(PowerMode::NormalMode) + .unwrap(); sleep(Duration::from_millis(1000)); } } @@ -73,9 +116,9 @@ fn templated(content: impl AsRef) -> String { } fn index_html() -> String { - templated("Hello from mcu!") + templated("Hello from ESP32-C3!") } fn temperature(val: f32) -> String { - templated(format!("chip temperature: {:.2}°C", val)) + templated(format!("Chip temperature: {:.2}°C", val)) } diff --git a/intro/http-server/rust-toolchain.toml b/intro/http-server/rust-toolchain.toml index d32a6a20..a550ad27 100644 --- a/intro/http-server/rust-toolchain.toml +++ b/intro/http-server/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly-2022-03-10" +channel = "nightly-2023-02-28" diff --git a/intro/http-server/src/main.rs b/intro/http-server/src/main.rs index 918b7c54..cc485833 100644 --- a/intro/http-server/src/main.rs +++ b/intro/http-server/src/main.rs @@ -1,21 +1,23 @@ +use anyhow::Result; use core::str; +use embedded_svc::{http::Method, io::Write}; +use esp_idf_hal::{ + i2c::{I2cConfig, I2cDriver}, + prelude::*, +}; +use esp_idf_svc::{ + eventloop::EspSystemEventLoop, + http::server::{Configuration, EspHttpServer}, +}; +use shtcx::{self, shtc3, PowerMode}; use std::{ sync::{Arc, Mutex}, thread::sleep, time::Duration, }; - -use bsc::{temp_sensor::BoardTempSensor, wifi::wifi}; -use embedded_svc::{ - http::{ - server::{registry::Registry, Response}, - Method, - }, - io::Write, -}; -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::http::server::{Configuration, EspHttpServer}; -use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use wifi::wifi; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; #[toml_cfg::toml_config] pub struct Config { @@ -25,29 +27,52 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); + + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + + // The constant `CONFIG` is auto-generated by `toml_config`. + let app_config = CONFIG; - let _wifi = wifi(CONFIG.wifi_ssid, CONFIG.wifi_psk)?; + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; - let mut temp_sensor = BoardTempSensor::new_taking_peripherals(); + // Initialize temperature sensor + let pins = peripherals.pins; + let sda = pins.gpio10; + let scl = pins.gpio8; + let i2c = peripherals.i2c0; + let config = I2cConfig::new().baudrate(100.kHz().into()); + let i2c = I2cDriver::new(i2c, sda, scl, &config)?; + let temp_sensor_main = Arc::new(Mutex::new(shtc3(i2c))); + let mut temp_sensor = temp_sensor_main.clone(); + temp_sensor + .lock() + .unwrap() + .start_measurement(PowerMode::NormalMode) + .unwrap(); - // TODO your code here: - // let server_config = ...; + // 1.Create a `EspHttpServer` instance using a default configuration // let mut server = EspHttpServer::new(...)?; - // server.set_inline_handler("/", Method::Get, |request, response| { - // TODO your code here: + // 2. Write a handler that returns the index page + // server.fn_handler("/", Method::Get, |request| { // ... //})?; - // TODO this is not true until you actually create one - println!("server awaiting connection"); + // This is not true until you actually create one + println!("Server awaiting connection"); - // prevent program from exiting + // Prevent program from exiting loop { - let current_temperature = temp_sensor.read_owning_peripherals(); - println!("board temperature: {:.2}", current_temperature); sleep(Duration::from_millis(1000)); } } diff --git a/intro/mqtt/exercise/Cargo.toml b/intro/mqtt/exercise/Cargo.toml index 327ec694..55c4b0aa 100644 --- a/intro/mqtt/exercise/Cargo.toml +++ b/intro/mqtt/exercise/Cargo.toml @@ -1,8 +1,11 @@ [package] name = "mqtt" version = "0.1.0" -authors = ["Anatol Ulrich "] -edition = "2018" +authors = [ + "Anatol Ulrich ", + "Sergio Gasquez ", +] +edition = "2021" resolver = "2" [profile.release] @@ -17,20 +20,21 @@ default = ["native"] native = ["esp-idf-sys/native"] [dependencies] -esp-idf-sys = { version = "=0.31.5", features = ["binstart"] } -esp-idf-svc = { version = "=0.41.4", features = ["experimental", "alloc"] } -embedded-svc = "=0.21" -esp32-c3-dkc02-bsc = { path = "../../../common/lib/esp32-c3-dkc02-bsc" } -log = "0.4" -anyhow = "1" -toml-cfg = "0.1" -esp32c3 = "=0.4" -riscv = { version = "0.8" } +esp-idf-hal = "=0.40.1" +embedded-svc = "=0.24.0" +esp-idf-sys = { version = "=0.32.1", features = ["binstart"] } +esp-idf-svc = { version = "=0.45.0", features = ["experimental", "alloc"] } +rgb-led = { path = "../../../common/lib/rgb-led" } +wifi = { path = "../../../common/lib/wifi" } +log = "=0.4.17" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" get-uuid = { path = "../../../common/lib/get-uuid" } mqtt-messages = { path = "../../../common/lib/mqtt-messages" } -ignore = "=0.4.11" +shtcx = "=0.11.0" + [build-dependencies] -embuild = "0.28" -anyhow = "1" -toml-cfg = "0.1" +embuild = "=0.31.0" +anyhow = "=1.0.69" +toml-cfg = "=0.1.3" diff --git a/intro/mqtt/exercise/examples/solution_publ.rs b/intro/mqtt/exercise/examples/solution_publ.rs index 7f67637d..5ce4a779 100644 --- a/intro/mqtt/exercise/examples/solution_publ.rs +++ b/intro/mqtt/exercise/examples/solution_publ.rs @@ -1,26 +1,20 @@ -use bsc::{ - led::{RGB8, WS2812RMT}, - temp_sensor::BoardTempSensor, - wifi::wifi, +use anyhow::Result; +use embedded_svc::mqtt::client::{Details::Complete, Event::Received, QoS}; +use esp_idf_hal::{ + delay, + i2c::{I2cConfig, I2cDriver}, + prelude::*, }; -use embedded_svc::mqtt::client::{ - Client, - Details::{Complete, InitialChunk, SubsequentChunk}, - Event::{self, Received}, - Message, Publish, QoS, -}; -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::{ - log::EspLogger, - mqtt::client::{EspMqttClient, EspMqttMessage, MqttClientConfiguration}, -}; -use std::{borrow::Cow, convert::TryFrom, thread::sleep, time::Duration}; +use esp_idf_svc::eventloop::EspSystemEventLoop; +use esp_idf_svc::mqtt::client::{EspMqttClient, EspMqttMessage, MqttClientConfiguration}; +use log::{error, info, warn}; +use mqtt_messages::{hello_topic, ColorData}; +use rgb_led::{RGB8, WS2812RMT}; +use shtcx::{self, shtc3, PowerMode}; +use std::{convert::TryFrom, thread::sleep, time::Duration}; +use wifi::wifi; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use esp_idf_sys as _; -use log::{error, info}; - -// imported message topics -use mqtt_messages::{cmd_topic_fragment, hello_topic, Command, RawCommandData}; const UUID: &'static str = get_uuid::uuid(); @@ -38,24 +32,39 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { - // Setup +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - EspLogger::initialize_default(); + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + // The constant `CONFIG` is auto-generated by `toml_config`. let app_config = CONFIG; - info!("our UUID is:"); + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; + + info!("Our UUID is:"); info!("{}", UUID); - let mut temp_sensor = BoardTempSensor::new_taking_peripherals(); + let pins = peripherals.pins; + let sda = pins.gpio10; + let scl = pins.gpio8; + let i2c = peripherals.i2c0; + let config = I2cConfig::new().baudrate(100.kHz().into()); + let i2c = I2cDriver::new(i2c, sda, scl, &config)?; + let mut temp_sensor = shtc3(i2c); + let mut delay = delay::Ets; - let mut led = WS2812RMT::new()?; + let mut led = WS2812RMT::new(pins.gpio2, peripherals.rmt.channel0)?; led.set_pixel(RGB8::new(1, 1, 0))?; - let _wifi = wifi(app_config.wifi_ssid, app_config.wifi_psk)?; - // Client configuration: let broker_url = if app_config.mqtt_user != "" { format!( @@ -82,8 +91,10 @@ fn main() -> anyhow::Result<()> { loop { sleep(Duration::from_secs(1)); - let temp = temp_sensor.read_owning_peripherals(); - + let temp = temp_sensor + .measure_temperature(PowerMode::NormalMode, &mut delay) + .unwrap() + .as_degrees_celsius(); // 3. publish CPU temperature client.publish( &mqtt_messages::temperature_data_topic(UUID), diff --git a/intro/mqtt/exercise/examples/solution_publ_rcv.rs b/intro/mqtt/exercise/examples/solution_publ_rcv.rs index 14494c71..5239489b 100644 --- a/intro/mqtt/exercise/examples/solution_publ_rcv.rs +++ b/intro/mqtt/exercise/examples/solution_publ_rcv.rs @@ -1,23 +1,20 @@ -//This solution is the same as main.rs -use std::{convert::TryFrom, thread::sleep, time::Duration}; - -use bsc::{ - led::{RGB8, WS2812RMT}, - temp_sensor::BoardTempSensor, - wifi::wifi, -}; -use embedded_svc::mqtt::client::{ - Client, Details::Complete, Event::Received, Message, MessageImpl, Publish, QoS, +use anyhow::Result; +use embedded_svc::mqtt::client::{Details::Complete, Event::Received, QoS}; +use esp_idf_hal::{ + delay, + i2c::{I2cConfig, I2cDriver}, + prelude::*, }; -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::{ - log::EspLogger, - mqtt::client::{EspMqttClient, EspMqttMessage, MqttClientConfiguration}, -}; -// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported -use esp_idf_sys as _; +use esp_idf_svc::eventloop::EspSystemEventLoop; +use esp_idf_svc::mqtt::client::{EspMqttClient, EspMqttMessage, MqttClientConfiguration}; use log::{error, info, warn}; use mqtt_messages::{hello_topic, ColorData}; +use rgb_led::{RGB8, WS2812RMT}; +use shtcx::{self, shtc3, PowerMode}; +use std::{convert::TryFrom, thread::sleep, time::Duration}; +use wifi::wifi; +// If using the `binstart` feature of `esp-idf-sys`, always keep this module imported +use esp_idf_sys as _; const UUID: &'static str = get_uuid::uuid(); @@ -35,23 +32,39 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - EspLogger::initialize_default(); + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + // The constant `CONFIG` is auto-generated by `toml_config`. let app_config = CONFIG; - info!("our UUID is:"); + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; + + info!("Our UUID is:"); info!("{}", UUID); - let mut temp_sensor = BoardTempSensor::new_taking_peripherals(); + let pins = peripherals.pins; + let sda = pins.gpio10; + let scl = pins.gpio8; + let i2c = peripherals.i2c0; + let config = I2cConfig::new().baudrate(100.kHz().into()); + let i2c = I2cDriver::new(i2c, sda, scl, &config)?; + let mut temp_sensor = shtc3(i2c); + let mut delay = delay::Ets; - let mut led = WS2812RMT::new()?; + let mut led = WS2812RMT::new(pins.gpio2, peripherals.rmt.channel0)?; led.set_pixel(RGB8::new(1, 1, 0))?; - let _wifi = wifi(app_config.wifi_ssid, app_config.wifi_psk)?; - let mqtt_config = MqttClientConfiguration::default(); let broker_url = if !app_config.mqtt_user.is_empty() { @@ -63,7 +76,7 @@ fn main() -> anyhow::Result<()> { format!("mqtt://{}", app_config.mqtt_host) }; - // mqtt client with + // 1. Create a client with default configuration and empty handler let mut client = EspMqttClient::new( broker_url, @@ -74,6 +87,7 @@ fn main() -> anyhow::Result<()> { }, )?; + // 2. publish an empty hello message let payload: &[u8] = &[]; client.publish(&hello_topic(UUID), QoS::AtLeastOnce, true, payload)?; @@ -81,7 +95,11 @@ fn main() -> anyhow::Result<()> { loop { sleep(Duration::from_secs(1)); - let temp = temp_sensor.read_owning_peripherals(); + let temp = temp_sensor + .measure_temperature(PowerMode::NormalMode, &mut delay) + .unwrap() + .as_degrees_celsius(); + // 3. publish CPU temperature client.publish( &mqtt_messages::temperature_data_topic(UUID), QoS::AtLeastOnce, @@ -95,14 +113,14 @@ fn process_message(message: &EspMqttMessage, led: &mut WS2812RMT) { match message.details() { Complete => { info!("{:?}", message); - let message_data: &[u8] = &message.data(); + let message_data: &[u8] = message.data(); if let Ok(ColorData::BoardLed(color)) = ColorData::try_from(message_data) { info!("{}", color); if let Err(e) = led.set_pixel(color) { - error!("could not set board LED: {:?}", e) + error!("Could not set board LED: {:?}", e) }; } } - _ => error!("could not set board LED"), + _ => error!("Could not set board LED"), } } diff --git a/intro/mqtt/exercise/rust-toolchain.toml b/intro/mqtt/exercise/rust-toolchain.toml index e8085426..a550ad27 100644 --- a/intro/mqtt/exercise/rust-toolchain.toml +++ b/intro/mqtt/exercise/rust-toolchain.toml @@ -1,3 +1,2 @@ [toolchain] -channel = "nightly-2022-03-10" - +channel = "nightly-2023-02-28" diff --git a/intro/mqtt/exercise/src/main.rs b/intro/mqtt/exercise/src/main.rs index 9948fcda..57377eec 100644 --- a/intro/mqtt/exercise/src/main.rs +++ b/intro/mqtt/exercise/src/main.rs @@ -1,23 +1,24 @@ -use bsc::{ - led::{RGB8, WS2812RMT}, - temp_sensor::BoardTempSensor, - wifi::wifi, -}; +use anyhow::Result; use embedded_svc::mqtt::client::{ Client, Details::{Complete, InitialChunk, SubsequentChunk}, Event::{self, Received}, Message, Publish, QoS, }; -use esp32_c3_dkc02_bsc as bsc; -use esp_idf_svc::{ - log::EspLogger, - mqtt::client::{EspMqttClient, EspMqttMessage, MqttClientConfiguration}, +use esp_idf_hal::{ + delay, + i2c::{I2cConfig, I2cDriver}, + prelude::*, }; +use esp_idf_svc::eventloop::EspSystemEventLoop; +use esp_idf_svc::mqtt::client::{EspMqttClient, EspMqttMessage, MqttClientConfiguration}; +use log::{error, info}; +use rgb_led::{RGB8, WS2812RMT}; +use shtcx::{self, shtc3, PowerMode}; use std::{borrow::Cow, convert::TryFrom, thread::sleep, time::Duration}; +use wifi::wifi; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use esp_idf_sys as _; -use log::{error, info}; // imported message topics use mqtt_messages::{cmd_topic_fragment, hello_topic, Command, RawCommandData}; @@ -38,25 +39,39 @@ pub struct Config { wifi_psk: &'static str, } -fn main() -> anyhow::Result<()> { - - // Setup +fn main() -> Result<()> { esp_idf_sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - EspLogger::initialize_default(); + let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + // The constant `CONFIG` is auto-generated by `toml_config`. let app_config = CONFIG; - info!("our UUID is:"); + // Connect to the Wi-Fi network + let _wifi = wifi( + app_config.wifi_ssid, + app_config.wifi_psk, + peripherals.modem, + sysloop, + )?; + + info!("Our UUID is:"); info!("{}", UUID); - let mut temp_sensor = BoardTempSensor::new_taking_peripherals(); + let pins = peripherals.pins; + let sda = pins.gpio10; + let scl = pins.gpio8; + let i2c = peripherals.i2c0; + let config = I2cConfig::new().baudrate(100.kHz().into()); + let i2c = I2cDriver::new(i2c, sda, scl, &config)?; + let mut temp_sensor = shtc3(i2c); + let mut delay = delay::Ets; - let mut led = WS2812RMT::new()?; + let mut led = WS2812RMT::new(pins.gpio2, peripherals.rmt.channel0)?; led.set_pixel(RGB8::new(1, 1, 0))?; - let _wifi = wifi(app_config.wifi_ssid, app_config.wifi_psk)?; - // Client configuration: let broker_url = if app_config.mqtt_user != "" { format!( @@ -76,10 +91,12 @@ fn main() -> anyhow::Result<()> { // 2. publish an empty hello message - loop { sleep(Duration::from_secs(1)); - let temp = temp_sensor.read_owning_peripherals(); + let temp = temp_sensor + .measure_temperature(PowerMode::NormalMode, &mut delay) + .unwrap() + .as_degrees_celsius(); // 3. publish CPU temperature // client.publish( ... )?; diff --git a/intro/mqtt/host-client/Cargo.toml b/intro/mqtt/host-client/Cargo.toml index 99067fbc..f33a1d0a 100644 --- a/intro/mqtt/host-client/Cargo.toml +++ b/intro/mqtt/host-client/Cargo.toml @@ -3,12 +3,9 @@ name = "host-client" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -rumqttc = "0.10.0" -rand = "0.8.4" -toml-cfg = "0.1" +rumqttc = "=0.20.0" +rand = "=0.8.5" +toml-cfg = "=0.1.3" get-uuid = { path = "../../../common/lib/get-uuid" } mqtt-messages = { path = "../../../common/lib/mqtt-messages" } - diff --git a/intro/mqtt/host-client/src/main.rs b/intro/mqtt/host-client/src/main.rs index 76173eee..d898abf1 100644 --- a/intro/mqtt/host-client/src/main.rs +++ b/intro/mqtt/host-client/src/main.rs @@ -38,15 +38,10 @@ fn main() -> Result<(), Box> { let g = rng.gen(); let b = rng.gen(); let color = RGB8::new(r, g, b); - println!("setting new color: {}", color); + println!("Setting new color: {}", color); let color = ColorData::BoardLed(color); client - .publish( - color.topic(UUID), - QoS::AtLeastOnce, - false, - color.data(), - ) + .publish(color.topic(UUID), QoS::AtLeastOnce, false, color.data()) .unwrap(); thread::sleep(Duration::from_secs(1)); } @@ -59,7 +54,7 @@ fn main() -> Result<(), Box> { if let Ok(rumqttc::Event::Incoming(Packet::Publish(publish_data))) = notification { if publish_data.topic == hello_topic(UUID) { - println!("board says hi!"); + println!("Board says hi!"); } if publish_data.topic == temperature_data_topic(UUID) { @@ -68,7 +63,7 @@ fn main() -> Result<(), Box> { if let Ok(data) = data { let temp: f32 = f32::from_be_bytes(data); - println!("board temperature: {:.2}°C", temp) + println!("Board temperature: {:.2}°C", temp) } } }