diff --git a/CHANGELOG.md b/CHANGELOG.md index b5896caa..832d370c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [v0.23.0] - 2025-09-22 + - Implement `embedded_hal::i2c::I2c` for `I2cMasterDma` [#838] - Back to `stm32f4` - Implement `Ptr`, `Sealed`, `Steal` for generic `Periph` [#834] @@ -1116,7 +1118,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Support for stm32f407 and stm32f429. -[Unreleased]: https://github.com/stm32-rs/stm32f4xx-hal/compare/v0.22.1...HEAD +[Unreleased]: https://github.com/stm32-rs/stm32f4xx-hal/compare/v0.23.0...HEAD +[v0.23.0]: https://github.com/stm32-rs/stm32f4xx-hal/compare/v0.22.1...v0.23.0 [v0.22.1]: https://github.com/stm32-rs/stm32f4xx-hal/compare/v0.22.0...v0.22.1 [v0.22.0]: https://github.com/stm32-rs/stm32f4xx-hal/compare/v0.21.0...v0.22.0 [v0.21.0]: https://github.com/stm32-rs/stm32f4xx-hal/compare/v0.20.0...v0.21.0 diff --git a/Cargo.toml b/Cargo.toml index bf124a1a..e7068df7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "0BSD" name = "stm32f4xx-hal" readme = "README.md" repository = "https://github.com/stm32-rs/stm32f4xx-hal" -version = "0.22.1" +version = "0.23.0" [package.metadata.docs.rs] features = [ @@ -27,12 +27,13 @@ features = [ targets = ["thumbv7em-none-eabihf"] [dependencies] -defmt = { version = "0.3.10", optional = true } +defmt = { version = "1.0.1", optional = true } bxcan = { version = "0.8", optional = true } cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.5" nb = "1.1" -rand_core = "0.6.4" +rand_core_06 = { package = "rand_core", version = "0.6.4" } +rand_core = "0.9.3" synopsys-usb-otg = { version = "0.4.0", features = [ "cortex-m", ], optional = true } @@ -52,14 +53,14 @@ cortex-m-rtic = { version = "1.1.4", features = [ "test-critical-section", ], optional = true } # rtic2 -rtic-time = { version = "2.0", optional = true } +rtic-time = { version = "2.0.1", optional = true } embedded-hal-async = { version = "1.0", optional = true } -rtic = { version = "2.1.2", features = ["thumbv7-backend"], optional = true } +rtic = { version = "2.2", features = ["thumbv7-backend"], optional = true } atomic-polyfill = { version = "1.0.3", optional = true } stm32-fmc = { version = "0.4.0", optional = true } -enumflags2 = "0.7.11" +enumflags2 = "0.7.12" embedded-storage = "0.3" document-features = "0.2" @@ -70,7 +71,7 @@ version = "0.16.0" features = ["atomics"] [dependencies.time] -version = "0.3.37" +version = "0.3.44" default-features = false [dependencies.embedded-hal-02] @@ -92,27 +93,28 @@ version = "0.5.0" optional = true [dev-dependencies] -defmt = "0.3.4" -defmt-rtt = "0.4.0" -panic-probe = { version = "0.3.2", features = ["print-defmt"] } +static_cell = "2.1.1" +defmt = "1.0.1" +defmt-rtt = "1.0" +panic-probe = { version = "1.0", features = ["print-defmt"] } panic-semihosting = "0.6.0" cortex-m-semihosting = "0.5.0" -heapless = "0.8" +heapless = "0.9.1" panic-halt = "1.0.0" -ssd1306 = "0.9.0" +ssd1306 = "0.10.0" embedded-graphics = "0.8.1" embedded-graphics-07 = { package = "embedded-graphics", version = "0.7.1" } embedded-hal-bus = "0.3.0" usb-device = "0.3.1" usbd-serial = "0.2.0" -micromath = "2" +micromath = "2.1" dwt-systick-monotonic = "1.1" st7789 = "0.7.0" rtt-target = { version = "0.6.1" } display-interface-spi-04 = { package = "display-interface-spi", version = "0.4.1" } ist7920 = "0.1.1" -smart-leds = "0.3.0" -ws2812-spi = { version = "0.4.0", features = [] } +smart-leds = "0.4.0" +ws2812-spi = { version = "0.5.1", features = [] } hd44780-driver = "0.4.0" display-interface = "0.5" display-interface-04 = { package = "display-interface", version = "0.4.1" } diff --git a/README.md b/README.md index 9dcd2d11..0da8c495 100644 --- a/README.md +++ b/README.md @@ -89,15 +89,15 @@ You also need to add some dependencies to your `Cargo.toml`: ```toml [dependencies] -embedded-hal = "0.2" +embedded-hal = "1.0" nb = "1" cortex-m = "0.7" cortex-m-rt = "0.7" # Panic behaviour, see https://crates.io/keywords/panic-impl for alternatives -panic-halt = "0.2" +panic-halt = "1.0" [dependencies.stm32f4xx-hal] -version = "0.22.1" +version = "0.23.0" features = ["stm32f407"] # replace the model of your microcontroller here # and add other required features ``` diff --git a/examples/ltdc-screen/main.rs b/examples/ltdc-screen/main.rs index 0c573707..abb0afb6 100644 --- a/examples/ltdc-screen/main.rs +++ b/examples/ltdc-screen/main.rs @@ -13,6 +13,7 @@ use embedded_graphics::{ text::Text, }; +use static_cell::ConstStaticCell; use stm32f4xx_hal::{ ltdc::{BluePins, GreenPins, Layer, LtdcPins, PixelFormat, RedPins}, pac, @@ -28,7 +29,8 @@ const HEIGHT: u16 = 272; // Graphics framebuffer const FB_GRAPHICS_SIZE: usize = (WIDTH as usize) * (HEIGHT as usize); -static mut FB_LAYER1: [u16; FB_GRAPHICS_SIZE] = [0; FB_GRAPHICS_SIZE]; +static FB_LAYER1: ConstStaticCell<[u16; FB_GRAPHICS_SIZE]> = + ConstStaticCell::new([0; FB_GRAPHICS_SIZE]); #[entry] fn main() -> ! { @@ -85,7 +87,7 @@ fn main() -> ! { let mut display = screen::Stm32F7DiscoDisplay::new(perif.LTDC, perif.DMA2D, pins); display .controller - .config_layer(Layer::L1, unsafe { &mut FB_LAYER1 }, PixelFormat::RGB565); + .config_layer(Layer::L1, FB_LAYER1.take(), PixelFormat::RGB565); display.controller.enable_layer(Layer::L1); display.controller.reload(); diff --git a/examples/qspi-w25q.rs b/examples/qspi-w25q.rs index e1a95122..e200ab65 100644 --- a/examples/qspi-w25q.rs +++ b/examples/qspi-w25q.rs @@ -18,6 +18,7 @@ pub struct W25Q { qspi: Qspi, } +#[allow(unused)] pub struct DeviceId(u8); impl W25Q diff --git a/examples/rtic-dual-i2s-audio-in-out.rs b/examples/rtic-dual-i2s-audio-in-out.rs index 49b1ff89..88885b96 100644 --- a/examples/rtic-dual-i2s-audio-in-out.rs +++ b/examples/rtic-dual-i2s-audio-in-out.rs @@ -121,10 +121,10 @@ mod app { #[local] struct Local { logs_chan: rtt_target::UpChannel, - adc_p: Producer<'static, (i32, i32), 2>, - process_c: Consumer<'static, (i32, i32), 2>, - process_p: Producer<'static, (i32, i32), 2>, - dac_c: Consumer<'static, (i32, i32), 2>, + adc_p: Producer<'static, (i32, i32)>, + process_c: Consumer<'static, (i32, i32)>, + process_p: Producer<'static, (i32, i32)>, + dac_c: Consumer<'static, (i32, i32)>, } #[init(local = [queue_1: Queue<(i32,i32), 2> = Queue::new(),queue_2: Queue<(i32,i32), 2> = Queue::new()])] diff --git a/examples/rtic-i2s-audio-in-out.rs b/examples/rtic-i2s-audio-in-out.rs index 2eb23ab4..8b4c4058 100644 --- a/examples/rtic-i2s-audio-in-out.rs +++ b/examples/rtic-i2s-audio-in-out.rs @@ -124,10 +124,10 @@ mod app { #[local] struct Local { logs_chan: rtt_target::UpChannel, - adc_p: Producer<'static, (i32, i32), 2>, - process_c: Consumer<'static, (i32, i32), 2>, - process_p: Producer<'static, (i32, i32), 2>, - dac_c: Consumer<'static, (i32, i32), 2>, + adc_p: Producer<'static, (i32, i32)>, + process_c: Consumer<'static, (i32, i32)>, + process_p: Producer<'static, (i32, i32)>, + dac_c: Consumer<'static, (i32, i32)>, } #[init(local = [queue_1: Queue<(i32,i32), 2> = Queue::new(),queue_2: Queue<(i32,i32), 2> = Queue::new()])] diff --git a/examples/rtic-usb-cdc-echo.rs b/examples/rtic-usb-cdc-echo.rs index aa824696..6b645447 100644 --- a/examples/rtic-usb-cdc-echo.rs +++ b/examples/rtic-usb-cdc-echo.rs @@ -5,6 +5,7 @@ use panic_halt as _; #[rtic::app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [USART1])] mod app { + use static_cell::{ConstStaticCell, StaticCell}; use stm32f4xx_hal::{ gpio::{Output, PC13}, otg_fs::{UsbBus, UsbBusType, USB}, @@ -33,8 +34,9 @@ mod app { #[init] fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { - static mut EP_MEMORY: [u32; 1024] = [0; 1024]; - static mut USB_BUS: Option> = None; + static EP_MEMORY: ConstStaticCell<[u32; 1024]> = ConstStaticCell::new([0; 1024]); + static USB_BUS: StaticCell> = + StaticCell::new(); let dp = ctx.device; @@ -59,22 +61,17 @@ mod app { pin_dp: gpioa.pa12.into(), hclk: rcc.clocks.hclk(), }; - unsafe { - USB_BUS.replace(UsbBus::new(usb, &mut EP_MEMORY)); - } - - let usb_serial = usbd_serial::SerialPort::new(unsafe { USB_BUS.as_ref().unwrap() }); - let usb_dev = UsbDeviceBuilder::new( - unsafe { USB_BUS.as_ref().unwrap() }, - UsbVidPid(0x16c0, 0x27dd), - ) - .device_class(usbd_serial::USB_CLASS_CDC) - .strings(&[StringDescriptors::default() - .manufacturer("Fake Company") - .product("Product") - .serial_number("TEST")]) - .unwrap() - .build(); + let usb_bus = USB_BUS.init(UsbBus::new(usb, EP_MEMORY.take())); + + let usb_serial = usbd_serial::SerialPort::new(usb_bus); + let usb_dev = UsbDeviceBuilder::new(usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .device_class(usbd_serial::USB_CLASS_CDC) + .strings(&[StringDescriptors::default() + .manufacturer("Fake Company") + .product("Product") + .serial_number("TEST")]) + .unwrap() + .build(); ( Shared { diff --git a/examples/spi-dma.rs b/examples/spi-dma.rs index 038cf6f4..1644d9c4 100644 --- a/examples/spi-dma.rs +++ b/examples/spi-dma.rs @@ -9,6 +9,7 @@ use core::cell::RefCell; use cortex_m::interrupt::Mutex; use cortex_m_rt::entry; use embedded_hal_02::spi::{Mode, Phase, Polarity}; +use static_cell::ConstStaticCell; use stm32f4xx_hal::pac::interrupt; use stm32f4xx_hal::{ dma::{config, MemoryToPeripheral, Stream4, StreamsTuple, Transfer}, @@ -105,12 +106,11 @@ fn DMA1_STREAM4() { // Its important to clear fifo errors as the transfer is paused until it is cleared transfer.clear_flags(DmaFlag::FifoError | DmaFlag::TransferComplete); if flags.is_transfer_complete() { - unsafe { - static mut BUFFER: [u8; ARRAY_SIZE] = [0; ARRAY_SIZE]; - for (i, b) in BUFFER.iter_mut().enumerate() { - *b = (i + 1) as u8; - } - transfer.next_transfer(&mut BUFFER).unwrap(); + static BUFFER: ConstStaticCell<[u8; ARRAY_SIZE]> = ConstStaticCell::new([0; ARRAY_SIZE]); + let buffer = BUFFER.take(); + for (i, b) in buffer.iter_mut().enumerate() { + *b = (i + 1) as u8; } + transfer.next_transfer(buffer).unwrap(); } } diff --git a/examples/uart-dma.rs b/examples/uart-dma.rs index 15cb0142..9d3fab63 100644 --- a/examples/uart-dma.rs +++ b/examples/uart-dma.rs @@ -8,6 +8,7 @@ use stm32f4xx_hal::dma::{DmaFlag, PeripheralToMemory, Stream1}; use core::cell::RefCell; use cortex_m::interrupt::Mutex; use cortex_m_rt::entry; +use static_cell::ConstStaticCell; use stm32f4xx_hal::dma::config::DmaConfig; use stm32f4xx_hal::pac::Interrupt; use stm32f4xx_hal::pac::{interrupt, DMA1}; @@ -74,7 +75,8 @@ pub static G_UART3_TX: Mutex>>> = Mutex::new(RefCell::new(None)); // dma buffer -pub static mut RX_UART3_BUFFER: [u8; UART_BUFFER_SIZE] = [0; UART_BUFFER_SIZE]; +pub static RX_UART3_BUFFER: ConstStaticCell<[u8; UART_BUFFER_SIZE]> = + ConstStaticCell::new([0; UART_BUFFER_SIZE]); // a wrapper function that reads out of the uart ring buffer pub fn uart3_read_until(eol: u8) -> Option<[u8; UART_BUFFER_SIZE]> { @@ -208,16 +210,14 @@ fn USART3() { if transfer.is_idle() { // Calc received bytes count let bytes_count = UART_BUFFER_SIZE - transfer.number_of_transfers() as usize; - unsafe { - let mut buffer = [0; UART_BUFFER_SIZE]; - match transfer.next_transfer(&mut RX_UART3_BUFFER) { - Ok((b, _)) => buffer = *b, - Err(_err) => {} - } - if let Some(ring_buffer) = G_UART3_BUFFER.borrow(cs).borrow_mut().as_mut() { - for i in 0..bytes_count { - ring_buffer.push(buffer[i]); - } + let mut buffer = [0; UART_BUFFER_SIZE]; + match transfer.next_transfer(RX_UART3_BUFFER.take()) { + Ok((b, _)) => buffer = *b, + Err(_err) => {} + } + if let Some(ring_buffer) = G_UART3_BUFFER.borrow(cs).borrow_mut().as_mut() { + for i in 0..bytes_count { + ring_buffer.push(buffer[i]); } } } diff --git a/examples/usb-serial-poll.rs b/examples/usb-serial-poll.rs index 9c0e2f6c..107c7a6e 100644 --- a/examples/usb-serial-poll.rs +++ b/examples/usb-serial-poll.rs @@ -6,12 +6,14 @@ use panic_halt as _; use cortex_m_rt::entry; +use static_cell::ConstStaticCell; use stm32f4xx_hal::otg_fs::{UsbBus, USB}; use stm32f4xx_hal::rcc::Config; use stm32f4xx_hal::{pac, prelude::*}; use usb_device::prelude::*; -static mut EP_MEMORY: [u32; 1024] = [0; 1024]; +// Statically allocate memory for a `u32`. +static EP_MEMORY: ConstStaticCell<[u32; 1024]> = ConstStaticCell::new([0; 1024]); #[entry] fn main() -> ! { @@ -29,7 +31,7 @@ fn main() -> ! { &rcc.clocks, ); - let usb_bus = UsbBus::new(usb, unsafe { &mut EP_MEMORY }); + let usb_bus = UsbBus::new(usb, EP_MEMORY.take()); let mut serial = usbd_serial::SerialPort::new(&usb_bus); diff --git a/examples/ws2812-spi.rs b/examples/ws2812-spi.rs index 8005aaa0..c52f896d 100644 --- a/examples/ws2812-spi.rs +++ b/examples/ws2812-spi.rs @@ -10,7 +10,7 @@ use hal::{ pac::{self, SPI1}, prelude::*, }; -use smart_leds::{brightness, hsv::RGB8, SmartLedsWrite}; +use smart_leds::{brightness, SmartLedsWrite, RGB8}; use ws2812_spi as ws2812; #[entry] diff --git a/src/rng.rs b/src/rng.rs index 60818cca..d590af6d 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -29,7 +29,6 @@ use core::num::NonZeroU32; use core::ops::Shl; use embedded_hal_02::blocking::rng; use fugit::RateExtU32; -use rand_core::RngCore; /// Random number generator specific errors #[derive(Debug, Eq, PartialEq, Copy, Clone)] @@ -43,10 +42,10 @@ pub enum ErrorKind { SeedError = 4, } -impl From for rand_core::Error { - fn from(err: ErrorKind) -> rand_core::Error { - let err_code = NonZeroU32::new(rand_core::Error::CUSTOM_START + err as u32).unwrap(); - rand_core::Error::from(err_code) +impl From for rand_core_06::Error { + fn from(err: ErrorKind) -> rand_core_06::Error { + let err_code = NonZeroU32::new(rand_core_06::Error::CUSTOM_START + err as u32).unwrap(); + rand_core_06::Error::from(err_code) } } @@ -135,6 +134,19 @@ impl Rng { } } + fn try_fill_bytes(&mut self, buffer: &mut [u8]) -> Result<(), ErrorKind> { + const BATCH_SIZE: usize = 4 / mem::size_of::(); + let mut i = 0_usize; + while i < buffer.len() { + let random_word = self.next_random_word()?; + let bytes = random_word.to_ne_bytes(); + let n = cmp::min(BATCH_SIZE, buffer.len() - i); + buffer[i..i + n].copy_from_slice(&bytes[..n]); + i += n; + } + Ok(()) + } + /// Releases ownership of the [`RNG`] peripheral object /// (after which `self` can't be used anymore). pub fn release(self) -> RNG { @@ -143,14 +155,31 @@ impl Rng { } impl rng::Read for Rng { - type Error = rand_core::Error; + type Error = rand_core_06::Error; fn read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.try_fill_bytes(buffer) + self.try_fill_bytes(buffer)?; + Ok(()) } } -impl RngCore for Rng { +impl rand_core::RngCore for Rng { + fn next_u32(&mut self) -> u32 { + self.next_random_word().unwrap() + } + + fn next_u64(&mut self) -> u64 { + let w1 = self.next_u32(); + let w2 = self.next_u32(); + (w1 as u64).shl(32) | (w2 as u64) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.try_fill_bytes(dest).unwrap() + } +} + +impl rand_core_06::RngCore for Rng { fn next_u32(&mut self) -> u32 { self.next_random_word().unwrap() } @@ -166,16 +195,8 @@ impl RngCore for Rng { } /// Fills buffer with random values, or returns an error - fn try_fill_bytes(&mut self, buffer: &mut [u8]) -> Result<(), rand_core::Error> { - const BATCH_SIZE: usize = 4 / mem::size_of::(); - let mut i = 0_usize; - while i < buffer.len() { - let random_word = self.next_random_word()?; - let bytes = random_word.to_ne_bytes(); - let n = cmp::min(BATCH_SIZE, buffer.len() - i); - buffer[i..i + n].copy_from_slice(&bytes[..n]); - i += n; - } + fn try_fill_bytes(&mut self, buffer: &mut [u8]) -> Result<(), rand_core_06::Error> { + self.try_fill_bytes(buffer)?; Ok(()) } } diff --git a/src/spi.rs b/src/spi.rs index 825be012..83d28f98 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -161,6 +161,7 @@ pub struct Inner { /// Spi in Master mode #[derive(Debug)] +#[allow(clippy::type_complexity)] pub struct Spi { inner: Inner, pins: (Option, Option, Option), @@ -182,6 +183,7 @@ impl DerefMut for Spi { /// Spi in Slave mode #[derive(Debug)] +#[allow(clippy::type_complexity)] pub struct SpiSlave { inner: Inner, pins: ( diff --git a/src/timer.rs b/src/timer.rs index 334b1cbf..752286e0 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -459,6 +459,7 @@ mod sealed { fn start_pwm(&mut self); } + #[allow(unused)] pub trait WithCapture: WithChannel { fn preload_capture(&mut self, c: u8, mode: CaptureMode); fn prescaler_capture(&mut self, c: u8, psc: CapturePrescaler); @@ -476,6 +477,7 @@ mod sealed { fn split() -> Self::Channels; } + #[allow(unused)] pub trait SplitCapture { type CaptureChannels; fn split_capture() -> Self::CaptureChannels; @@ -488,6 +490,7 @@ pub trait Instance: { } +#[allow(unused)] use sealed::{Split, SplitCapture}; macro_rules! split { ($TIM:ty: 1) => {