From 07387ea405b3228b9526d994da94e7d4a73339f7 Mon Sep 17 00:00:00 2001 From: elagil Date: Sat, 22 Mar 2025 11:46:28 +0100 Subject: [PATCH 1/4] fix: apply STM32H5 USB errata (OUT transfer delay) --- embassy-stm32/src/usb/usb.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 24983cf3c..d5cfa1bb8 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -7,6 +7,7 @@ use core::task::Poll; use embassy_hal_internal::into_ref; use embassy_sync::waitqueue::AtomicWaker; +use embassy_time::Timer; use embassy_usb_driver as driver; use embassy_usb_driver::{ Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, @@ -887,6 +888,16 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { }) .await; + // Errata for STM32H5, 2.20.1: + // During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + // have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + // + // Workaround: + // Software should ensure that a small delay is included before accessing the SRAM contents. This delay should be + // 800 ns in Full Speed mode and 6.4 μs in Low Speed mode. + #[cfg(stm32h5)] + Timer::after_nanos(800).await; + RX_COMPLETE[index].store(false, Ordering::Relaxed); if stat == Stat::DISABLED { From 5264d770079633786f6b34d6d656599bfc7efe7d Mon Sep 17 00:00:00 2001 From: elagil Date: Sat, 22 Mar 2025 11:46:38 +0100 Subject: [PATCH 2/4] fix: mute by default (UAC1) --- embassy-usb/src/class/uac1/speaker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-usb/src/class/uac1/speaker.rs b/embassy-usb/src/class/uac1/speaker.rs index 25de25d9c..1ff29088c 100644 --- a/embassy-usb/src/class/uac1/speaker.rs +++ b/embassy-usb/src/class/uac1/speaker.rs @@ -348,7 +348,7 @@ pub struct AudioSettings { impl Default for AudioSettings { fn default() -> Self { AudioSettings { - muted: [true; MAX_AUDIO_CHANNEL_COUNT], + muted: [false; MAX_AUDIO_CHANNEL_COUNT], volume_8q8_db: [MAX_VOLUME_DB * VOLUME_STEPS_PER_DB; MAX_AUDIO_CHANNEL_COUNT], } } From e34b4d69ee101f15f773381ca575a236f6dd452e Mon Sep 17 00:00:00 2001 From: elagil Date: Sat, 22 Mar 2025 11:58:50 +0100 Subject: [PATCH 3/4] fix: build --- embassy-stm32/src/usb/usb.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index d5cfa1bb8..f050c00ce 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -7,7 +7,6 @@ use core::task::Poll; use embassy_hal_internal::into_ref; use embassy_sync::waitqueue::AtomicWaker; -use embassy_time::Timer; use embassy_usb_driver as driver; use embassy_usb_driver::{ Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, @@ -896,7 +895,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { // Software should ensure that a small delay is included before accessing the SRAM contents. This delay should be // 800 ns in Full Speed mode and 6.4 μs in Low Speed mode. #[cfg(stm32h5)] - Timer::after_nanos(800).await; + embassy_time::Timer::after_nanos(800).await; RX_COMPLETE[index].store(false, Ordering::Relaxed); From 15394ae5fa9b8e3490fa7a600382ef549bff8f02 Mon Sep 17 00:00:00 2001 From: elagil Date: Mon, 24 Mar 2025 19:49:44 +0100 Subject: [PATCH 4/4] fix(usb): blocking wait --- embassy-stm32/src/usb/usb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index f050c00ce..6682374d3 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -895,7 +895,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { // Software should ensure that a small delay is included before accessing the SRAM contents. This delay should be // 800 ns in Full Speed mode and 6.4 μs in Low Speed mode. #[cfg(stm32h5)] - embassy_time::Timer::after_nanos(800).await; + embassy_time::block_for(embassy_time::Duration::from_nanos(800)); RX_COMPLETE[index].store(false, Ordering::Relaxed);