svd2rust
svd2rust copied to clipboard
Support for atomic `Peripherals::take()`
Hello,
I'm currently working on a toy kernel on a raspberry pi, and I'm using svd2rust to generate the bindings to the aarch64 BCM2837 chip that the raspberry pi 3b is running on.
When generating the peripherals I cannot select a Target
because the aarch64 is multi-core and critical sections do not work. Therefor the Peripherals::take() -> Option<Self>
method won't be generated.
Currently I inject the following code into the generated output:
use core::sync::atomic::{AtomicBool, Ordering};
static LOCKED: AtomicBool = AtomicBool::new(false);
impl Peripherals {
pub fn take() -> Option<Self> {
let was_locked = LOCKED.compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire).is_ok();
if was_locked {
None
} else {
Some(unsafe { Self::steal() })
}
}
}
impl Drop for Peripherals {
fn drop(&mut self) {
LOCKED.store(false, Ordering::Relaxed);
}
}
I was considering porting this to svd2rust but I'm not sure how to approach this. I could:
- add a
Target::Atomic
- Add a
Target::Custom(TargetOptions)
and
#[non_exhaustive]
#[derive(Default)]
pub struct TargetOptions {
pub atomic: bool,
pub interrupt_free: bool,
// other options
}
(This would make all the other Target
an alias for a hard-coded TargetOptions
implementation)
- Add a new boolean field to
svd2rust::utils::Config
to overwritePeripherals::take()
with an atomic implementation when that field is set
Or maybe another approach is better. What do you think?
I think it makes sense to do it the other way around, Target is the core thing, and TargetOptions is what is consumed, it has the target and its options
@VictorKoenders, does https://github.com/rust-embedded/svd2rust/pull/651 fix this? You will need an implementation for critical_section
that works correctly on multi-core of course.
Closing as solved