Skip to content

Commit a8db75e

Browse files
authored
Fix undefined behavior compile error (#346)
1 parent 8933e11 commit a8db75e

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2222
- Deprecate `Toggle` enum and use `Switch` instead for better naming purposes
2323
([#334])
2424
- Add `impl From<Toggle> for Switch` to reduce churn.
25+
- Fix undefined behavior in SPI implementation ([#346])
26+
- Add `num_traits::PrimInt` bounds to `Word`
2527

2628
### Added
2729

@@ -595,6 +597,7 @@ let clocks = rcc
595597
[defmt]: https://github.com/knurling-rs/defmt
596598
[filter]: https://defmt.ferrous-systems.com/filtering.html
597599

600+
[#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346
598601
[#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340
599602
[#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338
600603
[#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ embedded-hal = { version = "0.2.5", features = ["unproven"] }
3737
embedded-time = "0.12.0"
3838
enumset = { version = "1.0.6", optional = true }
3939
nb = "1.0.0"
40+
num-traits = { version = "0.2.17", default-features = false}
4041
paste = "1.0.5"
4142
rtcc = { version = "0.3.0", optional = true }
4243
stm32-usbd = { version = "0.6.0", optional = true }

src/spi.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//!
77
//! [examples/spi.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/spi.rs
88
9-
use core::{fmt, marker::PhantomData, ops::Deref, ptr};
9+
use core::{fmt, marker::PhantomData, ops::Deref};
1010

1111
use crate::hal::blocking::spi;
1212
use crate::hal::spi::FullDuplex;
@@ -24,6 +24,7 @@ use crate::{
2424
rcc::{self, Clocks},
2525
time::rate,
2626
};
27+
use num_traits::{AsPrimitive, PrimInt};
2728

2829
/// SPI error
2930
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -337,6 +338,8 @@ where
337338
// SckPin could technically be omitted, though not advisable.
338339
Miso: MisoPin<SPI>,
339340
Mosi: MosiPin<SPI>,
341+
Word: PrimInt + Into<u32> + 'static,
342+
u32: AsPrimitive<Word>,
340343
{
341344
type Error = Error;
342345

@@ -350,9 +353,9 @@ where
350353
} else if sr.crcerr().is_no_match() {
351354
nb::Error::Other(Error::Crc)
352355
} else if sr.rxne().is_not_empty() {
353-
let read_ptr = &self.spi.dr as *const _ as *const Word;
354-
// NOTE(unsafe) read from register owned by this Spi struct
355-
let value = unsafe { ptr::read_volatile(read_ptr) };
356+
let read_ptr = core::ptr::addr_of!(self.spi.dr) as *const Word;
357+
// SAFETY: Read from register owned by this Spi struct
358+
let value = unsafe { core::ptr::read_volatile(read_ptr) };
356359
return Ok(value);
357360
} else {
358361
nb::Error::WouldBlock
@@ -369,9 +372,9 @@ where
369372
} else if sr.crcerr().is_no_match() {
370373
nb::Error::Other(Error::Crc)
371374
} else if sr.txe().is_empty() {
372-
let write_ptr = &self.spi.dr as *const _ as *mut Word;
373-
// NOTE(unsafe) write to register owned by this Spi struct
374-
unsafe { ptr::write_volatile(write_ptr, word) };
375+
let write_ptr = core::ptr::addr_of!(self.spi.dr) as *mut Word;
376+
// SAFETY: Write to register owned by this Spi struct
377+
unsafe { core::ptr::write_volatile(write_ptr, word) };
375378
return Ok(());
376379
} else {
377380
nb::Error::WouldBlock
@@ -384,6 +387,8 @@ where
384387
SPI: Instance,
385388
Miso: MisoPin<SPI>,
386389
Mosi: MosiPin<SPI>,
390+
Word: PrimInt + Into<u32> + 'static,
391+
u32: AsPrimitive<Word>,
387392
{
388393
}
389394

@@ -392,6 +397,8 @@ where
392397
SPI: Instance,
393398
Miso: MisoPin<SPI>,
394399
Mosi: MosiPin<SPI>,
400+
Word: PrimInt + Into<u32> + 'static,
401+
u32: AsPrimitive<Word>,
395402
{
396403
}
397404

0 commit comments

Comments
 (0)