Skip to content

Commit 7146759

Browse files
committed
Remove references to static mut
rust/#114447 made `&mut MY_STATIC_MUT` a warning, with the intention of disallowing it entirely in the 2024 edition. We never used this in the crate itself, but it is used in many examples. This commit removes these references from the examples. In general the new approach is to change `static mut` of type `X` to type `MaybeUninit<X>`. These can then cleanly be accessed with [`MY_STATIC_MUT.write()`](https://doc.rust-lang.org/core/mem/union.MaybeUninit.html#method.write) followed by [`MY_STATIC_MUT.assume_init_mut()`](https://doc.rust-lang.org/core/mem/union.MaybeUninit.html#method.assume_init_mut). Where we need to cast a `MaybeUninit<[X; N]>` to a `[MaybeUninit<X>; N]` in order to initialise it element-by-element, the `&mut *ptr::addr_of_mut!(MY_STATIC_MUT)` construction is still used. After initialisation, we can then access it with `MY_STATIC_MUT.assume_init_mut()`. In a few DMA Examples we were taking a reference `&mut TARGET_BUFFER` without initialising TARGET_BUFFER. This commit changes this to `TARGET_BUFFER.assume_init_mut()` *without* initialising `TARGET_BUFFER`. This was and remains UB. * USB Examples: `static mut EP_MEMORY` now has type `MaybeUninit<[u32; 1024]>` * Ethernet Examples: `static mut DES_RING` now has type `MaybeUninit<ethernet::DesRing<4, 4>>`
1 parent 9bfd5b1 commit 7146759

18 files changed

+188
-83
lines changed

examples/adc_dma.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! For an example of using ADC1 and ADC2 together, see examples/adc12.rs
55
//! For an example of using ADC1 and ADC2 in parallel, see examples/adc12_parallel.rs
66
7+
#![deny(warnings)]
78
#![no_main]
89
#![no_std]
910

@@ -33,8 +34,11 @@ fn main() -> ! {
3334

3435
let adc_buffer: &'static mut [u16; 32_768] = {
3536
// Convert an uninitialised array into an array of uninitialised
36-
let buf: &mut [MaybeUninit<u16>; 32_768] =
37-
unsafe { mem::transmute(&mut BUFFER) };
37+
let buf: &mut [MaybeUninit<u16>; 32_768] = unsafe {
38+
&mut *(core::ptr::addr_of_mut!(BUFFER)
39+
as *mut [MaybeUninit<_>; 32_768])
40+
};
41+
3842
// Initialise memory to valid values
3943
for slot in buf.iter_mut() {
4044
// Never create even a _temporary_ reference to uninitialised memory

examples/dma.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//! Example of Memory to Memory Transfer with the DMA
22
3-
#![allow(clippy::transmute_ptr_to_ptr)]
43
#![deny(warnings)]
54
#![no_main]
65
#![no_std]
76

8-
use core::{mem, mem::MaybeUninit};
7+
use core::mem::MaybeUninit;
98

109
use cortex_m_rt::entry;
1110
#[macro_use]
@@ -57,15 +56,17 @@ fn main() -> ! {
5756
// Initialise the source buffer with truly random data, without taking any
5857
// references to uninitialisated memory
5958
let source_buffer: &'static mut [u32; 20] = {
60-
let buf: &mut [MaybeUninit<u32>; 20] =
61-
unsafe { mem::transmute(&mut SOURCE_BUFFER) };
59+
let buf: &mut [MaybeUninit<u32>; 20] = unsafe {
60+
&mut *(core::ptr::addr_of_mut!(SOURCE_BUFFER)
61+
as *mut [MaybeUninit<u32>; 20])
62+
};
6263

6364
for value in buf.iter_mut() {
6465
unsafe {
6566
value.as_mut_ptr().write(rng.gen().unwrap());
6667
}
6768
}
68-
unsafe { mem::transmute(buf) }
69+
unsafe { SOURCE_BUFFER.assume_init_mut() }
6970
};
7071
// Save a copy on the stack so we can check it later
7172
let source_buffer_cloned = *source_buffer;
@@ -85,7 +86,9 @@ fn main() -> ! {
8586
Transfer::init(
8687
streams.4,
8788
MemoryToMemory::new(),
88-
unsafe { mem::transmute(&mut TARGET_BUFFER) }, // Uninitialised memory
89+
unsafe {
90+
(*core::ptr::addr_of_mut!(TARGET_BUFFER)).assume_init_mut()
91+
}, // Uninitialised memory
8992
Some(source_buffer),
9093
config,
9194
);
@@ -97,7 +100,7 @@ fn main() -> ! {
97100

98101
// Now the target memory is actually initialised
99102
let target_buffer: &'static mut [u32; 20] =
100-
unsafe { mem::transmute(&mut TARGET_BUFFER) };
103+
unsafe { TARGET_BUFFER.assume_init_mut() };
101104

102105
// Comparison check
103106
assert_eq!(&source_buffer_cloned, target_buffer);

examples/ethernet-nucleo-h743zi2.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![no_std]
1414

1515
extern crate cortex_m_rt as rt;
16+
use core::mem::MaybeUninit;
1617
use core::sync::atomic::{AtomicU32, Ordering};
1718
use rt::{entry, exception};
1819

@@ -51,7 +52,8 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
5152

5253
/// Ethernet descriptor rings are a global singleton
5354
#[link_section = ".sram3.eth"]
54-
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();
55+
static mut DES_RING: MaybeUninit<ethernet::DesRing<4, 4>> =
56+
MaybeUninit::uninit();
5557

5658
// the program entry point
5759
#[entry]
@@ -112,6 +114,8 @@ fn main() -> ! {
112114

113115
let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
114116
let (_eth_dma, eth_mac) = unsafe {
117+
DES_RING.write(ethernet::DesRing::new());
118+
115119
ethernet::new(
116120
dp.ETHERNET_MAC,
117121
dp.ETHERNET_MTL,
@@ -127,7 +131,7 @@ fn main() -> ! {
127131
rmii_txd0,
128132
rmii_txd1,
129133
),
130-
&mut DES_RING,
134+
DES_RING.assume_init_mut(),
131135
mac_addr,
132136
ccdr.peripheral.ETH1MAC,
133137
&ccdr.clocks,

examples/ethernet-rtic-nucleo-h723zg.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#[allow(unused)]
2020
mod utilities;
2121

22+
use core::mem::MaybeUninit;
23+
use core::ptr::addr_of_mut;
2224
use core::sync::atomic::AtomicU32;
2325

2426
use smoltcp::iface::{Config, Interface, SocketSet, SocketStorage};
@@ -47,16 +49,17 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
4749

4850
/// Ethernet descriptor rings are a global singleton
4951
#[link_section = ".axisram.eth"]
50-
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();
52+
static mut DES_RING: MaybeUninit<ethernet::DesRing<4, 4>> =
53+
MaybeUninit::uninit();
5154

5255
/// Net storage with static initialisation - another global singleton
5356
pub struct NetStorageStatic<'a> {
5457
socket_storage: [SocketStorage<'a>; 8],
5558
}
5659

57-
static mut STORE: NetStorageStatic = NetStorageStatic {
58-
socket_storage: [SocketStorage::EMPTY; 8],
59-
};
60+
// MaybeUninit allows us write code that is correct even if STORE is not
61+
// initialised by the runtime
62+
static mut STORE: MaybeUninit<NetStorageStatic> = MaybeUninit::uninit();
6063

6164
pub struct Net<'a> {
6265
iface: Interface,
@@ -161,6 +164,8 @@ mod app {
161164

162165
let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
163166
let (eth_dma, eth_mac) = unsafe {
167+
DES_RING.write(ethernet::DesRing::new());
168+
164169
ethernet::new(
165170
ctx.device.ETHERNET_MAC,
166171
ctx.device.ETHERNET_MTL,
@@ -176,7 +181,7 @@ mod app {
176181
rmii_txd0,
177182
rmii_txd1,
178183
),
179-
&mut DES_RING,
184+
DES_RING.assume_init_mut(),
180185
mac_addr,
181186
ccdr.peripheral.ETH1MAC,
182187
&ccdr.clocks,
@@ -192,7 +197,20 @@ mod app {
192197
unsafe { ethernet::enable_interrupt() };
193198

194199
// unsafe: mutable reference to static storage, we only do this once
195-
let store = unsafe { &mut STORE };
200+
let store = unsafe {
201+
let store_ptr = STORE.as_mut_ptr();
202+
203+
// Initialise the socket_storage field. Using `write` instead of
204+
// assignment via `=` to not call `drop` on the old, uninitialised
205+
// value
206+
addr_of_mut!((*store_ptr).socket_storage)
207+
.write([SocketStorage::EMPTY; 8]);
208+
209+
// Now that all fields are initialised we can safely use
210+
// assume_init_mut to return a mutable reference to STORE
211+
STORE.assume_init_mut()
212+
};
213+
196214
let net = Net::new(store, eth_dma, mac_addr.into());
197215

198216
// 1ms tick

examples/ethernet-rtic-stm32h735g-dk.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
4545

4646
/// Ethernet descriptor rings are a global singleton
4747
#[link_section = ".axisram.eth"]
48-
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();
48+
static mut DES_RING: MaybeUninit<ethernet::DesRing<4, 4>> =
49+
MaybeUninit::uninit();
4950

5051
// This data will be held by Net through a mutable reference
5152
pub struct NetStorageStatic<'a> {
@@ -157,6 +158,8 @@ mod app {
157158

158159
let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
159160
let (eth_dma, eth_mac) = unsafe {
161+
DES_RING.write(ethernet::DesRing::new());
162+
160163
ethernet::new(
161164
ctx.device.ETHERNET_MAC,
162165
ctx.device.ETHERNET_MTL,
@@ -172,7 +175,7 @@ mod app {
172175
rmii_txd0,
173176
rmii_txd1,
174177
),
175-
&mut DES_RING,
178+
DES_RING.assume_init_mut(),
176179
mac_addr,
177180
ccdr.peripheral.ETH1MAC,
178181
&ccdr.clocks,

examples/ethernet-rtic-stm32h747i-disco.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
5252

5353
/// Ethernet descriptor rings are a global singleton
5454
#[link_section = ".sram3.eth"]
55-
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();
55+
static mut DES_RING: MaybeUninit<ethernet::DesRing<4, 4>> =
56+
MaybeUninit::uninit();
5657

5758
// This data will be held by Net through a mutable reference
5859
pub struct NetStorageStatic<'a> {
@@ -167,6 +168,8 @@ mod app {
167168

168169
let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
169170
let (eth_dma, eth_mac) = unsafe {
171+
DES_RING.write(ethernet::DesRing::new());
172+
170173
ethernet::new(
171174
ctx.device.ETHERNET_MAC,
172175
ctx.device.ETHERNET_MTL,
@@ -182,7 +185,7 @@ mod app {
182185
rmii_txd0,
183186
rmii_txd1,
184187
),
185-
&mut DES_RING,
188+
DES_RING.assume_init_mut(),
186189
mac_addr,
187190
ccdr.peripheral.ETH1MAC,
188191
&ccdr.clocks,

examples/ethernet-stm32h747i-disco.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#![no_main]
1212
#![no_std]
1313

14+
use core::mem::MaybeUninit;
1415
use cortex_m_rt as rt;
1516
use rt::{entry, exception};
1617

@@ -28,7 +29,8 @@ const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44];
2829

2930
/// Ethernet descriptor rings are a global singleton
3031
#[link_section = ".sram3.eth"]
31-
static mut DES_RING: ethernet::DesRing<4, 4> = ethernet::DesRing::new();
32+
static mut DES_RING: MaybeUninit<ethernet::DesRing<4, 4>> =
33+
MaybeUninit::uninit();
3234

3335
// the program entry point
3436
#[entry]
@@ -85,6 +87,8 @@ fn main() -> ! {
8587

8688
let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS);
8789
let (_eth_dma, eth_mac) = unsafe {
90+
DES_RING.write(ethernet::DesRing::new());
91+
8892
ethernet::new(
8993
dp.ETHERNET_MAC,
9094
dp.ETHERNET_MTL,
@@ -100,7 +104,7 @@ fn main() -> ! {
100104
rmii_txd0,
101105
rmii_txd1,
102106
),
103-
&mut DES_RING,
107+
DES_RING.assume_init_mut(),
104108
mac_addr,
105109
ccdr.peripheral.ETH1MAC,
106110
&ccdr.clocks,

examples/i2c4_bdma.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
//!
33
//!
44
5-
#![allow(clippy::transmute_ptr_to_ptr)]
65
#![deny(warnings)]
76
#![no_std]
87
#![no_main]
98

10-
use core::{mem, mem::MaybeUninit};
9+
use core::mem::MaybeUninit;
1110

1211
#[macro_use]
1312
mod utilities;
@@ -93,13 +92,14 @@ fn main() -> ! {
9392
let config = BdmaConfig::default().memory_increment(true);
9493

9594
// We need to specify the direction with a type annotation
96-
let mut transfer: Transfer<_, _, PeripheralToMemory, _, _> = Transfer::init(
97-
streams.0,
98-
i2c,
99-
unsafe { &mut BUFFER }, // uninitialised memory
100-
None,
101-
config,
102-
);
95+
let mut transfer: Transfer<_, _, PeripheralToMemory, &mut [u8; 10], _> =
96+
Transfer::init(
97+
streams.0,
98+
i2c,
99+
unsafe { BUFFER.assume_init_mut() }, // uninitialised memory
100+
None,
101+
config,
102+
);
103103

104104
transfer.start(|i2c| {
105105
// This closure runs right after enabling the stream
@@ -128,7 +128,7 @@ fn I2C4_EV() {
128128
info!("I2C transfer complete!");
129129

130130
// Look at BUFFER, which we expect to be initialised
131-
let buffer: &'static mut [u8; 10] = unsafe { mem::transmute(&mut BUFFER) };
131+
let buffer: &'static [u8; 10] = unsafe { BUFFER.assume_init_mut() };
132132

133133
assert_eq!(buffer[0], 0xBE);
134134

examples/mdma.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Example of Memory to Memory Transfer with the Master DMA (MDMA)
22
3-
#![allow(clippy::transmute_ptr_to_ptr)]
43
#![deny(warnings)]
54
#![no_main]
65
#![no_std]
@@ -52,15 +51,17 @@ fn main() -> ! {
5251
// Initialise the source buffer without taking any references to
5352
// uninitialisated memory
5453
let source_buffer: &'static mut [u32; 200] = {
55-
let buf: &mut [MaybeUninit<u32>; 200] =
56-
unsafe { mem::transmute(&mut SOURCE_BUFFER) };
54+
let buf: &mut [MaybeUninit<u32>; 200] = unsafe {
55+
&mut *(core::ptr::addr_of_mut!(SOURCE_BUFFER)
56+
as *mut [MaybeUninit<u32>; 200])
57+
};
5758

5859
for value in buf.iter_mut() {
5960
unsafe {
6061
value.as_mut_ptr().write(0x11223344u32);
6162
}
6263
}
63-
unsafe { mem::transmute(buf) }
64+
unsafe { SOURCE_BUFFER.assume_init_mut() }
6465
};
6566

6667
//
@@ -104,8 +105,7 @@ fn main() -> ! {
104105
while !transfer.get_transfer_complete_flag() {}
105106

106107
// Decompose the stream to get the source buffer back
107-
let (stream, _mem2mem, _target, source_buffer_opt) = transfer.free();
108-
let source_buffer = source_buffer_opt.unwrap();
108+
let (stream, _mem2mem, _target, _) = transfer.free();
109109

110110
for a in target_buffer.iter() {
111111
assert_eq!(*a, 0x11223344);
@@ -118,6 +118,7 @@ fn main() -> ! {
118118
//
119119

120120
// Reset source buffer
121+
let source_buffer = unsafe { SOURCE_BUFFER.assume_init_mut() };
121122
*source_buffer = [0xAABBCCDD; 200];
122123

123124
// New target buffer on the stack

0 commit comments

Comments
 (0)