From 2acc06d052d7c73b1ec628ef4f7684d7be1e6ab4 Mon Sep 17 00:00:00 2001 From: chrysn Date: Tue, 24 Jan 2023 15:21:23 +0100 Subject: [PATCH 01/15] ztimer: Make caller provide proof that we're in a thread --- src/ztimer.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ztimer.rs b/src/ztimer.rs index caf98c11..f8ffa411 100644 --- a/src/ztimer.rs +++ b/src/ztimer.rs @@ -16,6 +16,8 @@ use core::convert::TryInto; use riot_sys::ztimer_clock_t; +use crate::thread::ValueInThread; + // Useful for working with durations const NANOS_PER_SEC: u32 = 1_000_000_000; @@ -33,7 +35,7 @@ pub struct Clock(*mut ztimer_clock_t); pub struct Ticks(pub u32); -impl Clock { +impl ValueInThread> { /// Pause the current thread for the duration of ticks in the timer's time scale. /// /// Wraps [ztimer_sleep](https://doc.riot-os.org/group__sys__ztimer.html#gade98636e198f2d571c8acd861d29d360) @@ -49,6 +51,10 @@ impl Clock { /// *very* short delays.". /// /// Wraps [ztimer_spin](https://doc.riot-os.org/group__sys__ztimer.html#ga9de3d9e3290746b856bb23eb2dccaa7c) + /// + /// Note that this would not technically require the self to be a [ValueInThread] (as spinning + /// is doable in an ISR), but it's so discouraged that the Rust wrapper takes the position that + /// it's best done using a [ValueInThread]. #[doc(alias = "ztimer_spin")] pub fn spin_ticks(&self, duration: u32) { unsafe { riot_sys::ztimer_spin(crate::inline_cast_mut(self.0), duration) }; @@ -197,13 +203,13 @@ impl Clock<1000000> { } } -impl embedded_hal::blocking::delay::DelayMs for Clock<1000> { +impl embedded_hal::blocking::delay::DelayMs for ValueInThread> { fn delay_ms(&mut self, ms: u32) { self.sleep_ticks(ms.into()); } } -impl embedded_hal::blocking::delay::DelayUs for Clock<1000000> { +impl embedded_hal::blocking::delay::DelayUs for ValueInThread> { fn delay_us(&mut self, us: u32) { self.sleep_ticks(us); } From 34f078ce0419fb52581662d938fcecd1038ae9c6 Mon Sep 17 00:00:00 2001 From: chrysn Date: Fri, 24 Feb 2023 13:24:13 +0100 Subject: [PATCH 02/15] saul: Make Unit non_exhaustive This is a breaking change. --- src/saul.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/saul.rs b/src/saul.rs index 1e071e8a..5c0024ef 100644 --- a/src/saul.rs +++ b/src/saul.rs @@ -359,6 +359,7 @@ pub enum SensorClass { #[derive(Copy, Clone, Debug)] /// Unit of measurement required to interpret numeric values in a [Phydat] exchanged with a SAUL /// device +#[non_exhaustive] pub enum Unit { /// Note that this means "data has no physical unit", and is distinct from "No unit given", /// which is `Option::::None` as opposed to `Some(Unit::None)`. From 2cf8c8c21b2e74c81a86346c25499daed5e07d22 Mon Sep 17 00:00:00 2001 From: Teufelchen1 Date: Mon, 15 Apr 2024 16:35:37 +0200 Subject: [PATCH 03/15] build: Select heapless-crate with features for GBA support --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 068e9b50..bafc078f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ bare-metal = "1" cstr = "^0.2.11" -heapless = "^0.7" +heapless = { version="0.8", features = ["portable-atomic-unsafe-assume-single-core"] } rand_core_06 = { package = "rand_core", version = "^0.6" } # For nimble UUID parsing and some debug implementations From f6073c70b38bad5b734e12e884cb9bbc414e7325 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 15 Apr 2024 16:53:45 +0200 Subject: [PATCH 04/15] cargo/version: Announce breaking changes --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 068e9b50..93b8f095 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "riot-wrappers" -version = "0.8.3" +version = "0.8.999" # really 0.9.0-alpha.1, but we also try hard to not break realistic 0.8 users who fixed all deprecation warnings and don't hold things wrong. authors = ["Christian Amsüss "] edition = "2021" rust-version = "1.75" From 1167a817f6521661d83013fd2979915f567587a6 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 15 Apr 2024 16:53:58 +0200 Subject: [PATCH 05/15] dependencies: Update heapless This is a breaking change because heapless is a public dependency. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 93b8f095..38b11a97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ bare-metal = "1" cstr = "^0.2.11" -heapless = "^0.7" +heapless = "^0.8" rand_core_06 = { package = "rand_core", version = "^0.6" } # For nimble UUID parsing and some debug implementations From b238672cea4df9533b4111669fe6fed098ec7a24 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 09:24:11 +0200 Subject: [PATCH 06/15] Remove all previously deprecated items --- src/coap_handler/mod.rs | 3 --- src/error.rs | 6 +----- src/gnrc.rs | 4 ++-- src/i2c/mod.rs | 5 ----- src/interrupt.rs | 28 ++-------------------------- src/lib.rs | 6 ------ src/main_module.rs | 11 ----------- src/saul.rs | 28 ---------------------------- src/shell.rs | 14 -------------- src/spi/mod.rs | 2 +- src/thread.rs | 3 +-- src/thread/tokenparts.rs | 9 --------- 12 files changed, 7 insertions(+), 112 deletions(-) diff --git a/src/coap_handler/mod.rs b/src/coap_handler/mod.rs index 65d33a7f..5e223d53 100644 --- a/src/coap_handler/mod.rs +++ b/src/coap_handler/mod.rs @@ -3,6 +3,3 @@ pub mod v0_1; pub mod v0_2; - -#[deprecated(note = "Use through the v0_1 module.")] -pub use v0_1::*; diff --git a/src/error.rs b/src/error.rs index dd0d4284..10252dbf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -25,8 +25,7 @@ pub trait NegativeErrorExt { /// manually implemented newtype around isize that'd be used to represent the Result. #[derive(Debug, PartialEq, Eq)] pub struct NumericError { - #[deprecated(note = "Use the .number() method")] - pub number: isize, + number: isize, } impl NumericError { @@ -56,13 +55,11 @@ impl NumericError { name > 0, "Error names are expected to be positive for conversion into negative error numbers." ); - #[allow(deprecated)] // it's deprecated *pub* NumericError { number: -name } } /// Numeric value of the error pub const fn number(&self) -> isize { - #[allow(deprecated)] // it's deprecated *pub* self.number } @@ -94,7 +91,6 @@ where if self >= Self::zero() { Ok(self) } else { - #[allow(deprecated)] // it's deprecated *pub* Err(NumericError { number: self.try_into().unwrap_or(-(riot_sys::EOVERFLOW as isize)), }) diff --git a/src/gnrc.rs b/src/gnrc.rs index 53839700..088edb80 100644 --- a/src/gnrc.rs +++ b/src/gnrc.rs @@ -5,8 +5,8 @@ pub mod ipv6; pub mod netapi; pub mod netreg; -#[deprecated(note = "moved to gnrc_pktbuf toplevel module")] -pub use crate::gnrc_pktbuf as pktbuf; +#[deprecated(note = "Internally, use gnrc_pktbuf directly")] +pub(crate) use crate::gnrc_pktbuf as pktbuf; use riot_sys::{gnrc_netif_iter, gnrc_netif_t}; diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs index 7bd09683..2526e384 100644 --- a/src/i2c/mod.rs +++ b/src/i2c/mod.rs @@ -25,8 +25,3 @@ impl I2CDevice { I2CDevice { dev } } } - -#[deprecated( - note = "This error type applies to embedded-hal 0.2 only, use it through the impl_0_2 module." -)] -pub use impl_0_2::Error; diff --git a/src/interrupt.rs b/src/interrupt.rs index a458a232..d4034a62 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -27,8 +27,7 @@ /// [`irq_is_in`](https://doc.riot-os.org/group__core__irq.html#ga83decbeef665d955290f730125ef0e3f) /// /// Returns true when called from an interrupt service routine -#[deprecated(note = "Use crate::thread::InThread::new() instead")] -pub fn irq_is_in() -> bool { +pub(crate) fn irq_is_in() -> bool { unsafe { riot_sys::irq_is_in() } } @@ -38,8 +37,7 @@ pub fn irq_is_in() -> bool { /// Returns true if interrupts are currently enabled /// /// Note that this only returns reliable values when called from a thread context. -#[deprecated(note = "use crate::thread::InThread::irq_is_enabled() instead")] -pub fn irq_is_enabled() -> bool { +pub(crate) fn irq_is_enabled() -> bool { unsafe { riot_sys::irq_is_enabled() } } @@ -77,25 +75,3 @@ pub fn free R>(f: F) -> R { unsafe { riot_sys::irq_restore(stored) }; ret } - -/// Wrap a Rust interrupt handler in an extern "C" wrapper that does the post-return cleaups. -/// -/// As with all code executed in interrupt contexts, the wrapped function should not panic. -/// -/// ## Caveats -/// -/// This is Cortex-M specific. -#[deprecated( - note = "See module documentation: This needs to be done manually per platform; it is incomplete as riot-wrappers provides no method of enabling platform specific interrupts, and provides no other access to configure the peripheral through registers. If it is re-introduced, it will likely carry an `InIsr` token into the function." -)] -#[macro_export] -macro_rules! interrupt { - ($isr_name:ident, $rust_handler:expr) => { - #[no_mangle] - pub extern "C" fn $isr_name() -> () { - $rust_handler(); - - unsafe { riot_sys::inline::cortexm_isr_end() }; - } - }; -} diff --git a/src/lib.rs b/src/lib.rs index b08230f6..1d8dd2de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,12 +55,6 @@ pub const BOARD: &'static str = { b }; -/// Name of the RIOT board that is being used -#[deprecated(note = "Access BOARD instead")] -pub const fn board() -> &'static str { - BOARD -} - /// Cast pointers around before passing them in to functions; this is sometimes needed when a /// struct is used from bindgen (`riot_sys::*`) but passed to a C2Rust function that uses its own /// definition (`riot_sys::inline::*`). diff --git a/src/main_module.rs b/src/main_module.rs index c0943517..96dcea3b 100644 --- a/src/main_module.rs +++ b/src/main_module.rs @@ -121,17 +121,6 @@ macro_rules! riot_main { }; } -#[deprecated(note = "Use `riot_main` instead, which takes multiple signatures")] -#[macro_export] -macro_rules! riot_main_with_tokens { - ($main:ident) => { - #[export_name = "main"] - pub extern "C" fn c_main() -> i32 { - unsafe { <_ as $crate::main::UsableAsMain<_>>::call_main(&$main) } - } - }; -} - /// A result trait for main methods, analogous to std::process::Termination pub trait Termination { fn report(self) -> i32; diff --git a/src/saul.rs b/src/saul.rs index 275812fd..1cd8ab34 100644 --- a/src/saul.rs +++ b/src/saul.rs @@ -393,18 +393,6 @@ pub enum Unit { } impl Unit { - // Note that on the C side the code still uses the aliases on the C side -- they're deprecated, - // but we'd need to introduce a marker, and given they'll stay deprecated on C for a release, - // we can just switch over before they go. - #[deprecated(note = "Use the GForce variant instead")] - pub const G: Self = Unit::GForce; - #[allow(non_upper_case_globals)] - #[deprecated(note = "Use the Gram variant instead")] - pub const Gr: Self = Unit::Gram; - #[allow(non_upper_case_globals)] - #[deprecated(note = "Use the Gauss variant instead")] - pub const Gs: Self = Unit::Gauss; - fn from_c(input: u8) -> Option { match input as _ { riot_sys::UNIT_NONE => Some(Unit::None), @@ -485,22 +473,6 @@ impl Unit { }) as _ } - /// String representation of a given unit (e.g. `V` or `m`) - #[deprecated( - note = "RIOT's mechanism changed; this returns None unconditionally, use .name_owned() instead" - )] - pub fn name(self) -> Option<&'static str> { - None - } - - /// Like [`.name()`](Unit::name), but with additional names like "none" or "time". - #[deprecated( - note = "RIOT's mechanism changed; this returns None unconditionally, use .name_owned() instead" - )] - pub fn name_verbose(self) -> Option<&'static str> { - None - } - /// String representation of a given unit (e.g. `V`, `m`, `none` or `time`) #[doc(alias = "phydat_unit_write")] pub fn name_owned(self) -> Option> { diff --git a/src/shell.rs b/src/shell.rs index 03c5d6a4..3f995177 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -136,13 +136,6 @@ pub trait CommandList ! { // unsafe: See unsafe in run_any where it's called self.run_any(linebuffer, |built, buf, len| unsafe { @@ -151,13 +144,6 @@ pub trait CommandList ! { - self.run_forever_with_buf(linebuffer) - } - /// Run the shell prompt on stdio /// /// See [shell_run_forever] for details. diff --git a/src/spi/mod.rs b/src/spi/mod.rs index f8ed4410..53db151f 100644 --- a/src/spi/mod.rs +++ b/src/spi/mod.rs @@ -4,7 +4,7 @@ use riot_sys::{ spi_acquire, spi_clk_t, spi_cs_t, spi_mode_t, spi_release, spi_t, spi_transfer_bytes, }; -pub struct SPIDevice(#[deprecated(note = "Use constructor instead")] pub spi_t); +pub struct SPIDevice(spi_t); pub struct AcquiredSPI<'a> { device: &'a mut SPIDevice, diff --git a/src/thread.rs b/src/thread.rs index aa9e964a..93e950bb 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -23,8 +23,7 @@ pub use riot_c::*; mod tokenparts; #[cfg(doc)] pub use tokenparts::TokenParts; -#[allow(deprecated)] -pub use tokenparts::{EndToken, InIsr, InThread, StartToken, TerminationToken, ValueInThread}; +pub use tokenparts::{EndToken, InIsr, InThread, StartToken, ValueInThread}; mod stack_stats; pub use stack_stats::{StackStats, StackStatsError}; diff --git a/src/thread/tokenparts.rs b/src/thread/tokenparts.rs index ccd4afc8..a3644c74 100644 --- a/src/thread/tokenparts.rs +++ b/src/thread/tokenparts.rs @@ -18,9 +18,6 @@ pub struct EndToken { _not_send: PhantomData<*const ()>, } -#[deprecated(note = "Renamed to EndToken")] -pub type TerminationToken = EndToken; - /// A [StartToken] that has possibly already lost some of its properties. /// /// Note that while this item shows up in the documentation, the type is actually hidden and only @@ -186,11 +183,6 @@ impl TokenParts { _not_send: PhantomData, } } - - #[deprecated(note = "Renamed to can_end")] - pub fn termination(self) -> EndToken { - self.can_end() - } } /// Zero-size statement that the current code is not running in an interrupt @@ -217,7 +209,6 @@ impl InThread { /// Note that this is actually running code; to avoid that, call [`TokenParts::in_thread()`], /// which is a purely type-level procedure. pub fn new() -> Result { - #[allow(deprecated)] // It's deprecatedly pub match crate::interrupt::irq_is_in() { true => Err(unsafe { InIsr::new_unchecked() }), false => Ok(unsafe { InThread::new_unchecked() }), From c75bd1cb4fb1bed07ac45d9b68a8f81da7f2b1c4 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 09:26:47 +0200 Subject: [PATCH 07/15] shell: Remove _providing_buf suffix from names, making the old versions deprecated aliases --- src/shell.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/shell.rs b/src/shell.rs index 3f995177..7d15cf02 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -151,10 +151,9 @@ pub trait CommandList()` to alter that. The method will be renamed to - /// `run_forever` once that name is free. + /// trait type; use `.with_buffer_size::<>()` to alter that. #[doc(alias = "shell_run_forever")] - fn run_forever_providing_buf(&mut self) -> ! { + fn run_forever(&mut self) -> ! { let mut linebuffer = [0; BUFSIZE]; self.run_forever_with_buf(&mut linebuffer) } @@ -166,14 +165,23 @@ pub trait CommandList()` to alter that. The method will be renamed to - /// `run_once` once that name is free. + /// trait type; use `.with_buffer_size::<>()` to alter that. #[doc(alias = "shell_run_once")] - fn run_once_providing_buf(&mut self) { + fn run_once(&mut self) { let mut linebuffer = [0; BUFSIZE]; self.run_once_with_buf(&mut linebuffer) } + #[deprecated(note = "Renamed to run_forever", since = "0.9")] + fn run_forever_providing_buf(&mut self) -> ! { + self.run_forever() + } + + #[deprecated(note = "Renamed to run_once", since = "0.9")] + fn run_once_providing_buf(&mut self) { + self.run_once() + } + /// Extend the list of commands by an additional one. /// /// The handler will be called every time the command is entered, and is passed the arguments From 118b093cf02b726fdbbc5b6f260fd9ab71f38665 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 09:56:40 +0200 Subject: [PATCH 08/15] Change `!` in associated error types to Infallible The `Never` helper still exists, because it is necessary to implement traits such as Termination for `!`, and to express that an input closure must not terminate, but the public error types are changed. While this is a breaking change that was not preceded by a deprecation, it is unlikely people match on the precise type (and all error conversions should be implemented or implementable on both types). --- src/adc.rs | 6 +++--- src/gnrc/netreg.rs | 2 +- src/gpio/impl_0_2.rs | 32 ++++++++++++++++---------------- src/gpio/mod.rs | 2 +- src/led.rs | 16 ++++++++-------- src/lib.rs | 1 - src/main_module.rs | 6 +++--- src/microbit.rs | 6 +++--- src/saul/registration.rs | 4 ++-- src/spi/mod.rs | 4 ++-- src/thread/tokenparts.rs | 2 +- 11 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index d3567917..febc92c5 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,4 +1,4 @@ -use crate::Never; +use core::convert::Infallible; pub struct ADCLine(riot_sys::adc_t); @@ -43,9 +43,9 @@ impl embedded_hal_0_2::adc::Channel for ADCLine { } impl embedded_hal_0_2::adc::OneShot for ADC { - type Error = Never; + type Error = Infallible; - fn read(&mut self, pin: &mut ADCLine) -> nb::Result { + fn read(&mut self, pin: &mut ADCLine) -> nb::Result { // Sorry, blocking still Ok(unsafe { riot_sys::adc_sample(pin.0, self.resolution) }) } diff --git a/src/gnrc/netreg.rs b/src/gnrc/netreg.rs index 573bf1b2..ad6bdaf9 100644 --- a/src/gnrc/netreg.rs +++ b/src/gnrc/netreg.rs @@ -25,7 +25,7 @@ type PktsnipPort = crate::msg::v2::SendPort< /// used once more (with the risk that messages from the old registration arrive in the new one, /// which is wrong correctness-wise but safe because it'll still be a pointer to a pktsnip). #[cfg(feature = "with_msg_v2")] -pub fn register_for_messages crate::Never>( +pub fn register_for_messages crate::never::Never>( grant: PktsnipPort, nettype: riot_sys::gnrc_nettype_t, demux_ctx: u32, diff --git a/src/gpio/impl_0_2.rs b/src/gpio/impl_0_2.rs index 0381aa35..ebf2e2c5 100644 --- a/src/gpio/impl_0_2.rs +++ b/src/gpio/impl_0_2.rs @@ -3,70 +3,70 @@ use super::*; use embedded_hal_0_2::digital::v2::{InputPin, OutputPin, ToggleableOutputPin}; impl InputPin for InputGPIO { - type Error = Never; + type Error = Infallible; - fn is_high(&self) -> Result { + fn is_high(&self) -> Result { Ok(unsafe { gpio_read(self.to_c()) } != 0) } - fn is_low(&self) -> Result { + fn is_low(&self) -> Result { Ok(unsafe { gpio_read(self.to_c()) } == 0) } } impl OutputPin for OutputGPIO { - type Error = Never; + type Error = Infallible; - fn set_high(&mut self) -> Result<(), Never> { + fn set_high(&mut self) -> Result<(), Infallible> { unsafe { gpio_set(self.to_c()) }; Ok(()) } - fn set_low(&mut self) -> Result<(), Never> { + fn set_low(&mut self) -> Result<(), Infallible> { unsafe { gpio_clear(self.to_c()) }; Ok(()) } } impl ToggleableOutputPin for OutputGPIO { - type Error = Never; + type Error = Infallible; - fn toggle(&mut self) -> Result<(), Never> { + fn toggle(&mut self) -> Result<(), Infallible> { unsafe { gpio_toggle(self.to_c()) }; Ok(()) } } impl InputPin for InOutGPIO { - type Error = Never; + type Error = Infallible; - fn is_high(&self) -> Result { + fn is_high(&self) -> Result { Ok(unsafe { gpio_read(self.to_c()) } != 0) } - fn is_low(&self) -> Result { + fn is_low(&self) -> Result { Ok(unsafe { gpio_read(self.to_c()) } == 0) } } impl OutputPin for InOutGPIO { - type Error = Never; + type Error = Infallible; - fn set_high(&mut self) -> Result<(), Never> { + fn set_high(&mut self) -> Result<(), Infallible> { unsafe { gpio_set(self.to_c()) }; Ok(()) } - fn set_low(&mut self) -> Result<(), Never> { + fn set_low(&mut self) -> Result<(), Infallible> { unsafe { gpio_clear(self.to_c()) }; Ok(()) } } impl ToggleableOutputPin for InOutGPIO { - type Error = Never; + type Error = Infallible; - fn toggle(&mut self) -> Result<(), Never> { + fn toggle(&mut self) -> Result<(), Infallible> { unsafe { gpio_toggle(self.to_c()) }; Ok(()) } diff --git a/src/gpio/mod.rs b/src/gpio/mod.rs index 41bf5e92..b6a2c971 100644 --- a/src/gpio/mod.rs +++ b/src/gpio/mod.rs @@ -10,7 +10,7 @@ mod impl_1; use riot_sys::{gpio_clear, gpio_mode_t, gpio_read, gpio_set, gpio_t, gpio_toggle, gpio_write}; use crate::error::NegativeErrorExt; -use crate::Never; +use core::convert::Infallible; /// A Rust representation of RIOT's gpio_t, representing a single pin in no particular /// configuration. diff --git a/src/led.rs b/src/led.rs index 4282ebb7..2f3cfb20 100644 --- a/src/led.rs +++ b/src/led.rs @@ -1,6 +1,6 @@ //! Wrappers for the `LEDn_{ON,OFF,TOGGLE}` macros -use crate::Never; +use core::convert::Infallible; /// The Ith LED (calling the `LED_{ON,OFF,TOGGLE}` macros). /// @@ -21,7 +21,7 @@ impl LED { } impl switch_hal::OutputSwitch for LED { - type Error = Never; + type Error = Infallible; fn on(&mut self) -> Result<(), Self::Error> { use embedded_hal_0_2::digital::v2::OutputPin; @@ -35,7 +35,7 @@ impl switch_hal::OutputSwitch for LED { } impl switch_hal::ToggleableOutputSwitch for LED { - type Error = Never; + type Error = Infallible; fn toggle(&mut self) -> Result<(), Self::Error> { ::toggle(self) @@ -43,9 +43,9 @@ impl switch_hal::ToggleableOutputSwitch for LED { } impl embedded_hal_0_2::digital::v2::OutputPin for LED { - type Error = Never; + type Error = Infallible; - fn set_high(&mut self) -> Result<(), Never> { + fn set_high(&mut self) -> Result<(), Infallible> { // unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs) unsafe { match I { @@ -63,7 +63,7 @@ impl embedded_hal_0_2::digital::v2::OutputPin for LED { Ok(()) } - fn set_low(&mut self) -> Result<(), Never> { + fn set_low(&mut self) -> Result<(), Infallible> { // unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs) unsafe { match I { @@ -83,9 +83,9 @@ impl embedded_hal_0_2::digital::v2::OutputPin for LED { } impl embedded_hal_0_2::digital::v2::ToggleableOutputPin for LED { - type Error = Never; + type Error = Infallible; - fn toggle(&mut self) -> Result<(), Never> { + fn toggle(&mut self) -> Result<(), Infallible> { // unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs) unsafe { match I { diff --git a/src/lib.rs b/src/lib.rs index 1d8dd2de..a1616cbf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,6 @@ pub mod error; mod helpers; mod never; -use never::Never; /// The identifier of the RIOT board the program is being built for (`RIOT_BOARD` in C). #[doc(alias = "RIOT_BOARD")] diff --git a/src/main_module.rs b/src/main_module.rs index 96dcea3b..7c8196d9 100644 --- a/src/main_module.rs +++ b/src/main_module.rs @@ -144,12 +144,12 @@ impl Termination for Result<(), E> { fn report(self) -> i32 { match self { Ok(()) => ().report(), - Err(err) => Err::(err).report(), + Err(err) => Err::(err).report(), } } } -impl Termination for crate::Never { +impl Termination for crate::never::Never { fn report(self) -> i32 { self } @@ -161,7 +161,7 @@ impl Termination for core::convert::Infallible { } } -impl Termination for Result { +impl Termination for Result { fn report(self) -> i32 { match self { Err(err) => { diff --git a/src/microbit.rs b/src/microbit.rs index f451917e..a0e4a924 100644 --- a/src/microbit.rs +++ b/src/microbit.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ drawable::Pixel, geometry::Point, geometry::Size, pixelcolor::BinaryColor, DrawTarget, }; -use crate::Never; +use core::convert::Infallible; /// The 5x5 LED matrix of the micro:bit boards /// @@ -24,9 +24,9 @@ impl LEDs { } impl DrawTarget for LEDs { - type Error = Never; + type Error = Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Never> { + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Infallible> { let Pixel(Point { x, y }, color) = pixel; let setter = match color { diff --git a/src/saul/registration.rs b/src/saul/registration.rs index 74c264cd..2993ecb9 100644 --- a/src/saul/registration.rs +++ b/src/saul/registration.rs @@ -14,7 +14,7 @@ use riot_sys::libc; use super::{Class, Phydat}; use crate::error::NegativeErrorExt; -use crate::Never; +use core::convert::Infallible; /// The single error read and write operations may produce; corresponds to an `-ECANCELED`. /// (-ENOTSUP is expressed by not having support for the operation in the first place, indicated by @@ -229,7 +229,7 @@ pub fn register_and_then( driver: &Driver, device: &DEV, name: Option<&CStr>, - f: impl FnOnce() -> Never, + f: impl FnOnce() -> crate::never::Never, ) -> ! where DEV: Sized + Sync + 'static, diff --git a/src/spi/mod.rs b/src/spi/mod.rs index 53db151f..b3740b84 100644 --- a/src/spi/mod.rs +++ b/src/spi/mod.rs @@ -1,4 +1,4 @@ -use crate::Never; +use core::convert::Infallible; use embedded_hal_0_2::blocking; use riot_sys::{ spi_acquire, spi_clk_t, spi_cs_t, spi_mode_t, spi_release, spi_t, spi_transfer_bytes, @@ -65,7 +65,7 @@ impl SPIDevice { // } impl<'a> blocking::spi::Transfer for AcquiredSPI<'a> { - type Error = Never; + type Error = Infallible; fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { unsafe { diff --git a/src/thread/tokenparts.rs b/src/thread/tokenparts.rs index a3644c74..057e2787 100644 --- a/src/thread/tokenparts.rs +++ b/src/thread/tokenparts.rs @@ -149,7 +149,7 @@ impl TokenParts { // would be sent to again. pub fn with_message_queue< const N: usize, - F: FnOnce(TokenParts) -> crate::Never, + F: FnOnce(TokenParts) -> crate::never::Never, >( self, f: F, From 2191ddfc582fc486b7f87ca5c0c3ac4bc42c3361 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 10:13:06 +0200 Subject: [PATCH 09/15] Drop support for embedded-hal 0.2 except where 1.0 has no traits for it (ADC) SPI is not dropped either because the 1.0 trait includes acquisition in the trait (which makes it not trivial to port). Closes: https://github.com/RIOT-OS/rust-riot-wrappers/issues/65 --- src/gpio/impl_0_2.rs | 73 ----------------------------- src/gpio/mod.rs | 1 - src/i2c/impl_0_2.rs | 106 ------------------------------------------- src/i2c/mod.rs | 1 - src/led.rs | 32 ++----------- src/ztimer/mod.rs | 12 ----- 6 files changed, 3 insertions(+), 222 deletions(-) delete mode 100644 src/gpio/impl_0_2.rs delete mode 100644 src/i2c/impl_0_2.rs diff --git a/src/gpio/impl_0_2.rs b/src/gpio/impl_0_2.rs deleted file mode 100644 index ebf2e2c5..00000000 --- a/src/gpio/impl_0_2.rs +++ /dev/null @@ -1,73 +0,0 @@ -use super::*; - -use embedded_hal_0_2::digital::v2::{InputPin, OutputPin, ToggleableOutputPin}; - -impl InputPin for InputGPIO { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(unsafe { gpio_read(self.to_c()) } != 0) - } - - fn is_low(&self) -> Result { - Ok(unsafe { gpio_read(self.to_c()) } == 0) - } -} - -impl OutputPin for OutputGPIO { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Infallible> { - unsafe { gpio_set(self.to_c()) }; - Ok(()) - } - - fn set_low(&mut self) -> Result<(), Infallible> { - unsafe { gpio_clear(self.to_c()) }; - Ok(()) - } -} - -impl ToggleableOutputPin for OutputGPIO { - type Error = Infallible; - - fn toggle(&mut self) -> Result<(), Infallible> { - unsafe { gpio_toggle(self.to_c()) }; - Ok(()) - } -} - -impl InputPin for InOutGPIO { - type Error = Infallible; - - fn is_high(&self) -> Result { - Ok(unsafe { gpio_read(self.to_c()) } != 0) - } - - fn is_low(&self) -> Result { - Ok(unsafe { gpio_read(self.to_c()) } == 0) - } -} - -impl OutputPin for InOutGPIO { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Infallible> { - unsafe { gpio_set(self.to_c()) }; - Ok(()) - } - - fn set_low(&mut self) -> Result<(), Infallible> { - unsafe { gpio_clear(self.to_c()) }; - Ok(()) - } -} - -impl ToggleableOutputPin for InOutGPIO { - type Error = Infallible; - - fn toggle(&mut self) -> Result<(), Infallible> { - unsafe { gpio_toggle(self.to_c()) }; - Ok(()) - } -} diff --git a/src/gpio/mod.rs b/src/gpio/mod.rs index b6a2c971..6e0bc4dc 100644 --- a/src/gpio/mod.rs +++ b/src/gpio/mod.rs @@ -4,7 +4,6 @@ //! the [embedded_hal::digital::v2] traits. As recommended for infallible types, they also //! provide identically named direct methods, which (for input pins) also work on shared reference. -mod impl_0_2; mod impl_1; use riot_sys::{gpio_clear, gpio_mode_t, gpio_read, gpio_set, gpio_t, gpio_toggle, gpio_write}; diff --git a/src/i2c/impl_0_2.rs b/src/i2c/impl_0_2.rs deleted file mode 100644 index b3c0e98e..00000000 --- a/src/i2c/impl_0_2.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! Implementation of embedded-hal 0.2's I2C for [I2CDevice] -//! -//! As the implementation is on the [I2CDevice directly], all that is in this module is the -//! suitable [Error] type. - -use embedded_hal_0_2::blocking; - -use super::*; - -use riot_sys::libc; -use riot_sys::{i2c_acquire, i2c_read_bytes, i2c_release, i2c_write_bytes}; - -#[derive(Debug)] -#[non_exhaustive] -pub enum Error { - AcquireError, - WriteError(i32), - ReadError(i32), -} - -impl blocking::i2c::WriteRead for I2CDevice { - type Error = Error; - - fn write_read( - &mut self, - address: u8, - bytes: &[u8], - buffer: &mut [u8], - ) -> Result<(), Self::Error> { - unsafe { i2c_acquire(self.dev) }; - let err = unsafe { - i2c_write_bytes( - self.dev, - address as u16, - bytes.as_ptr() as *const libc::c_void, - bytes.len() as _, - 0, - ) - }; - if err != 0 { - unsafe { i2c_release(self.dev) }; - return Err(Error::WriteError(err)); - } - let err = unsafe { - i2c_read_bytes( - self.dev, - address as u16, - buffer.as_ptr() as *mut libc::c_void, - buffer.len() as _, - 0, - ) - }; - if err != 0 { - unsafe { i2c_release(self.dev) }; - return Err(Error::ReadError(err)); - } - unsafe { i2c_release(self.dev) }; - Ok(()) - } -} - -impl blocking::i2c::Write for I2CDevice { - type Error = Error; - - fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { - unsafe { i2c_acquire(self.dev) }; - let err = unsafe { - i2c_write_bytes( - self.dev, - address as u16, - bytes.as_ptr() as *const libc::c_void, - bytes.len() as _, - 0, - ) - }; - if err != 0 { - unsafe { i2c_release(self.dev) }; - return Err(Error::WriteError(err)); - } - unsafe { i2c_release(self.dev) }; - Ok(()) - } -} - -impl blocking::i2c::Read for I2CDevice { - type Error = Error; - - fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { - unsafe { i2c_acquire(self.dev) }; - let err = unsafe { - i2c_read_bytes( - self.dev, - address as u16, - buffer.as_ptr() as *mut libc::c_void, - buffer.len() as _, - 0, - ) - }; - if err != 0 { - unsafe { i2c_release(self.dev) }; - return Err(Error::ReadError(err)); - } - unsafe { i2c_release(self.dev) }; - Ok(()) - } -} diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs index 2526e384..93afc04a 100644 --- a/src/i2c/mod.rs +++ b/src/i2c/mod.rs @@ -1,6 +1,5 @@ //! Controlling the I²C bus -pub mod impl_0_2; pub mod impl_1; use riot_sys::i2c_t; diff --git a/src/led.rs b/src/led.rs index 2f3cfb20..c61cd1bb 100644 --- a/src/led.rs +++ b/src/led.rs @@ -7,10 +7,6 @@ use core::convert::Infallible; /// The preferred interface for turning a LED on and off is [switch_hal::OutputSwitch]. /// /// LEDs are accessible safely; any not implemented on a board are silently ignored. -/// -/// LEDs are wrapped into embedded-hal 0.2 GPIOs for compatibility reasons (but that integration is -/// discontinued with embedded-hal 1.0); GPIO is interpreted such that "high" is having the LED on, -/// and "low" is off. pub struct LED(()); impl LED { @@ -24,28 +20,6 @@ impl switch_hal::OutputSwitch for LED { type Error = Infallible; fn on(&mut self) -> Result<(), Self::Error> { - use embedded_hal_0_2::digital::v2::OutputPin; - self.set_high() - } - - fn off(&mut self) -> Result<(), Self::Error> { - use embedded_hal_0_2::digital::v2::OutputPin; - self.set_low() - } -} - -impl switch_hal::ToggleableOutputSwitch for LED { - type Error = Infallible; - - fn toggle(&mut self) -> Result<(), Self::Error> { - ::toggle(self) - } -} - -impl embedded_hal_0_2::digital::v2::OutputPin for LED { - type Error = Infallible; - - fn set_high(&mut self) -> Result<(), Infallible> { // unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs) unsafe { match I { @@ -63,7 +37,7 @@ impl embedded_hal_0_2::digital::v2::OutputPin for LED { Ok(()) } - fn set_low(&mut self) -> Result<(), Infallible> { + fn off(&mut self) -> Result<(), Self::Error> { // unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs) unsafe { match I { @@ -82,10 +56,10 @@ impl embedded_hal_0_2::digital::v2::OutputPin for LED { } } -impl embedded_hal_0_2::digital::v2::ToggleableOutputPin for LED { +impl switch_hal::ToggleableOutputSwitch for LED { type Error = Infallible; - fn toggle(&mut self) -> Result<(), Infallible> { + fn toggle(&mut self) -> Result<(), Self::Error> { // unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs) unsafe { match I { diff --git a/src/ztimer/mod.rs b/src/ztimer/mod.rs index b6916f6d..b984b1a7 100644 --- a/src/ztimer/mod.rs +++ b/src/ztimer/mod.rs @@ -213,18 +213,6 @@ impl Clock<1000000> { } } -impl embedded_hal_0_2::blocking::delay::DelayMs for Clock<1000> { - fn delay_ms(&mut self, ms: u32) { - self.sleep_ticks(ms.into()); - } -} - -impl embedded_hal_0_2::blocking::delay::DelayUs for Clock<1000000> { - fn delay_us(&mut self, us: u32) { - self.sleep_ticks(us); - } -} - #[cfg(all(feature = "embedded-hal-async", riot_module_ztimer_usec))] /// Struct that provides the [embedded_hal_async::delay::DelayNs] trait /// From f0d3e1587313c60f9e4a90d029f0a2f16edfd674 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 10:29:12 +0200 Subject: [PATCH 10/15] Drop support for older coap-{handler,message} traits --- Cargo.toml | 2 - src/coap_handler/mod.rs | 1 - src/coap_handler/v0_1.rs | 115 ----------------------------------- src/coap_message/impl_0_2.rs | 85 -------------------------- src/coap_message/mod.rs | 1 - 5 files changed, 204 deletions(-) delete mode 100644 src/coap_handler/v0_1.rs delete mode 100644 src/coap_message/impl_0_2.rs diff --git a/Cargo.toml b/Cargo.toml index 38b11a97..308a0d75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,9 +40,7 @@ coap-numbers = "^0.2.0" embedded-graphics = "0.6" -coap-message-0-2 = { package = "coap-message", version = "^0.2.3" } coap-message-0-3 = { package = "coap-message", version = "^0.3.0" } -coap-handler-0-1 = { package = "coap-handler", version = "^0.1.4" } coap-handler-0-2 = { package = "coap-handler", version = "^0.2.0" } embedded-nal = { version = "0.6.0", optional = true } embedded-nal-tcpextensions = { version = "0.1", optional = true } diff --git a/src/coap_handler/mod.rs b/src/coap_handler/mod.rs index 5e223d53..91999242 100644 --- a/src/coap_handler/mod.rs +++ b/src/coap_handler/mod.rs @@ -1,5 +1,4 @@ //! This module provides a wrappers around a coap_handler::Handler in different versions, all of //! which can be registered at a RIOT GcoapHandler. -pub mod v0_1; pub mod v0_2; diff --git a/src/coap_handler/v0_1.rs b/src/coap_handler/v0_1.rs deleted file mode 100644 index e64bfbbe..00000000 --- a/src/coap_handler/v0_1.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! This module provides a wrapper around a coap_handler::Handler that can be registered at a RIOT -//! GcoapHandler. - -use core::convert::TryInto; - -use coap_handler_0_1::{Attribute, Handler, Record, Reporting}; - -use coap_message_0_2::{MutableWritableMessage, ReadableMessage}; - -use crate::coap_message::ResponseMessage; -use crate::gcoap::PacketBuffer; - -/// Adapter to get a [crate::gcoap::Handler] from a more generic [coap_handler::Handler], typically -/// to register it through a [crate::gcoap::SingleHandlerListener]. -pub struct GcoapHandler(pub H) -where - H: Handler; - -impl crate::gcoap::Handler for GcoapHandler -where - H: Handler, -{ - fn handle(&mut self, pkt: &mut PacketBuffer) -> isize { - let request_data = self.0.extract_request_data(pkt); - let mut lengthwrapped = ResponseMessage::new(pkt); - self.0.build_response(&mut lengthwrapped, request_data); - lengthwrapped.finish() - } -} - -impl crate::gcoap::WithLinkEncoder for GcoapHandler -where - H: Handler + Reporting, -{ - fn encode(&self, writer: &mut crate::gcoap::LinkEncoder) { - for record in self.0.report() { - writer.write_comma_maybe(); - writer.write(b"<"); - for pathelement in record.path() { - writer.write(b"/"); - writer.write(pathelement.as_ref().as_bytes()); - } - writer.write(b">"); - if let Some(rel) = record.rel() { - // Not trying to be smart about whether or not we need the quotes - writer.write(b";rel=\""); - writer.write(rel.as_bytes()); - writer.write(b"\""); - } - for attr in record.attributes() { - use Attribute::*; - match attr { - Observable => writer.write(b";obs"), - Interface(i) => { - writer.write(b";if=\""); - writer.write(i.as_bytes()); - writer.write(b"\""); - } - ResourceType(r) => { - writer.write(b";rt=\""); - writer.write(r.as_bytes()); - writer.write(b"\""); - } - // FIXME: deduplicate with what's somewhere in coap-handler-implementations; - // implement remaining items - _ => (), - } - } - } - } -} - -/// Blanket implementation for mutex wrapped resources -/// -/// This is useful in combination with the defauilt implementation for Option as well. -impl<'b, H> Handler for &'b crate::mutex::Mutex -where - H: Handler, -{ - type RequestData = Option; - - fn extract_request_data<'a>(&mut self, request: &'a impl ReadableMessage) -> Self::RequestData { - self.try_lock().map(|mut h| h.extract_request_data(request)) - } - - fn estimate_length(&mut self, request: &Self::RequestData) -> usize { - if let Some(r) = request { - if let Some(mut s) = self.try_lock() { - return s.estimate_length(r); - } - } - - 1 - } - - fn build_response( - &mut self, - response: &mut impl MutableWritableMessage, - request: Self::RequestData, - ) { - if let Some(r) = request { - if let Some(mut s) = self.try_lock() { - return s.build_response(response, r); - } - } - - response.set_code( - coap_numbers::code::SERVICE_UNAVAILABLE - .try_into() - .map_err(|_| "Message type can't even exprss Service Unavailable") - .unwrap(), - ); - response.set_payload(b""); - } -} diff --git a/src/coap_message/impl_0_2.rs b/src/coap_message/impl_0_2.rs deleted file mode 100644 index c908cf09..00000000 --- a/src/coap_message/impl_0_2.rs +++ /dev/null @@ -1,85 +0,0 @@ -use coap_message_0_2::{ - MessageOption, MinimalWritableMessage, MutableWritableMessage, ReadableMessage, - WithSortedOptions, -}; - -impl<'a> MessageOption for super::MessageOption<'a> { - fn number(&self) -> u16 { - self.number - } - - fn value(&self) -> &[u8] { - self.value - } -} - -impl WithSortedOptions for super::PacketBuffer { - // valid because gcoap just reads options from the message where they are stored in sequence -} - -impl ReadableMessage for super::PacketBuffer { - type Code = u8; - type OptionsIter<'a> = super::OptionsIterator<'a>; - type MessageOption<'a> = super::MessageOption<'a>; - - fn code(&self) -> Self::Code { - self.get_code_raw() - } - - fn payload(&self) -> &[u8] { - self.payload() - } - - fn options(&self) -> Self::OptionsIter<'_> { - super::OptionsIterator(self.opt_iter()) - } -} - -impl<'a> MinimalWritableMessage for super::ResponseMessage<'a> { - type Code = u8; - type OptionNumber = u16; - - fn set_code(&mut self, code: Self::Code) { - self.message.set_code_raw(code); - } - - fn add_option(&mut self, number: Self::OptionNumber, value: &[u8]) { - if self.payload_written.is_some() { - panic!("Options can not be added after payload was added"); - } - self.message - .opt_add_opaque(number.into(), value) - .expect("Options exceed allocated buffer"); - } - - fn set_payload(&mut self, data: &[u8]) { - self.payload_mut_with_len(data.len()).copy_from_slice(data); - self.truncate(data.len()); - } -} - -impl<'a> MutableWritableMessage for super::ResponseMessage<'a> { - fn available_space(&self) -> usize { - self.message.payload().len() - } - - fn payload_mut(&mut self) -> &mut [u8] { - self.payload_written = Some(0); - let payload = self.message.payload_mut(); - payload[0] = 0xff; - &mut payload[1..] - } - - fn truncate(&mut self, len: usize) { - self.payload_written = Some(len); - } - - fn mutate_options(&mut self, mut callback: F) - where - F: FnMut(Self::OptionNumber, &mut [u8]), - { - for (opt_num, slice) in self.message.opt_iter_mut() { - callback(opt_num.into(), slice); - } - } -} diff --git a/src/coap_message/mod.rs b/src/coap_message/mod.rs index 5140e54a..dd91968c 100644 --- a/src/coap_message/mod.rs +++ b/src/coap_message/mod.rs @@ -1,7 +1,6 @@ //! This module implements [coap_message::ReadableMessage] for, and a wrapper that provides //! [coap_message::WritableMessage] around RIOT's coap_pkt_t. -mod impl_0_2; mod impl_0_3; use crate::gcoap::{PacketBuffer, PacketBufferOptIter}; From b99e8085f206f5ec45da921320429654c26f566b Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 10:32:33 +0200 Subject: [PATCH 11/15] Drop support for older embedded-nal-async traits --- Cargo.toml | 3 +- src/socket.rs | 72 ---------------------------- src/socket_embedded_nal_async_udp.rs | 3 -- 3 files changed, 1 insertion(+), 77 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 308a0d75..2af6f8f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ coap-message-0-3 = { package = "coap-message", version = "^0.3.0" } coap-handler-0-2 = { package = "coap-handler", version = "^0.2.0" } embedded-nal = { version = "0.6.0", optional = true } embedded-nal-tcpextensions = { version = "0.1", optional = true } -embedded-nal-async = { version = "0.6", optional = true } embedded-nal-async-0-7 = { package = "embedded-nal-async", version = "0.7.1", optional = true } embedded-io-async = { version = "0.6", optional = true } pin-utils = "0.1" @@ -83,7 +82,7 @@ with_coap_message = [] with_coap_handler = [] with_embedded_nal = ["embedded-nal", "embedded-nal-tcpextensions"] -with_embedded_nal_async = [ "embedded-nal-async", "embedded-io-async", "embedded-nal-async-0-7" ] +with_embedded_nal_async = [ "embedded-io-async", "embedded-nal-async-0-7" ] with_embedded_hal_async = [ "embedded-hal-async" ] diff --git a/src/socket.rs b/src/socket.rs index af7ef6b6..16d871d7 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -134,75 +134,3 @@ mod nal_impls { } } } - -// FIXME: This is literally copied from above, just with another module -#[cfg(feature = "with_embedded_nal_async")] -mod nal_impls_async { - use super::*; - use embedded_nal_async::SocketAddr; - - impl Into for &SocketAddr { - fn into(self) -> UdpEp { - use SocketAddr::*; - - // Constructing via default avoids using the volatile names of the union types - let mut ep: riot_sys::sock_udp_ep_t = Default::default(); - - ep.family = match self { - V4(_) => riot_sys::AF_INET as _, - V6(_) => riot_sys::AF_INET6 as _, - }; - ep.netif = match self { - V4(_) => 0, - V6(a) => a.scope_id() as _, - }; - ep.port = self.port(); - match self { - V4(a) => { - ep.addr.ipv4 = a.ip().octets(); - } - V6(a) => { - ep.addr.ipv6 = a.ip().octets(); - } - } - - UdpEp(ep) - } - } - - impl Into for SocketAddr { - fn into(self) -> UdpEp { - (&self).into() - } - } - - impl Into for &UdpEp { - fn into(self) -> SocketAddr { - match self.0.family as _ { - riot_sys::AF_INET6 => embedded_nal_async::SocketAddrV6::new( - // unsafe: Access to C union whose type was just checked - unsafe { self.0.addr.ipv6.into() }, - self.0.port, - 0, - self.0.netif.into(), - ) - .into(), - - riot_sys::AF_INET => embedded_nal_async::SocketAddrV4::new( - // unsafe: Access to C union whose type was just checked - unsafe { self.0.addr.ipv4.into() }, - self.0.port, - ) - .into(), - - _ => panic!("Endpoint not expressible in embedded_nal_async"), - } - } - } - - impl Into for UdpEp { - fn into(self) -> SocketAddr { - (&self).into() - } - } -} diff --git a/src/socket_embedded_nal_async_udp.rs b/src/socket_embedded_nal_async_udp.rs index cf62ceaa..48530f0f 100644 --- a/src/socket_embedded_nal_async_udp.rs +++ b/src/socket_embedded_nal_async_udp.rs @@ -346,9 +346,6 @@ macro_rules! implementation_module { } } -mod implementation { - implementation_module! {embedded_nal_async} -} mod implementation_0_7 { implementation_module! {embedded_nal_async_0_7} } From 5185340e9583040c590415d5e157c67ba706b045 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 11:00:07 +0200 Subject: [PATCH 12/15] Fix building with the various embedded-nal This makes implicit what caused breakage in b99e8085: embedded-nal{,-async}'s socket types are re-exports of no_std_net (and thus public dependencies). Conversions are now implemented explicitly for the relevant no_std_net versions. --- Cargo.toml | 9 +++- src/socket.rs | 129 +++++++++++++++++++++++++++----------------------- 2 files changed, 77 insertions(+), 61 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2af6f8f9..718a5c8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,11 @@ embedded-io-async = { version = "0.6", optional = true } pin-utils = "0.1" pin-project = "1.0.11" +# as used in embedded-nal 0.6 +no-std-net-0-5 = { package = "no-std-net", version = "0.5", optional = true } +# as used in embedded-nal-async +no-std-net-0-6 = { package = "no-std-net", version = "0.6", optional = true } + embedded-hal-async = { version = "1", optional = true } critical-section = { version = "1.0", optional = true } @@ -81,8 +86,8 @@ provide_critical_section_1_0 = ["critical-section/restore-state-u32"] with_coap_message = [] with_coap_handler = [] -with_embedded_nal = ["embedded-nal", "embedded-nal-tcpextensions"] -with_embedded_nal_async = [ "embedded-io-async", "embedded-nal-async-0-7" ] +with_embedded_nal = ["embedded-nal", "embedded-nal-tcpextensions", "no-std-net-0-5"] +with_embedded_nal_async = [ "embedded-io-async", "embedded-nal-async-0-7", "no-std-net-0-6" ] with_embedded_hal_async = [ "embedded-hal-async" ] diff --git a/src/socket.rs b/src/socket.rs index 16d871d7..a1207e65 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -64,73 +64,84 @@ impl Into for UdpEp { } } -#[cfg(feature = "with_embedded_nal")] -mod nal_impls { - use super::*; - use embedded_nal::SocketAddr; - - impl Into for &SocketAddr { - fn into(self) -> UdpEp { - use SocketAddr::*; - - // Constructing via default avoids using the volatile names of the union types - let mut ep: riot_sys::sock_udp_ep_t = Default::default(); - - ep.family = match self { - V4(_) => riot_sys::AF_INET as _, - V6(_) => riot_sys::AF_INET6 as _, - }; - ep.netif = match self { - V4(_) => 0, - V6(a) => a.scope_id() as _, - }; - ep.port = self.port(); - match self { - V4(a) => { - ep.addr.ipv4 = a.ip().octets(); - } - V6(a) => { - ep.addr.ipv6 = a.ip().octets(); +macro_rules! implementation_no_std_net { + ($nsn_crate:ident) => { + use super::*; + use $nsn_crate::SocketAddr; + + impl Into for &SocketAddr { + fn into(self) -> UdpEp { + use SocketAddr::*; + + // Constructing via default avoids using the volatile names of the union types + let mut ep: riot_sys::sock_udp_ep_t = Default::default(); + + ep.family = match self { + V4(_) => riot_sys::AF_INET as _, + V6(_) => riot_sys::AF_INET6 as _, + }; + ep.netif = match self { + V4(_) => 0, + V6(a) => a.scope_id() as _, + }; + ep.port = self.port(); + match self { + V4(a) => { + ep.addr.ipv4 = a.ip().octets(); + } + V6(a) => { + ep.addr.ipv6 = a.ip().octets(); + } } - } - UdpEp(ep) + UdpEp(ep) + } } - } - impl Into for SocketAddr { - fn into(self) -> UdpEp { - (&self).into() + impl Into for SocketAddr { + fn into(self) -> UdpEp { + (&self).into() + } } - } - impl Into for &UdpEp { - fn into(self) -> SocketAddr { - match self.0.family as _ { - riot_sys::AF_INET6 => embedded_nal::SocketAddrV6::new( - // unsafe: Access to C union whose type was just checked - unsafe { self.0.addr.ipv6.into() }, - self.0.port, - 0, - self.0.netif.into(), - ) - .into(), - - riot_sys::AF_INET => embedded_nal::SocketAddrV4::new( - // unsafe: Access to C union whose type was just checked - unsafe { self.0.addr.ipv4.into() }, - self.0.port, - ) - .into(), - - _ => panic!("Endpoint not expressible in embedded_nal"), + impl Into for &UdpEp { + fn into(self) -> SocketAddr { + match self.0.family as _ { + riot_sys::AF_INET6 => $nsn_crate::SocketAddrV6::new( + // unsafe: Access to C union whose type was just checked + unsafe { self.0.addr.ipv6.into() }, + self.0.port, + 0, + self.0.netif.into(), + ) + .into(), + + riot_sys::AF_INET => $nsn_crate::SocketAddrV4::new( + // unsafe: Access to C union whose type was just checked + unsafe { self.0.addr.ipv4.into() }, + self.0.port, + ) + .into(), + + _ => panic!("Endpoint not expressible in no_std_net"), + } } } - } - impl Into for UdpEp { - fn into(self) -> SocketAddr { - (&self).into() + impl Into for UdpEp { + fn into(self) -> SocketAddr { + (&self).into() + } } - } + }; +} + +#[cfg(feature = "with_embedded_nal")] +mod implementation_no_std_net_0_5 { + implementation_no_std_net! {no_std_net_0_5} +} + +#[cfg(feature = "with_embedded_nal_async")] +mod implementation_no_std_net_0_6 { + implementation_no_std_net! {no_std_net_0_6} } From 79ad3bbb8d14247ea95d0ee19c4e7b27493c69de Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 11:48:41 +0200 Subject: [PATCH 13/15] gcoap: Add lifetime to PacketBuffer ... and use it in owned form more frequently Closes: https://github.com/RIOT-OS/rust-riot-wrappers/issues/64 --- src/coap_handler/v0_2.rs | 4 ++-- src/coap_message/impl_0_3.rs | 8 ++++---- src/coap_message/mod.rs | 12 ++++++------ src/gcoap.rs | 35 ++++++++++++++++------------------- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/coap_handler/v0_2.rs b/src/coap_handler/v0_2.rs index cc90c603..e8c60a0b 100644 --- a/src/coap_handler/v0_2.rs +++ b/src/coap_handler/v0_2.rs @@ -22,8 +22,8 @@ impl crate::gcoap::Handler for GcoapHandler where H: Handler, { - fn handle(&mut self, pkt: &mut PacketBuffer) -> isize { - let request_data = self.0.extract_request_data(pkt); + fn handle(&mut self, pkt: PacketBuffer) -> isize { + let request_data = self.0.extract_request_data(&pkt); let mut lengthwrapped = ResponseMessage::new(pkt); match request_data { Ok(r) => { diff --git a/src/coap_message/impl_0_3.rs b/src/coap_message/impl_0_3.rs index 80dacd38..bc7df531 100644 --- a/src/coap_message/impl_0_3.rs +++ b/src/coap_message/impl_0_3.rs @@ -39,14 +39,14 @@ impl<'a> MessageOption for super::MessageOption<'a> { } } -impl WithSortedOptions for super::PacketBuffer { +impl<'b> WithSortedOptions for super::PacketBuffer<'b> { // valid because gcoap just reads options from the message where they are stored in sequence } -impl ReadableMessage for super::PacketBuffer { +impl<'b> ReadableMessage for super::PacketBuffer<'b> { type Code = u8; - type OptionsIter<'a> = super::OptionsIterator<'a>; - type MessageOption<'a> = super::MessageOption<'a>; + type OptionsIter<'a> = super::OptionsIterator<'a, 'b> where Self: 'a; + type MessageOption<'a> = super::MessageOption<'a> where Self: 'a; fn code(&self) -> Self::Code { self.get_code_raw() diff --git a/src/coap_message/mod.rs b/src/coap_message/mod.rs index dd91968c..ea9258f5 100644 --- a/src/coap_message/mod.rs +++ b/src/coap_message/mod.rs @@ -10,8 +10,8 @@ pub struct MessageOption<'a> { value: &'a [u8], } -pub struct OptionsIterator<'a>(PacketBufferOptIter<'a>); -impl<'a> Iterator for OptionsIterator<'a> { +pub struct OptionsIterator<'a, 'b>(PacketBufferOptIter<'a, 'b>); +impl<'a, 'b> Iterator for OptionsIterator<'a, 'b> { type Item = MessageOption<'a>; fn next(&mut self) -> Option { @@ -23,15 +23,15 @@ impl<'a> Iterator for OptionsIterator<'a> { } } -pub struct ResponseMessage<'a> { +pub struct ResponseMessage<'b> { /// Note that this is a slightly weird version of PacketBuffer, where opt_finish is never /// called, and .payload() perpetually reports the payload marker as part of the payload. - message: &'a mut PacketBuffer, + message: PacketBuffer<'b>, payload_written: Option, } -impl<'a> ResponseMessage<'a> { - pub fn new(buf: &'a mut PacketBuffer) -> Self { +impl<'b> ResponseMessage<'b> { + pub fn new(mut buf: PacketBuffer<'b>) -> Self { // Can't really err; FIXME ensure that such a check won't affect ROM too much buf.resp_init(5 << 5).unwrap(); diff --git a/src/gcoap.rs b/src/gcoap.rs index f2043590..e8a0f133 100644 --- a/src/gcoap.rs +++ b/src/gcoap.rs @@ -180,11 +180,11 @@ where let h = &mut *h; let mut pb = PacketBuffer { - pkt, + pkt: &mut *pkt, buf, len: len.try_into().unwrap(), }; - H::handle(h, &mut pb).try_into().unwrap() + H::handle(h, pb).try_into().unwrap() } } @@ -277,7 +277,7 @@ where // Can be implemented by application code that'd then need to call some gcoap response functions, // but preferably using the coap_handler module (behind the with-coap-handler feature). pub trait Handler { - fn handle(&mut self, pkt: &mut PacketBuffer) -> isize; + fn handle(&mut self, pkt: PacketBuffer) -> isize; } /// The message buffer of a .well-known/core file in appication/link-format, as it is passed to a @@ -347,20 +347,17 @@ use riot_sys::{ /// messages are created. (For example, it does not keep the user from adding options after the /// payload marker). Use CoAP generalization for that. #[derive(Debug)] -pub struct PacketBuffer { - pkt: *mut coap_pkt_t, +pub struct PacketBuffer<'b> { + pkt: &'b mut coap_pkt_t, buf: *mut u8, len: usize, } -impl PacketBuffer { +impl<'b> PacketBuffer<'b> { /// Wrapper for coap_get_code_raw pub fn get_code_raw(&self) -> u8 { - (unsafe { - riot_sys::coap_get_code_raw( - self.pkt as *mut _, // missing const in C - ) - }) as u8 // odd return type in C + (unsafe { riot_sys::coap_get_code_raw(crate::inline_cast_ref(self.pkt)) }) as u8 + // odd return type in C } /// Wrapper for gcoap_resp_init @@ -446,14 +443,14 @@ impl PacketBuffer { .map(|_| ()) } - pub fn opt_iter<'a>(&'a self) -> PacketBufferOptIter<'a> { + pub fn opt_iter<'a>(&'a self) -> PacketBufferOptIter<'a, 'b> { PacketBufferOptIter { buffer: self, state: None, } } - pub fn opt_iter_mut<'a>(&'a mut self) -> PacketBufferOptIterMut<'a> { + pub fn opt_iter_mut<'a>(&'a mut self) -> PacketBufferOptIterMut<'a, 'b> { PacketBufferOptIterMut { buffer: self, state: None, @@ -461,12 +458,12 @@ impl PacketBuffer { } } -pub struct PacketBufferOptIter<'a> { - buffer: &'a PacketBuffer, +pub struct PacketBufferOptIter<'a, 'b> { + buffer: &'a PacketBuffer<'b>, state: Option, } -impl<'a> Iterator for PacketBufferOptIter<'a> { +impl<'a, 'b> Iterator for PacketBufferOptIter<'a, 'b> { type Item = (u16, &'a [u8]); fn next(&mut self) -> Option { @@ -512,12 +509,12 @@ impl<'a> Iterator for PacketBufferOptIter<'a> { } } -pub struct PacketBufferOptIterMut<'a> { - buffer: &'a mut PacketBuffer, +pub struct PacketBufferOptIterMut<'a, 'b> { + buffer: &'a mut PacketBuffer<'b>, state: Option, } -impl<'a> Iterator for PacketBufferOptIterMut<'a> { +impl<'a, 'b> Iterator for PacketBufferOptIterMut<'a, 'b> { type Item = (u16, &'a mut [u8]); fn next(&mut self) -> Option { From 6cb818dec6d3fee4ff890f684d870411dec00076 Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 14:37:21 +0200 Subject: [PATCH 14/15] ZTimer: Restore compatibility of `.sec().sleep()` This is still what most users will expect to do; documentation points out a way with less overhead. --- src/ztimer/mod.rs | 61 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/src/ztimer/mod.rs b/src/ztimer/mod.rs index eb7fce58..ba4cb083 100644 --- a/src/ztimer/mod.rs +++ b/src/ztimer/mod.rs @@ -20,7 +20,7 @@ use pin_project::{pin_project, pinned_drop}; use riot_sys::ztimer_clock_t; -use crate::thread::ValueInThread; +use crate::thread::{InThread, ValueInThread}; // Useful for working with durations const NANOS_PER_SEC: u32 = 1_000_000_000; @@ -198,10 +198,23 @@ impl Clock { impl Clock<1> { /// Get the global second ZTimer clock, ZTIMER_SEC. /// - /// This function is only available if the ztimer_sec module is built. + /// This function verifies (at a small runtime cost) that the caller is in a thread context. + /// This can be avoided by calling `in_thread.promote(Clock::sec_unbound())` on an existing + /// [riot_wrappers::thread::InThread] token. #[cfg(riot_module_ztimer_sec)] #[doc(alias = "ZTIMER_SEC")] - pub fn sec() -> Self { + pub fn sec() -> ValueInThread { + InThread::new() + .expect("Thread-bound ZTimer clock created in ISR") + .promote(Self::sec_unbound()) + } + + /// Get the global second ZTimer clock, ZTIMER_SEC. + /// + /// The clock is *not* packed in a [ValueInThread], which makes the blocking sleep methods and + /// delay implementations unavailable, but works even in interrupts contexts. + #[cfg(riot_module_ztimer_sec)] + pub fn sec_unbound() -> Self { Clock(unsafe { riot_sys::ZTIMER_SEC }) } } @@ -209,10 +222,23 @@ impl Clock<1> { impl Clock<1000> { /// Get the global milliseconds ZTimer clock, ZTIMER_MSEC. /// - /// This function is only available if the ztimer_msec module is built. + /// This function verifies (at a small runtime cost) that the caller is in a thread context. + /// This can be avoided by calling `in_thread.promote(Clock::msec_unbound())` on an existing + /// [riot_wrappers::thread::InThread] token. #[cfg(riot_module_ztimer_msec)] #[doc(alias = "ZTIMER_MSEC")] - pub fn msec() -> Self { + pub fn msec() -> ValueInThread { + InThread::new() + .expect("Thread-bound ZTimer clock created in ISR") + .promote(Self::msec_unbound()) + } + + /// Get the global milliseconds ZTimer clock, ZTIMER_MSEC. + /// + /// The clock is *not* packed in a [ValueInThread], which makes the blocking sleep methods and + /// delay implementations unavailable, but works even in interrupts contexts. + #[cfg(riot_module_ztimer_msec)] + pub fn msec_unbound() -> Self { Clock(unsafe { riot_sys::ZTIMER_MSEC }) } } @@ -220,10 +246,23 @@ impl Clock<1000> { impl Clock<1000000> { /// Get the global microseconds ZTimer clock, ZTIMER_USEC. /// - /// This function is only available if the ztimer_usec module is built. + /// This function verifies (at a small runtime cost) that the caller is in a thread context. + /// This can be avoided by calling `in_thread.promote(Clock::usec_unbound())` on an existing + /// [riot_wrappers::thread::InThread] token. #[cfg(riot_module_ztimer_usec)] #[doc(alias = "ZTIMER_USEC")] - pub fn usec() -> Self { + pub fn usec() -> ValueInThread { + InThread::new() + .expect("Thread-bound ZTimer clock created in ISR") + .promote(Self::usec_unbound()) + } + + /// Get the global microseconds ZTimer clock, ZTIMER_USEC. + /// + /// The clock is *not* packed in a [ValueInThread], which makes the blocking sleep methods and + /// delay implementations unavailable, but works even in interrupts contexts. + #[cfg(riot_module_ztimer_usec)] + pub fn usec_unbound() -> Self { Clock(unsafe { riot_sys::ZTIMER_USEC }) } } @@ -250,15 +289,17 @@ pub struct Delay; impl embedded_hal_async::delay::DelayNs for Delay { async fn delay_ns(&mut self, ns: u32) { // See struct level documentation - Clock::usec().sleep_async(Ticks(ns.div_ceil(1000))).await + Clock::usec_unbound() + .sleep_async(Ticks(ns.div_ceil(1000))) + .await } async fn delay_us(&mut self, us: u32) { - Clock::usec().sleep_async(Ticks(us)).await + Clock::usec_unbound().sleep_async(Ticks(us)).await } async fn delay_ms(&mut self, us: u32) { - Clock::msec().sleep_async(Ticks(us)).await + Clock::msec_unbound().sleep_async(Ticks(us)).await } } From 9928b48b09ebe5c394516d6cfc1291c1c492194c Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 19 Aug 2024 15:00:21 +0200 Subject: [PATCH 15/15] Revert "Merge remote-tracking branch 'teufelchen/feat/gba' into v09" This reverts commit b644ff672f62b949e0579755125cbfaaf3ed5ccc, reversing changes made to 5ba10e1e2dc21ec9d16a0541897da170869b0cf4. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2fbdb177..718a5c8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ bare-metal = "1" cstr = "^0.2.11" -heapless = { version="0.8", features = ["portable-atomic-unsafe-assume-single-core"] } +heapless = "^0.8" rand_core_06 = { package = "rand_core", version = "^0.6" } # For nimble UUID parsing and some debug implementations