Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed use of static mut. #85

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nrf52-code/boards/dk-solution/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ cortex-m-semihosting = "0.5.0"
defmt = "0.3.5"
defmt-rtt = "0.4"
embedded-hal = "0.2.7"
grounded = { version = "0.2.0", features = ["cas"] }
hal = { package = "nrf52840-hal", version = "0.16.0" }

[features]
Expand Down
40 changes: 32 additions & 8 deletions nrf52-code/boards/dk-solution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ use core::{
use cortex_m::peripheral::NVIC;
use cortex_m_semihosting::debug;
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
#[cfg(feature = "radio")]
#[cfg(any(feature = "advanced"))]
use grounded::uninit::GroundedArrayCell;
#[cfg(any(feature = "radio"))]
use grounded::uninit::GroundedCell;
#[cfg(any(feature = "radio"))]
pub use hal::ieee802154;
pub use hal::pac::{interrupt, Interrupt, NVIC_PRIO_BITS, RTC0};
use hal::{
Expand All @@ -40,6 +44,14 @@ pub mod peripheral;
#[cfg(feature = "advanced")]
pub mod usbd;

#[cfg(feature = "radio")]
struct ClockSyncWrapper<H, L, LSTAT> {
clocks: Clocks<H, L, LSTAT>,
}

#[cfg(feature = "radio")]
unsafe impl<H, L, LSTAT> Sync for ClockSyncWrapper<H, L, LSTAT> {}

/// Components on the board
pub struct Board {
/// LEDs
Expand Down Expand Up @@ -210,6 +222,7 @@ impl ops::DerefMut for Timer {
}

/// The ways that initialisation can fail
#[derive(Debug, Copy, Clone, defmt::Format)]
pub enum Error {
/// You tried to initialise the board twice
DoubleInit = 1,
Expand All @@ -224,12 +237,16 @@ pub fn init() -> Result<Board, Error> {
};
// NOTE(static mut) this branch runs at most once
#[cfg(feature = "advanced")]
static mut EP0IN_BUF: [u8; 64] = [0; 64];
static EP0IN_BUF: GroundedArrayCell<u8, 64> = GroundedArrayCell::const_init();
#[cfg(feature = "radio")]
static mut CLOCKS: Option<
Clocks<clocks::ExternalOscillator, clocks::ExternalOscillator, clocks::LfOscStarted>,
> = None;

// We need the wrapper to make this type Sync, as it contains raw pointers
static CLOCKS: GroundedCell<
ClockSyncWrapper<
clocks::ExternalOscillator,
clocks::ExternalOscillator,
clocks::LfOscStarted,
>,
> = GroundedCell::uninit();
defmt::debug!("Initializing the board");

let clocks = Clocks::new(periph.CLOCK);
Expand All @@ -239,7 +256,14 @@ pub fn init() -> Result<Board, Error> {
let _clocks = clocks.enable_ext_hfosc();
// extend lifetime to `'static`
#[cfg(feature = "radio")]
let clocks = unsafe { CLOCKS.get_or_insert(_clocks) };
let clocks = unsafe {
let clocks_ptr = CLOCKS.get();
clocks_ptr.write(ClockSyncWrapper { clocks: _clocks });
// Now it's initialised, we can take a static reference to the clocks
// object it contains.
let clock_wrapper: &'static ClockSyncWrapper<_, _, _> = &*clocks_ptr;
&clock_wrapper.clocks
};

defmt::debug!("Clocks configured");

Expand Down Expand Up @@ -311,7 +335,7 @@ pub fn init() -> Result<Board, Error> {
#[cfg(feature = "advanced")]
power: periph.POWER,
#[cfg(feature = "advanced")]
ep0in: unsafe { Ep0In::new(&mut EP0IN_BUF) },
ep0in: unsafe { Ep0In::new(&EP0IN_BUF) },
})
}

Expand Down
15 changes: 10 additions & 5 deletions nrf52-code/boards/dk-solution/src/usbd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

use core::sync::atomic::{self, Ordering};

use grounded::uninit::GroundedArrayCell;

use crate::{
errata,
peripheral::{POWER, USBD},
};

/// Endpoint IN 0
pub struct Ep0In {
buffer: &'static mut [u8; 64],
buffer: &'static GroundedArrayCell<u8, 64>,
busy: bool,
}

impl Ep0In {
/// # Safety
/// Must be created at most once (singleton)
pub(crate) unsafe fn new(buffer: &'static mut [u8; 64]) -> Self {
pub(crate) unsafe fn new(buffer: &'static GroundedArrayCell<u8, 64>) -> Self {
Self {
buffer,
busy: false,
Expand All @@ -30,14 +32,17 @@ impl Ep0In {
/// - This function panics if the last transfer was not finished by calling the `end` function
/// - This function panics if `bytes` is larger than the maximum packet size (64 bytes)
pub fn start(&mut self, bytes: &[u8], usbd: &USBD) {
let (buffer_ptr, buffer_len) = self.buffer.get_ptr_len();
assert!(!self.busy, "EP0IN: last transfer has not completed");
assert!(
bytes.len() <= self.buffer.len(),
bytes.len() <= buffer_len,
"EP0IN: multi-packet data transfers are not supported"
);

let n = bytes.len();
self.buffer[..n].copy_from_slice(bytes);
unsafe {
core::ptr::copy_nonoverlapping(bytes.as_ptr(), buffer_ptr, n);
}

// use a "shortcut" to issue a status stage after the data transfer is complete
usbd.shorts
Expand All @@ -47,7 +52,7 @@ impl Ep0In {
.write(|w| unsafe { w.maxcnt().bits(n as u8) });
usbd.epin0
.ptr
.write(|w| unsafe { w.ptr().bits(self.buffer.as_ptr() as u32) });
.write(|w| unsafe { w.ptr().bits(buffer_ptr as u32) });

self.busy = true;

Expand Down
1 change: 1 addition & 0 deletions nrf52-code/boards/dk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ cortex-m-semihosting = "0.5.0"
defmt = "0.3.5"
defmt-rtt = "0.4"
embedded-hal = "0.2.7"
grounded = { version = "0.2.0", features = ["cas"] }
hal = { package = "nrf52840-hal", version = "0.16.0" }

[features]
Expand Down
39 changes: 31 additions & 8 deletions nrf52-code/boards/dk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ use core::{
use cortex_m::peripheral::NVIC;
use cortex_m_semihosting::debug;
use embedded_hal::digital::v2::{OutputPin, StatefulOutputPin};
#[cfg(feature = "radio")]
#[cfg(any(feature = "advanced"))]
use grounded::uninit::GroundedArrayCell;
#[cfg(any(feature = "radio"))]
use grounded::uninit::GroundedCell;
#[cfg(any(feature = "radio"))]
pub use hal::ieee802154;
pub use hal::pac::{interrupt, Interrupt, NVIC_PRIO_BITS, RTC0};
use hal::{
Expand All @@ -40,6 +44,14 @@ pub mod peripheral;
#[cfg(feature = "advanced")]
pub mod usbd;

#[cfg(feature = "radio")]
struct ClockSyncWrapper<H, L, LSTAT> {
clocks: Clocks<H, L, LSTAT>,
}

#[cfg(feature = "radio")]
unsafe impl<H, L, LSTAT> Sync for ClockSyncWrapper<H, L, LSTAT> {}

/// Components on the board
pub struct Board {
/// LEDs
Expand Down Expand Up @@ -199,12 +211,16 @@ pub fn init() -> Result<Board, Error> {
};
// NOTE(static mut) this branch runs at most once
#[cfg(feature = "advanced")]
static mut EP0IN_BUF: [u8; 64] = [0; 64];
static EP0IN_BUF: GroundedArrayCell<u8, 64> = GroundedArrayCell::const_init();
#[cfg(feature = "radio")]
static mut CLOCKS: Option<
Clocks<clocks::ExternalOscillator, clocks::ExternalOscillator, clocks::LfOscStarted>,
> = None;

// We need the wrapper to make this type Sync, as it contains raw pointers
static CLOCKS: GroundedCell<
ClockSyncWrapper<
clocks::ExternalOscillator,
clocks::ExternalOscillator,
clocks::LfOscStarted,
>,
> = GroundedCell::uninit();
defmt::debug!("Initializing the board");

let clocks = Clocks::new(periph.CLOCK);
Expand All @@ -214,7 +230,14 @@ pub fn init() -> Result<Board, Error> {
let _clocks = clocks.enable_ext_hfosc();
// extend lifetime to `'static`
#[cfg(feature = "radio")]
let clocks = unsafe { CLOCKS.get_or_insert(_clocks) };
let clocks = unsafe {
let clocks_ptr = CLOCKS.get();
clocks_ptr.write(ClockSyncWrapper { clocks: _clocks });
// Now it's initialised, we can take a static reference to the clocks
// object it contains.
let clock_wrapper: &'static ClockSyncWrapper<_, _, _> = &*clocks_ptr;
&clock_wrapper.clocks
};

defmt::debug!("Clocks configured");

Expand Down Expand Up @@ -274,7 +297,7 @@ pub fn init() -> Result<Board, Error> {
#[cfg(feature = "advanced")]
power: periph.POWER,
#[cfg(feature = "advanced")]
ep0in: unsafe { Ep0In::new(&mut EP0IN_BUF) },
ep0in: unsafe { Ep0In::new(&EP0IN_BUF) },
})
}

Expand Down
15 changes: 10 additions & 5 deletions nrf52-code/boards/dk/src/usbd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

use core::sync::atomic::{self, Ordering};

use grounded::uninit::GroundedArrayCell;

use crate::{
errata,
peripheral::{POWER, USBD},
};

/// Endpoint IN 0
pub struct Ep0In {
buffer: &'static mut [u8; 64],
buffer: &'static GroundedArrayCell<u8, 64>,
busy: bool,
}

impl Ep0In {
/// # Safety
/// Must be created at most once (singleton)
pub(crate) unsafe fn new(buffer: &'static mut [u8; 64]) -> Self {
pub(crate) unsafe fn new(buffer: &'static GroundedArrayCell<u8, 64>) -> Self {
Self {
buffer,
busy: false,
Expand All @@ -30,14 +32,17 @@ impl Ep0In {
/// - This function panics if the last transfer was not finished by calling the `end` function
/// - This function panics if `bytes` is larger than the maximum packet size (64 bytes)
pub fn start(&mut self, bytes: &[u8], usbd: &USBD) {
let (buffer_ptr, buffer_len) = self.buffer.get_ptr_len();
assert!(!self.busy, "EP0IN: last transfer has not completed");
assert!(
bytes.len() <= self.buffer.len(),
bytes.len() <= buffer_len,
"EP0IN: multi-packet data transfers are not supported"
);

let n = bytes.len();
self.buffer[..n].copy_from_slice(bytes);
unsafe {
core::ptr::copy_nonoverlapping(bytes.as_ptr(), buffer_ptr, n);
}

// use a "shortcut" to issue a status stage after the data transfer is complete
usbd.shorts
Expand All @@ -47,7 +52,7 @@ impl Ep0In {
.write(|w| unsafe { w.maxcnt().bits(n as u8) });
usbd.epin0
.ptr
.write(|w| unsafe { w.ptr().bits(self.buffer.as_ptr() as u32) });
.write(|w| unsafe { w.ptr().bits(buffer_ptr as u32) });

self.busy = true;

Expand Down
17 changes: 16 additions & 1 deletion nrf52-code/hal-app/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions nrf52-code/radio-app/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions nrf52-code/usb-app-solutions/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading