diff --git a/Cargo.toml b/Cargo.toml index e2c1df3d..d1b08e71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,6 +83,7 @@ tinybmp = "0.5" embedded-graphics = "0.8" otm8009a = "0.1" eg-seven-segment = "0.2.0" +static_cell = "2.1.0" [features] default = ["rt"] diff --git a/examples/dma.rs b/examples/dma.rs index c1ec1762..e0463819 100644 --- a/examples/dma.rs +++ b/examples/dma.rs @@ -1,6 +1,7 @@ //! Example of Memory to Memory Transfer with the DMA #![deny(warnings)] +#![allow(static_mut_refs)] #![no_main] #![no_std] diff --git a/examples/ethernet-nucleo-h743zi2.rs b/examples/ethernet-nucleo-h743zi2.rs index 917f56d8..e8aaede6 100644 --- a/examples/ethernet-nucleo-h743zi2.rs +++ b/examples/ethernet-nucleo-h743zi2.rs @@ -13,7 +13,6 @@ #![no_std] extern crate cortex_m_rt as rt; -use core::mem::MaybeUninit; use core::sync::atomic::{AtomicU32, Ordering}; use rt::{entry, exception}; @@ -22,6 +21,7 @@ extern crate cortex_m; #[macro_use] mod utilities; use log::info; +use static_cell::StaticCell; use stm32h7xx_hal::rcc::CoreClocks; use stm32h7xx_hal::{ethernet, ethernet::PHY}; @@ -52,8 +52,7 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; /// Ethernet descriptor rings are a global singleton #[link_section = ".sram3.eth"] -static mut DES_RING: MaybeUninit> = - MaybeUninit::uninit(); +static DES_RING: StaticCell> = StaticCell::new(); // the program entry point #[entry] @@ -113,30 +112,26 @@ fn main() -> ! { assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000); // PCLK 100MHz let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); - let (_eth_dma, eth_mac) = unsafe { - DES_RING.write(ethernet::DesRing::new()); - - ethernet::new( - dp.ETHERNET_MAC, - dp.ETHERNET_MTL, - dp.ETHERNET_DMA, - ( - rmii_ref_clk, - rmii_mdio, - rmii_mdc, - rmii_crs_dv, - rmii_rxd0, - rmii_rxd1, - rmii_tx_en, - rmii_txd0, - rmii_txd1, - ), - DES_RING.assume_init_mut(), - mac_addr, - ccdr.peripheral.ETH1MAC, - &ccdr.clocks, - ) - }; + let (_eth_dma, eth_mac) = ethernet::new( + dp.ETHERNET_MAC, + dp.ETHERNET_MTL, + dp.ETHERNET_DMA, + ( + rmii_ref_clk, + rmii_mdio, + rmii_mdc, + rmii_crs_dv, + rmii_rxd0, + rmii_rxd1, + rmii_tx_en, + rmii_txd0, + rmii_txd1, + ), + DES_RING.init_with(ethernet::DesRing::new), + mac_addr, + ccdr.peripheral.ETH1MAC, + &ccdr.clocks, + ); // Initialise ethernet PHY... let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac.set_phy_addr(0)); diff --git a/examples/ethernet-rtic-nucleo-h723zg.rs b/examples/ethernet-rtic-nucleo-h723zg.rs index b155bec7..4d1d7593 100644 --- a/examples/ethernet-rtic-nucleo-h723zg.rs +++ b/examples/ethernet-rtic-nucleo-h723zg.rs @@ -19,14 +19,14 @@ #[allow(unused)] mod utilities; -use core::mem::MaybeUninit; -use core::ptr::addr_of_mut; use core::sync::atomic::AtomicU32; use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage}; use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr}; +use static_cell::StaticCell; + use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; /// Configure SYSTICK for 1ms timebase @@ -49,17 +49,16 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; /// Ethernet descriptor rings are a global singleton #[link_section = ".axisram.eth"] -static mut DES_RING: MaybeUninit> = - MaybeUninit::uninit(); +static DES_RING: StaticCell> = StaticCell::new(); /// Net storage with static initialisation - another global singleton pub struct NetStorageStatic<'a> { socket_storage: [SocketStorage<'a>; 8], } -// MaybeUninit allows us write code that is correct even if STORE is not +// StaticCell allows us write code that is correct even if STORE is not // initialised by the runtime -static mut STORE: MaybeUninit = MaybeUninit::uninit(); +static STORE: StaticCell = StaticCell::new(); pub struct Net<'a> { iface: Interface, @@ -163,30 +162,26 @@ mod app { assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000); // PCLK 100MHz let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); - let (eth_dma, eth_mac) = unsafe { - DES_RING.write(ethernet::DesRing::new()); - - ethernet::new( - ctx.device.ETHERNET_MAC, - ctx.device.ETHERNET_MTL, - ctx.device.ETHERNET_DMA, - ( - rmii_ref_clk, - rmii_mdio, - rmii_mdc, - rmii_crs_dv, - rmii_rxd0, - rmii_rxd1, - rmii_tx_en, - rmii_txd0, - rmii_txd1, - ), - DES_RING.assume_init_mut(), - mac_addr, - ccdr.peripheral.ETH1MAC, - &ccdr.clocks, - ) - }; + let (eth_dma, eth_mac) = ethernet::new( + ctx.device.ETHERNET_MAC, + ctx.device.ETHERNET_MTL, + ctx.device.ETHERNET_DMA, + ( + rmii_ref_clk, + rmii_mdio, + rmii_mdc, + rmii_crs_dv, + rmii_rxd0, + rmii_rxd1, + rmii_tx_en, + rmii_txd0, + rmii_txd1, + ), + DES_RING.init_with(ethernet::DesRing::new), + mac_addr, + ccdr.peripheral.ETH1MAC, + &ccdr.clocks, + ); // Initialise ethernet PHY... let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac); @@ -196,20 +191,9 @@ mod app { unsafe { ethernet::enable_interrupt() }; - // unsafe: mutable reference to static storage, we only do this once - let store = unsafe { - let store_ptr = STORE.as_mut_ptr(); - - // Initialise the socket_storage field. Using `write` instead of - // assignment via `=` to not call `drop` on the old, uninitialised - // value - addr_of_mut!((*store_ptr).socket_storage) - .write([SocketStorage::EMPTY; 8]); - - // Now that all fields are initialised we can safely use - // assume_init_mut to return a mutable reference to STORE - STORE.assume_init_mut() - }; + let store = STORE.init_with(|| NetStorageStatic { + socket_storage: [SocketStorage::EMPTY; 8], + }); let net = Net::new(store, eth_dma, mac_addr.into()); diff --git a/examples/ethernet-rtic-stm32h735g-dk.rs b/examples/ethernet-rtic-stm32h735g-dk.rs index 9cedf52b..94f9ec02 100644 --- a/examples/ethernet-rtic-stm32h735g-dk.rs +++ b/examples/ethernet-rtic-stm32h735g-dk.rs @@ -15,14 +15,14 @@ #[allow(unused)] mod utilities; -use core::mem::MaybeUninit; -use core::ptr::addr_of_mut; use core::sync::atomic::AtomicU32; use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage}; use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr}; +use static_cell::StaticCell; + use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; /// Configure SYSTICK for 1ms timebase @@ -45,16 +45,16 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; /// Ethernet descriptor rings are a global singleton #[link_section = ".axisram.eth"] -static mut DES_RING: MaybeUninit> = - MaybeUninit::uninit(); +static DES_RING: StaticCell> = StaticCell::new(); // This data will be held by Net through a mutable reference pub struct NetStorageStatic<'a> { socket_storage: [SocketStorage<'a>; 8], } -// MaybeUninit allows us write code that is correct even if STORE is not + +// StaticCell allows us write code that is correct even if STORE is not // initialised by the runtime -static mut STORE: MaybeUninit = MaybeUninit::uninit(); +static STORE: StaticCell = StaticCell::new(); pub struct Net<'a> { iface: Interface, @@ -157,30 +157,26 @@ mod app { assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000); // PCLK 100MHz let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); - let (eth_dma, eth_mac) = unsafe { - DES_RING.write(ethernet::DesRing::new()); - - ethernet::new( - ctx.device.ETHERNET_MAC, - ctx.device.ETHERNET_MTL, - ctx.device.ETHERNET_DMA, - ( - rmii_ref_clk, - rmii_mdio, - rmii_mdc, - rmii_crs_dv, - rmii_rxd0, - rmii_rxd1, - rmii_tx_en, - rmii_txd0, - rmii_txd1, - ), - DES_RING.assume_init_mut(), - mac_addr, - ccdr.peripheral.ETH1MAC, - &ccdr.clocks, - ) - }; + let (eth_dma, eth_mac) = ethernet::new( + ctx.device.ETHERNET_MAC, + ctx.device.ETHERNET_MTL, + ctx.device.ETHERNET_DMA, + ( + rmii_ref_clk, + rmii_mdio, + rmii_mdc, + rmii_crs_dv, + rmii_rxd0, + rmii_rxd1, + rmii_tx_en, + rmii_txd0, + rmii_txd1, + ), + DES_RING.init_with(ethernet::DesRing::new), + mac_addr, + ccdr.peripheral.ETH1MAC, + &ccdr.clocks, + ); // Initialise ethernet PHY... let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac); @@ -190,20 +186,9 @@ mod app { unsafe { ethernet::enable_interrupt() }; - // unsafe: mutable reference to static storage, we only do this once - let store = unsafe { - let store_ptr = STORE.as_mut_ptr(); - - // Initialise the socket_storage field. Using `write` instead of - // assignment via `=` to not call `drop` on the old, uninitialised - // value - addr_of_mut!((*store_ptr).socket_storage) - .write([SocketStorage::EMPTY; 8]); - - // Now that all fields are initialised we can safely use - // assume_init_mut to return a mutable reference to STORE - STORE.assume_init_mut() - }; + let store = STORE.init_with(|| NetStorageStatic { + socket_storage: [SocketStorage::EMPTY; 8], + }); let net = Net::new(store, eth_dma, mac_addr.into(), Instant::ZERO); diff --git a/examples/ethernet-rtic-stm32h747i-disco.rs b/examples/ethernet-rtic-stm32h747i-disco.rs index 682fa111..1c710f9e 100644 --- a/examples/ethernet-rtic-stm32h747i-disco.rs +++ b/examples/ethernet-rtic-stm32h747i-disco.rs @@ -22,14 +22,14 @@ #[allow(unused)] mod utilities; -use core::mem::MaybeUninit; -use core::ptr::addr_of_mut; use core::sync::atomic::AtomicU32; use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage}; use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr}; +use static_cell::StaticCell; + use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; /// Configure SYSTICK for 1ms timebase @@ -52,16 +52,16 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; /// Ethernet descriptor rings are a global singleton #[link_section = ".sram3.eth"] -static mut DES_RING: MaybeUninit> = - MaybeUninit::uninit(); +static DES_RING: StaticCell> = StaticCell::new(); // This data will be held by Net through a mutable reference pub struct NetStorageStatic<'a> { socket_storage: [SocketStorage<'a>; 8], } -// MaybeUninit allows us write code that is correct even if STORE is not + +// StaticCell allows us write code that is correct even if STORE is not // initialised by the runtime -static mut STORE: MaybeUninit = MaybeUninit::uninit(); +static STORE: StaticCell = StaticCell::new(); pub struct Net<'a> { iface: Interface, @@ -167,30 +167,26 @@ mod app { assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000); // PCLK 100MHz let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); - let (eth_dma, eth_mac) = unsafe { - DES_RING.write(ethernet::DesRing::new()); - - ethernet::new( - ctx.device.ETHERNET_MAC, - ctx.device.ETHERNET_MTL, - ctx.device.ETHERNET_DMA, - ( - rmii_ref_clk, - rmii_mdio, - rmii_mdc, - rmii_crs_dv, - rmii_rxd0, - rmii_rxd1, - rmii_tx_en, - rmii_txd0, - rmii_txd1, - ), - DES_RING.assume_init_mut(), - mac_addr, - ccdr.peripheral.ETH1MAC, - &ccdr.clocks, - ) - }; + let (eth_dma, eth_mac) = ethernet::new( + ctx.device.ETHERNET_MAC, + ctx.device.ETHERNET_MTL, + ctx.device.ETHERNET_DMA, + ( + rmii_ref_clk, + rmii_mdio, + rmii_mdc, + rmii_crs_dv, + rmii_rxd0, + rmii_rxd1, + rmii_tx_en, + rmii_txd0, + rmii_txd1, + ), + DES_RING.init_with(ethernet::DesRing::new), + mac_addr, + ccdr.peripheral.ETH1MAC, + &ccdr.clocks, + ); // Initialise ethernet PHY... let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac); @@ -200,20 +196,9 @@ mod app { unsafe { ethernet::enable_interrupt() }; - // unsafe: mutable reference to static storage, we only do this once - let store = unsafe { - let store_ptr = STORE.as_mut_ptr(); - - // Initialise the socket_storage field. Using `write` instead of - // assignment via `=` to not call `drop` on the old, uninitialised - // value - addr_of_mut!((*store_ptr).socket_storage) - .write([SocketStorage::EMPTY; 8]); - - // Now that all fields are initialised we can safely use - // assume_init_mut to return a mutable reference to STORE - STORE.assume_init_mut() - }; + let store = STORE.init_with(|| NetStorageStatic { + socket_storage: [SocketStorage::EMPTY; 8], + }); let net = Net::new(store, eth_dma, mac_addr.into(), Instant::ZERO); diff --git a/examples/ethernet-stm32h747i-disco.rs b/examples/ethernet-stm32h747i-disco.rs index e4c1a199..653f4931 100644 --- a/examples/ethernet-stm32h747i-disco.rs +++ b/examples/ethernet-stm32h747i-disco.rs @@ -11,7 +11,6 @@ #![no_main] #![no_std] -use core::mem::MaybeUninit; use cortex_m_rt as rt; use rt::{entry, exception}; @@ -20,6 +19,7 @@ use rt::{entry, exception}; mod utilities; use log::info; +use static_cell::StaticCell; use stm32h7xx_hal::{ethernet, ethernet::PHY}; use stm32h7xx_hal::{prelude::*, stm32, stm32::interrupt}; @@ -29,8 +29,7 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; /// Ethernet descriptor rings are a global singleton #[link_section = ".sram3.eth"] -static mut DES_RING: MaybeUninit> = - MaybeUninit::uninit(); +static DES_RING: StaticCell> = StaticCell::new(); // the program entry point #[entry] @@ -86,30 +85,26 @@ fn main() -> ! { assert_eq!(ccdr.clocks.pclk4().raw(), 100_000_000); // PCLK 100MHz let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); - let (_eth_dma, eth_mac) = unsafe { - DES_RING.write(ethernet::DesRing::new()); - - ethernet::new( - dp.ETHERNET_MAC, - dp.ETHERNET_MTL, - dp.ETHERNET_DMA, - ( - rmii_ref_clk, - rmii_mdio, - rmii_mdc, - rmii_crs_dv, - rmii_rxd0, - rmii_rxd1, - rmii_tx_en, - rmii_txd0, - rmii_txd1, - ), - DES_RING.assume_init_mut(), - mac_addr, - ccdr.peripheral.ETH1MAC, - &ccdr.clocks, - ) - }; + let (_eth_dma, eth_mac) = ethernet::new( + dp.ETHERNET_MAC, + dp.ETHERNET_MTL, + dp.ETHERNET_DMA, + ( + rmii_ref_clk, + rmii_mdio, + rmii_mdc, + rmii_crs_dv, + rmii_rxd0, + rmii_rxd1, + rmii_tx_en, + rmii_txd0, + rmii_txd1, + ), + DES_RING.init_with(ethernet::DesRing::new), + mac_addr, + ccdr.peripheral.ETH1MAC, + &ccdr.clocks, + ); // Initialise ethernet PHY... let mut lan8742a = ethernet::phy::LAN8742A::new(eth_mac.set_phy_addr(0)); diff --git a/examples/i2c4_bdma.rs b/examples/i2c4_bdma.rs index e6402567..27b3dfa5 100644 --- a/examples/i2c4_bdma.rs +++ b/examples/i2c4_bdma.rs @@ -3,6 +3,7 @@ //! #![deny(warnings)] +#![allow(static_mut_refs)] #![no_std] #![no_main] diff --git a/examples/mdma.rs b/examples/mdma.rs index 1b3451af..9dd9fc90 100644 --- a/examples/mdma.rs +++ b/examples/mdma.rs @@ -1,6 +1,7 @@ //! Example of Memory to Memory Transfer with the Master DMA (MDMA) #![deny(warnings)] +#![allow(static_mut_refs)] #![no_main] #![no_std] diff --git a/examples/mdma_bursts.rs b/examples/mdma_bursts.rs index bfcd6083..a8c21796 100644 --- a/examples/mdma_bursts.rs +++ b/examples/mdma_bursts.rs @@ -6,6 +6,7 @@ //! beats/burst. The latter gives an approximately 25% speedup. #![deny(warnings)] +#![allow(static_mut_refs)] #![no_main] #![no_std] diff --git a/examples/sai_dma_passthru.rs b/examples/sai_dma_passthru.rs index ca6c14c9..7012cdb8 100644 --- a/examples/sai_dma_passthru.rs +++ b/examples/sai_dma_passthru.rs @@ -3,6 +3,7 @@ #![allow(unused_macros)] #![deny(warnings)] +#![allow(static_mut_refs)] #![no_main] #![no_std] diff --git a/examples/serial-dma.rs b/examples/serial-dma.rs index c61a36e2..dc6fff06 100644 --- a/examples/serial-dma.rs +++ b/examples/serial-dma.rs @@ -11,7 +11,7 @@ #![no_main] #![no_std] -use core::{mem, mem::MaybeUninit}; +use core::{array, mem}; use cortex_m_rt::entry; #[macro_use] @@ -24,6 +24,7 @@ use stm32h7xx_hal::dma::{ }; use log::info; +use static_cell::StaticCell; // DMA1/DMA2 cannot interact with our stack. Instead, buffers for use with the // DMA must be placed somewhere that DMA1/DMA2 can access. In this case we use @@ -31,10 +32,10 @@ use log::info; // // The runtime does not initialise these SRAM banks #[link_section = ".axisram.buffers"] -static mut SHORT_BUFFER: MaybeUninit<[u8; 10]> = MaybeUninit::uninit(); +static SHORT_BUFFER: StaticCell<[u8; 10]> = StaticCell::new(); #[link_section = ".axisram.buffers"] -static mut LONG_BUFFER: MaybeUninit<[u32; 0x8000]> = MaybeUninit::uninit(); +static LONG_BUFFER: StaticCell<[u32; 0x8000]> = StaticCell::new(); #[entry] fn main() -> ! { @@ -80,30 +81,12 @@ fn main() -> ! { // Initialise the source buffer, without taking any references to // uninitialised memory - let short_buffer: &'static mut [u8; 10] = { - let buf: &mut [MaybeUninit; 10] = - unsafe { &mut *(core::ptr::addr_of_mut!(SHORT_BUFFER) as *mut _) }; - - for (i, value) in buf.iter_mut().enumerate() { - unsafe { - value.as_mut_ptr().write(i as u8 + 96); // 0x60, 0x61, 0x62... - } - } - unsafe { SHORT_BUFFER.assume_init_mut() } - }; + let short_buffer: &'static mut [u8; 10] = + SHORT_BUFFER.init_with(|| array::from_fn(|i| i as u8 + 0x60)); + // view u32 buffer as u8. Endianess is undefined (little-endian on STM32H7) - let long_buffer: &'static mut [u8; 0x2_0010] = { - let buf: &mut [MaybeUninit; 0x8004] = - unsafe { &mut *(core::ptr::addr_of_mut!(LONG_BUFFER) as *mut _) }; - - for (i, value) in buf.iter_mut().enumerate() { - unsafe { - value.as_mut_ptr().write(i as u32); - } - } - unsafe { - &mut *(core::ptr::addr_of_mut!(LONG_BUFFER) as *mut [u8; 0x2_0010]) - } + let long_buffer: &'static mut [u8; 0x2_0010] = unsafe { + mem::transmute(LONG_BUFFER.init_with(|| array::from_fn(|i| i as u32))) }; // Setup the DMA transfer on stream 0 diff --git a/examples/spi-dma-rtic.rs b/examples/spi-dma-rtic.rs index bd78229c..16e067e5 100644 --- a/examples/spi-dma-rtic.rs +++ b/examples/spi-dma-rtic.rs @@ -7,7 +7,9 @@ #![no_main] #![no_std] -use core::mem::MaybeUninit; +use core::array; + +use static_cell::StaticCell; #[macro_use] mod utilities; @@ -21,7 +23,7 @@ const BUFFER_SIZE: usize = 100; // // The runtime does not initialise these SRAM banks #[link_section = ".axisram.buffers"] -static mut BUFFER: MaybeUninit<[u8; BUFFER_SIZE]> = MaybeUninit::uninit(); +static BUFFER: StaticCell<[u8; BUFFER_SIZE]> = StaticCell::new(); #[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] mod app { @@ -95,20 +97,8 @@ mod app { cs.set_high(); // Initialize our transmit buffer. - let buffer: &'static mut [u8; BUFFER_SIZE] = { - let buf: &mut [MaybeUninit; BUFFER_SIZE] = unsafe { - &mut *(core::ptr::addr_of_mut!(BUFFER) - as *mut [MaybeUninit; BUFFER_SIZE]) - }; - - for (i, value) in buf.iter_mut().enumerate() { - unsafe { - value.as_mut_ptr().write(i as u8 + 0x60); // 0x60, 0x61, 0x62... - } - } - - unsafe { BUFFER.assume_init_mut() } - }; + let buffer: &'static mut [u8; BUFFER_SIZE] = + BUFFER.init_with(|| array::from_fn(|i| i as u8 + 0x60)); let streams = hal::dma::dma::StreamsTuple::new( ctx.device.DMA1, diff --git a/examples/spi-dma.rs b/examples/spi-dma.rs index b3a59a2e..fd1de9db 100644 --- a/examples/spi-dma.rs +++ b/examples/spi-dma.rs @@ -11,7 +11,7 @@ #![no_main] #![no_std] -use core::{mem, mem::MaybeUninit}; +use core::{array, mem}; use cortex_m_rt::entry; #[macro_use] @@ -24,6 +24,7 @@ use stm32h7xx_hal::dma::{ }; use log::info; +use static_cell::StaticCell; // DMA1/DMA2 cannot interact with our stack. Instead, buffers for use with the // DMA must be placed somewhere that DMA1/DMA2 can access. In this case we use @@ -31,10 +32,10 @@ use log::info; // // The runtime does not initialise these SRAM banks #[link_section = ".axisram.buffers"] -static mut SHORT_BUFFER: MaybeUninit<[u8; 10]> = MaybeUninit::uninit(); +static SHORT_BUFFER: StaticCell<[u8; 10]> = StaticCell::new(); #[link_section = ".axisram.buffers"] -static mut LONG_BUFFER: MaybeUninit<[u32; 0x8000]> = MaybeUninit::uninit(); +static LONG_BUFFER: StaticCell<[u32; 0x8000]> = StaticCell::new(); #[entry] fn main() -> ! { @@ -80,32 +81,11 @@ fn main() -> ! { // SPI must be disabled to configure DMA let spi = spi.disable(); - // Initialise the source buffer, without taking any references to - // uninitialisated memory - let short_buffer: &'static mut [u8; 10] = { - let buf: &mut [MaybeUninit; 10] = - unsafe { &mut *(core::ptr::addr_of_mut!(SHORT_BUFFER) as *mut _) }; - - for (i, value) in buf.iter_mut().enumerate() { - unsafe { - value.as_mut_ptr().write(i as u8 + 96); // 0x60, 0x61, 0x62... - } - } - unsafe { SHORT_BUFFER.assume_init_mut() } - }; + let short_buffer: &'static mut [u8; 10] = + SHORT_BUFFER.init_with(|| array::from_fn(|i| i as u8 + 0x60)); // view u32 buffer as u8. Endianess is undefined (little-endian on STM32H7) - let long_buffer: &'static mut [u8; 0x2_0010] = { - let buf: &mut [MaybeUninit; 0x8004] = - unsafe { &mut *(core::ptr::addr_of_mut!(LONG_BUFFER) as *mut _) }; - - for (i, value) in buf.iter_mut().enumerate() { - unsafe { - value.as_mut_ptr().write(i as u32); - } - } - unsafe { - &mut *(core::ptr::addr_of_mut!(LONG_BUFFER) as *mut [u8; 0x2_0010]) - } + let long_buffer: &'static mut [u8; 0x2_0010] = unsafe { + mem::transmute(LONG_BUFFER.init_with(|| array::from_fn(|i| i as u32))) }; // Setup the DMA transfer on stream 0 diff --git a/examples/usb_passthrough.rs b/examples/usb_passthrough.rs index f7f68f80..e816a8ac 100644 --- a/examples/usb_passthrough.rs +++ b/examples/usb_passthrough.rs @@ -10,18 +10,17 @@ use panic_itm as _; -use core::mem::MaybeUninit; - use cortex_m_rt::entry; use stm32h7xx_hal::rcc::rec::UsbClkSel; use stm32h7xx_hal::usb_hs::{UsbBus, USB1, USB2}; use stm32h7xx_hal::{prelude::*, stm32}; +use static_cell::StaticCell; use usb_device::prelude::*; -static mut EP_MEMORY_1: MaybeUninit<[u32; 1024]> = MaybeUninit::uninit(); -static mut EP_MEMORY_2: MaybeUninit<[u32; 1024]> = MaybeUninit::uninit(); +static EP_MEMORY_1: StaticCell<[u32; 1024]> = StaticCell::new(); +static EP_MEMORY_2: StaticCell<[u32; 1024]> = StaticCell::new(); #[entry] fn main() -> ! { @@ -72,24 +71,12 @@ fn main() -> ! { ); // Initialise EP_MEMORY_1 to zero - unsafe { - let buf: &mut [MaybeUninit; 1024] = - &mut *(core::ptr::addr_of_mut!(EP_MEMORY_1) as *mut _); - for value in buf.iter_mut() { - value.as_mut_ptr().write(0); - } - } + let ep_memory_1 = EP_MEMORY_1.init_with(|| [0; 1024]); // Initialise EP_MEMORY_2 to zero - unsafe { - let buf: &mut [MaybeUninit; 1024] = - &mut *(core::ptr::addr_of_mut!(EP_MEMORY_2) as *mut _); - for value in buf.iter_mut() { - value.as_mut_ptr().write(0); - } - } + let ep_memory_2 = EP_MEMORY_2.init_with(|| [0; 1024]); // Port 1 - let usb1_bus = UsbBus::new(usb1, unsafe { EP_MEMORY_1.assume_init_mut() }); + let usb1_bus = UsbBus::new(usb1, ep_memory_1); let mut serial1 = usbd_serial::SerialPort::new(&usb1_bus); let mut usb1_dev = UsbDeviceBuilder::new(&usb1_bus, UsbVidPid(0x16c0, 0x27dd)) @@ -102,7 +89,7 @@ fn main() -> ! { .build(); // Port 2 - let usb2_bus = UsbBus::new(usb2, unsafe { EP_MEMORY_2.assume_init_mut() }); + let usb2_bus = UsbBus::new(usb2, ep_memory_2); let mut serial2 = usbd_serial::SerialPort::new(&usb2_bus); let mut usb2_dev = UsbDeviceBuilder::new(&usb2_bus, UsbVidPid(0x16c0, 0x27dd)) diff --git a/examples/usb_phy_serial_interrupt.rs b/examples/usb_phy_serial_interrupt.rs index 90b2533a..f37b7ca8 100644 --- a/examples/usb_phy_serial_interrupt.rs +++ b/examples/usb_phy_serial_interrupt.rs @@ -3,6 +3,7 @@ //! This example is for RM0433/RM0399 parts. It has been tested on the Arduino //! Portenta H7 #![deny(warnings)] +#![allow(static_mut_refs)] #![allow(clippy::type_complexity)] #![no_std] #![no_main] diff --git a/examples/usb_rtic.rs b/examples/usb_rtic.rs index 418bb8b6..db48d917 100644 --- a/examples/usb_rtic.rs +++ b/examples/usb_rtic.rs @@ -7,6 +7,7 @@ //! NUCLEO-H743ZI2 board. //! #![deny(warnings)] +#![allow(static_mut_refs)] #![no_std] #![no_main] diff --git a/examples/usb_serial.rs b/examples/usb_serial.rs index ed9100b4..d76ccb10 100644 --- a/examples/usb_serial.rs +++ b/examples/usb_serial.rs @@ -12,8 +12,6 @@ #![no_std] #![no_main] -use core::mem::MaybeUninit; - #[macro_use] #[allow(unused)] mod utilities; @@ -24,9 +22,10 @@ use stm32h7xx_hal::rcc::rec::UsbClkSel; use stm32h7xx_hal::usb_hs::{UsbBus, USB1}; use stm32h7xx_hal::{prelude::*, stm32}; +use static_cell::StaticCell; use usb_device::prelude::*; -static mut EP_MEMORY: MaybeUninit<[u32; 1024]> = MaybeUninit::uninit(); +static EP_MEMORY: StaticCell<[u32; 1024]> = StaticCell::new(); #[entry] fn main() -> ! { @@ -76,16 +75,10 @@ fn main() -> ! { ); // Initialise EP_MEMORY to zero - unsafe { - let buf: &mut [MaybeUninit; 1024] = - &mut *(core::ptr::addr_of_mut!(EP_MEMORY) as *mut _); - for value in buf.iter_mut() { - value.as_mut_ptr().write(0); - } - } + let ep_memory = EP_MEMORY.init_with(|| [0; 1024]); // Now we may assume that EP_MEMORY is initialised - let usb_bus = UsbBus::new(usb, unsafe { EP_MEMORY.assume_init_mut() }); + let usb_bus = UsbBus::new(usb, ep_memory); let mut serial = usbd_serial::SerialPort::new(&usb_bus);