diff --git a/CHANGELOG.md b/CHANGELOG.md index 32d6df1f..e03f4791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Deprecate `Toggle` enum and use `Switch` instead for better naming purposes ([#334]) - Add `impl From for Switch` to reduce churn. +- Fix undefined behavior in SPI implementation ([#346]) + - Add `num_traits::PrimInt` bounds to `Word` ### Added @@ -595,6 +597,7 @@ let clocks = rcc [defmt]: https://github.com/knurling-rs/defmt [filter]: https://defmt.ferrous-systems.com/filtering.html +[#346]: https://github.com/stm32-rs/stm32f3xx-hal/pull/346 [#340]: https://github.com/stm32-rs/stm32f3xx-hal/pull/340 [#338]: https://github.com/stm32-rs/stm32f3xx-hal/pull/338 [#337]: https://github.com/stm32-rs/stm32f3xx-hal/pull/337 diff --git a/Cargo.toml b/Cargo.toml index 849ad150..55b64fd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ embedded-hal = { version = "0.2.5", features = ["unproven"] } embedded-time = "0.12.0" enumset = { version = "1.0.6", optional = true } nb = "1.0.0" +num-traits = { version = "0.2.17", default-features = false} paste = "1.0.5" rtcc = { version = "0.3.0", optional = true } stm32-usbd = { version = "0.6.0", optional = true } diff --git a/src/spi.rs b/src/spi.rs index 2942e7fb..13932263 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -6,7 +6,7 @@ //! //! [examples/spi.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/spi.rs -use core::{fmt, marker::PhantomData, ops::Deref, ptr}; +use core::{fmt, marker::PhantomData, ops::Deref}; use crate::hal::blocking::spi; use crate::hal::spi::FullDuplex; @@ -24,6 +24,7 @@ use crate::{ rcc::{self, Clocks}, time::rate, }; +use num_traits::{AsPrimitive, PrimInt}; /// SPI error #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -337,6 +338,8 @@ where // SckPin could technically be omitted, though not advisable. Miso: MisoPin, Mosi: MosiPin, + Word: PrimInt + Into + 'static, + u32: AsPrimitive, { type Error = Error; @@ -350,9 +353,9 @@ where } else if sr.crcerr().is_no_match() { nb::Error::Other(Error::Crc) } else if sr.rxne().is_not_empty() { - let read_ptr = &self.spi.dr as *const _ as *const Word; - // NOTE(unsafe) read from register owned by this Spi struct - let value = unsafe { ptr::read_volatile(read_ptr) }; + let read_ptr = core::ptr::addr_of!(self.spi.dr) as *const Word; + // SAFETY: Read from register owned by this Spi struct + let value = unsafe { core::ptr::read_volatile(read_ptr) }; return Ok(value); } else { nb::Error::WouldBlock @@ -369,9 +372,9 @@ where } else if sr.crcerr().is_no_match() { nb::Error::Other(Error::Crc) } else if sr.txe().is_empty() { - let write_ptr = &self.spi.dr as *const _ as *mut Word; - // NOTE(unsafe) write to register owned by this Spi struct - unsafe { ptr::write_volatile(write_ptr, word) }; + let write_ptr = core::ptr::addr_of!(self.spi.dr) as *mut Word; + // SAFETY: Write to register owned by this Spi struct + unsafe { core::ptr::write_volatile(write_ptr, word) }; return Ok(()); } else { nb::Error::WouldBlock @@ -384,6 +387,8 @@ where SPI: Instance, Miso: MisoPin, Mosi: MosiPin, + Word: PrimInt + Into + 'static, + u32: AsPrimitive, { } @@ -392,6 +397,8 @@ where SPI: Instance, Miso: MisoPin, Mosi: MosiPin, + Word: PrimInt + Into + 'static, + u32: AsPrimitive, { }