From 7576183225158b62223dd19afd270482746d1245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ioan-Cristian=20C=C3=8ERSTEA?= Date: Mon, 2 Dec 2024 17:04:37 +0200 Subject: [PATCH 1/6] Use const operand for ARM syscall implementation `asm_const` feature has been stabilized in Rust 1.82. Using const operands for inline assembly eliminates a lot of the duplicated code in the ARM syscall implementation. This commit has been tested by running a simple application that periodically blinks and writes a message on Raspberry Pi Pico. --- Cargo.toml | 2 +- runtime/src/syscalls_impl_arm.rs | 92 ++++++++------------------- rust-toolchain.toml | 2 +- syscalls_tests/src/subscribe_tests.rs | 5 ++ 4 files changed, 35 insertions(+), 66 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 10d7a29b8..776b3431b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ version = "0.1.0" [workspace.package] # This must be kept in sync with rust-toolchain.toml; please see that file for # more information. -rust-version = "1.77" +rust-version = "1.82" [features] rust_embedded = [ diff --git a/runtime/src/syscalls_impl_arm.rs b/runtime/src/syscalls_impl_arm.rs index 5bcf923ad..4a74943e9 100644 --- a/runtime/src/syscalls_impl_arm.rs +++ b/runtime/src/syscalls_impl_arm.rs @@ -1,5 +1,5 @@ use core::arch::asm; -use libtock_platform::{syscall_class, RawSyscalls, Register}; +use libtock_platform::{RawSyscalls, Register}; unsafe impl RawSyscalls for crate::TockSyscalls { unsafe fn yield1([Register(r0)]: [Register; 1]) { @@ -43,92 +43,56 @@ unsafe impl RawSyscalls for crate::TockSyscalls { } } - unsafe fn syscall1([Register(mut r0)]: [Register; 1]) -> [Register; 2] { + unsafe fn syscall1( + [Register(mut r0)]: [Register; 1], + ) -> [Register; 2] { let r1; // Safety: This matches the invariants required by the documentation on // RawSyscalls::syscall1 unsafe { - // Syscall class 5 is Memop, the only syscall class that syscall1 - // supports. - asm!("svc 5", - inlateout("r0") r0, - lateout("r1") r1, - options(preserves_flags, nostack, nomem), + asm!( + "svc {SYSCALL_CLASS_NUMBER}", + inlateout("r0") r0, + lateout("r1") r1, + options(preserves_flags, nostack, nomem), + SYSCALL_CLASS_NUMBER = const SYSCALL_CLASS_NUMBER, ); } [Register(r0), Register(r1)] } - unsafe fn syscall2( + unsafe fn syscall2( [Register(mut r0), Register(mut r1)]: [Register; 2], ) -> [Register; 2] { // Safety: This matches the invariants required by the documentation on // RawSyscalls::syscall2 unsafe { - // TODO: Replace this match statement with a `const` operand when - // asm_const [1] is stabilized, or redesign RawSyscalls to not need - // this match statement. - // - // [1] https://github.com/rust-lang/rust/issues/93332 - match CLASS { - syscall_class::MEMOP => asm!("svc 5", - inlateout("r0") r0, - inlateout("r1") r1, - options(preserves_flags, nostack, nomem) - ), - syscall_class::EXIT => asm!("svc 6", - inlateout("r0") r0, - inlateout("r1") r1, - options(preserves_flags, nostack, nomem) - ), - _ => unreachable!(), - } + asm!( + "svc {SYSCALL_CLASS_NUMBER}", + inlateout("r0") r0, + inlateout("r1") r1, + options(preserves_flags, nostack, nomem), + SYSCALL_CLASS_NUMBER = const SYSCALL_CLASS_NUMBER, + ); } [Register(r0), Register(r1)] } - unsafe fn syscall4( + unsafe fn syscall4( [Register(mut r0), Register(mut r1), Register(mut r2), Register(mut r3)]: [Register; 4], ) -> [Register; 4] { // Safety: This matches the invariants required by the documentation on // RawSyscalls::syscall4 unsafe { - // TODO: Replace this match statement with a `const` operand when - // asm_const [1] is stabilized, or redesign RawSyscalls to not need - // this match statement. - // - // [1] https://github.com/rust-lang/rust/issues/93332 - match CLASS { - syscall_class::SUBSCRIBE => asm!("svc 1", - inlateout("r0") r0, - inlateout("r1") r1, - inlateout("r2") r2, - inlateout("r3") r3, - options(preserves_flags, nostack), - ), - syscall_class::COMMAND => asm!("svc 2", - inlateout("r0") r0, - inlateout("r1") r1, - inlateout("r2") r2, - inlateout("r3") r3, - options(preserves_flags, nostack), - ), - syscall_class::ALLOW_RW => asm!("svc 3", - inlateout("r0") r0, - inlateout("r1") r1, - inlateout("r2") r2, - inlateout("r3") r3, - options(preserves_flags, nostack), - ), - syscall_class::ALLOW_RO => asm!("svc 4", - inlateout("r0") r0, - inlateout("r1") r1, - inlateout("r2") r2, - inlateout("r3") r3, - options(preserves_flags, nostack), - ), - _ => unreachable!(), - } + asm!( + "svc {SYSCALL_CLASS_NUMBER}", + inlateout("r0") r0, + inlateout("r1") r1, + inlateout("r2") r2, + inlateout("r3") r3, + options(preserves_flags, nostack), + SYSCALL_CLASS_NUMBER = const SYSCALL_CLASS_NUMBER, + ); } [Register(r0), Register(r1), Register(r2), Register(r3)] } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 795603e64..f87df8148 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -5,7 +5,7 @@ # you'd like to use. When you do so, update this to the first Rust version that # includes that feature. Whenever this value is updated, the rust-version field # in Cargo.toml must be updated as well. -channel = "1.77" +channel = "1.82" components = ["clippy", "rustfmt"] targets = [ "thumbv6m-none-eabi", diff --git a/syscalls_tests/src/subscribe_tests.rs b/syscalls_tests/src/subscribe_tests.rs index 673f7d5e7..7af62f290 100644 --- a/syscalls_tests/src/subscribe_tests.rs +++ b/syscalls_tests/src/subscribe_tests.rs @@ -104,6 +104,10 @@ fn success() { assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); } +// The toolchain update from 1.78 to 1.82 broke this test. However, this test will start working +// again as of Rust 1.84. See https://github.com/tock/libtock-rs/pull/565#issuecomment-2546915870 +// for more details. +/* #[cfg(not(miri))] #[test] fn unwinding_upcall() { @@ -131,3 +135,4 @@ fn unwinding_upcall() { }); assert_eq!(exit, libtock_unittest::ExitCall::Terminate(0)); } +*/ From 0c7862a86a2cbef328ae39d85ef4d9537195b62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ioan-Cristian=20C=C3=8ERSTEA?= Date: Thu, 16 Jan 2025 19:03:05 +0200 Subject: [PATCH 2/6] Fixed transmute clippy lint warnings. The toolchain bump from 1.79 to 1.82 introduced a new clippy lint regarding transmutes. This commit fixes the emitted lint warnings. --- platform/src/command_return.rs | 14 +++++++++----- platform/src/error_code.rs | 2 +- platform/src/syscalls_impl.rs | 16 ++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/platform/src/command_return.rs b/platform/src/command_return.rs index a8b89a914..c3696536d 100644 --- a/platform/src/command_return.rs +++ b/platform/src/command_return.rs @@ -139,7 +139,7 @@ impl CommandReturn { if !self.is_failure() { return None; } - Some(unsafe { transmute(self.r1) }) + Some(unsafe { transmute::(self.r1) }) } /// Returns the error code and value if this CommandReturn is of type @@ -148,7 +148,7 @@ impl CommandReturn { if !self.is_failure_u32() { return None; } - Some((unsafe { transmute(self.r1) }, self.r2)) + Some((unsafe { transmute::(self.r1) }, self.r2)) } /// Returns the error code and return values if this CommandReturn is of @@ -157,7 +157,11 @@ impl CommandReturn { if !self.is_failure_2_u32() { return None; } - Some((unsafe { transmute(self.r1) }, self.r2, self.r3)) + Some(( + unsafe { transmute::(self.r1) }, + self.r2, + self.r3, + )) } /// Returns the error code and return value if this CommandReturn is of type @@ -167,7 +171,7 @@ impl CommandReturn { return None; } Some(( - unsafe { transmute(self.r1) }, + unsafe { transmute::(self.r1) }, self.r2 as u64 + ((self.r3 as u64) << 32), )) } @@ -244,7 +248,7 @@ impl CommandReturn { let ec: ErrorCode = if return_variant == E::RETURN_VARIANT { // Safety: E::RETURN_VARIANT must be a failure variant, and // failure variants must contain a valid ErrorCode in r1. - unsafe { transmute(r1) } + unsafe { transmute::(r1) } } else { r2 = 0; r3 = 0; diff --git a/platform/src/error_code.rs b/platform/src/error_code.rs index c78b75965..9bbb159af 100644 --- a/platform/src/error_code.rs +++ b/platform/src/error_code.rs @@ -277,7 +277,7 @@ impl TryFrom for ErrorCode { fn try_from(value: u32) -> Result { if (1..=1024).contains(&value) { - Ok(unsafe { transmute(value) }) + Ok(unsafe { transmute::(value) }) } else { Err(NotAnErrorCode) } diff --git a/platform/src/syscalls_impl.rs b/platform/src/syscalls_impl.rs index d2057ede3..cd1961cfd 100644 --- a/platform/src/syscalls_impl.rs +++ b/platform/src/syscalls_impl.rs @@ -118,7 +118,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - return Err(unsafe { core::mem::transmute(r1.as_u32()) }); + return Err(unsafe { core::mem::transmute::(r1.as_u32()) }); } // r0 indicates Success with 2 u32s. Confirm the null upcall was @@ -231,7 +231,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - return Err(unsafe { core::mem::transmute(r1.as_u32()) }); + return Err(unsafe { core::mem::transmute::(r1.as_u32()) }); } // r0 indicates Success with 2 u32s. Confirm a zero buffer was @@ -318,7 +318,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - return Err(unsafe { core::mem::transmute(r1.as_u32()) }); + return Err(unsafe { core::mem::transmute::(r1.as_u32()) }); } // r0 indicates Success with 2 u32s. Confirm a zero buffer was @@ -380,7 +380,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - Err(unsafe { core::mem::transmute(r1.as_u32()) }) + Err(unsafe { core::mem::transmute::(r1.as_u32()) }) } else { Ok(()) } @@ -407,7 +407,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - Err(unsafe { core::mem::transmute(r1.as_u32()) }) + Err(unsafe { core::mem::transmute::(r1.as_u32()) }) } else { Ok(r1.into()) } @@ -436,7 +436,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - Err(unsafe { core::mem::transmute(r1.as_u32()) }) + Err(unsafe { core::mem::transmute::(r1.as_u32()) }) } else { Ok(r1.into()) } @@ -464,7 +464,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - Err(unsafe { core::mem::transmute(r1.as_u32()) }) + Err(unsafe { core::mem::transmute::(r1.as_u32()) }) } else { Ok(()) } @@ -493,7 +493,7 @@ impl Syscalls for S { // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. - Err(unsafe { core::mem::transmute(r1.as_u32()) }) + Err(unsafe { core::mem::transmute::(r1.as_u32()) }) } else { Ok(()) } From c90284113aa388a2acf61b6ea333ed3a3e3f2748 Mon Sep 17 00:00:00 2001 From: Amit Aryeh Levy Date: Tue, 3 Jun 2025 20:45:51 -0700 Subject: [PATCH 3/6] Update to rustc 1.84 and fix shell.nix --- Cargo.toml | 2 +- rust-toolchain.toml | 4 +- shell.nix | 89 +++++++++++++++++++++++++++ syscalls_tests/src/subscribe_tests.rs | 5 -- 4 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 shell.nix diff --git a/Cargo.toml b/Cargo.toml index 776b3431b..a0a67da87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ version = "0.1.0" [workspace.package] # This must be kept in sync with rust-toolchain.toml; please see that file for # more information. -rust-version = "1.82" +rust-version = "1.84" [features] rust_embedded = [ diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f87df8148..3e58261b7 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -5,8 +5,8 @@ # you'd like to use. When you do so, update this to the first Rust version that # includes that feature. Whenever this value is updated, the rust-version field # in Cargo.toml must be updated as well. -channel = "1.82" -components = ["clippy", "rustfmt"] +channel = "1.84" +components = ["clippy", "rustfmt" ] targets = [ "thumbv6m-none-eabi", "thumbv7em-none-eabi", diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..4ae45a628 --- /dev/null +++ b/shell.nix @@ -0,0 +1,89 @@ +# Shell expression for the Nix package manager +# +# This nix expression creates an environment with necessary packages installed: +# +# * `tockloader` +# * arm-none-eabi toolchain +# * elf2tab +# * riscv32-embedded toolchain +# +# To use: +# +# $ nix-shell + +{ pkgs ? import {}, withUnfreePkgs ? false }: + +with builtins; +let + inherit (pkgs) stdenv stdenvNoCC lib; + + tockloader = import (pkgs.fetchFromGitHub { + owner = "tock"; + repo = "tockloader"; + rev = "v1.12.0"; + sha256 = "sha256-VgbAKDY/7ZVINDkqSHF7C0zRzVgtk8YG6O/ZmUpsh/g="; + }) { inherit pkgs withUnfreePkgs; }; + + elf2tab = pkgs.rustPlatform.buildRustPackage rec { + name = "elf2tab-${version}"; + version = "0.12.0"; + + src = pkgs.fetchFromGitHub { + owner = "tock"; + repo = "elf2tab"; + rev = "v${version}"; + sha256 = "sha256-+VeWLBI6md399Oaumt4pJrOkm0Nz7fmpXN2TjglUE34="; + }; + + cargoHash = "sha256-C1hg2/y557jRLkSBvFLxYKH+t8xEJudDvU72kO9sPug="; + }; + + + rust_overlay = import "${pkgs.fetchFromGitHub { + owner = "nix-community"; + repo = "fenix"; + rev = "2da33335e40ca932b4c5ea632816eed573736fba"; + sha256 = "sha256-1HiKieYFvFi5Hw3x2/mptbbvAuL0QwlZQC9UIGNNb1w="; + }}/overlay.nix"; + + nixpkgs = import { overlays = [ rust_overlay ]; }; + + # Get a custom cross-compile capable Rust install of a specific channel and + # build. Tock expects a specific version of Rust with a selection of targets + # and components to be present. + rustBuild = ( + nixpkgs.fenix.fromToolchainFile { file = ./rust-toolchain.toml; } + ); +in + pkgs.mkShell { + name = "tock-dev"; + + buildInputs = with pkgs; [ + rustBuild + elf2tab + qemu + gcc-arm-embedded + python3Full + tockloader + pkgsCross.riscv32-embedded.buildPackages.gcc + openocd + ]; + + # Unfortunately, `segger-jlink` has been removed from Nixpkgs due to its + # hard dependency in Qt4, which has multiple security issues and is + # deprecated since a few years now. Efforts exist to bring the package back, + # but for now we don't assume it's available. Once [1] is merged, we can add + # the following back: + # + # buildInputs ++ (lib.optionals withUnfreePkgs [ + # segger-jlink + # tockloader.nrf-command-line-tools + # ]) + # + # shellHook = '' + # # TODO: This should be patched into the rpath of the respective libraries! + # export LD_LIBRARY_PATH=${pkgs.libusb}/lib:${pkgs.segger-jlink}/lib:$LD_LIBRARY_PATH + # ''; + # + # [1]: https://github.com/NixOS/nixpkgs/pull/255185 + } diff --git a/syscalls_tests/src/subscribe_tests.rs b/syscalls_tests/src/subscribe_tests.rs index 7af62f290..673f7d5e7 100644 --- a/syscalls_tests/src/subscribe_tests.rs +++ b/syscalls_tests/src/subscribe_tests.rs @@ -104,10 +104,6 @@ fn success() { assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); } -// The toolchain update from 1.78 to 1.82 broke this test. However, this test will start working -// again as of Rust 1.84. See https://github.com/tock/libtock-rs/pull/565#issuecomment-2546915870 -// for more details. -/* #[cfg(not(miri))] #[test] fn unwinding_upcall() { @@ -135,4 +131,3 @@ fn unwinding_upcall() { }); assert_eq!(exit, libtock_unittest::ExitCall::Terminate(0)); } -*/ From 94ec8b67f6debcfdf01a561c4eb837327972916b Mon Sep 17 00:00:00 2001 From: Amit Aryeh Levy Date: Tue, 3 Jun 2025 20:48:15 -0700 Subject: [PATCH 4/6] Fix clippy lints --- apis/interface/buttons/src/lib.rs | 43 ++++++++++---------- apis/interface/leds/src/lib.rs | 1 - apis/kernel/low_level_debug/src/lib.rs | 1 - apis/net/ieee802154/src/rx.rs | 12 ++++-- apis/peripherals/alarm/src/lib.rs | 19 ++++----- apis/peripherals/gpio/src/lib.rs | 29 +++++++------ panic_handlers/debug_panic/src/lib.rs | 1 - platform/src/allow_ro.rs | 12 +++--- platform/src/allow_rw.rs | 12 +++--- platform/src/raw_syscalls.rs | 1 - platform/src/share/handle.rs | 4 +- platform/src/subscribe.rs | 12 +++--- syscalls_tests/src/lib.rs | 1 + tools/print_sizes/src/main.rs | 2 +- unittest/src/fake/kernel.rs | 4 +- unittest/src/fake/syscalls/subscribe_impl.rs | 7 +++- 16 files changed, 82 insertions(+), 79 deletions(-) diff --git a/apis/interface/buttons/src/lib.rs b/apis/interface/buttons/src/lib.rs index 76e1ee808..27daad212 100644 --- a/apis/interface/buttons/src/lib.rs +++ b/apis/interface/buttons/src/lib.rs @@ -1,31 +1,30 @@ #![no_std] +//! The Buttons driver +//! +//! # Example +//! ```ignore +//! use libtock::Buttons; +//! +//! // Read button state +//! Buttons::is_pressed(0); +//! +//! // Register for events +//! +//! let listener = ButtonListener(|button, state| { +//! // make use of the button's state +//! }); +//! +//! share::scope(|subscribe| { +//! if let Ok(()) = Buttons::register_listener(&listener, subscribe) { +//! // yield +//! } +//! }); +//! ``` use libtock_platform::{ share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, }; -/// The Buttons driver -/// -/// # Example -/// ```ignore -/// use libtock::Buttons; -/// -/// // Read button state -/// Buttons::is_pressed(0); -/// -/// // Register for events -/// -/// let listener = ButtonListener(|button, state| { -/// // make use of the button's state -/// }); -/// -/// share::scope(|subscribe| { -/// if let Ok(()) = Buttons::register_listener(&listener, subscribe) { -/// // yield -/// } -/// }); -/// ``` - pub struct Buttons(S); #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/apis/interface/leds/src/lib.rs b/apis/interface/leds/src/lib.rs index 8f90e2c7f..c388ab42d 100644 --- a/apis/interface/leds/src/lib.rs +++ b/apis/interface/leds/src/lib.rs @@ -11,7 +11,6 @@ use libtock_platform::{ErrorCode, Syscalls}; /// // Turn on led 0 /// let _ = Leds::on(0); /// ``` - pub struct Leds(S); impl Leds { diff --git a/apis/kernel/low_level_debug/src/lib.rs b/apis/kernel/low_level_debug/src/lib.rs index 8733b9a73..13b893c5a 100644 --- a/apis/kernel/low_level_debug/src/lib.rs +++ b/apis/kernel/low_level_debug/src/lib.rs @@ -15,7 +15,6 @@ use libtock_platform::Syscalls; /// // Prints 0x45 and the app which called it. /// LowLevelDebug::print_1(0x45); /// ``` - pub struct LowLevelDebug(S); impl LowLevelDebug { diff --git a/apis/net/ieee802154/src/rx.rs b/apis/net/ieee802154/src/rx.rs index db727f040..39dbb35e6 100644 --- a/apis/net/ieee802154/src/rx.rs +++ b/apis/net/ieee802154/src/rx.rs @@ -23,7 +23,7 @@ const EMPTY_FRAME: Frame = Frame { /// The ring buffer that is shared with kernel using allow-rw syscall, with kernel acting /// as a producer of frames and we acting a consumer. - +/// /// The `N` parameter specifies the capacity of the buffer in number of frames. /// Unfortunately, due to a design flaw of the ring buffer, it can never be fully utilised, /// as it's impossible to distinguish an empty buffer from a full one. The kernel code @@ -52,6 +52,12 @@ pub struct RxRingBuffer { frames: [Frame; N], } +impl Default for RxRingBuffer { + fn default() -> Self { + Self::new() + } +} + impl RxRingBuffer { /// Creates a new [RxRingBuffer] that can be used to receive frames into. pub const fn new() -> Self { @@ -116,9 +122,7 @@ impl<'buf, const N: usize, S: Syscalls, C: Config> RxSingleBufferOperator<'buf, } } } -impl<'buf, const N: usize, S: Syscalls, C: Config> RxOperator - for RxSingleBufferOperator<'buf, N, S, C> -{ +impl RxOperator for RxSingleBufferOperator<'_, N, S, C> { fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode> { if self.buf.has_frame() { Ok(self.buf.next_frame()) diff --git a/apis/peripherals/alarm/src/lib.rs b/apis/peripherals/alarm/src/lib.rs index bdb4b6d8c..7b3e4fc4a 100644 --- a/apis/peripherals/alarm/src/lib.rs +++ b/apis/peripherals/alarm/src/lib.rs @@ -1,20 +1,19 @@ #![no_std] +//! The alarm driver +//! +//! # Example +//! ```ignore +//! use libtock2::Alarm; +//! +//! // Wait for timeout +//! Alarm::sleep(Alarm::Milliseconds(2500)); +//! ``` use core::cell::Cell; use libtock_platform as platform; use libtock_platform::share; use libtock_platform::{DefaultConfig, ErrorCode, Syscalls}; -/// The alarm driver -/// -/// # Example -/// ```ignore -/// use libtock2::Alarm; -/// -/// // Wait for timeout -/// Alarm::sleep(Alarm::Milliseconds(2500)); -/// ``` - pub struct Alarm(S, C); #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/apis/peripherals/gpio/src/lib.rs b/apis/peripherals/gpio/src/lib.rs index c7c77d0e9..32e108d0d 100644 --- a/apis/peripherals/gpio/src/lib.rs +++ b/apis/peripherals/gpio/src/lib.rs @@ -1,4 +1,14 @@ #![no_std] +//! The GPIO driver. +//! +//! # Example +//! ```ignore +//! use libtock::gpio; +//! +//! // Set pin to high. +//! let pin = gpio::Gpio::get_pin(0).unwrap().make_output().unwrap(); +//! let _ = pin.set(); +//! ``` use core::marker::PhantomData; @@ -6,17 +16,6 @@ use libtock_platform::{ share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, }; -/// The GPIO driver. -/// -/// # Example -/// ```ignore -/// use libtock::gpio; -/// -/// // Set pin to high. -/// let pin = gpio::Gpio::get_pin(0).unwrap().make_output().unwrap(); -/// let _ = pin.set(); -/// ``` - #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum GpioState { Low = 0, @@ -145,7 +144,7 @@ pub struct OutputPin<'a, S: Syscalls> { pin: &'a Pin, } -impl<'a, S: Syscalls> OutputPin<'a, S> { +impl OutputPin<'_, S> { pub fn toggle(&mut self) -> Result<(), ErrorCode> { Gpio::::toggle(self.pin.pin_number) } @@ -162,7 +161,7 @@ pub struct InputPin<'a, S: Syscalls, P: Pull> { _pull: PhantomData

, } -impl<'a, S: Syscalls, P: Pull> InputPin<'a, S, P> { +impl InputPin<'_, S, P> { pub fn read(&self) -> Result { Gpio::::read(self.pin.pin_number) } @@ -232,12 +231,12 @@ impl Gpio { } #[cfg(feature = "rust_embedded")] -impl<'a, S: Syscalls> embedded_hal::digital::ErrorType for OutputPin<'a, S> { +impl embedded_hal::digital::ErrorType for OutputPin<'_, S> { type Error = ErrorCode; } #[cfg(feature = "rust_embedded")] -impl<'a, S: Syscalls> embedded_hal::digital::OutputPin for OutputPin<'a, S> { +impl embedded_hal::digital::OutputPin for OutputPin<'_, S> { fn set_low(&mut self) -> Result<(), Self::Error> { self.clear() } diff --git a/panic_handlers/debug_panic/src/lib.rs b/panic_handlers/debug_panic/src/lib.rs index bafbeda33..cbe4b21f2 100644 --- a/panic_handlers/debug_panic/src/lib.rs +++ b/panic_handlers/debug_panic/src/lib.rs @@ -6,7 +6,6 @@ use libtock_platform::{ErrorCode, Syscalls}; use libtock_runtime::TockSyscalls; /// This handler requires some 0x400 bytes of stack - #[panic_handler] fn panic_handler(info: &core::panic::PanicInfo) -> ! { // Signal a panic using the LowLevelDebug capsule (if available). diff --git a/platform/src/allow_ro.rs b/platform/src/allow_ro.rs index a71fa6997..026e33767 100644 --- a/platform/src/allow_ro.rs +++ b/platform/src/allow_ro.rs @@ -34,8 +34,8 @@ pub struct AllowRo<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: // We can't derive(Default) because S is not Default, and derive(Default) // generates a Default implementation that requires S to be Default. Instead, we // manually implement Default. -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Default - for AllowRo<'share, S, DRIVER_NUM, BUFFER_NUM> +impl Default + for AllowRo<'_, S, DRIVER_NUM, BUFFER_NUM> { fn default() -> Self { Self { @@ -45,16 +45,16 @@ impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Default } } -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Drop - for AllowRo<'share, S, DRIVER_NUM, BUFFER_NUM> +impl Drop + for AllowRo<'_, S, DRIVER_NUM, BUFFER_NUM> { fn drop(&mut self) { S::unallow_ro(DRIVER_NUM, BUFFER_NUM); } } -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> List - for AllowRo<'share, S, DRIVER_NUM, BUFFER_NUM> +impl List + for AllowRo<'_, S, DRIVER_NUM, BUFFER_NUM> { } diff --git a/platform/src/allow_rw.rs b/platform/src/allow_rw.rs index 52fcf1e20..725352ae4 100644 --- a/platform/src/allow_rw.rs +++ b/platform/src/allow_rw.rs @@ -34,8 +34,8 @@ pub struct AllowRw<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: // We can't derive(Default) because S is not Default, and derive(Default) // generates a Default implementation that requires S to be Default. Instead, we // manually implement Default. -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Default - for AllowRw<'share, S, DRIVER_NUM, BUFFER_NUM> +impl Default + for AllowRw<'_, S, DRIVER_NUM, BUFFER_NUM> { fn default() -> Self { Self { @@ -45,16 +45,16 @@ impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Default } } -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Drop - for AllowRw<'share, S, DRIVER_NUM, BUFFER_NUM> +impl Drop + for AllowRw<'_, S, DRIVER_NUM, BUFFER_NUM> { fn drop(&mut self) { S::unallow_rw(DRIVER_NUM, BUFFER_NUM); } } -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> List - for AllowRw<'share, S, DRIVER_NUM, BUFFER_NUM> +impl List + for AllowRw<'_, S, DRIVER_NUM, BUFFER_NUM> { } diff --git a/platform/src/raw_syscalls.rs b/platform/src/raw_syscalls.rs index 663485f3d..50bb72f9a 100644 --- a/platform/src/raw_syscalls.rs +++ b/platform/src/raw_syscalls.rs @@ -9,7 +9,6 @@ use crate::Register; /// # Safety /// `RawSyscalls` is unsafe because `unsafe` code depends on its methods to /// return the correct register values. - // The RawSyscalls trait is designed to minimize the complexity and size of its // implementation, as its implementation is difficult to test (it cannot be used // in unit tests, with sanitizers, or in Miri). It is also designed to minimize diff --git a/platform/src/share/handle.rs b/platform/src/share/handle.rs index 2ffd67d9a..e002c89a9 100644 --- a/platform/src/share/handle.rs +++ b/platform/src/share/handle.rs @@ -22,13 +22,13 @@ pub struct Handle<'handle, L: List> { // We can't #[derive(Clone, Copy)] because derive's implementations of Clone and // Copy have `L: Clone` and `L: Copy` constraints, respectively. We don't want // those constraints, so we manually implement Clone and Copy. -impl<'handle, L: List> Clone for Handle<'handle, L> { +impl Clone for Handle<'_, L> { fn clone(&self) -> Self { *self } } -impl<'handle, L: List> Copy for Handle<'handle, L> {} +impl Copy for Handle<'_, L> {} impl<'handle, L: List> Handle<'handle, L> { /// Constructs a new `Handle`, typing its lifetime to the provided list. diff --git a/platform/src/subscribe.rs b/platform/src/subscribe.rs index 3a0408b03..07aa77375 100644 --- a/platform/src/subscribe.rs +++ b/platform/src/subscribe.rs @@ -29,8 +29,8 @@ pub struct Subscribe<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE // We can't derive(Default) because S is not Default, and derive(Default) // generates a Default implementation that requires S to be Default. Instead, we // manually implement Default. -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> Default - for Subscribe<'share, S, DRIVER_NUM, SUBSCRIBE_NUM> +impl Default + for Subscribe<'_, S, DRIVER_NUM, SUBSCRIBE_NUM> { fn default() -> Self { Self { @@ -40,16 +40,16 @@ impl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> Defau } } -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> Drop - for Subscribe<'share, S, DRIVER_NUM, SUBSCRIBE_NUM> +impl Drop + for Subscribe<'_, S, DRIVER_NUM, SUBSCRIBE_NUM> { fn drop(&mut self) { S::unsubscribe(DRIVER_NUM, SUBSCRIBE_NUM); } } -impl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> List - for Subscribe<'share, S, DRIVER_NUM, SUBSCRIBE_NUM> +impl List + for Subscribe<'_, S, DRIVER_NUM, SUBSCRIBE_NUM> { } diff --git a/syscalls_tests/src/lib.rs b/syscalls_tests/src/lib.rs index 353c0a908..a3b3b3b50 100644 --- a/syscalls_tests/src/lib.rs +++ b/syscalls_tests/src/lib.rs @@ -7,6 +7,7 @@ //! 1. The `libtock_platform` with `cfg(test)` enabled //! 2. The `libtock_platform` that `libtock_unittest` depends on, which has //! `cfg(test)` disabled. +//! //! Mixing types from the two `libtock_platform` instantiations in tests results //! in confusing error messages, so instead those tests live in this crate. diff --git a/tools/print_sizes/src/main.rs b/tools/print_sizes/src/main.rs index 12f05c4e8..5c095b05f 100644 --- a/tools/print_sizes/src/main.rs +++ b/tools/print_sizes/src/main.rs @@ -40,7 +40,7 @@ fn find_examples() -> Vec { // Skip entries that are not files. If file_type() returns // Err(_) we skip the entry as well. - if !file.file_type().map_or(false, |t| t.is_file()) { + if !file.file_type().is_ok_and(|t| t.is_file()) { continue; } diff --git a/unittest/src/fake/kernel.rs b/unittest/src/fake/kernel.rs index c26c72b81..da560a61c 100644 --- a/unittest/src/fake/kernel.rs +++ b/unittest/src/fake/kernel.rs @@ -113,14 +113,14 @@ impl Kernel { /// Returns true if the specified driver installed. pub fn is_driver_present(driver_num: u32) -> bool { with_kernel_data(|kernel_data| { - kernel_data.map_or(false, |kernel| kernel.drivers.contains_key(&driver_num)) + kernel_data.is_some_and(|kernel| kernel.drivers.contains_key(&driver_num)) }) } /// Returns true if there are any pending upcalls. pub fn is_upcall_pending() -> bool { with_kernel_data(|kernel_data| { - kernel_data.map_or(false, |kernel| !kernel.upcall_queue.is_empty()) + kernel_data.is_some_and(|kernel| !kernel.upcall_queue.is_empty()) }) } } diff --git a/unittest/src/fake/syscalls/subscribe_impl.rs b/unittest/src/fake/syscalls/subscribe_impl.rs index 2b320c11a..6f71807ac 100644 --- a/unittest/src/fake/syscalls/subscribe_impl.rs +++ b/unittest/src/fake/syscalls/subscribe_impl.rs @@ -97,7 +97,12 @@ pub(super) unsafe fn subscribe( // guarantees that an unsafe extern fn(u32, u32, u32, Register) can // be transmuted into an Option. - _ => unsafe { core::mem::transmute(upcall_fn) }, + _ => unsafe { + core::mem::transmute::< + Register, + Option, + >(upcall_fn) + }, }, data, }; From dc38e9c6a215c4e04b0669db158a039700700ef4 Mon Sep 17 00:00:00 2001 From: Amit Aryeh Levy Date: Tue, 3 Jun 2025 21:24:02 -0700 Subject: [PATCH 5/6] Upgrade to rust 1.87 --- Cargo.toml | 2 +- nightly/rust-toolchain.toml | 2 +- runtime/src/lib.rs | 1 + rust-toolchain.toml | 2 +- unittest/src/share_data.rs | 15 ++++++++++++--- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a0a67da87..ab3bb3b18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ version = "0.1.0" [workspace.package] # This must be kept in sync with rust-toolchain.toml; please see that file for # more information. -rust-version = "1.84" +rust-version = "1.87" [features] rust_embedded = [ diff --git a/nightly/rust-toolchain.toml b/nightly/rust-toolchain.toml index f30a8bc4f..8a3954fe7 100644 --- a/nightly/rust-toolchain.toml +++ b/nightly/rust-toolchain.toml @@ -1,4 +1,4 @@ # This is the nightly Rust toolchain used by `make test`. [toolchain] -channel = "nightly-2024-11-11" +channel = "nightly-2025-05-19" components = ["miri", "rust-src"] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f6f4d69f9..1cf8d935e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -19,6 +19,7 @@ //! and provide its own layout file. #![no_std] +#![allow(clippy::pointers_in_nomem_asm_block)] #![warn(unsafe_op_in_unsafe_fn)] pub mod startup; diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 3e58261b7..2bae2d53d 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -5,7 +5,7 @@ # you'd like to use. When you do so, update this to the first Rust version that # includes that feature. Whenever this value is updated, the rust-version field # in Cargo.toml must be updated as well. -channel = "1.84" +channel = "1.87" components = ["clippy", "rustfmt" ] targets = [ "thumbv6m-none-eabi", diff --git a/unittest/src/share_data.rs b/unittest/src/share_data.rs index a66ae47fb..d5e493755 100644 --- a/unittest/src/share_data.rs +++ b/unittest/src/share_data.rs @@ -174,7 +174,10 @@ mod tests { subscribe_num: 2 } ); - assert!(upcall_queue_entry.upcall.fn_pointer == Some(upcall_ptr)); + assert!( + upcall_queue_entry.upcall.fn_pointer.map(|f| f as *const ()) + == Some(upcall_ptr as *const _) + ); let data: usize = upcall_queue_entry.upcall.data.into(); assert_eq!(data, 1111); @@ -207,7 +210,10 @@ mod tests { subscribe_num: 2 } ); - assert!(front_queue_entry.upcall.fn_pointer == Some(upcall_ptr)); + assert!( + front_queue_entry.upcall.fn_pointer.map(|f| f as *const ()) + == Some(upcall_ptr as *const _) + ); let front_data: usize = front_queue_entry.upcall.data.into(); assert_eq!(front_data, 1111); let back_queue_entry = kernel_data.upcall_queue.back().expect("Upcall not queued"); @@ -219,7 +225,10 @@ mod tests { subscribe_num: 2 } ); - assert!(back_queue_entry.upcall.fn_pointer == Some(upcall_ptr)); + assert!( + back_queue_entry.upcall.fn_pointer.map(|f| f as *const ()) + == Some(upcall_ptr as *const _) + ); let back_data: usize = back_queue_entry.upcall.data.into(); assert_eq!(back_data, 2222); }); From 8bc95d32dab8f88aba42d2480b312fcdd74e05ab Mon Sep 17 00:00:00 2001 From: Amit Aryeh Levy Date: Tue, 3 Jun 2025 22:20:11 -0700 Subject: [PATCH 6/6] updat st7789-slint demo to new HEAP style --- demos/st7789-slint/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/st7789-slint/src/main.rs b/demos/st7789-slint/src/main.rs index 64833e3fc..0b7d74daa 100644 --- a/demos/st7789-slint/src/main.rs +++ b/demos/st7789-slint/src/main.rs @@ -51,7 +51,7 @@ unsafe fn setup_heap() { const HEAP_SIZE: usize = 1024 * 6; static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; - unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } + unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) } } // Display