Skip to content

Commit

Permalink
Use addr_of_mut! to access static muts.
Browse files Browse the repository at this point in the history
Newer versions of Rust disallow taking a
&mut reference on static mut variables.
  • Loading branch information
surban committed May 6, 2024
1 parent ce74fb5 commit fc304de
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 8 deletions.
6 changes: 4 additions & 2 deletions defmt-ringbuf/defmt-ringbuf-test/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![no_std]
#![no_main]

use core::mem;
use core::{mem, ptr::addr_of_mut};
use cortex_m::{asm::nop, peripheral::SCB};
use cortex_m_rt::entry;

Expand All @@ -20,7 +20,9 @@ fn main() -> ! {
let _dp = Peripherals::take().unwrap();

defmt::info!("Init");
let buffer = unsafe { RingBuffer::init(&mut BUFFER) };

// Safety: BUFFER is only accessed here and nowhere else.
let buffer = unsafe { RingBuffer::init(&mut *addr_of_mut!(BUFFER)) };

let mut data = [0; 128];
let (n, lost) = buffer.read(&mut data);
Expand Down
3 changes: 1 addition & 2 deletions defmt-ringbuf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ fn do_write(data: &[u8]) {
/// This must be called exactly once.
/// Log messages received before initiailization are discarded.
pub unsafe fn init<const SIZE: usize>(
ring_buffer: &'static mut MaybeUninit<RingBuffer<SIZE>>,
log_available: fn(),
ring_buffer: &'static mut MaybeUninit<RingBuffer<SIZE>>, log_available: fn(),
) {
defmt::assert!(RING_BUFFER.is_none());

Expand Down
4 changes: 3 additions & 1 deletion openemc-bootloader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ fn main() -> ! {
// Initialize logging.
#[cfg(feature = "defmt-ringbuf")]
unsafe {
defmt_ringbuf::init(&mut BOOTLOADER_LOG, || ());
use core::ptr::addr_of_mut;
// Safety: BOOTLOADER_LOG is only accessed here and nowhere else while the bootloader is running.
defmt_ringbuf::init(&mut *addr_of_mut!(BOOTLOADER_LOG), || ());
}

// Enable backup domain and check for valid signature.
Expand Down
14 changes: 13 additions & 1 deletion openemc-firmware/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use core::{
ptr,
ptr::{addr_of, addr_of_mut},
slice,
sync::atomic::{AtomicBool, Ordering},
};
use cortex_m::peripheral::{scb::Exception, SCB};
use stm32f1::stm32f103::Peripherals;
Expand Down Expand Up @@ -82,8 +83,13 @@ pub trait BootInfoExt {
fn bootloader_version(&self) -> Option<&[u8]>;
}

/// Whether boot information has been initialized.
static BOOT_INFO_INITIALIZED: AtomicBool = AtomicBool::new(false);

impl BootInfoExt for BootInfo {
unsafe fn init(bkp: &BackupDomain) {
defmt::assert!(!BOOT_INFO_INITIALIZED.load(Ordering::SeqCst));

// Make sure BOOT_INFO is read from memory.
let ptr = BOOT_INFO.as_mut_ptr();
let powered_on_ptr = addr_of_mut!((*ptr).powered_on) as *mut u8;
Expand All @@ -107,13 +113,19 @@ impl BootInfoExt for BootInfo {
// Get boot reason.
STANDALONE_BOOT_INFO.boot_reason = BootReason::get(bkp);
}

BOOT_INFO_INITIALIZED.store(true, Ordering::SeqCst);
}

fn get() -> &'static Self {
defmt::assert!(BOOT_INFO_INITIALIZED.load(Ordering::SeqCst));

if Self::is_from_bootloader() {
// Safety: BOOT_INFO has been verified during init()
unsafe { BOOT_INFO.assume_init_ref() }
} else {
unsafe { &STANDALONE_BOOT_INFO }
// Safety: STANDALONE_BOOT_INFO is only modified during init()
unsafe { &*ptr::addr_of!(STANDALONE_BOOT_INFO) }
}
}

Expand Down
7 changes: 5 additions & 2 deletions openemc-firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,11 @@ mod app {
// Initialize logging.
#[cfg(feature = "defmt-ringbuf")]
unsafe {
defmt_ringbuf::init(&mut LOG, || NVIC::pend(Interrupt::USART3));
BOOTLOADER_LOG_REF = Some(defmt_ringbuf::RingBuffer::init(&mut BOOTLOADER_LOG));
use core::ptr::addr_of_mut;
// Safety: LOG is only accessed here and nowhere else.
defmt_ringbuf::init(&mut *addr_of_mut!(LOG), || NVIC::pend(Interrupt::USART3));
// Safety: BOOTLOADER_LOG is only accessed here and nowhere else.
BOOTLOADER_LOG_REF = Some(defmt_ringbuf::RingBuffer::init(&mut *addr_of_mut!(BOOTLOADER_LOG)));
}

defmt::warn!("OpenEMC version {:a}", VERSION);
Expand Down
2 changes: 2 additions & 0 deletions scripts/crates-fmt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ cargo +nightly fmt --manifest-path openemc-firmware/Cargo.toml
cargo +nightly fmt --manifest-path openemc-shared/Cargo.toml
cargo +nightly fmt --manifest-path openemc-log/Cargo.toml
cargo +nightly fmt --manifest-path xtask/Cargo.toml
cargo +nightly fmt --manifest-path defmt-ringbuf/Cargo.toml
cargo +nightly fmt --manifest-path defmt-ringbuf/defmt-ringbuf-test/Cargo.toml

rustup run nightly rustfmt openemc-bootloader/src/boards/*.rs
rustup run nightly rustfmt openemc-firmware/src/boards/*.rs

0 comments on commit fc304de

Please sign in to comment.