From eff0bab88f5390cde339cd1a8f34a5a9c7754130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Fri, 23 Feb 2024 11:53:43 +0100 Subject: [PATCH 01/11] Update RIOT version --- RIOT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RIOT b/RIOT index ee8569f..73e90c5 160000 --- a/RIOT +++ b/RIOT @@ -1 +1 @@ -Subproject commit ee8569f7dae998407fcf3b9598d61e8101e7fd48 +Subproject commit 73e90c50494f30a8195ebf30d8c60aff59bc3a6c From 137d5436cb51507340d68eb2efe4d378518ce8a5 Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 4 Sep 2024 15:11:28 +0200 Subject: [PATCH 02/11] rust02: Explain exotic Rust syntax people stumble over --- rust02-timers/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rust02-timers/README.md b/rust02-timers/README.md index db5661b..0e07fc0 100644 --- a/rust02-timers/README.md +++ b/rust02-timers/README.md @@ -77,6 +77,11 @@ Clock::msec().set_during( }); ``` +The `||` indicates a [closure](https://doc.rust-lang.org/book/ch13-01-closures.html): +a block of code that is not evaluated immediately, +but passed into another call as a combination of a function and any variables captured from the context. +(They do look a bit odd without arguments; the syntax may look more intuitive in examples with arguments such as `differentiate(|x| x**2 - 2*x + 1);`). + Note that the LED 1 was sent from the main thread to the interrupt handler defined in the first closure. Code that should execute inside an interrupt handler is limited (for example, no blocking operations should occur). From 406c524b402442cd0a598b27c2e982a3a0bf06e1 Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 4 Sep 2024 15:15:00 +0200 Subject: [PATCH 03/11] rust02: Align code and documentation, clarify --- rust02-timers/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rust02-timers/README.md b/rust02-timers/README.md index 0e07fc0..77fc524 100644 --- a/rust02-timers/README.md +++ b/rust02-timers/README.md @@ -33,10 +33,10 @@ $ cd ../rust02-timers $ make all flash term ``` -**2. Reset the board. You should see a "Timeout!" string after 2 seconds.** +**2. Reset the board. You should see "This is a timers example", and then a "Timeout!" string after 4 seconds.** ## Task 2 -Modify the application so that the board blinks the LED only for 250 ms for 10 iterations. +Modify the application so that the board has the LED on for only 250 ms, and runs only 10 iterations. **1. Adapt the loop to be true for 10 iterations:** ```rust @@ -73,6 +73,8 @@ Clock::msec().set_during( || { ``` +(existing `for` loop remains in here) + ```rust }); ``` From 2f220b2c94c5c46b481140bf7d5a4a919287b909 Mon Sep 17 00:00:00 2001 From: chrysn Date: Fri, 16 Aug 2024 15:15:28 +0200 Subject: [PATCH 04/11] Add rust05-gpio exercise --- rust05-gpio/Cargo.toml | 19 +++++ rust05-gpio/Makefile | 33 ++++++++ rust05-gpio/README.md | 177 +++++++++++++++++++++++++++++++++++++++++ rust05-gpio/src/lib.rs | 33 ++++++++ 4 files changed, 262 insertions(+) create mode 100644 rust05-gpio/Cargo.toml create mode 100644 rust05-gpio/Makefile create mode 100644 rust05-gpio/README.md create mode 100644 rust05-gpio/src/lib.rs diff --git a/rust05-gpio/Cargo.toml b/rust05-gpio/Cargo.toml new file mode 100644 index 0000000..44db660 --- /dev/null +++ b/rust05-gpio/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "gpio-example" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["staticlib"] + +[profile.release] +# Setting the panic mode has little effect on the built code (as Rust on RIOT +# supports no unwinding), but setting it allows builds on native without using +# the nightly-only lang_items feature. +panic = "abort" + +[dependencies] +embedded-hal = "1.0.0" +riot-wrappers = { version = "0.8", features = [ "set_panic_handler", "panic_handler_format" ] } + +rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } diff --git a/rust05-gpio/Makefile b/rust05-gpio/Makefile new file mode 100644 index 0000000..2e410d6 --- /dev/null +++ b/rust05-gpio/Makefile @@ -0,0 +1,33 @@ +APPLICATION = gpio_example + +# If no BOARD is found in the environment, use this default: +BOARD ?= feather-nrf52840-sense + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../RIOT + +USEMODULE += periph_gpio +USEMODULE += periph_gpio_irq + +USEMODULE += ztimer +USEMODULE += ztimer_msec +USEMODULE += ztimer_sec + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Some workarounds are needed in order to get the tutorial running on +# some computers. +-include ../lab_workarounds.mk + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +# Tell the build system to use the Rust crate here +FEATURES_REQUIRED += rust_target +APPLICATION_RUST_MODULE = gpio_example +BASELIBS += $(APPLICATION_RUST_MODULE).module + +include $(RIOTBASE)/Makefile.include diff --git a/rust05-gpio/README.md b/rust05-gpio/README.md new file mode 100644 index 0000000..c80836e --- /dev/null +++ b/rust05-gpio/README.md @@ -0,0 +1,177 @@ +# GPIOs + +General Purpose Input/Outputs (GPIOs) are a peripheral that allows +microcontrollers to interact with the physical world. They are +commonly known as pins. As the name suggests, they can be either configured as +digital inputs or digital outputs. That is, they can read a digital value from +the outside, or present a digital value to the outside (which translates in +presenting a voltage of either 0V for digital `0` or commonly 3.3V for `1`). + +They are useful for a huge range of tasks. As outputs, they could drive an +indication LED or a circuit like a valve or a lock (special electrical +adaption is needed in this case, such as a transistor, as the GPIOs don't +handle high currents). As inputs, they can be used to read buttons, switches +or digital sensors (e.g. a presence or a window sensor). + +RIOT provides the `periph_gpio` module to interact with the peripheral. It +exposes a simple API that allows to use GPIOs independently of the underlying +platform. In this example we will make use of the most common functionalities +of the GPIO module. + +To change to this directory from a different exercise, use the following command in the terminal. + +```sh +$ cd ../rust05-gpios +``` + +## Task 1 + +Drive an LED using the GPIO API. So far we have operated on LEDs using a series +of LED abstractions provided by the board. What these macros do under the hood is to +write particular registers that control the GPIO peripheral. + +**1. Outside the `main` function, `use` the gpio module to type less later:** + +```rust +use riot_wrappers::gpio::{GPIO, OutputMode}; +``` + +**2. Inside the `main` function define the led0 GPIO pin, and configure it as an output.** +**In the `feather-nrf52840-sense` we are currently using, the LED0 is connected to the** +**Port 1, Pin 9:** + +```rust +let mut led0 = GPIO::from_port_and_pin(1, 9) + .expect("Pin should be available") + .configure_as_output(OutputMode::Out) + .expect("Pin should be usable as output"); +``` + +**3. The LEDs on the board are on when the GPIO outputs `1`.** +**Inside the `main` function, periodically set the GPIO to high (turning the LED on) and low (turning the LED off):** + +```rust +loop { + led0.set_high(); + Clock::msec().sleep(Duration::from_millis(200)); + led0.set_low(); + Clock::msec().sleep(Duration::from_millis(800)); +} +``` + +**5. Build and flash the application:** + +```sh +$ make all flash +``` + +## GPIO interrupts + +We could constantly read a GPIO input to check if the value has changed, but this +consumes CPU cycles and energy. Instead, we can configure a GPIO to generate an +event: an **interrupt** (we will see more about threads and interrupts in the +next task). Interrupts are generated when certain pre-established conditions +are met. We can configure a GPIO to generate an interrupt when the external +value changes to `0`, to `1`, or whenever there is a change. + +*Unfortunately, there are no safe Rust wrappers for this functionality yet.* +*Thus, we jump right into how C functions are accessed in unsafe Rust --* +*an exercise that under ideal conditions is needed rarely, but hey:* +*learning how to do it by hand is a way towards having the high-level wrappers around!* + +## Task 2 + +Turn the LED1 on whenever a button is pressed, and turn it off when the button has been released. +Use an interrupt to detect the value change. + +**1. The same way as done in the previous task, initialize the GPIO pin for the LED1.** +**LED1 is connected to the Port 1, Pin 10.** +**Define `led1` in the main function.** + +**2. Add crates we will need:** + +``` +$ cargo add riot-sys +$ cargo add static-cell +``` + +**and add** + +```rust +use static_cell::StaticCell; +use riot_wrappers::gpio::OutputGPIO; +``` + +**below the use of task 1.** + +We will use riot-sys to gain access to the low-level C functions, +and static-cell to safely obtain a mutable reference to static memory. + +**2. Define a struct to transfer ownership of the used pins to the callback function.** +**While this could be done with statics just as well, mutable statics are discouraged in Rust.** + +```rust +struct PinsForInterrupt { + button: GPIO, + led1: OutputGPIO, +} +``` + +**3. Write a callback function, which will be called when an interrupt occurs.** +**Whenever the button is pressed, the button's pin value is read to `0`.** +**As all we can pass across the C API for interrupts is a pointer,** +**we define that this pointer has the semantics of a `&'static mut PinsForInterrupt` pointer,** +**and cast it back accordingly.** + +```rust +extern "C" fn button_callback(arg: *mut riot_sys::libc::c_void) { + let pins = unsafe { &mut *(arg as *mut PinsForInterrupt) }; + + // On a regular input pin we could run `.is_low()`, but the `riot_wrappers::gpio::OutputGPIO` + // type would reconfigure the pin in its constructor, so we even read it manually. + if unsafe { riot_sys::gpio_read(pins.button.to_c()) } == 0 { + pins.led1.set_high(); + } + else { + pins.led1.set_low(); + } +} +``` + +**3. Define the GPIO pin connected to the user button on your board, and store its address for initialization.** +**The user button is connected to the Port 1, Pin 2.** + +```rust +let button = GPIO::from_port_and_pin(1, 2) + .expect("Pin should be available"); +let button_address = button.to_c(); +``` + +**4. Define a local static, move the pins into it, and get a static mutable reference to it.** + +```rust +static PINS: StaticCell = StaticCell::new(); +let pins: &mut PinsForInterrupt = PINS.init(PinsForInterrupt { + led1, + button, +}); +``` + +The documentation of [static_cell](https://docs.rs/static_cell/latest/static_cell/) explains well when it is convenient, +and which alternatives there are. +Particularly tempting alternatives here are +just unsafely using mutable statics (we know what we are doing … but we may miss details when refactoring later), +or using a RIOT Mutex (but then we'd have to do more error handling, because if a mutex is locked, it can not be awaited in an interrupt). + +**5. Initialize the button from its address, configuring the callback to be called on any change, and passing in control of the pins.** + +```rust +unsafe { + riot_sys::gpio_init_int(button_address, riot_sys::gpio_mode_t_GPIO_IN_PU, riot_sys::gpio_flank_t_GPIO_BOTH, Some(button_callback), pins as *mut _ as *mut riot_sys::libc::c_void); +}; +``` + +Note that the safety of this relies on GPIO interrupts not preempting themselves: +While RIOT can be used with priorized interrupts, the same interrupt will not trigger a jump while it is being executed. + +**6. Build and flash the application.** diff --git a/rust05-gpio/src/lib.rs b/rust05-gpio/src/lib.rs new file mode 100644 index 0000000..6da4b51 --- /dev/null +++ b/rust05-gpio/src/lib.rs @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Christian Amsüss +// SPDX-License-Identifier: Apache-2.0 OR MIT +#![no_std] + +use riot_wrappers::riot_main; +use riot_wrappers::println; +use riot_wrappers::ztimer::Clock; +use core::time::Duration; + +// [TASK 1: Add convenience `use` line] + +// [TASK 2: Add convenience `use` line] + +extern crate rust_riotmodules; + +riot_main!(main); + +// [TASK 2: Define the interrupt's struct] + +fn main() { + // Startup delay to ensure the terminal is connected + Clock::sec().sleep(Duration::from_secs(5)); + + println!("GPIOs example."); + + // [TASK 1: Initialize led0 here] + + // [TASK 2: Initialize led1 and button here] + + // [TASK 1: Loop here] +} + +// [TASK 2: Define button_callback here] From 0755fc522f858a3c3fa6b55487df866a5644016c Mon Sep 17 00:00:00 2001 From: chrysn Date: Sun, 18 Aug 2024 09:11:06 +0200 Subject: [PATCH 05/11] rust05: Follow best practice of always gating hardcoded numbers behind a board match --- rust05-gpio/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/rust05-gpio/README.md b/rust05-gpio/README.md index c80836e..b71ba82 100644 --- a/rust05-gpio/README.md +++ b/rust05-gpio/README.md @@ -41,12 +41,20 @@ use riot_wrappers::gpio::{GPIO, OutputMode}; **Port 1, Pin 9:** ```rust -let mut led0 = GPIO::from_port_and_pin(1, 9) +let led0 = match riot_wrappers::BOARD { + "feather-nrf52840-sense" => GPIO::from_port_and_pin(1, 9), + _ => panic!("No pinout known for this board"), +}; + +let mut led0 = led0 .expect("Pin should be available") .configure_as_output(OutputMode::Out) .expect("Pin should be usable as output"); ``` +By gating the pin creation with the board's name, +we can ensure that changing the board will not accidentally drive a pin that releases the magic smoke. + **3. The LEDs on the board are on when the GPIO outputs `1`.** **Inside the `main` function, periodically set the GPIO to high (turning the LED on) and low (turning the LED off):** From 10f198138fac2758609a353593abb3cf23e1d8c3 Mon Sep 17 00:00:00 2001 From: chrysn Date: Sun, 18 Aug 2024 10:06:04 +0200 Subject: [PATCH 06/11] rust05-gpio: Add portability task with traits and in RIOT --- rust05-gpio/README.md | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/rust05-gpio/README.md b/rust05-gpio/README.md index b71ba82..dcae5ee 100644 --- a/rust05-gpio/README.md +++ b/rust05-gpio/README.md @@ -183,3 +183,61 @@ Note that the safety of this relies on GPIO interrupts not preempting themselves While RIOT can be used with priorized interrupts, the same interrupt will not trigger a jump while it is being executed. **6. Build and flash the application.** + +## Task 3 + +Refactor the blinking loop to make it portable across the embedded Rust ecosystem. +By not using methods on a RIOT [`OutputGPIO`](https://rustdoc.etonomy.org/riot_wrappers/gpio/struct.OutputGPIO.html) +but accessing it as an implementation of embedded-hal's [`OutputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.OutputPin.html), +and doing the same with the ZTimer [clock](https://rustdoc.etonomy.org/riot_wrappers/ztimer/struct.Clock.html) +(as embedded-hal's [`DelayNs`](https://docs.rs/embedded-hal/latest/embedded_hal/delay/trait.DelayNs.html)), +we create the same binary program +using different abstractions. + +* **1. Move the loop into a dedicated function. The signature could look like this:** + +```rust +fn blink(mut led0: OutputGPIO, clock: Clock<1000>) -> ! { +``` + +You may need to adjust the convenience imports; the Rust compiler will make sensible suggestions. + +* **2. Add the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate as a dependency:** + +```sh +$ cargo add embedded-hal +``` + +Note that this does not really increase the dependency tree: +`riot-wrappers` already depends on that crate, +but we need to explicitly depend on it to name its traits. + +* **3. Alter the `blink` function to be generic over the traits' implementation:** + **The signature could look like this:** + +```rust +fn blink2( + mut led0: impl embedded_hal::digital::OutputPin, + mut clock: impl embedded_hal::delay::DelayNs, +) -> ! { +``` + +While GPIO pins' inherent methods are identical to the OutputPin's, +generic clocks require exclusive clock access and do not provide a [`Duration`](https://doc.rust-lang.org/std/time/struct.Duration.html) based sleep. +Instead, look up a suitable delay method in the [documentation of `DelayNs`](https://docs.rs/embedded-hal/latest/embedded_hal/delay/trait.DelayNs.html). + +## Task 4 + +With another board available, +porting between RIOT boards is trivial. + +* **1. Connect a micro:bit v2 to your system.** + +* **2. Add a LED0 definition for the `BOARD == "microbit-v2"` case`.** + **Use Port 0 Pin 20 -- that's actually enabling the microphone, but it is the closest that board has to a simple LED.** + +* **3. Flash the example:** + +```sh +$ BOARD=microbit-v2 make all flash +``` From a67393ec2ea5d958ca12e32433ec3b3086e279db Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 4 Sep 2024 15:20:31 +0200 Subject: [PATCH 07/11] rust05-gpio: Swap sequence of tasks 3/4 --- rust05-gpio/README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/rust05-gpio/README.md b/rust05-gpio/README.md index dcae5ee..115dc26 100644 --- a/rust05-gpio/README.md +++ b/rust05-gpio/README.md @@ -186,6 +186,22 @@ While RIOT can be used with priorized interrupts, the same interrupt will not tr ## Task 3 +With another board available, +porting between RIOT boards is trivial. + +* **1. Connect a micro:bit v2 to your system.** + +* **2. Add a LED0 definition for the `BOARD == "microbit-v2"` case`.** + **Use Port 0 Pin 20 -- that's actually enabling the microphone, but it is the closest that board has to a simple LED.** + +* **3. Flash the example:** + +```sh +$ BOARD=microbit-v2 make all flash +``` + +## Task 4 + Refactor the blinking loop to make it portable across the embedded Rust ecosystem. By not using methods on a RIOT [`OutputGPIO`](https://rustdoc.etonomy.org/riot_wrappers/gpio/struct.OutputGPIO.html) but accessing it as an implementation of embedded-hal's [`OutputPin`](https://docs.rs/embedded-hal/latest/embedded_hal/digital/trait.OutputPin.html), @@ -225,19 +241,3 @@ fn blink2( While GPIO pins' inherent methods are identical to the OutputPin's, generic clocks require exclusive clock access and do not provide a [`Duration`](https://doc.rust-lang.org/std/time/struct.Duration.html) based sleep. Instead, look up a suitable delay method in the [documentation of `DelayNs`](https://docs.rs/embedded-hal/latest/embedded_hal/delay/trait.DelayNs.html). - -## Task 4 - -With another board available, -porting between RIOT boards is trivial. - -* **1. Connect a micro:bit v2 to your system.** - -* **2. Add a LED0 definition for the `BOARD == "microbit-v2"` case`.** - **Use Port 0 Pin 20 -- that's actually enabling the microphone, but it is the closest that board has to a simple LED.** - -* **3. Flash the example:** - -```sh -$ BOARD=microbit-v2 make all flash -``` From 6c5601002b2854e752918c23b2adc09ca5e2266d Mon Sep 17 00:00:00 2001 From: chrysn Date: Fri, 16 Aug 2024 17:45:42 +0200 Subject: [PATCH 08/11] Add rust06-threads example --- rust06-threads/Cargo.toml | 21 +++++++ rust06-threads/Makefile | 31 ++++++++++ rust06-threads/README.md | 127 ++++++++++++++++++++++++++++++++++++++ rust06-threads/src/lib.rs | 40 ++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 rust06-threads/Cargo.toml create mode 100644 rust06-threads/Makefile create mode 100644 rust06-threads/README.md create mode 100644 rust06-threads/src/lib.rs diff --git a/rust06-threads/Cargo.toml b/rust06-threads/Cargo.toml new file mode 100644 index 0000000..6408fda --- /dev/null +++ b/rust06-threads/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "thread-example" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["staticlib"] + +[profile.release] +# Setting the panic mode has little effect on the built code (as Rust on RIOT +# supports no unwinding), but setting it allows builds on native without using +# the nightly-only lang_items feature. +panic = "abort" + +[dependencies] +riot-sys = "0.7.12" +riot-wrappers = { version = "0.8", features = ["set_panic_handler", "panic_handler_format"] } + +rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } +static_cell = "2.1.0" +switch-hal = "0.4.0" diff --git a/rust06-threads/Makefile b/rust06-threads/Makefile new file mode 100644 index 0000000..99a08a9 --- /dev/null +++ b/rust06-threads/Makefile @@ -0,0 +1,31 @@ +# name of your application +APPLICATION = thread_example + +# If no BOARD is found in the environment, use this default: +BOARD ?= feather-nrf52840-sense + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../RIOT + +USEMODULE += ztimer +USEMODULE += ztimer_msec +USEMODULE += ztimer_sec + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Some workarounds are needed in order to get the tutorial running on +# some computers. +-include ../lab_workarounds.mk + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +# Tell the build system to use the Rust crate here +FEATURES_REQUIRED += rust_target +APPLICATION_RUST_MODULE = thread_example +BASELIBS += $(APPLICATION_RUST_MODULE).module + +include $(RIOTBASE)/Makefile.include diff --git a/rust06-threads/README.md b/rust06-threads/README.md new file mode 100644 index 0000000..b58eb88 --- /dev/null +++ b/rust06-threads/README.md @@ -0,0 +1,127 @@ +# Threads + +Threads are functions designed to be scheduled and executed by the CPU +independently. An example of a thread is the `main()` function. +In single-core MCUs only one thread can have control of the CPU at a given time. +The scheduler is in charge of deciding which thread takes control, depending on +its state and priority. Usually threads are waiting for some event to occur, +and are not 'runnable' (e.g., waiting for a certain time to pass, a packet to +arrive, an external interrupt or an event to be posted on a queue). + +To create threads, we first define a function with the following signature: + +```rust +fn thread_handler() +``` + +The function content is what will be executed whenever our thread is running. +The function gets called from the beginning only once: at the moment of creation. +That is why, commonly, thread handlers contain a loop which would run forever. + +In addition to a handler function, threads require memory: a stack. There local +variables and other information will be stored when performing function calls. + +To create a new thread, we provide stack memory, a function, and spawn a thread: + +```C +fn thread_handler() { + // Some task for our thread +} + +let my_thread = riot_wrappers::thread::spawn( + // Memory stack + thread_stack, + // The thread handler function + &mut thread_handler, + // Human readable name of the thread + c"my_thread", + // Priority of the thread. The lower value, the higher priority + (riot_sys::THREAD_PRIORITY_MAIN - 1) as _, + // Thread flags. By default, enable stack memory usage measurements. + (riot_sys::THREAD_CREATE_STACKTEST) as _, + ); +``` + +RIOT scheduler executes a thread until one of the following conditions occurs: +- The thread finishes +- The thread waits for an incoming event (e.g event queue) +- An interrupt source is triggered (button, GPIO pin, timer, etc). In this case, + the scheduler resumes execution in the highest priority thread that does not have + pending events. + +For more information visit the +[thread documentation page](https://doc.riot-os.org/group__core__thread.html). + +To change to this directory from a different exercise, use the following command in the terminal. + +```sh +$ cd ../riot06-threads +``` + +## A note on interrupts + +We usually don't want to perform lengthy tasks from interrupt contexts, as they +will block the execution of all threads. What is commonly done instead, is to +use some signalization mechanism to offload a task to a thread. A good choice is +to use events, as they are allocated by the sender and we are certain that they +will not get lost (as opposed to messages in RIOT). We will see how to utilize +events on the next exercise. + +## Task 1 + +Create a "blinky" thread that toggles the LED1 every 250 milliseconds. + +**1. Create a handler function for your thread.** +**As we want the task to be repeated indefinitely, we include an infinite loop:** + + +```rust +fn blinky_handler() { + let mut led1 = riot_wrappers::led::LED::<1>::new(); + + loop { + println!( + "Thread {}\n", + riot_wrappers::thread::get_pid() + .get_name() + .unwrap_or("unnamed") + ); + + led1.on().unwrap(); + Clock::msec().sleep(Duration::from_millis(20)); + led1.off().unwrap(); + Clock::msec().sleep(Duration::from_millis(180)); + } +} +``` + +**2. Define a stack for your thread:** +```rust +use riot_sys::THREAD_STACKSIZE_DEFAULT; +use static_cell::StaticCell; +static THREAD_STACK: StaticCell<[u8; THREAD_STACKSIZE_DEFAULT as usize]> = StaticCell::new(); +``` + +**3. Take possession of the stack, and spawn your thread.** +```rust +let thread_stack = THREAD_STACK.init_with(|| [0; THREAD_STACKSIZE_DEFAULT as usize]); +// Due to a bug in the spawn function +// , we must provide the pointer +// inside a &'static mut +static STATIC_POINTER: StaticCell = StaticCell::new(); +let static_pointer = STATIC_POINTER.init(blinky_handler); +let my_thread = riot_wrappers::thread::spawn( + thread_stack, + static_pointer, + c"blinky", + (riot_sys::THREAD_PRIORITY_MAIN - 1) as _, + (riot_sys::THREAD_CREATE_STACKTEST) as _, +); +``` + +**4. Build and flash your application. Open a serial communication:** +```sh +$ make all flash term +``` + +You should see messages from both threads and the LEDs blinking at different rates. diff --git a/rust06-threads/src/lib.rs b/rust06-threads/src/lib.rs new file mode 100644 index 0000000..a225285 --- /dev/null +++ b/rust06-threads/src/lib.rs @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Christian Amsüss +// SPDX-License-Identifier: Apache-2.0 OR MIT +#![no_std] + +use core::time::Duration; +use riot_wrappers::println; +use riot_wrappers::riot_main; +use riot_wrappers::ztimer::Clock; + +// We are using the LED through a generic "on"/"off" interface. +use switch_hal::OutputSwitch; + +extern crate rust_riotmodules; + +riot_main!(main); + +fn main() { + // Startup delay to ensure the terminal is connected + Clock::sec().sleep(Duration::from_secs(5)); + + println!("Thread example."); + + /* [TASK 1: create the thread here] */ + + let mut led0 = riot_wrappers::led::LED::<0>::new(); + + loop { + println!( + "Thread {}\n", + riot_wrappers::thread::get_pid() + .get_name() + .unwrap_or("unnamed") + ); + + led0.on().unwrap(); + Clock::msec().sleep(Duration::from_millis(100)); + led0.off().unwrap(); + Clock::msec().sleep(Duration::from_millis(900)); + } +} From 7d0af6ff380fbca59ebd580136687e25e7cca5f7 Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 4 Sep 2024 15:35:01 +0200 Subject: [PATCH 09/11] rust*: Notes on language constructs that may not be obvious to newcomers --- rust02-timers/README.md | 4 ++++ rust04-saul/README.md | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/rust02-timers/README.md b/rust02-timers/README.md index 77fc524..c12bcf5 100644 --- a/rust02-timers/README.md +++ b/rust02-timers/README.md @@ -62,6 +62,10 @@ Add a new timer to turn LED1 on after 1 second. let mut led1 = riot_wrappers::led::LED::<1>::new(); ``` +The `::<1>` is a generic argument: +The LED subsystem of RIOT is optimized for low latency to assist in debugging, +and the generic argument ensures that the number is known at build time. + **2. Around the loop, call the [`set_during`](https://rustdoc.etonomy.org/riot_wrappers/ztimer/struct.Clock.html#method.set_during) function, and in the callback, turn on LED1.** ```rust diff --git a/rust04-saul/README.md b/rust04-saul/README.md index 586dd9c..759de17 100644 --- a/rust04-saul/README.md +++ b/rust04-saul/README.md @@ -99,6 +99,11 @@ let accel = accel_sensor println!("Read acceleration: {accel:?}"); ``` +The `{accel:?}` uses Rust's string formatting macros: +`println!` and similar macros expand variables between `{}`. +The `:?` tells the macro to use [Debug](https://doc.rust-lang.org/std/fmt/trait.Debug.html) formatting -- +we need to use it because the "plain" [Display](https://doc.rust-lang.org/std/fmt/trait.Display.html) human-readable format is not available on that type. + **3. Build and flash the application. Open a serial port communication.** ## Task 4 From f0a356be1b5378656198ad9449139a1d4b610567 Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 4 Sep 2024 16:24:41 +0200 Subject: [PATCH 10/11] rust: Update to latest riot-wrappers --- rust01-hello-world/Cargo.toml | 2 +- rust01-hello-world/src/lib.rs | 2 +- rust02-timers/Cargo.toml | 2 +- rust02-timers/README.md | 2 +- rust02-timers/src/lib.rs | 12 ++++++------ rust03-shell/Cargo.toml | 2 +- rust03-shell/src/lib.rs | 2 +- rust04-saul/Cargo.toml | 2 +- rust04-saul/src/lib.rs | 6 +++--- rust05-gpio/Cargo.toml | 2 +- rust05-gpio/README.md | 4 ++-- rust05-gpio/src/lib.rs | 2 +- rust06-threads/Cargo.toml | 2 +- rust06-threads/README.md | 4 ++-- rust06-threads/src/lib.rs | 8 ++++---- 15 files changed, 27 insertions(+), 27 deletions(-) diff --git a/rust01-hello-world/Cargo.toml b/rust01-hello-world/Cargo.toml index 6b6e4d2..9d95a19 100644 --- a/rust01-hello-world/Cargo.toml +++ b/rust01-hello-world/Cargo.toml @@ -13,6 +13,6 @@ crate-type = ["staticlib"] panic = "abort" [dependencies] -riot-wrappers = { version = "0.8", features = [ "set_panic_handler", "panic_handler_format" ] } +riot-wrappers = { version = "0.9.1", features = [ "set_panic_handler", "panic_handler_format" ] } rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } diff --git a/rust01-hello-world/src/lib.rs b/rust01-hello-world/src/lib.rs index 34a4e36..21c1cb3 100644 --- a/rust01-hello-world/src/lib.rs +++ b/rust01-hello-world/src/lib.rs @@ -12,7 +12,7 @@ riot_main!(main); fn main() { // Startup delay to ensure the terminal is connected - Clock::sec().sleep(core::time::Duration::from_secs(5)); + Clock::sec().sleep_extended(core::time::Duration::from_secs(5)); println!("Hello Rust!"); println!("You are running RIOT on a(n) {} board.\n", riot_wrappers::BOARD); diff --git a/rust02-timers/Cargo.toml b/rust02-timers/Cargo.toml index 65aa7f4..f5938b4 100644 --- a/rust02-timers/Cargo.toml +++ b/rust02-timers/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["staticlib"] panic = "abort" [dependencies] -riot-wrappers = { version = "0.8", features = [ "set_panic_handler", "panic_handler_format" ] } +riot-wrappers = { version = "0.9.1", features = [ "set_panic_handler", "panic_handler_format" ] } rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } switch-hal = "0.4.0" diff --git a/rust02-timers/README.md b/rust02-timers/README.md index c12bcf5..491ce93 100644 --- a/rust02-timers/README.md +++ b/rust02-timers/README.md @@ -45,7 +45,7 @@ for _ in 0..10 { **2. Sleep only for 250 ms for each iteration after setting the LED to "on":** ```rust -Clock::msec().sleep(Duration::from_millis(250)); +Clock::msec().sleep_extended(Duration::from_millis(250)); ``` **3. Build and flash the application. Connect to the serial port:** diff --git a/rust02-timers/src/lib.rs b/rust02-timers/src/lib.rs index 2575c48..8cc60cb 100644 --- a/rust02-timers/src/lib.rs +++ b/rust02-timers/src/lib.rs @@ -16,19 +16,19 @@ riot_main!(main); fn main() { // Startup delay to ensure the terminal is connected - Clock::sec().sleep(Duration::from_secs(5)); + Clock::sec().sleep_extended(Duration::from_secs(5)); println!("This is a timers example"); // We can use sleep to just get delays - Clock::sec().sleep(Duration::from_secs(2)); + Clock::sec().sleep_extended(Duration::from_secs(2)); // Many times can be expressed on different timers, but usable ranges and precision vary. - Clock::msec().sleep(Duration::from_secs(2)); + Clock::msec().sleep_extended(Duration::from_secs(2)); println!("Timeout!"); - let mut led0 = riot_wrappers::led::LED::<0>::new(); + let mut led0 = riot_wrappers::led::LED::<0>::new_checked().expect("Our board has an LED0"); for _ in 0..20 { @@ -38,9 +38,9 @@ fn main() { // In future Rust versions we can express this even more clearly // . led0.on().unwrap(); - Clock::msec().sleep(Duration::from_millis(500)); + Clock::msec().sleep_extended(Duration::from_millis(500)); led0.off().unwrap(); - Clock::msec().sleep(Duration::from_millis(500)); + Clock::msec().sleep_extended(Duration::from_millis(500)); } println!("Done!"); diff --git a/rust03-shell/Cargo.toml b/rust03-shell/Cargo.toml index f0d07d9..8e2051b 100644 --- a/rust03-shell/Cargo.toml +++ b/rust03-shell/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["staticlib"] panic = "abort" [dependencies] -riot-wrappers = { version = "0.8", features = [ "set_panic_handler", "panic_handler_format" ] } +riot-wrappers = { version = "0.9.1", features = [ "set_panic_handler", "panic_handler_format" ] } switch-hal = "0.4.0" rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } diff --git a/rust03-shell/src/lib.rs b/rust03-shell/src/lib.rs index bdf5110..452ddf6 100644 --- a/rust03-shell/src/lib.rs +++ b/rust03-shell/src/lib.rs @@ -13,7 +13,7 @@ riot_main!(main); fn main() { use riot_wrappers::shell::CommandList; riot_wrappers::shell::new() - .run_forever_providing_buf(); + .run_forever(); } diff --git a/rust04-saul/Cargo.toml b/rust04-saul/Cargo.toml index efb3d7c..8ab973f 100644 --- a/rust04-saul/Cargo.toml +++ b/rust04-saul/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["staticlib"] panic = "abort" [dependencies] -riot-wrappers = { version = "0.8", features = [ "set_panic_handler", "panic_handler_format" ] } +riot-wrappers = { version = "0.9.1", features = [ "set_panic_handler", "panic_handler_format" ] } switch-hal = "0.4.0" rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } diff --git a/rust04-saul/src/lib.rs b/rust04-saul/src/lib.rs index 00edfa8..77368b0 100644 --- a/rust04-saul/src/lib.rs +++ b/rust04-saul/src/lib.rs @@ -16,10 +16,10 @@ const TEMPERATURE_THRESHOLD: i16 = 2400; // °C * 10^-2 fn main() { // Startup delay to ensure the terminal is connected - Clock::sec().sleep(Duration::from_secs(5)); + Clock::sec().sleep_extended(Duration::from_secs(5)); use switch_hal::OutputSwitch; - let mut led0 = riot_wrappers::led::LED::<0>::new(); + let mut led0 = riot_wrappers::led::LED::<0>::new_checked().expect("Our board has an LED0"); let temp_sensor = RegistryEntry::all() .filter(|e| matches!(e.type_(), Some(Class::Sensor(Some(SensorClass::Temp))))) @@ -44,6 +44,6 @@ fn main() { led0.off().unwrap(); } - Clock::msec().sleep(Duration::from_millis(500)); + Clock::msec().sleep_extended(Duration::from_millis(500)); } } diff --git a/rust05-gpio/Cargo.toml b/rust05-gpio/Cargo.toml index 44db660..31fd5ea 100644 --- a/rust05-gpio/Cargo.toml +++ b/rust05-gpio/Cargo.toml @@ -14,6 +14,6 @@ panic = "abort" [dependencies] embedded-hal = "1.0.0" -riot-wrappers = { version = "0.8", features = [ "set_panic_handler", "panic_handler_format" ] } +riot-wrappers = { version = "0.9.1", features = [ "set_panic_handler", "panic_handler_format" ] } rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } diff --git a/rust05-gpio/README.md b/rust05-gpio/README.md index 115dc26..ca5e78c 100644 --- a/rust05-gpio/README.md +++ b/rust05-gpio/README.md @@ -61,9 +61,9 @@ we can ensure that changing the board will not accidentally drive a pin that rel ```rust loop { led0.set_high(); - Clock::msec().sleep(Duration::from_millis(200)); + Clock::msec().sleep_extended(Duration::from_millis(200)); led0.set_low(); - Clock::msec().sleep(Duration::from_millis(800)); + Clock::msec().sleep_extended(Duration::from_millis(800)); } ``` diff --git a/rust05-gpio/src/lib.rs b/rust05-gpio/src/lib.rs index 6da4b51..a89d253 100644 --- a/rust05-gpio/src/lib.rs +++ b/rust05-gpio/src/lib.rs @@ -19,7 +19,7 @@ riot_main!(main); fn main() { // Startup delay to ensure the terminal is connected - Clock::sec().sleep(Duration::from_secs(5)); + Clock::sec().sleep_extended(Duration::from_secs(5)); println!("GPIOs example."); diff --git a/rust06-threads/Cargo.toml b/rust06-threads/Cargo.toml index 6408fda..ebc8600 100644 --- a/rust06-threads/Cargo.toml +++ b/rust06-threads/Cargo.toml @@ -14,7 +14,7 @@ panic = "abort" [dependencies] riot-sys = "0.7.12" -riot-wrappers = { version = "0.8", features = ["set_panic_handler", "panic_handler_format"] } +riot-wrappers = { version = "0.9.1", features = ["set_panic_handler", "panic_handler_format"] } rust_riotmodules = { path = "../RIOT/sys/rust_riotmodules/" } static_cell = "2.1.0" diff --git a/rust06-threads/README.md b/rust06-threads/README.md index b58eb88..fc838b6 100644 --- a/rust06-threads/README.md +++ b/rust06-threads/README.md @@ -88,9 +88,9 @@ fn blinky_handler() { ); led1.on().unwrap(); - Clock::msec().sleep(Duration::from_millis(20)); + Clock::msec().sleep_extended(Duration::from_millis(20)); led1.off().unwrap(); - Clock::msec().sleep(Duration::from_millis(180)); + Clock::msec().sleep_extended(Duration::from_millis(180)); } } ``` diff --git a/rust06-threads/src/lib.rs b/rust06-threads/src/lib.rs index a225285..79f5f20 100644 --- a/rust06-threads/src/lib.rs +++ b/rust06-threads/src/lib.rs @@ -16,13 +16,13 @@ riot_main!(main); fn main() { // Startup delay to ensure the terminal is connected - Clock::sec().sleep(Duration::from_secs(5)); + Clock::sec().sleep_extended(Duration::from_secs(5)); println!("Thread example."); /* [TASK 1: create the thread here] */ - let mut led0 = riot_wrappers::led::LED::<0>::new(); + let mut led0 = riot_wrappers::led::LED::<0>::new().expect("Our board has an LED0"); loop { println!( @@ -33,8 +33,8 @@ fn main() { ); led0.on().unwrap(); - Clock::msec().sleep(Duration::from_millis(100)); + Clock::msec().sleep_extended(Duration::from_millis(100)); led0.off().unwrap(); - Clock::msec().sleep(Duration::from_millis(900)); + Clock::msec().sleep_extended(Duration::from_millis(900)); } } From 52229d07501abd753c63495dcc379cecb605875a Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 4 Sep 2024 16:24:54 +0200 Subject: [PATCH 11/11] rust: Don't check in lock files --- rust01-hello-world/Cargo.lock | 882 ---------------------------------- 1 file changed, 882 deletions(-) delete mode 100644 rust01-hello-world/Cargo.lock diff --git a/rust01-hello-world/Cargo.lock b/rust01-hello-world/Cargo.lock deleted file mode 100644 index 5549a7c..0000000 --- a/rust01-hello-world/Cargo.lock +++ /dev/null @@ -1,882 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - -[[package]] -name = "bindgen" -version = "0.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex 1.3.0", - "syn 1.0.109", - "which", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "build_const" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "c2rust-asm-casts" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99883a495b2e1ea1c26a2b5fd08ff58490d127b638582cc4a0f7e336ccbea178" - -[[package]] -name = "c2rust-bitfields" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb34f0c0ace43530b2df7f18bc69ee0c4082158aa451ece29602f8c841e73764" -dependencies = [ - "c2rust-bitfields-derive", -] - -[[package]] -name = "c2rust-bitfields-derive" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dd1601a7b828ab874d890e5a895563ca8ad485bdd3d2a359f148c8b72537241" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[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 = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "coap-handler" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a2c21db09a4ce20cdf7153ed88b678f728aa8698109203e7f3087b12628e19" -dependencies = [ - "byteorder", - "coap-message 0.2.3", - "coap-numbers", - "crc 1.8.1", - "serde", - "serde_cbor", - "windowed-infinity", -] - -[[package]] -name = "coap-handler" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8600ae8e54c9be6e0c5273fad0503e12f827742e4e3fea5a521412478d603b72" -dependencies = [ - "coap-message 0.3.2", - "coap-numbers", -] - -[[package]] -name = "coap-message" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc888e15f6be910b58fda4f056f673f58fb9348ea45da014283a14e6d2b58ec" - -[[package]] -name = "coap-message" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e126d86a35f4c5dfcf454da6c9c58a6e703150989e536945ef3813f2bc60565" -dependencies = [ - "num-traits", -] - -[[package]] -name = "coap-numbers" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d78a5634393ab2c11d173d66107200a730e200a3b3ca063c344d4459c90a5f9" - -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -dependencies = [ - "build_const", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "critical-section" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "cstr" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" - -[[package]] -name = "embedded-graphics" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a69991ceb896bd4810a0cf2bcc46fc94b7860573c71f965d8e5b3d66942fed" -dependencies = [ - "byteorder", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "half" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "hello-world" -version = "0.1.0" -dependencies = [ - "riot-wrappers", - "rust_riotmodules", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[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.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "mutex-trait" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4bb1638d419e12f8b1c43d9e639abd0d1424285bdea2f76aa231e233c63cd3a" - -[[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 = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[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" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro2" -version = "1.0.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "riot-sys" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93898cb23235389269f9b8f89308d4e224727184f9b2efd8f5c0242758ad1f70" -dependencies = [ - "bindgen", - "c2rust-asm-casts", - "c2rust-bitfields", - "cty", - "regex", - "serde", - "serde_json", - "shlex 1.3.0", -] - -[[package]] -name = "riot-wrappers" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "007410ae5c976f7263711151b9b85271f8cf729afc05f9aeed1e09c5b6f00aca" -dependencies = [ - "bare-metal", - "coap-handler 0.1.6", - "coap-handler 0.2.0", - "coap-message 0.2.3", - "coap-message 0.3.2", - "coap-numbers", - "cstr", - "embedded-graphics", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "heapless", - "hex", - "mutex-trait", - "nb 0.1.3", - "num-traits", - "pin-project", - "pin-utils", - "rand_core", - "riot-sys", - "shlex 0.1.1", - "switch-hal", - "syn 1.0.109", -] - -[[package]] -name = "rust_riotmodules" -version = "0.1.0" - -[[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.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "serde_json" -version = "1.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -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 = "switch-hal" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a4adc8cbd1726249b161898e48e0f3f1ce74d34dc784cbbc98fba4ed283fbf" -dependencies = [ - "embedded-hal 0.2.7", -] - -[[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 = "syn" -version = "2.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[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 = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windowed-infinity" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9487d1d565a9db59e1fd0b3c2d3f0c277bc375d348a6c46ff2b322917fbc035" -dependencies = [ - "crc 3.2.1", - "digest", - "embedded-io", - "serde", - "serde_cbor", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"