diff --git a/defmt-ringbuf/defmt-ringbuf-test/src/main.rs b/defmt-ringbuf/defmt-ringbuf-test/src/main.rs index 099bc27..c832c01 100644 --- a/defmt-ringbuf/defmt-ringbuf-test/src/main.rs +++ b/defmt-ringbuf/defmt-ringbuf-test/src/main.rs @@ -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; @@ -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); diff --git a/defmt-ringbuf/src/lib.rs b/defmt-ringbuf/src/lib.rs index 5fcf850..73c4ac3 100644 --- a/defmt-ringbuf/src/lib.rs +++ b/defmt-ringbuf/src/lib.rs @@ -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( - ring_buffer: &'static mut MaybeUninit>, - log_available: fn(), + ring_buffer: &'static mut MaybeUninit>, log_available: fn(), ) { defmt::assert!(RING_BUFFER.is_none()); diff --git a/openemc-bootloader/src/main.rs b/openemc-bootloader/src/main.rs index a4384a4..552e76e 100644 --- a/openemc-bootloader/src/main.rs +++ b/openemc-bootloader/src/main.rs @@ -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. diff --git a/openemc-firmware/src/boot.rs b/openemc-firmware/src/boot.rs index 62c3517..3467127 100644 --- a/openemc-firmware/src/boot.rs +++ b/openemc-firmware/src/boot.rs @@ -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; @@ -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; @@ -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) } } } diff --git a/openemc-firmware/src/main.rs b/openemc-firmware/src/main.rs index e6514fc..0ec59e8 100644 --- a/openemc-firmware/src/main.rs +++ b/openemc-firmware/src/main.rs @@ -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); diff --git a/scripts/crates-fmt.sh b/scripts/crates-fmt.sh index 452bee5..d71f531 100755 --- a/scripts/crates-fmt.sh +++ b/scripts/crates-fmt.sh @@ -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