From 1a028a9fb0d557b4b495033044e27f36c6a629d8 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Mon, 19 Feb 2024 13:45:39 +0000 Subject: [PATCH] Remove chip features from `xtensa-lx` package, add a super simple CI workflow (#34) * Remove chip features from `xtensa-lx` package * Add `rustfmt.toml` config file, format source * Add a CI workflow to check the `xtensa-lx` and `xtensa-lx-rt` packages --- .github/workflows/ci.yml | 88 +++++++++++++++++++++++++++ rustfmt.toml | 9 +++ xtensa-lx-rt/build.rs | 15 +++-- xtensa-lx-rt/procmacros/src/lib.rs | 20 +++--- xtensa-lx-rt/src/exception.rs | 34 +++++------ xtensa-lx-rt/src/exception/asm.rs | 34 +++++++---- xtensa-lx-rt/src/exception/context.rs | 12 ++-- xtensa-lx-rt/src/lib.rs | 4 +- xtensa-lx/Cargo.toml | 40 ++++-------- xtensa-lx/build.rs | 3 +- xtensa-lx/src/interrupt.rs | 4 +- xtensa-lx/src/lib.rs | 25 +++++--- xtensa-lx/src/macros.rs | 9 +-- xtensa-lx/src/mutex.rs | 19 +++--- xtensa-lx/src/timer.rs | 15 ++--- 15 files changed, 214 insertions(+), 117 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 rustfmt.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6ba42ec --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,88 @@ +name: CI + +on: + pull_request: + paths-ignore: + - "**/README.md" + push: + paths-ignore: + - "**/README.md" + merge_group: + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +# Cancel any currently running workflows from the same PR, branch, or +# tag when a new workflow is triggered. +# +# https://stackoverflow.com/a/66336834 +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + +jobs: + # -------------------------------------------------------------------------- + # Check Packages + + xtensa-lx: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: esp-rs/xtensa-toolchain@v1.5 + with: + default: true + ldproxy: false + - uses: Swatinem/rust-cache@v2 + + # Build the 'xtensa-lx' package: + - name: check (no features) + run: cd xtensa-lx/ && cargo build + - name: check (all features) + run: cd xtensa-lx/ && cargo build --features=float-save-restore,spin + + # xtensa-lx-rt: + # runs-on: ubuntu-latest + # + # strategy: + # fail-fast: false + # matrix: + # chip: ["esp32", "esp32s2", "esp32s3"] + # + # steps: + # - uses: actions/checkout@v4 + # - uses: esp-rs/xtensa-toolchain@v1.5 + # with: + # default: true + # ldproxy: false + # - uses: Swatinem/rust-cache@v2 + # + # # Build the 'xtensa-lx-rt' package: + # - name: check (${{ matrix.chip }}, no features) + # run: cd xtensa-lx-rt/ && cargo build --features=${{ matrix.chip }} + # - name: check (${{ matrix.chip }}, all features) + # run: cd xtensa-lx-rt/ && cargo build --features=${{ matrix.chip }},float-save-restore + + # -------------------------------------------------------------------------- + # Lint + + rustfmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + # Some of the configuration items in 'rustfmt.toml' require the 'nightly' + # release channel: + - uses: dtolnay/rust-toolchain@v1 + with: + toolchain: nightly + components: rustfmt + - uses: Swatinem/rust-cache@v2 + + # Check the formatting of all packages: + - name: rustfmt (xtensa-lx) + run: cargo fmt --all --manifest-path=xtensa-lx/Cargo.toml -- --check + - name: rustfmt (xtensa-lx-rt) + run: cargo fmt --all --manifest-path=xtensa-lx-rt/Cargo.toml -- --check diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..0a9902d --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,9 @@ +# Comments +format_code_in_doc_comments = true +normalize_comments = true +wrap_comments = true + +# Imports +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +imports_layout = "HorizontalVertical" diff --git a/xtensa-lx-rt/build.rs b/xtensa-lx-rt/build.rs index 3326c8e..a5dabc2 100644 --- a/xtensa-lx-rt/build.rs +++ b/xtensa-lx-rt/build.rs @@ -1,8 +1,10 @@ -use std::collections::{HashMap, HashSet}; -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; +use std::{ + collections::{HashMap, HashSet}, + env, + fs::File, + io::Write, + path::PathBuf, +}; use core_isa_parser::{get_config, Chip, Value}; use minijinja::{context, Environment}; @@ -35,7 +37,8 @@ fn handle_esp32() { let mut features_to_disable: HashSet = HashSet::new(); - // Users can pass -Ctarget-feature to the compiler multiple times, so we have to handle that + // Users can pass -Ctarget-feature to the compiler multiple times, so we have to + // handle that let target_flags = rustflags .split(0x1f as char) .filter(|s| s.starts_with("target-feature=")) diff --git a/xtensa-lx-rt/procmacros/src/lib.rs b/xtensa-lx-rt/procmacros/src/lib.rs index 637d0f2..f41b93b 100644 --- a/xtensa-lx-rt/procmacros/src/lib.rs +++ b/xtensa-lx-rt/procmacros/src/lib.rs @@ -80,8 +80,9 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { let ty = &statik.ty; let attrs = &statik.attrs; - // Note that we use an explicit `'static` lifetime for the entry point arguments. This makes - // it more flexible, and is sound here, since the entry will not be called again, ever. + // Note that we use an explicit `'static` lifetime for the entry point + // arguments. This makes it more flexible, and is sound here, since the + // entry will not be called again, ever. syn::parse::( quote!(#[allow(non_snake_case)] #(#attrs)* #ident: &'static mut #ty).into(), ) @@ -201,12 +202,13 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream { .into() } -/// Marks a function as the interrupt handler, with optional interrupt level indicated +/// Marks a function as the interrupt handler, with optional interrupt level +/// indicated /// -/// When the function is also marked `#[naked]`, it is a low-level interrupt handler: -/// no entry and exit code to store processor state will be generated. -/// The user needs to ensure that all registers which are used are saved and restored and that -/// the proper return instruction is used. +/// When the function is also marked `#[naked]`, it is a low-level interrupt +/// handler: no entry and exit code to store processor state will be generated. +/// The user needs to ensure that all registers which are used are saved and +/// restored and that the proper return instruction is used. #[proc_macro_attribute] pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { let mut f: ItemFn = syn::parse(input).expect("`#[interrupt]` must be applied to a function"); @@ -403,8 +405,8 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { } } -/// Marks a function as the pre_init function. This function is called before main and *before -/// the memory is initialized*. +/// Marks a function as the pre_init function. This function is called before +/// main and *before the memory is initialized*. #[proc_macro_attribute] pub fn pre_init(args: TokenStream, input: TokenStream) -> TokenStream { let f = parse_macro_input!(input as ItemFn); diff --git a/xtensa-lx-rt/src/exception.rs b/xtensa-lx-rt/src/exception.rs index 4b39afe..962ddb3 100644 --- a/xtensa-lx-rt/src/exception.rs +++ b/xtensa-lx-rt/src/exception.rs @@ -1,38 +1,37 @@ //! Exception handling //! -//! Currently specialized for ESP32 (LX6) configuration: which extra registers to store, -//! how many interrupt levels etc. +//! Currently specialized for ESP32 (LX6) configuration: which extra registers +//! to store, how many interrupt levels etc. //! -//! First level interrupts and exceptions save full processor state to the user stack. -//! This includes the coprocessor registers contrary to the esp-idf where these are lazily saved. -//! (Kernel mode option is currently not used.) +//! First level interrupts and exceptions save full processor state to the user +//! stack. This includes the coprocessor registers contrary to the esp-idf where +//! these are lazily saved. (Kernel mode option is currently not used.) //! //! WindowUnder/Overflow and AllocA use default Xtensa implementation. //! -//! LoadStoreError and Unaligned are not (yet) implemented: so all accesses to IRAM must -//! be word sized and aligned. +//! LoadStoreError and Unaligned are not (yet) implemented: so all accesses to +//! IRAM must be word sized and aligned. //! //! Syscall 0 is not (yet) implemented: it doesn't seem to be used in rust. //! -//! Double Exceptions can only occur during the early setup of the exception handler. Afterwards -//! PS.EXCM is set to 0 to be able to handle WindowUnderflow/Overflow and recursive exceptions will -//! happen instead. -//! -//! In various places call0 are used as long jump: `j.l` syntax is not supported and `call0` -//! can always be expanded to `mov a0,label; call a0`. Care must be taken since A0 is overwritten. +//! Double Exceptions can only occur during the early setup of the exception +//! handler. Afterwards PS.EXCM is set to 0 to be able to handle +//! WindowUnderflow/Overflow and recursive exceptions will happen instead. //! +//! In various places call0 are used as long jump: `j.l` syntax is not supported +//! and `call0` can always be expanded to `mov a0,label; call a0`. Care must be +//! taken since A0 is overwritten. mod asm; mod context; pub use context::Context; - /// EXCCAUSE register values /// -/// General Exception Causes. (Values of EXCCAUSE special register set by general exceptions, -/// which vector to the user, kernel, or double-exception vectors). -/// +/// General Exception Causes. (Values of EXCCAUSE special register set by +/// general exceptions, which vector to the user, kernel, or double-exception +/// vectors). #[allow(unused)] #[derive(Debug)] #[repr(C)] @@ -120,4 +119,3 @@ pub enum ExceptionCause { None = 255, } - diff --git a/xtensa-lx-rt/src/exception/asm.rs b/xtensa-lx-rt/src/exception/asm.rs index b481859..d4b4757 100644 --- a/xtensa-lx-rt/src/exception/asm.rs +++ b/xtensa-lx-rt/src/exception/asm.rs @@ -1,12 +1,13 @@ -use crate::cfg_asm; use core::arch::{asm, global_asm}; +use crate::cfg_asm; + // we could cfg symbols away and reduce frame size depending on features enabled // i.e the frame size is a fixed size based on all the features right now // we know at compile time if a target has loops for example, if it doesn't // we could cut that memory usage. -// However in order to conveniently use `addmi` we need 256-byte alignment anyway -// so wasting a bit more stack space seems to be the better option. +// However in order to conveniently use `addmi` we need 256-byte alignment +// anyway so wasting a bit more stack space seems to be the better option. // Additionally there is a chunk of memory reserved for spilled registers. global_asm!( " @@ -481,8 +482,8 @@ global_asm!( "# ); -/// Handle Other Exceptions or Level 1 interrupt by storing full context and then -/// calling regular function +/// Handle Other Exceptions or Level 1 interrupt by storing full context and +/// then calling regular function /// /// # Input: /// * A0 stored in EXCSAVE1 @@ -524,8 +525,9 @@ unsafe extern "C" fn __default_naked_exception() { ) } -/// Handle Double Exceptions by storing full context and then calling regular function -/// Double exceptions are not a normal occurrence. They indicate a bug of some kind. +/// Handle Double Exceptions by storing full context and then calling regular +/// function Double exceptions are not a normal occurrence. They indicate a bug +/// of some kind. /// /// # Input: /// * A0 stored in EXCSAVE1 @@ -602,7 +604,8 @@ global_asm!( "# ); -/// Handle Level 2 Interrupt by storing full context and then calling regular function +/// Handle Level 2 Interrupt by storing full context and then calling regular +/// function /// /// # Input: /// * A0 stored in EXCSAVE2 @@ -613,7 +616,8 @@ unsafe extern "C" fn __default_naked_level_2_interrupt() { asm!("HANDLE_INTERRUPT_LEVEL 2", options(noreturn)); } -/// Handle Level 3 Interrupt by storing full context and then calling regular function +/// Handle Level 3 Interrupt by storing full context and then calling regular +/// function /// /// # Input: /// * A0 stored in EXCSAVE3 @@ -624,7 +628,8 @@ unsafe extern "C" fn __default_naked_level_3_interrupt() { asm!("HANDLE_INTERRUPT_LEVEL 3", options(noreturn)); } -/// Handle Level 4 Interrupt by storing full context and then calling regular function +/// Handle Level 4 Interrupt by storing full context and then calling regular +/// function /// /// # Input: /// * A0 stored in EXCSAVE4 @@ -635,7 +640,8 @@ unsafe extern "C" fn __default_naked_level_4_interrupt() { asm!("HANDLE_INTERRUPT_LEVEL 4", options(noreturn)); } -/// Handle Level 5 Interrupt by storing full context and then calling regular function +/// Handle Level 5 Interrupt by storing full context and then calling regular +/// function /// /// # Input: /// * A0 stored in EXCSAVE5 @@ -646,7 +652,8 @@ unsafe extern "C" fn __default_naked_level_5_interrupt() { asm!("HANDLE_INTERRUPT_LEVEL 5", options(noreturn)); } -/// Handle Level 6 (=Debug) Interrupt by storing full context and then calling regular function +/// Handle Level 6 (=Debug) Interrupt by storing full context and then calling +/// regular function /// /// # Input: /// * A0 stored in EXCSAVE6 @@ -657,7 +664,8 @@ unsafe extern "C" fn __default_naked_level_6_interrupt() { asm!("HANDLE_INTERRUPT_LEVEL 6", options(noreturn)); } -/// Handle Level 7 (=NMI) Interrupt by storing full context and then calling regular function +/// Handle Level 7 (=NMI) Interrupt by storing full context and then calling +/// regular function /// /// # Input: /// * A0 stored in EXCSAVE7 diff --git a/xtensa-lx-rt/src/exception/context.rs b/xtensa-lx-rt/src/exception/context.rs index 10d1bd6..4c4099d 100644 --- a/xtensa-lx-rt/src/exception/context.rs +++ b/xtensa-lx-rt/src/exception/context.rs @@ -92,7 +92,8 @@ extern "Rust" { fn __exception(cause: ExceptionCause, save_frame: &mut Context); /// This symbol will be provided by the user via `#[exception]` fn __user_exception(cause: ExceptionCause, save_frame: &mut Context); - /// No attribute is supplied for this symbol as the double exception can hardly occur + /// No attribute is supplied for this symbol as the double exception can + /// hardly occur fn __double_exception(cause: ExceptionCause, save_frame: &mut Context); /// This symbol will be provided by the user via `#[interrupt(1)]` @@ -139,10 +140,11 @@ extern "C" fn __default_double_exception(cause: ExceptionCause, save_frame: &Con // // The interrupt handlers all use special return instructions. // rust still generates a ret.w instruction, which will never be reached. -// generation of the ret.w can be prevented by using core::intrinsics::unreachable, -// but then a break 15,1 will be generated (which takes 3 bytes instead of 2) or a 'loop {}', -// but then a jump to own address will be generated which is also 3 bytes. -// No way found yet to prevent this generation altogether. +// generation of the ret.w can be prevented by using +// core::intrinsics::unreachable, but then a break 15,1 will be generated (which +// takes 3 bytes instead of 2) or a 'loop {}', but then a jump to own address +// will be generated which is also 3 bytes. No way found yet to prevent this +// generation altogether. #[naked] #[no_mangle] diff --git a/xtensa-lx-rt/src/lib.rs b/xtensa-lx-rt/src/lib.rs index 418ab98..abc992e 100644 --- a/xtensa-lx-rt/src/lib.rs +++ b/xtensa-lx-rt/src/lib.rs @@ -58,8 +58,8 @@ pub unsafe extern "C" fn Reset() -> ! { // Copy of data segment is done by bootloader - // According to 4.4.6.2 of the xtensa isa, ccount and compare are undefined on reset, - // set all values to zero to disable + // According to 4.4.6.2 of the xtensa isa, ccount and compare are undefined on + // reset, set all values to zero to disable reset_internal_timers(); // move vec table diff --git a/xtensa-lx/Cargo.toml b/xtensa-lx/Cargo.toml index 43edb89..42eba7a 100644 --- a/xtensa-lx/Cargo.toml +++ b/xtensa-lx/Cargo.toml @@ -1,40 +1,24 @@ [package] -name = "xtensa-lx" -version = "0.8.0" -description = "Low level access for Xtensa LX processors and peripherals" -categories = ["embedded", "hardware-support", "no-std"] -keywords = ["xtensa", "lx", "register", "peripheral"] -license = "MIT OR Apache-2.0" -readme = "README.md" -repository = "https://github.com/esp-rs/xtensa-lx" -authors = ["Scott Mabin ", "Arjan Mels "] -edition = "2018" +name = "xtensa-lx" +version = "0.8.0" +edition = "2021" +description = "Low-level access for Xtensa LX processors and peripherals" +repository = "https://github.com/esp-rs/xtensa-lx" +license = "MIT OR Apache-2.0" +categories = ["embedded", "hardware-support", "no-std"] +keywords = ["lx", "peripheral", "register", "xtensa"] # Prevent multiple versions of this crate to be linked together links = "xtensa-lx" [package.metadata.docs.rs] -features = ["esp32"] +features = ["spin"] [dependencies] -bare-metal = "1.0.0" +bare-metal = "1.0.0" mutex-trait = "0.2.0" -spin = { version = "0.9.8", optional = true } +spin = { version = "0.9.8", optional = true } [features] -esp32 = ["ccompare0", "ccompare1", "ccompare2", "ccount", "spin"] -esp32s2 = ["ccompare0", "ccompare1", "ccompare2", "ccount"] -esp32s3 = ["ccompare0", "ccompare1", "ccompare2", "ccount", "spin"] - -# CPU configurations, taken from: https://github.com/espressif/xtensa-overlays - -# Timers up to 4 -ccompare0 = [] -ccompare1 = [] -ccompare2 = [] -ccompare3 = [] - -# ccount -ccount = [] - float-save-restore = [] +spin = ["dep:spin"] diff --git a/xtensa-lx/build.rs b/xtensa-lx/build.rs index d54d29c..56354ee 100644 --- a/xtensa-lx/build.rs +++ b/xtensa-lx/build.rs @@ -1,5 +1,4 @@ -use std::env; -use std::path::PathBuf; +use std::{env, path::PathBuf}; fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); diff --git a/xtensa-lx/src/interrupt.rs b/xtensa-lx/src/interrupt.rs index adeced6..bfbce1e 100644 --- a/xtensa-lx/src/interrupt.rs +++ b/xtensa-lx/src/interrupt.rs @@ -142,7 +142,9 @@ pub unsafe fn clear(mask: u32) { #[inline] pub fn get_level() -> u32 { let ps: u32; - unsafe { asm!("rsr.ps {0}", out(reg) ps, options(nostack)); }; + unsafe { + asm!("rsr.ps {0}", out(reg) ps, options(nostack)); + }; ps & 0xf } diff --git a/xtensa-lx/src/lib.rs b/xtensa-lx/src/lib.rs index a892519..3c54150 100644 --- a/xtensa-lx/src/lib.rs +++ b/xtensa-lx/src/lib.rs @@ -28,19 +28,24 @@ pub fn get_stack_pointer() -> *const u32 { /// Set the core stack pointer /// /// *This is highly unsafe!* -/// It should be used with care at e.g. program start or when building a task scheduler +/// It should be used with care at e.g. program start or when building a task +/// scheduler /// -/// `stack` pointer to the non-inclusive end of the stack (must be 16-byte aligned) +/// `stack` pointer to the non-inclusive end of the stack (must be 16-byte +/// aligned) #[inline(always)] pub unsafe fn set_stack_pointer(stack: *mut u32) { - // FIXME: this function relies on it getting inlined - if it doesn't inline it will try and return from this function using the adress in `a0` which has just been trashed... - // According to https://nnethercote.github.io/perf-book/inlining.html: - // "Inline attributes do not guarantee that a function is inlined or not inlined, but in practice, #[inline(always)] will cause inlining in all but the most exceptional cases." - // Is this good enough? Should we rewrite these as a macro to guarentee inlining? - - - // NOTE: modification of the `sp` & `a0` is not typically allowed inside inline asm!, - // but because we *need* to modify it we can do so by ommiting it from the clobber + // FIXME: this function relies on it getting inlined - if it doesn't inline it + // will try and return from this function using the adress in `a0` which has + // just been trashed... According to https://nnethercote.github.io/perf-book/inlining.html: + // "Inline attributes do not guarantee that a function is inlined or not + // inlined, but in practice, #[inline(always)] will cause inlining in all but + // the most exceptional cases." Is this good enough? Should we rewrite these + // as a macro to guarentee inlining? + + // NOTE: modification of the `sp` & `a0` is not typically allowed inside inline + // asm!, but because we *need* to modify it we can do so by ommiting it from + // the clobber asm!( "movi a0, 0", // trash return register "mov sp, {0}", // move stack pointer diff --git a/xtensa-lx/src/macros.rs b/xtensa-lx/src/macros.rs index 2490d49..31c7a0a 100644 --- a/xtensa-lx/src/macros.rs +++ b/xtensa-lx/src/macros.rs @@ -1,9 +1,10 @@ /// Macro to create a mutable reference to a statically allocated value /// -/// This macro returns a value with type `Option<&'static mut $ty>`. `Some($expr)` will be returned -/// the first time the macro is executed; further calls will return `None`. To avoid `unwrap`ping a -/// `None` variant the caller must ensure that the macro is called from a function that's executed -/// at most once in the whole lifetime of the program. +/// This macro returns a value with type `Option<&'static mut $ty>`. +/// `Some($expr)` will be returned the first time the macro is executed; further +/// calls will return `None`. To avoid `unwrap`ping a `None` variant the caller +/// must ensure that the macro is called from a function that's executed at most +/// once in the whole lifetime of the program. /// /// # Example /// diff --git a/xtensa-lx/src/mutex.rs b/xtensa-lx/src/mutex.rs index ba31fa4..cbb0b7e 100644 --- a/xtensa-lx/src/mutex.rs +++ b/xtensa-lx/src/mutex.rs @@ -5,13 +5,13 @@ use core::cell::UnsafeCell; pub use mutex_trait::{self, Mutex}; /// A spinlock and critical section section based mutex. -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] #[derive(Default)] pub struct CriticalSectionSpinLockMutex { data: spin::Mutex, } -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] impl CriticalSectionSpinLockMutex { /// Create a new mutex pub const fn new(data: T) -> Self { @@ -21,7 +21,7 @@ impl CriticalSectionSpinLockMutex { } } -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] impl mutex_trait::Mutex for &'_ CriticalSectionSpinLockMutex { type Data = T; @@ -33,7 +33,7 @@ impl mutex_trait::Mutex for &'_ CriticalSectionSpinLockMutex { // NOTE A `Mutex` can be used as a channel so the protected data must be `Send` // to prevent sending non-Sendable stuff (e.g. access tokens) across different // execution contexts (e.g. interrupts) -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] unsafe impl Sync for CriticalSectionSpinLockMutex where T: Send {} /// A Mutex based on critical sections @@ -42,7 +42,8 @@ unsafe impl Sync for CriticalSectionSpinLockMutex where T: Send {} /// /// **This Mutex is only safe on single-core applications.** /// -/// A `CriticalSection` **is not sufficient** to ensure exclusive access across cores. +/// A `CriticalSection` **is not sufficient** to ensure exclusive access across +/// cores. #[derive(Default)] pub struct CriticalSectionMutex { data: UnsafeCell, @@ -71,13 +72,13 @@ impl mutex_trait::Mutex for &'_ CriticalSectionMutex { unsafe impl Sync for CriticalSectionMutex where T: Send {} /// A spinlock based mutex. -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] #[derive(Default)] pub struct SpinLockMutex { data: spin::Mutex, } -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] impl SpinLockMutex { /// Create a new mutex pub const fn new(data: T) -> Self { @@ -87,7 +88,7 @@ impl SpinLockMutex { } } -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] impl mutex_trait::Mutex for &'_ SpinLockMutex { type Data = T; @@ -99,5 +100,5 @@ impl mutex_trait::Mutex for &'_ SpinLockMutex { // NOTE A `Mutex` can be used as a channel so the protected data must be `Send` // to prevent sending non-Sendable stuff (e.g. access tokens) across different // execution contexts (e.g. interrupts) -#[cfg(not(feature = "esp32s2"))] +#[cfg(feature = "spin")] unsafe impl Sync for SpinLockMutex where T: Send {} diff --git a/xtensa-lx/src/timer.rs b/xtensa-lx/src/timer.rs index 5f62168..a21aa10 100644 --- a/xtensa-lx/src/timer.rs +++ b/xtensa-lx/src/timer.rs @@ -2,21 +2,20 @@ use core::arch::asm; -#[cfg(feature = "ccompare0")] #[inline] pub fn get_ccompare0() -> u32 { let x: u32; unsafe { asm!("rsr.ccompare0 {0}", out(reg) x, options(nostack)) }; x } -#[cfg(feature = "ccompare1")] + #[inline] pub fn get_ccompare1() -> u32 { let x: u32; unsafe { asm!("rsr.ccompare1 {0}", out(reg) x, options(nostack)) }; x } -#[cfg(feature = "ccompare2")] + #[inline] pub fn get_ccompare2() -> u32 { let x: u32; @@ -24,7 +23,6 @@ pub fn get_ccompare2() -> u32 { x } -#[cfg(feature = "ccompare3")] #[inline] pub fn get_ccompare3() -> u32 { let x: u32; @@ -32,7 +30,6 @@ pub fn get_ccompare3() -> u32 { x } -#[cfg(feature = "ccompare0")] #[inline] pub fn set_ccompare0(val: u32) { unsafe { @@ -42,7 +39,7 @@ pub fn set_ccompare0(val: u32) { ", in(reg) val, options(nostack)) }; } -#[cfg(feature = "ccompare1")] + #[inline] pub fn set_ccompare1(val: u32) { unsafe { @@ -52,7 +49,7 @@ pub fn set_ccompare1(val: u32) { ", in(reg) val, options(nostack)) }; } -#[cfg(feature = "ccompare2")] + #[inline] pub fn set_ccompare2(val: u32) { unsafe { @@ -62,7 +59,7 @@ pub fn set_ccompare2(val: u32) { ", in(reg) val, options(nostack)) }; } -#[cfg(feature = "ccompare3")] + #[inline] pub fn set_ccompare3(val: u32) { unsafe { @@ -74,7 +71,6 @@ pub fn set_ccompare3(val: u32) { } /// Get the core cycle count -#[cfg(feature = "ccount")] #[inline] pub fn get_cycle_count() -> u32 { let x: u32; @@ -83,7 +79,6 @@ pub fn get_cycle_count() -> u32 { } /// cycle accurate delay using the cycle counter register -#[cfg(feature = "ccount")] #[inline] pub fn delay(clocks: u32) { let start = get_cycle_count();