aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Davis <[email protected]>2023-05-03 21:07:28 -0500
committerGitHub <[email protected]>2023-05-03 21:07:28 -0500
commit91d1fff4edf41a251044ccde03af4ccf8a135f65 (patch)
treef76426657679c7a400894f71278086ac83dfd554
parent629e0ea595b28d89aad3f953b7190b04d78ff9d3 (diff)
parent374c92a4f0fda2932a0a86e5dcc3dc33651a48c7 (diff)
Merge branch 'embassy-rs:master' into master
-rw-r--r--embassy-rp/src/gpio.rs143
-rw-r--r--embassy-rp/src/lib.rs1
-rw-r--r--embassy-rp/src/multicore.rs5
-rw-r--r--embassy-rp/src/pio.rs482
-rw-r--r--embassy-rp/src/uart/mod.rs8
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/usart/buffered.rs4
-rw-r--r--embassy-stm32/src/usart/mod.rs128
-rw-r--r--examples/rp/src/bin/pio_async.rs34
-rw-r--r--examples/rp/src/bin/pio_dma.rs10
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs243
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs15
-rw-r--r--tests/rp/src/bin/gpio_multicore.rs63
-rw-r--r--tests/rp/src/bin/uart_dma.rs4
-rw-r--r--tests/stm32/Cargo.toml1
-rw-r--r--tests/stm32/build.rs13
-rw-r--r--tests/stm32/src/bin/spi.rs1
-rw-r--r--tests/stm32/src/bin/usart.rs77
-rw-r--r--tests/stm32/src/bin/usart_dma.rs3
-rw-r--r--tests/stm32/src/bin/usart_rx_ringbuffered.rs7
-rw-r--r--tests/stm32/src/example_common.rs5
21 files changed, 748 insertions, 503 deletions
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 98e182868..da8efba91 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -9,7 +9,7 @@ use embassy_sync::waitqueue::AtomicWaker;
9 9
10use crate::pac::common::{Reg, RW}; 10use crate::pac::common::{Reg, RW};
11use crate::pac::SIO; 11use crate::pac::SIO;
12use crate::{interrupt, pac, peripherals, Peripheral}; 12use crate::{interrupt, pac, peripherals, Peripheral, RegExt};
13 13
14const PIN_COUNT: usize = 30; 14const PIN_COUNT: usize = 30;
15const NEW_AW: AtomicWaker = AtomicWaker::new(); 15const NEW_AW: AtomicWaker = AtomicWaker::new();
@@ -136,16 +136,11 @@ pub enum InterruptTrigger {
136 AnyEdge, 136 AnyEdge,
137} 137}
138 138
139impl InterruptTrigger { 139pub(crate) unsafe fn init() {
140 fn from_u32(value: u32) -> Option<InterruptTrigger> { 140 let irq = interrupt::IO_IRQ_BANK0::steal();
141 match value { 141 irq.disable();
142 1 => Some(InterruptTrigger::LevelLow), 142 irq.set_priority(interrupt::Priority::P3);
143 2 => Some(InterruptTrigger::LevelHigh), 143 irq.enable();
144 3 => Some(InterruptTrigger::EdgeLow),
145 4 => Some(InterruptTrigger::EdgeHigh),
146 _ => None,
147 }
148 }
149} 144}
150 145
151#[interrupt] 146#[interrupt]
@@ -166,27 +161,15 @@ unsafe fn IO_IRQ_BANK0() {
166 let pin_group = (pin % 8) as usize; 161 let pin_group = (pin % 8) as usize;
167 let event = (intsx.read().0 >> pin_group * 4) & 0xf as u32; 162 let event = (intsx.read().0 >> pin_group * 4) & 0xf as u32;
168 163
169 if let Some(trigger) = InterruptTrigger::from_u32(event) { 164 // no more than one event can be awaited per pin at any given time, so
170 critical_section::with(|_| { 165 // we can just clear all interrupt enables for that pin without having
171 proc_intx.inte(pin / 8).modify(|w| match trigger { 166 // to check which event was signalled.
172 InterruptTrigger::AnyEdge => { 167 if event != 0 {
173 w.set_edge_high(pin_group, false); 168 proc_intx.inte(pin / 8).write_clear(|w| {
174 w.set_edge_low(pin_group, false); 169 w.set_edge_high(pin_group, true);
175 } 170 w.set_edge_low(pin_group, true);
176 InterruptTrigger::LevelHigh => { 171 w.set_level_high(pin_group, true);
177 trace!("IO_IRQ_BANK0 pin {} LevelHigh triggered", pin); 172 w.set_level_low(pin_group, true);
178 w.set_level_high(pin_group, false);
179 }
180 InterruptTrigger::LevelLow => {
181 w.set_level_low(pin_group, false);
182 }
183 InterruptTrigger::EdgeHigh => {
184 w.set_edge_high(pin_group, false);
185 }
186 InterruptTrigger::EdgeLow => {
187 w.set_edge_low(pin_group, false);
188 }
189 });
190 }); 173 });
191 INTERRUPT_WAKERS[pin as usize].wake(); 174 INTERRUPT_WAKERS[pin as usize].wake();
192 } 175 }
@@ -203,16 +186,26 @@ impl<'d, T: Pin> InputFuture<'d, T> {
203 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self { 186 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
204 into_ref!(pin); 187 into_ref!(pin);
205 unsafe { 188 unsafe {
206 let irq = interrupt::IO_IRQ_BANK0::steal(); 189 let pin_group = (pin.pin() % 8) as usize;
207 irq.disable(); 190 // first, clear the INTR register bits. without this INTR will still
208 irq.set_priority(interrupt::Priority::P3); 191 // contain reports of previous edges, causing the IRQ to fire early
192 // on stale state. clearing these means that we can only detect edges
193 // that occur *after* the clear happened, but since both this and the
194 // alternative are fundamentally racy it's probably fine.
195 // (the alternative being checking the current level and waiting for
196 // its inverse, but that requires reading the current level and thus
197 // missing anything that happened before the level was read.)
198 pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| {
199 w.set_edge_high(pin_group, true);
200 w.set_edge_low(pin_group, true);
201 });
209 202
210 // Each INTR register is divided into 8 groups, one group for each 203 // Each INTR register is divided into 8 groups, one group for each
211 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, 204 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW,
212 // and EGDE_HIGH. 205 // and EGDE_HIGH.
213 let pin_group = (pin.pin() % 8) as usize; 206 pin.int_proc()
214 critical_section::with(|_| { 207 .inte((pin.pin() / 8) as usize)
215 pin.int_proc().inte((pin.pin() / 8) as usize).modify(|w| match level { 208 .write_set(|w| match level {
216 InterruptTrigger::LevelHigh => { 209 InterruptTrigger::LevelHigh => {
217 trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin()); 210 trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin());
218 w.set_level_high(pin_group, true); 211 w.set_level_high(pin_group, true);
@@ -227,12 +220,10 @@ impl<'d, T: Pin> InputFuture<'d, T> {
227 w.set_edge_low(pin_group, true); 220 w.set_edge_low(pin_group, true);
228 } 221 }
229 InterruptTrigger::AnyEdge => { 222 InterruptTrigger::AnyEdge => {
230 // noop 223 w.set_edge_high(pin_group, true);
224 w.set_edge_low(pin_group, true);
231 } 225 }
232 }); 226 });
233 });
234
235 irq.enable();
236 } 227 }
237 228
238 Self { pin, level } 229 Self { pin, level }
@@ -257,47 +248,21 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
257 // LEVEL_HIGH, EDGE_LOW, and EDGE_HIGH for each pin. 248 // LEVEL_HIGH, EDGE_LOW, and EDGE_HIGH for each pin.
258 let pin_group = (self.pin.pin() % 8) as usize; 249 let pin_group = (self.pin.pin() % 8) as usize;
259 250
260 // This should check the the level of the interrupt trigger level of 251 // since the interrupt handler clears all INTE flags we'll check that
261 // the pin and if it has been disabled that means it was done by the 252 // all have been cleared and unconditionally return Ready(()) if so.
262 // interrupt service routine, so we then know that the event/trigger 253 // we don't need further handshaking since only a single event wait
263 // happened and Poll::Ready will be returned. 254 // is possible for any given pin at any given time.
264 trace!("{:?} for pin {}", self.level, self.pin.pin()); 255 if !inte.edge_high(pin_group)
265 match self.level { 256 && !inte.edge_low(pin_group)
266 InterruptTrigger::AnyEdge => { 257 && !inte.level_high(pin_group)
267 if !inte.edge_high(pin_group) && !inte.edge_low(pin_group) { 258 && !inte.level_low(pin_group)
268 #[rustfmt::skip] 259 {
269 trace!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin()); 260 trace!(
270 return Poll::Ready(()); 261 "{:?} for pin {} was cleared, return Poll::Ready",
271 } 262 self.level,
272 } 263 self.pin.pin()
273 InterruptTrigger::LevelHigh => { 264 );
274 if !inte.level_high(pin_group) { 265 return Poll::Ready(());
275 #[rustfmt::skip]
276 trace!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin());
277 return Poll::Ready(());
278 }
279 }
280 InterruptTrigger::LevelLow => {
281 if !inte.level_low(pin_group) {
282 #[rustfmt::skip]
283 trace!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin());
284 return Poll::Ready(());
285 }
286 }
287 InterruptTrigger::EdgeHigh => {
288 if !inte.edge_high(pin_group) {
289 #[rustfmt::skip]
290 trace!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin());
291 return Poll::Ready(());
292 }
293 }
294 InterruptTrigger::EdgeLow => {
295 if !inte.edge_low(pin_group) {
296 #[rustfmt::skip]
297 trace!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin());
298 return Poll::Ready(());
299 }
300 }
301 } 266 }
302 trace!("InputFuture::poll return Poll::Pending"); 267 trace!("InputFuture::poll return Poll::Pending");
303 Poll::Pending 268 Poll::Pending
@@ -644,23 +609,17 @@ impl<'d, T: Pin> Flex<'d, T> {
644 609
645 #[inline] 610 #[inline]
646 pub async fn wait_for_rising_edge(&mut self) { 611 pub async fn wait_for_rising_edge(&mut self) {
647 self.wait_for_low().await; 612 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeHigh).await;
648 self.wait_for_high().await;
649 } 613 }
650 614
651 #[inline] 615 #[inline]
652 pub async fn wait_for_falling_edge(&mut self) { 616 pub async fn wait_for_falling_edge(&mut self) {
653 self.wait_for_high().await; 617 InputFuture::new(&mut self.pin, InterruptTrigger::EdgeLow).await;
654 self.wait_for_low().await;
655 } 618 }
656 619
657 #[inline] 620 #[inline]
658 pub async fn wait_for_any_edge(&mut self) { 621 pub async fn wait_for_any_edge(&mut self) {
659 if self.is_high() { 622 InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await;
660 self.wait_for_low().await;
661 } else {
662 self.wait_for_high().await;
663 }
664 } 623 }
665} 624}
666 625
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index d69d12a30..cba7559df 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -157,6 +157,7 @@ pub fn init(_config: config::Config) -> Peripherals {
157 timer::init(); 157 timer::init();
158 dma::init(); 158 dma::init();
159 pio::init(); 159 pio::init();
160 gpio::init();
160 } 161 }
161 162
162 peripherals 163 peripherals
diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs
index e51fc218a..c84fea5c8 100644
--- a/embassy-rp/src/multicore.rs
+++ b/embassy-rp/src/multicore.rs
@@ -33,7 +33,7 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
33 33
34use crate::interrupt::{Interrupt, InterruptExt}; 34use crate::interrupt::{Interrupt, InterruptExt};
35use crate::peripherals::CORE1; 35use crate::peripherals::CORE1;
36use crate::{interrupt, pac}; 36use crate::{gpio, interrupt, pac};
37 37
38const PAUSE_TOKEN: u32 = 0xDEADBEEF; 38const PAUSE_TOKEN: u32 = 0xDEADBEEF;
39const RESUME_TOKEN: u32 = !0xDEADBEEF; 39const RESUME_TOKEN: u32 = !0xDEADBEEF;
@@ -68,6 +68,9 @@ fn install_stack_guard(stack_bottom: *mut usize) {
68#[inline(always)] 68#[inline(always)]
69fn core1_setup(stack_bottom: *mut usize) { 69fn core1_setup(stack_bottom: *mut usize) {
70 install_stack_guard(stack_bottom); 70 install_stack_guard(stack_bottom);
71 unsafe {
72 gpio::init();
73 }
71} 74}
72 75
73/// Data type for a properly aligned stack of N bytes 76/// Data type for a properly aligned stack of N bytes
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 7faec10b5..5433d3f21 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -5,14 +5,14 @@ use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::{Context, Poll}; 5use core::task::{Context, Poll};
6 6
7use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 7use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
8use embassy_hal_common::PeripheralRef; 8use embassy_hal_common::{Peripheral, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use crate::dma::{Channel, Transfer}; 11use crate::dma::{Channel, Transfer, Word};
12use crate::gpio::sealed::Pin as SealedPin; 12use crate::gpio::sealed::Pin as SealedPin;
13use crate::gpio::{Drive, Pin, Pull, SlewRate}; 13use crate::gpio::{Drive, Pin, Pull, SlewRate};
14use crate::pac::dma::vals::{DataSize, TreqSel}; 14use crate::pac::dma::vals::TreqSel;
15use crate::pio::sealed::{PioInstance as _, SmInstance as _}; 15use crate::pio::sealed::PioInstance as _;
16use crate::{interrupt, pac, peripherals, RegExt}; 16use crate::{interrupt, pac, peripherals, RegExt};
17 17
18struct Wakers([AtomicWaker; 12]); 18struct Wakers([AtomicWaker; 12]);
@@ -119,10 +119,10 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Future for FifoOutFuture
119 if self.get_mut().sm.try_push_tx(value) { 119 if self.get_mut().sm.try_push_tx(value) {
120 Poll::Ready(()) 120 Poll::Ready(())
121 } else { 121 } else {
122 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM::Sm::SM_NO as usize].register(cx.waker()); 122 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM::SM as usize].register(cx.waker());
123 unsafe { 123 unsafe {
124 PIO::PIO.irqs(0).inte().write_set(|m| { 124 PIO::PIO.irqs(0).inte().write_set(|m| {
125 m.0 = TXNFULL_MASK << SM::Sm::SM_NO; 125 m.0 = TXNFULL_MASK << SM::SM;
126 }); 126 });
127 } 127 }
128 // debug!("Pending"); 128 // debug!("Pending");
@@ -135,7 +135,7 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine + Unpin> Drop for FifoOutFuture<'
135 fn drop(&mut self) { 135 fn drop(&mut self) {
136 unsafe { 136 unsafe {
137 PIO::PIO.irqs(0).inte().write_clear(|m| { 137 PIO::PIO.irqs(0).inte().write_clear(|m| {
138 m.0 = TXNFULL_MASK << SM::Sm::SM_NO; 138 m.0 = TXNFULL_MASK << SM::SM;
139 }); 139 });
140 } 140 }
141 } 141 }
@@ -164,10 +164,10 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Future for FifoInFuture<'d, PIO,
164 if let Some(v) = self.sm.try_pull_rx() { 164 if let Some(v) = self.sm.try_pull_rx() {
165 Poll::Ready(v) 165 Poll::Ready(v)
166 } else { 166 } else {
167 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM::Sm::SM_NO as usize].register(cx.waker()); 167 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM::SM].register(cx.waker());
168 unsafe { 168 unsafe {
169 PIO::PIO.irqs(0).inte().write_set(|m| { 169 PIO::PIO.irqs(0).inte().write_set(|m| {
170 m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO; 170 m.0 = RXNEMPTY_MASK << SM::SM;
171 }); 171 });
172 } 172 }
173 //debug!("Pending"); 173 //debug!("Pending");
@@ -180,7 +180,7 @@ impl<'d, PIO: PioInstance, SM: PioStateMachine> Drop for FifoInFuture<'d, PIO, S
180 fn drop(&mut self) { 180 fn drop(&mut self) {
181 unsafe { 181 unsafe {
182 PIO::PIO.irqs(0).inte().write_clear(|m| { 182 PIO::PIO.irqs(0).inte().write_clear(|m| {
183 m.0 = RXNEMPTY_MASK << SM::Sm::SM_NO; 183 m.0 = RXNEMPTY_MASK << SM::SM;
184 }); 184 });
185 } 185 }
186 } 186 }
@@ -277,15 +277,14 @@ impl<PIO: PioInstance> PioPin<PIO> {
277 #[inline] 277 #[inline]
278 pub fn set_pull(&mut self, pull: Pull) { 278 pub fn set_pull(&mut self, pull: Pull) {
279 unsafe { 279 unsafe {
280 self.pad_ctrl().modify(|w| match pull { 280 self.pad_ctrl().modify(|w| {
281 Pull::Up => w.set_pue(true), 281 w.set_pue(pull == Pull::Up);
282 Pull::Down => w.set_pde(true), 282 w.set_pde(pull == Pull::Down);
283 Pull::None => {}
284 }); 283 });
285 } 284 }
286 } 285 }
287 286
288 /// Set the pin's pull. 287 /// Set the pin's schmitt trigger.
289 #[inline] 288 #[inline]
290 pub fn set_schmitt(&mut self, enable: bool) { 289 pub fn set_schmitt(&mut self, enable: bool) {
291 unsafe { 290 unsafe {
@@ -298,9 +297,11 @@ impl<PIO: PioInstance> PioPin<PIO> {
298 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { 297 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) {
299 let mask = 1 << self.pin(); 298 let mask = 1 << self.pin();
300 unsafe { 299 unsafe {
301 PIO::PIO 300 if bypass {
302 .input_sync_bypass() 301 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask);
303 .modify(|w| *w = if bypass { *w & !mask } else { *w | mask }); 302 } else {
303 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask);
304 }
304 } 305 }
305 } 306 }
306 307
@@ -315,16 +316,15 @@ impl<PIO: PioInstance> SealedPin for PioPin<PIO> {
315 } 316 }
316} 317}
317 318
318pub struct PioStateMachineInstance<PIO: PioInstance, SM: SmInstance> { 319pub struct PioStateMachineInstance<'d, PIO: PioInstance, const SM: usize> {
319 pio: PhantomData<PIO>, 320 pio: PhantomData<&'d PIO>,
320 sm: PhantomData<SM>,
321} 321}
322 322
323impl<PIO: PioInstance, SM: SmInstance> sealed::PioStateMachine for PioStateMachineInstance<PIO, SM> { 323impl<'d, PIO: PioInstance, const SM: usize> sealed::PioStateMachine for PioStateMachineInstance<'d, PIO, SM> {
324 type Pio = PIO; 324 type Pio = PIO;
325 type Sm = SM; 325 const SM: usize = SM;
326} 326}
327impl<PIO: PioInstance, SM: SmInstance> PioStateMachine for PioStateMachineInstance<PIO, SM> {} 327impl<'d, PIO: PioInstance, const SM: usize> PioStateMachine for PioStateMachineInstance<'d, PIO, SM> {}
328 328
329pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { 329pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
330 fn pio_no(&self) -> u8 { 330 fn pio_no(&self) -> u8 {
@@ -332,60 +332,61 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
332 } 332 }
333 333
334 fn sm_no(&self) -> u8 { 334 fn sm_no(&self) -> u8 {
335 Self::Sm::SM_NO 335 Self::SM as u8
336 } 336 }
337 337
338 fn restart(&mut self) { 338 fn restart(&mut self) {
339 let mask = 1u8 << Self::SM;
339 unsafe { 340 unsafe {
340 Self::Pio::PIO 341 Self::Pio::PIO.ctrl().write_set(|w| w.set_sm_restart(mask));
341 .ctrl()
342 .modify(|w| w.set_sm_restart(1u8 << Self::Sm::SM_NO));
343 } 342 }
344 } 343 }
345 fn set_enable(&mut self, enable: bool) { 344 fn set_enable(&mut self, enable: bool) {
346 let mask = 1u8 << Self::Sm::SM_NO; 345 let mask = 1u8 << Self::SM;
347 unsafe { 346 unsafe {
348 Self::Pio::PIO 347 if enable {
349 .ctrl() 348 Self::Pio::PIO.ctrl().write_set(|w| w.set_sm_enable(mask));
350 .modify(|w| w.set_sm_enable((w.sm_enable() & !mask) | (if enable { mask } else { 0 }))); 349 } else {
350 Self::Pio::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask));
351 }
351 } 352 }
352 } 353 }
353 354
354 fn is_enabled(&self) -> bool { 355 fn is_enabled(&self) -> bool {
355 unsafe { Self::Pio::PIO.ctrl().read().sm_enable() & (1u8 << Self::Sm::SM_NO) != 0 } 356 unsafe { Self::Pio::PIO.ctrl().read().sm_enable() & (1u8 << Self::SM) != 0 }
356 } 357 }
357 358
358 fn is_tx_empty(&self) -> bool { 359 fn is_tx_empty(&self) -> bool {
359 unsafe { Self::Pio::PIO.fstat().read().txempty() & (1u8 << Self::Sm::SM_NO) != 0 } 360 unsafe { Self::Pio::PIO.fstat().read().txempty() & (1u8 << Self::SM) != 0 }
360 } 361 }
361 fn is_tx_full(&self) -> bool { 362 fn is_tx_full(&self) -> bool {
362 unsafe { Self::Pio::PIO.fstat().read().txfull() & (1u8 << Self::Sm::SM_NO) != 0 } 363 unsafe { Self::Pio::PIO.fstat().read().txfull() & (1u8 << Self::SM) != 0 }
363 } 364 }
364 365
365 fn is_rx_empty(&self) -> bool { 366 fn is_rx_empty(&self) -> bool {
366 unsafe { Self::Pio::PIO.fstat().read().rxempty() & (1u8 << Self::Sm::SM_NO) != 0 } 367 unsafe { Self::Pio::PIO.fstat().read().rxempty() & (1u8 << Self::SM) != 0 }
367 } 368 }
368 fn is_rx_full(&self) -> bool { 369 fn is_rx_full(&self) -> bool {
369 unsafe { Self::Pio::PIO.fstat().read().rxfull() & (1u8 << Self::Sm::SM_NO) != 0 } 370 unsafe { Self::Pio::PIO.fstat().read().rxfull() & (1u8 << Self::SM) != 0 }
370 } 371 }
371 372
372 fn tx_level(&self) -> u8 { 373 fn tx_level(&self) -> u8 {
373 unsafe { 374 unsafe {
374 let flevel = Self::Pio::PIO.flevel().read().0; 375 let flevel = Self::Pio::PIO.flevel().read().0;
375 (flevel >> (Self::Sm::SM_NO * 8)) as u8 & 0x0f 376 (flevel >> (Self::SM * 8)) as u8 & 0x0f
376 } 377 }
377 } 378 }
378 379
379 fn rx_level(&self) -> u8 { 380 fn rx_level(&self) -> u8 {
380 unsafe { 381 unsafe {
381 let flevel = Self::Pio::PIO.flevel().read().0; 382 let flevel = Self::Pio::PIO.flevel().read().0;
382 (flevel >> (Self::Sm::SM_NO * 8 + 4)) as u8 & 0x0f 383 (flevel >> (Self::SM * 8 + 4)) as u8 & 0x0f
383 } 384 }
384 } 385 }
385 386
386 fn push_tx(&mut self, v: u32) { 387 fn push_tx(&mut self, v: u32) {
387 unsafe { 388 unsafe {
388 Self::Pio::PIO.txf(Self::Sm::SM_NO as usize).write_value(v); 389 Self::Pio::PIO.txf(Self::SM).write_value(v);
389 } 390 }
390 } 391 }
391 392
@@ -398,7 +399,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
398 } 399 }
399 400
400 fn pull_rx(&mut self) -> u32 { 401 fn pull_rx(&mut self) -> u32 {
401 unsafe { Self::Pio::PIO.rxf(Self::Sm::SM_NO as usize).read() } 402 unsafe { Self::Pio::PIO.rxf(Self::SM).read() }
402 } 403 }
403 404
404 fn try_pull_rx(&mut self) -> Option<u32> { 405 fn try_pull_rx(&mut self) -> Option<u32> {
@@ -410,73 +411,54 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
410 411
411 fn set_clkdiv(&mut self, div_x_256: u32) { 412 fn set_clkdiv(&mut self, div_x_256: u32) {
412 unsafe { 413 unsafe {
413 Self::Pio::PIO 414 Self::this_sm().clkdiv().write(|w| w.0 = div_x_256 << 8);
414 .sm(Self::Sm::SM_NO as usize)
415 .clkdiv()
416 .write(|w| w.0 = div_x_256 << 8);
417 } 415 }
418 } 416 }
419 417
420 fn get_clkdiv(&self) -> u32 { 418 fn get_clkdiv(&self) -> u32 {
421 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).clkdiv().read().0 >> 8 } 419 unsafe { Self::this_sm().clkdiv().read().0 >> 8 }
422 } 420 }
423 421
424 fn clkdiv_restart(&mut self) { 422 fn clkdiv_restart(&mut self) {
423 let mask = 1u8 << Self::SM;
425 unsafe { 424 unsafe {
426 Self::Pio::PIO 425 Self::Pio::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask));
427 .ctrl()
428 .modify(|w| w.set_clkdiv_restart(1u8 << Self::Sm::SM_NO));
429 } 426 }
430 } 427 }
431 428
432 fn set_side_enable(&self, enable: bool) { 429 fn set_side_enable(&self, enable: bool) {
433 unsafe { 430 unsafe {
434 Self::Pio::PIO 431 Self::this_sm().execctrl().modify(|w| w.set_side_en(enable));
435 .sm(Self::Sm::SM_NO as usize)
436 .execctrl()
437 .modify(|w| w.set_side_en(enable));
438 } 432 }
439 } 433 }
440 434
441 fn is_side_enabled(&self) -> bool { 435 fn is_side_enabled(&self) -> bool {
442 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().side_en() } 436 unsafe { Self::this_sm().execctrl().read().side_en() }
443 } 437 }
444 438
445 fn set_side_pindir(&mut self, pindir: bool) { 439 fn set_side_pindir(&mut self, pindir: bool) {
446 unsafe { 440 unsafe {
447 Self::Pio::PIO 441 Self::this_sm().execctrl().modify(|w| w.set_side_pindir(pindir));
448 .sm(Self::Sm::SM_NO as usize)
449 .execctrl()
450 .modify(|w| w.set_side_pindir(pindir));
451 } 442 }
452 } 443 }
453 444
454 fn is_side_pindir(&self) -> bool { 445 fn is_side_pindir(&self) -> bool {
455 unsafe { 446 unsafe { Self::this_sm().execctrl().read().side_pindir() }
456 Self::Pio::PIO
457 .sm(Self::Sm::SM_NO as usize)
458 .execctrl()
459 .read()
460 .side_pindir()
461 }
462 } 447 }
463 448
464 fn set_jmp_pin(&mut self, pin: u8) { 449 fn set_jmp_pin(&mut self, pin: u8) {
465 unsafe { 450 unsafe {
466 Self::Pio::PIO 451 Self::this_sm().execctrl().modify(|w| w.set_jmp_pin(pin));
467 .sm(Self::Sm::SM_NO as usize)
468 .execctrl()
469 .modify(|w| w.set_jmp_pin(pin));
470 } 452 }
471 } 453 }
472 454
473 fn get_jmp_pin(&mut self) -> u8 { 455 fn get_jmp_pin(&mut self) -> u8 {
474 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read().jmp_pin() } 456 unsafe { Self::this_sm().execctrl().read().jmp_pin() }
475 } 457 }
476 458
477 fn set_wrap(&self, source: u8, target: u8) { 459 fn set_wrap(&self, source: u8, target: u8) {
478 unsafe { 460 unsafe {
479 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().modify(|w| { 461 Self::this_sm().execctrl().modify(|w| {
480 w.set_wrap_top(source); 462 w.set_wrap_top(source);
481 w.set_wrap_bottom(target) 463 w.set_wrap_bottom(target)
482 }); 464 });
@@ -486,7 +468,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
486 /// Get wrapping addresses. Returns (source, target). 468 /// Get wrapping addresses. Returns (source, target).
487 fn get_wrap(&self) -> (u8, u8) { 469 fn get_wrap(&self) -> (u8, u8) {
488 unsafe { 470 unsafe {
489 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).execctrl().read(); 471 let r = Self::this_sm().execctrl().read();
490 (r.wrap_top(), r.wrap_bottom()) 472 (r.wrap_top(), r.wrap_bottom())
491 } 473 }
492 } 474 }
@@ -498,7 +480,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
498 FifoJoin::TxOnly => (false, true), 480 FifoJoin::TxOnly => (false, true),
499 }; 481 };
500 unsafe { 482 unsafe {
501 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().modify(|w| { 483 Self::this_sm().shiftctrl().modify(|w| {
502 w.set_fjoin_rx(rx); 484 w.set_fjoin_rx(rx);
503 w.set_fjoin_tx(tx) 485 w.set_fjoin_tx(tx)
504 }); 486 });
@@ -506,7 +488,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
506 } 488 }
507 fn get_fifo_join(&self) -> FifoJoin { 489 fn get_fifo_join(&self) -> FifoJoin {
508 unsafe { 490 unsafe {
509 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read(); 491 let r = Self::this_sm().shiftctrl().read();
510 // Ignores the invalid state when both bits are set 492 // Ignores the invalid state when both bits are set
511 if r.fjoin_rx() { 493 if r.fjoin_rx() {
512 FifoJoin::RxOnly 494 FifoJoin::RxOnly
@@ -521,7 +503,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
521 fn clear_fifos(&mut self) { 503 fn clear_fifos(&mut self) {
522 // Toggle FJOIN_RX to flush FIFOs 504 // Toggle FJOIN_RX to flush FIFOs
523 unsafe { 505 unsafe {
524 let shiftctrl = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl(); 506 let shiftctrl = Self::this_sm().shiftctrl();
525 shiftctrl.modify(|w| { 507 shiftctrl.modify(|w| {
526 w.set_fjoin_rx(!w.fjoin_rx()); 508 w.set_fjoin_rx(!w.fjoin_rx());
527 }); 509 });
@@ -533,51 +515,33 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
533 515
534 fn set_pull_threshold(&mut self, threshold: u8) { 516 fn set_pull_threshold(&mut self, threshold: u8) {
535 unsafe { 517 unsafe {
536 Self::Pio::PIO 518 Self::this_sm().shiftctrl().modify(|w| w.set_pull_thresh(threshold));
537 .sm(Self::Sm::SM_NO as usize)
538 .shiftctrl()
539 .modify(|w| w.set_pull_thresh(threshold));
540 } 519 }
541 } 520 }
542 521
543 fn get_pull_threshold(&self) -> u8 { 522 fn get_pull_threshold(&self) -> u8 {
544 unsafe { 523 unsafe { Self::this_sm().shiftctrl().read().pull_thresh() }
545 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
546 r.pull_thresh()
547 }
548 } 524 }
549 fn set_push_threshold(&mut self, threshold: u8) { 525 fn set_push_threshold(&mut self, threshold: u8) {
550 unsafe { 526 unsafe {
551 Self::Pio::PIO 527 Self::this_sm().shiftctrl().modify(|w| w.set_push_thresh(threshold));
552 .sm(Self::Sm::SM_NO as usize)
553 .shiftctrl()
554 .modify(|w| w.set_push_thresh(threshold));
555 } 528 }
556 } 529 }
557 530
558 fn get_push_threshold(&self) -> u8 { 531 fn get_push_threshold(&self) -> u8 {
559 unsafe { 532 unsafe { Self::this_sm().shiftctrl().read().push_thresh() }
560 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).shiftctrl().read();
561 r.push_thresh()
562 }
563 } 533 }
564 534
565 fn set_out_shift_dir(&mut self, dir: ShiftDirection) { 535 fn set_out_shift_dir(&mut self, dir: ShiftDirection) {
566 unsafe { 536 unsafe {
567 Self::Pio::PIO 537 Self::this_sm()
568 .sm(Self::Sm::SM_NO as usize)
569 .shiftctrl() 538 .shiftctrl()
570 .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right)); 539 .modify(|w| w.set_out_shiftdir(dir == ShiftDirection::Right));
571 } 540 }
572 } 541 }
573 fn get_out_shiftdir(&self) -> ShiftDirection { 542 fn get_out_shiftdir(&self) -> ShiftDirection {
574 unsafe { 543 unsafe {
575 if Self::Pio::PIO 544 if Self::this_sm().shiftctrl().read().out_shiftdir() {
576 .sm(Self::Sm::SM_NO as usize)
577 .shiftctrl()
578 .read()
579 .out_shiftdir()
580 {
581 ShiftDirection::Right 545 ShiftDirection::Right
582 } else { 546 } else {
583 ShiftDirection::Left 547 ShiftDirection::Left
@@ -587,20 +551,14 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
587 551
588 fn set_in_shift_dir(&mut self, dir: ShiftDirection) { 552 fn set_in_shift_dir(&mut self, dir: ShiftDirection) {
589 unsafe { 553 unsafe {
590 Self::Pio::PIO 554 Self::this_sm()
591 .sm(Self::Sm::SM_NO as usize)
592 .shiftctrl() 555 .shiftctrl()
593 .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right)); 556 .modify(|w| w.set_in_shiftdir(dir == ShiftDirection::Right));
594 } 557 }
595 } 558 }
596 fn get_in_shiftdir(&self) -> ShiftDirection { 559 fn get_in_shiftdir(&self) -> ShiftDirection {
597 unsafe { 560 unsafe {
598 if Self::Pio::PIO 561 if Self::this_sm().shiftctrl().read().in_shiftdir() {
599 .sm(Self::Sm::SM_NO as usize)
600 .shiftctrl()
601 .read()
602 .in_shiftdir()
603 {
604 ShiftDirection::Right 562 ShiftDirection::Right
605 } else { 563 } else {
606 ShiftDirection::Left 564 ShiftDirection::Left
@@ -610,76 +568,46 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
610 568
611 fn set_autopull(&mut self, auto: bool) { 569 fn set_autopull(&mut self, auto: bool) {
612 unsafe { 570 unsafe {
613 Self::Pio::PIO 571 Self::this_sm().shiftctrl().modify(|w| w.set_autopull(auto));
614 .sm(Self::Sm::SM_NO as usize)
615 .shiftctrl()
616 .modify(|w| w.set_autopull(auto));
617 } 572 }
618 } 573 }
619 574
620 fn is_autopull(&self) -> bool { 575 fn is_autopull(&self) -> bool {
621 unsafe { 576 unsafe { Self::this_sm().shiftctrl().read().autopull() }
622 Self::Pio::PIO
623 .sm(Self::Sm::SM_NO as usize)
624 .shiftctrl()
625 .read()
626 .autopull()
627 }
628 } 577 }
629 578
630 fn set_autopush(&mut self, auto: bool) { 579 fn set_autopush(&mut self, auto: bool) {
631 unsafe { 580 unsafe {
632 Self::Pio::PIO 581 Self::this_sm().shiftctrl().modify(|w| w.set_autopush(auto));
633 .sm(Self::Sm::SM_NO as usize)
634 .shiftctrl()
635 .modify(|w| w.set_autopush(auto));
636 } 582 }
637 } 583 }
638 584
639 fn is_autopush(&self) -> bool { 585 fn is_autopush(&self) -> bool {
640 unsafe { 586 unsafe { Self::this_sm().shiftctrl().read().autopush() }
641 Self::Pio::PIO
642 .sm(Self::Sm::SM_NO as usize)
643 .shiftctrl()
644 .read()
645 .autopush()
646 }
647 } 587 }
648 588
649 fn get_addr(&self) -> u8 { 589 fn get_addr(&self) -> u8 {
650 unsafe { 590 unsafe { Self::this_sm().addr().read().addr() }
651 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).addr().read();
652 r.addr()
653 }
654 } 591 }
655 fn set_sideset_count(&mut self, count: u8) { 592 fn set_sideset_count(&mut self, count: u8) {
656 unsafe { 593 unsafe {
657 Self::Pio::PIO 594 Self::this_sm().pinctrl().modify(|w| w.set_sideset_count(count));
658 .sm(Self::Sm::SM_NO as usize)
659 .pinctrl()
660 .modify(|w| w.set_sideset_count(count));
661 } 595 }
662 } 596 }
663 597
664 fn get_sideset_count(&self) -> u8 { 598 fn get_sideset_count(&self) -> u8 {
665 unsafe { 599 unsafe { Self::this_sm().pinctrl().read().sideset_count() }
666 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read();
667 r.sideset_count()
668 }
669 } 600 }
670 601
671 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) { 602 fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) {
672 unsafe { 603 unsafe {
673 Self::Pio::PIO 604 Self::this_sm().pinctrl().modify(|w| w.set_sideset_base(base_pin.pin()));
674 .sm(Self::Sm::SM_NO as usize)
675 .pinctrl()
676 .modify(|w| w.set_sideset_base(base_pin.pin()));
677 } 605 }
678 } 606 }
679 607
680 fn get_sideset_base(&self) -> u8 { 608 fn get_sideset_base(&self) -> u8 {
681 unsafe { 609 unsafe {
682 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 610 let r = Self::this_sm().pinctrl().read();
683 r.sideset_base() 611 r.sideset_base()
684 } 612 }
685 } 613 }
@@ -688,7 +616,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
688 fn set_set_range(&mut self, base: u8, count: u8) { 616 fn set_set_range(&mut self, base: u8, count: u8) {
689 assert!(base + count < 32); 617 assert!(base + count < 32);
690 unsafe { 618 unsafe {
691 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| { 619 Self::this_sm().pinctrl().modify(|w| {
692 w.set_set_base(base); 620 w.set_set_base(base);
693 w.set_set_count(count) 621 w.set_set_count(count)
694 }); 622 });
@@ -698,23 +626,20 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
698 /// Get the range of out pins affected by a set instruction. Returns (base, count). 626 /// Get the range of out pins affected by a set instruction. Returns (base, count).
699 fn get_set_range(&self) -> (u8, u8) { 627 fn get_set_range(&self) -> (u8, u8) {
700 unsafe { 628 unsafe {
701 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 629 let r = Self::this_sm().pinctrl().read();
702 (r.set_base(), r.set_count()) 630 (r.set_base(), r.set_count())
703 } 631 }
704 } 632 }
705 633
706 fn set_in_base_pin(&mut self, base: &PioPin<Self::Pio>) { 634 fn set_in_base_pin(&mut self, base: &PioPin<Self::Pio>) {
707 unsafe { 635 unsafe {
708 Self::Pio::PIO 636 Self::this_sm().pinctrl().modify(|w| w.set_in_base(base.pin()));
709 .sm(Self::Sm::SM_NO as usize)
710 .pinctrl()
711 .modify(|w| w.set_in_base(base.pin()));
712 } 637 }
713 } 638 }
714 639
715 fn get_in_base(&self) -> u8 { 640 fn get_in_base(&self) -> u8 {
716 unsafe { 641 unsafe {
717 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 642 let r = Self::this_sm().pinctrl().read();
718 r.in_base() 643 r.in_base()
719 } 644 }
720 } 645 }
@@ -722,7 +647,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
722 fn set_out_range(&mut self, base: u8, count: u8) { 647 fn set_out_range(&mut self, base: u8, count: u8) {
723 assert!(base + count < 32); 648 assert!(base + count < 32);
724 unsafe { 649 unsafe {
725 Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().modify(|w| { 650 Self::this_sm().pinctrl().modify(|w| {
726 w.set_out_base(base); 651 w.set_out_base(base);
727 w.set_out_count(count) 652 w.set_out_count(count)
728 }); 653 });
@@ -732,7 +657,7 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
732 /// Get the range of out pins affected by a set instruction. Returns (base, count). 657 /// Get the range of out pins affected by a set instruction. Returns (base, count).
733 fn get_out_range(&self) -> (u8, u8) { 658 fn get_out_range(&self) -> (u8, u8) {
734 unsafe { 659 unsafe {
735 let r = Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).pinctrl().read(); 660 let r = Self::this_sm().pinctrl().read();
736 (r.out_base(), r.out_count()) 661 (r.out_base(), r.out_count())
737 } 662 }
738 } 663 }
@@ -760,15 +685,12 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
760 } 685 }
761 686
762 fn get_current_instr() -> u32 { 687 fn get_current_instr() -> u32 {
763 unsafe { Self::Pio::PIO.sm(Self::Sm::SM_NO as usize).instr().read().0 } 688 unsafe { Self::this_sm().instr().read().0 }
764 } 689 }
765 690
766 fn exec_instr(&mut self, instr: u16) { 691 fn exec_instr(&mut self, instr: u16) {
767 unsafe { 692 unsafe {
768 Self::Pio::PIO 693 Self::this_sm().instr().write(|w| w.set_instr(instr));
769 .sm(Self::Sm::SM_NO as usize)
770 .instr()
771 .write(|w| w.set_instr(instr));
772 } 694 }
773 } 695 }
774 696
@@ -787,8 +709,8 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
787 fn has_tx_stalled(&self) -> bool { 709 fn has_tx_stalled(&self) -> bool {
788 unsafe { 710 unsafe {
789 let fdebug = Self::Pio::PIO.fdebug(); 711 let fdebug = Self::Pio::PIO.fdebug();
790 let ret = fdebug.read().txstall() & (1 << Self::Sm::SM_NO) != 0; 712 let ret = fdebug.read().txstall() & (1 << Self::SM) != 0;
791 fdebug.write(|w| w.set_txstall(1 << Self::Sm::SM_NO)); 713 fdebug.write(|w| w.set_txstall(1 << Self::SM));
792 ret 714 ret
793 } 715 }
794 } 716 }
@@ -796,8 +718,8 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
796 fn has_tx_overflowed(&self) -> bool { 718 fn has_tx_overflowed(&self) -> bool {
797 unsafe { 719 unsafe {
798 let fdebug = Self::Pio::PIO.fdebug(); 720 let fdebug = Self::Pio::PIO.fdebug();
799 let ret = fdebug.read().txover() & (1 << Self::Sm::SM_NO) != 0; 721 let ret = fdebug.read().txover() & (1 << Self::SM) != 0;
800 fdebug.write(|w| w.set_txover(1 << Self::Sm::SM_NO)); 722 fdebug.write(|w| w.set_txover(1 << Self::SM));
801 ret 723 ret
802 } 724 }
803 } 725 }
@@ -805,8 +727,8 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
805 fn has_rx_stalled(&self) -> bool { 727 fn has_rx_stalled(&self) -> bool {
806 unsafe { 728 unsafe {
807 let fdebug = Self::Pio::PIO.fdebug(); 729 let fdebug = Self::Pio::PIO.fdebug();
808 let ret = fdebug.read().rxstall() & (1 << Self::Sm::SM_NO) != 0; 730 let ret = fdebug.read().rxstall() & (1 << Self::SM) != 0;
809 fdebug.write(|w| w.set_rxstall(1 << Self::Sm::SM_NO)); 731 fdebug.write(|w| w.set_rxstall(1 << Self::SM));
810 ret 732 ret
811 } 733 }
812 } 734 }
@@ -814,25 +736,25 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
814 fn has_rx_underflowed(&self) -> bool { 736 fn has_rx_underflowed(&self) -> bool {
815 unsafe { 737 unsafe {
816 let fdebug = Self::Pio::PIO.fdebug(); 738 let fdebug = Self::Pio::PIO.fdebug();
817 let ret = fdebug.read().rxunder() & (1 << Self::Sm::SM_NO) != 0; 739 let ret = fdebug.read().rxunder() & (1 << Self::SM) != 0;
818 fdebug.write(|w| w.set_rxunder(1 << Self::Sm::SM_NO)); 740 fdebug.write(|w| w.set_rxunder(1 << Self::SM));
819 ret 741 ret
820 } 742 }
821 } 743 }
822 744
823 fn dma_push<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [u32]) -> Transfer<'a, C> { 745 fn dma_push<'a, C: Channel, W: Word>(&'a self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> {
824 unsafe { 746 unsafe {
825 let pio_no = Self::Pio::PIO_NO; 747 let pio_no = Self::Pio::PIO_NO;
826 let sm_no = Self::Sm::SM_NO; 748 let sm_no = Self::SM;
827 let p = ch.regs(); 749 let p = ch.regs();
828 p.read_addr().write_value(data.as_ptr() as u32); 750 p.read_addr().write_value(data.as_ptr() as u32);
829 p.write_addr() 751 p.write_addr().write_value(Self::Pio::PIO.txf(sm_no).ptr() as u32);
830 .write_value(Self::Pio::PIO.txf(sm_no as usize).ptr() as u32);
831 p.trans_count().write_value(data.len() as u32); 752 p.trans_count().write_value(data.len() as u32);
753 compiler_fence(Ordering::SeqCst);
832 p.ctrl_trig().write(|w| { 754 p.ctrl_trig().write(|w| {
833 // Set TX DREQ for this statemachine 755 // Set TX DREQ for this statemachine
834 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no)); 756 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no as u8));
835 w.set_data_size(DataSize::SIZE_WORD); 757 w.set_data_size(W::size());
836 w.set_chain_to(ch.number()); 758 w.set_chain_to(ch.number());
837 w.set_incr_read(true); 759 w.set_incr_read(true);
838 w.set_incr_write(false); 760 w.set_incr_write(false);
@@ -843,19 +765,19 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
843 Transfer::new(ch) 765 Transfer::new(ch)
844 } 766 }
845 767
846 fn dma_pull<'a, C: Channel>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [u32]) -> Transfer<'a, C> { 768 fn dma_pull<'a, C: Channel, W: Word>(&'a self, ch: PeripheralRef<'a, C>, data: &'a mut [W]) -> Transfer<'a, C> {
847 unsafe { 769 unsafe {
848 let pio_no = Self::Pio::PIO_NO; 770 let pio_no = Self::Pio::PIO_NO;
849 let sm_no = Self::Sm::SM_NO; 771 let sm_no = Self::SM;
850 let p = ch.regs(); 772 let p = ch.regs();
851 p.write_addr().write_value(data.as_ptr() as u32); 773 p.write_addr().write_value(data.as_ptr() as u32);
852 p.read_addr() 774 p.read_addr().write_value(Self::Pio::PIO.rxf(sm_no).ptr() as u32);
853 .write_value(Self::Pio::PIO.rxf(sm_no as usize).ptr() as u32);
854 p.trans_count().write_value(data.len() as u32); 775 p.trans_count().write_value(data.len() as u32);
776 compiler_fence(Ordering::SeqCst);
855 p.ctrl_trig().write(|w| { 777 p.ctrl_trig().write(|w| {
856 // Set TX DREQ for this statemachine 778 // Set RX DREQ for this statemachine
857 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no + 4)); 779 w.set_treq_sel(TreqSel(pio_no * 8 + sm_no as u8 + 4));
858 w.set_data_size(DataSize::SIZE_WORD); 780 w.set_data_size(W::size());
859 w.set_chain_to(ch.number()); 781 w.set_chain_to(ch.number());
860 w.set_incr_read(false); 782 w.set_incr_read(false);
861 w.set_incr_write(true); 783 w.set_incr_write(true);
@@ -867,21 +789,18 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
867 } 789 }
868} 790}
869 791
870pub struct PioCommonInstance<PIO: PioInstance> { 792pub struct PioCommon<'d, PIO: PioInstance> {
871 instructions_used: u32, 793 instructions_used: u32,
872 pio: PhantomData<PIO>, 794 pio: PhantomData<&'d PIO>,
873} 795}
874 796
875pub struct PioInstanceMemory<PIO: PioInstance> { 797pub struct PioInstanceMemory<'d, PIO: PioInstance> {
876 used_mask: u32, 798 used_mask: u32,
877 pio: PhantomData<PIO>, 799 pio: PhantomData<&'d PIO>,
878} 800}
879 801
880impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> { 802impl<'d, PIO: PioInstance> PioCommon<'d, PIO> {
881 type Pio = PIO; 803 pub fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<'d, PIO>
882}
883impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {
884 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
885 where 804 where
886 I: Iterator<Item = u16>, 805 I: Iterator<Item = u16>,
887 { 806 {
@@ -908,66 +827,50 @@ impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {
908 } 827 }
909 } 828 }
910 829
911 fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>) { 830 // TODO make instruction memory that is currently in use unfreeable
831 pub fn free_instr(&mut self, instrs: PioInstanceMemory<PIO>) {
912 self.instructions_used &= !instrs.used_mask; 832 self.instructions_used &= !instrs.used_mask;
913 } 833 }
914}
915
916pub trait PioCommon: sealed::PioCommon + Sized {
917 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
918 where
919 I: Iterator<Item = u16>;
920 834
921 // TODO make instruction memory that is currently in use unfreeable 835 pub fn is_irq_set(&self, irq_no: u8) -> bool {
922 fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>);
923
924 fn is_irq_set(&self, irq_no: u8) -> bool {
925 assert!(irq_no < 8); 836 assert!(irq_no < 8);
926 unsafe { 837 unsafe {
927 let irq_flags = Self::Pio::PIO.irq(); 838 let irq_flags = PIO::PIO.irq();
928 irq_flags.read().0 & (1 << irq_no) != 0 839 irq_flags.read().0 & (1 << irq_no) != 0
929 } 840 }
930 } 841 }
931 842
932 fn clear_irq(&mut self, irq_no: usize) { 843 pub fn clear_irq(&mut self, irq_no: usize) {
933 assert!(irq_no < 8); 844 assert!(irq_no < 8);
934 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) } 845 unsafe { PIO::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
935 } 846 }
936 847
937 fn clear_irqs(&mut self, mask: u8) { 848 pub fn clear_irqs(&mut self, mask: u8) {
938 unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(mask)) } 849 unsafe { PIO::PIO.irq().write(|w| w.set_irq(mask)) }
939 } 850 }
940 851
941 fn force_irq(&mut self, irq_no: usize) { 852 pub fn force_irq(&mut self, irq_no: usize) {
942 assert!(irq_no < 8); 853 assert!(irq_no < 8);
943 unsafe { Self::Pio::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) } 854 unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(1 << irq_no)) }
944 } 855 }
945 856
946 fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { 857 pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) {
947 unsafe { 858 unsafe {
948 Self::Pio::PIO 859 // this can interfere with per-pin bypass functions. splitting the
949 .input_sync_bypass() 860 // modification is going to be fine since nothing that relies on
950 .modify(|w| *w = (*w & !mask) | (bypass & mask)); 861 // it can reasonably run before we finish.
862 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass);
863 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass);
951 } 864 }
952 } 865 }
953 866
954 fn get_input_sync_bypass(&self) -> u32 { 867 pub fn get_input_sync_bypass(&self) -> u32 {
955 unsafe { Self::Pio::PIO.input_sync_bypass().read() } 868 unsafe { PIO::PIO.input_sync_bypass().read() }
956 } 869 }
957 870
958 fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> { 871 pub fn make_pio_pin(&self, pin: impl Pin) -> PioPin<PIO> {
959 unsafe { 872 unsafe {
960 pin.io().ctrl().write(|w| { 873 pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0));
961 w.set_funcsel(
962 if Self::Pio::PIO_NO == 1 {
963 pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
964 } else {
965 // PIO == 0
966 pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
967 }
968 .0,
969 );
970 });
971 } 874 }
972 PioPin { 875 PioPin {
973 pin_bank: pin.pin_bank(), 876 pin_bank: pin.pin_bank(),
@@ -976,112 +879,63 @@ pub trait PioCommon: sealed::PioCommon + Sized {
976 } 879 }
977} 880}
978 881
979// Identifies a specific state machine inside a PIO device 882pub struct Pio<'d, PIO: PioInstance> {
980pub struct SmInstanceBase<const SM_NO: u8> {} 883 pub common: PioCommon<'d, PIO>,
981 884 pub sm0: PioStateMachineInstance<'d, PIO, 0>,
982pub trait SmInstance: sealed::SmInstance + Unpin {} 885 pub sm1: PioStateMachineInstance<'d, PIO, 1>,
983 886 pub sm2: PioStateMachineInstance<'d, PIO, 2>,
984impl<const SM_NO: u8> sealed::SmInstance for SmInstanceBase<SM_NO> { 887 pub sm3: PioStateMachineInstance<'d, PIO, 3>,
985 const SM_NO: u8 = SM_NO;
986} 888}
987impl<const SM_NO: u8> SmInstance for SmInstanceBase<SM_NO> {}
988
989pub trait PioPeripheral: sealed::PioPeripheral + Sized {
990 fn pio(&self) -> u8 {
991 Self::Pio::PIO_NO
992 }
993 889
994 fn split( 890impl<'d, PIO: PioInstance> Pio<'d, PIO> {
995 self, 891 pub fn new(_pio: impl Peripheral<P = PIO> + 'd) -> Self {
996 ) -> ( 892 Self {
997 PioCommonInstance<Self::Pio>, 893 common: PioCommon {
998 PioStateMachineInstance<Self::Pio, SmInstanceBase<0>>,
999 PioStateMachineInstance<Self::Pio, SmInstanceBase<1>>,
1000 PioStateMachineInstance<Self::Pio, SmInstanceBase<2>>,
1001 PioStateMachineInstance<Self::Pio, SmInstanceBase<3>>,
1002 ) {
1003 (
1004 PioCommonInstance {
1005 instructions_used: 0, 894 instructions_used: 0,
1006 pio: PhantomData::default(), 895 pio: PhantomData,
1007 }, 896 },
1008 PioStateMachineInstance { 897 sm0: PioStateMachineInstance { pio: PhantomData },
1009 sm: PhantomData::default(), 898 sm1: PioStateMachineInstance { pio: PhantomData },
1010 pio: PhantomData::default(), 899 sm2: PioStateMachineInstance { pio: PhantomData },
1011 }, 900 sm3: PioStateMachineInstance { pio: PhantomData },
1012 PioStateMachineInstance { 901 }
1013 sm: PhantomData::default(),
1014 pio: PhantomData::default(),
1015 },
1016 PioStateMachineInstance {
1017 sm: PhantomData::default(),
1018 pio: PhantomData::default(),
1019 },
1020 PioStateMachineInstance {
1021 sm: PhantomData::default(),
1022 pio: PhantomData::default(),
1023 },
1024 )
1025 } 902 }
1026} 903}
1027 904
1028mod sealed { 905pub trait PioInstance: sealed::PioInstance + Sized + Unpin {
1029 pub trait PioInstance { 906 fn pio(&self) -> u8 {
1030 const PIO_NO: u8; 907 Self::PIO_NO
1031 const PIO: &'static crate::pac::pio::Pio;
1032 }
1033
1034 pub trait PioCommon {
1035 type Pio: super::PioInstance;
1036 } 908 }
909}
1037 910
911mod sealed {
1038 pub trait PioStateMachine { 912 pub trait PioStateMachine {
1039 type Pio: super::PioInstance; 913 type Pio: super::PioInstance;
1040 type Sm: super::SmInstance; 914 const SM: usize;
1041 }
1042 915
1043 pub trait SmInstance { 916 #[inline(always)]
1044 const SM_NO: u8; 917 fn this_sm() -> crate::pac::pio::StateMachine {
918 Self::Pio::PIO.sm(Self::SM as usize)
919 }
1045 } 920 }
1046 921
1047 pub trait PioPeripheral { 922 pub trait PioInstance {
1048 type Pio: super::PioInstance; 923 const PIO_NO: u8;
924 const PIO: &'static crate::pac::pio::Pio;
925 const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel;
1049 } 926 }
1050} 927}
1051 928
1052// Identifies a specific PIO device 929macro_rules! impl_pio {
1053pub struct PioInstanceBase<const PIO_NO: u8> {} 930 ($name:ident, $pio:expr, $pac:ident, $funcsel:ident) => {
1054 931 impl sealed::PioInstance for peripherals::$name {
1055pub trait PioInstance: sealed::PioInstance + Unpin {} 932 const PIO_NO: u8 = $pio;
1056 933 const PIO: &'static pac::pio::Pio = &pac::$pac;
1057impl sealed::PioInstance for PioInstanceBase<0> { 934 const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel;
1058 const PIO_NO: u8 = 0;
1059 const PIO: &'static pac::pio::Pio = &pac::PIO0;
1060}
1061impl PioInstance for PioInstanceBase<0> {}
1062
1063impl sealed::PioInstance for PioInstanceBase<1> {
1064 const PIO_NO: u8 = 1;
1065 const PIO: &'static pac::pio::Pio = &pac::PIO1;
1066}
1067impl PioInstance for PioInstanceBase<1> {}
1068
1069pub type Pio0 = PioInstanceBase<0>;
1070pub type Pio1 = PioInstanceBase<1>;
1071
1072pub type Sm0 = SmInstanceBase<0>;
1073pub type Sm1 = SmInstanceBase<1>;
1074pub type Sm2 = SmInstanceBase<2>;
1075pub type Sm3 = SmInstanceBase<3>;
1076
1077macro_rules! impl_pio_sm {
1078 ($name:ident, $pio:expr) => {
1079 impl sealed::PioPeripheral for peripherals::$name {
1080 type Pio = PioInstanceBase<$pio>;
1081 } 935 }
1082 impl PioPeripheral for peripherals::$name {} 936 impl PioInstance for peripherals::$name {}
1083 }; 937 };
1084} 938}
1085 939
1086impl_pio_sm!(PIO0, 0); 940impl_pio!(PIO0, 0, PIO0, PIO0_0);
1087impl_pio_sm!(PIO1, 1); 941impl_pio!(PIO1, 1, PIO1, PIO1_0);
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index ebe32cc66..4084c158a 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -874,7 +874,6 @@ mod sealed {
874 pub trait Instance { 874 pub trait Instance {
875 const TX_DREQ: u8; 875 const TX_DREQ: u8;
876 const RX_DREQ: u8; 876 const RX_DREQ: u8;
877 const ID: usize;
878 877
879 type Interrupt: crate::interrupt::Interrupt; 878 type Interrupt: crate::interrupt::Interrupt;
880 879
@@ -909,11 +908,10 @@ impl_mode!(Async);
909pub trait Instance: sealed::Instance {} 908pub trait Instance: sealed::Instance {}
910 909
911macro_rules! impl_instance { 910macro_rules! impl_instance {
912 ($inst:ident, $irq:ident, $id:expr, $tx_dreq:expr, $rx_dreq:expr) => { 911 ($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {
913 impl sealed::Instance for peripherals::$inst { 912 impl sealed::Instance for peripherals::$inst {
914 const TX_DREQ: u8 = $tx_dreq; 913 const TX_DREQ: u8 = $tx_dreq;
915 const RX_DREQ: u8 = $rx_dreq; 914 const RX_DREQ: u8 = $rx_dreq;
916 const ID: usize = $id;
917 915
918 type Interrupt = crate::interrupt::$irq; 916 type Interrupt = crate::interrupt::$irq;
919 917
@@ -939,8 +937,8 @@ macro_rules! impl_instance {
939 }; 937 };
940} 938}
941 939
942impl_instance!(UART0, UART0_IRQ, 0, 20, 21); 940impl_instance!(UART0, UART0_IRQ, 20, 21);
943impl_instance!(UART1, UART1_IRQ, 1, 22, 23); 941impl_instance!(UART1, UART1_IRQ, 22, 23);
944 942
945pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 943pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
946pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 944pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 9686b10ce..b9887f9b3 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -58,7 +58,7 @@ sdio-host = "0.5.0"
58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
59critical-section = "1.1" 59critical-section = "1.1"
60atomic-polyfill = "1.0.1" 60atomic-polyfill = "1.0.1"
61stm32-metapac = "6" 61stm32-metapac = "7"
62vcell = "0.1.3" 62vcell = "0.1.3"
63bxcan = "0.7.0" 63bxcan = "0.7.0"
64nb = "1.0.0" 64nb = "1.0.0"
@@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] }
74[build-dependencies] 74[build-dependencies]
75proc-macro2 = "1.0.36" 75proc-macro2 = "1.0.36"
76quote = "1.0.15" 76quote = "1.0.15"
77stm32-metapac = { version = "6", default-features = false, features = ["metadata"]} 77stm32-metapac = { version = "7", default-features = false, features = ["metadata"]}
78 78
79[features] 79[features]
80default = ["stm32-metapac/rt"] 80default = ["stm32-metapac/rt"]
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 3e23e7ca1..12cf8b0fc 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -84,7 +84,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
84 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config) 84 Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
85 } 85 }
86 86
87 #[cfg(not(usart_v1))] 87 #[cfg(not(any(usart_v1, usart_v2)))]
88 pub fn new_with_de( 88 pub fn new_with_de(
89 peri: impl Peripheral<P = T> + 'd, 89 peri: impl Peripheral<P = T> + 'd,
90 irq: impl Peripheral<P = T::Interrupt> + 'd, 90 irq: impl Peripheral<P = T::Interrupt> + 'd,
@@ -133,7 +133,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
133 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 133 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
134 } 134 }
135 135
136 configure(r, &config, T::frequency(), T::MULTIPLIER, true, true); 136 configure(r, &config, T::frequency(), T::KIND, true, true);
137 137
138 unsafe { 138 unsafe {
139 r.cr1().modify(|w| { 139 r.cr1().modify(|w| {
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index ad450f2b3..dbce668c2 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -12,10 +12,11 @@ use futures::future::{select, Either};
12 12
13use crate::dma::{NoDma, Transfer}; 13use crate::dma::{NoDma, Transfer};
14use crate::gpio::sealed::AFType; 14use crate::gpio::sealed::AFType;
15#[cfg(any(lpuart_v1, lpuart_v2))] 15#[cfg(not(any(usart_v1, usart_v2)))]
16use crate::pac::lpuart::{regs, vals, Lpuart as Regs}; 16use crate::pac::usart::Lpuart as Regs;
17#[cfg(not(any(lpuart_v1, lpuart_v2)))] 17#[cfg(any(usart_v1, usart_v2))]
18use crate::pac::usart::{regs, vals, Usart as Regs}; 18use crate::pac::usart::Usart as Regs;
19use crate::pac::usart::{regs, vals};
19use crate::time::Hertz; 20use crate::time::Hertz;
20use crate::{peripherals, Peripheral}; 21use crate::{peripherals, Peripheral};
21 22
@@ -159,7 +160,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
159 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 160 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
160 } 161 }
161 162
162 configure(r, &config, T::frequency(), T::MULTIPLIER, false, true); 163 configure(r, &config, T::frequency(), T::KIND, false, true);
163 164
164 // create state once! 165 // create state once!
165 let _s = T::state(); 166 let _s = T::state();
@@ -261,7 +262,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
261 rx.set_as_af(rx.af_num(), AFType::Input); 262 rx.set_as_af(rx.af_num(), AFType::Input);
262 } 263 }
263 264
264 configure(r, &config, T::frequency(), T::MULTIPLIER, true, false); 265 configure(r, &config, T::frequency(), T::KIND, true, false);
265 266
266 irq.set_handler(Self::on_interrupt); 267 irq.set_handler(Self::on_interrupt);
267 irq.unpend(); 268 irq.unpend();
@@ -653,7 +654,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
653 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config) 654 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
654 } 655 }
655 656
656 #[cfg(not(usart_v1))] 657 #[cfg(not(any(usart_v1, usart_v2)))]
657 pub fn new_with_de( 658 pub fn new_with_de(
658 peri: impl Peripheral<P = T> + 'd, 659 peri: impl Peripheral<P = T> + 'd,
659 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 660 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -696,7 +697,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
696 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 697 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
697 } 698 }
698 699
699 configure(r, &config, T::frequency(), T::MULTIPLIER, true, true); 700 configure(r, &config, T::frequency(), T::KIND, true, true);
700 701
701 irq.set_handler(UartRx::<T, RxDma>::on_interrupt); 702 irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
702 irq.unpend(); 703 irq.unpend();
@@ -763,16 +764,74 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
763 } 764 }
764} 765}
765 766
766fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32, enable_rx: bool, enable_tx: bool) { 767fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: bool, enable_tx: bool) {
767 if !enable_rx && !enable_tx { 768 if !enable_rx && !enable_tx {
768 panic!("USART: At least one of RX or TX should be enabled"); 769 panic!("USART: At least one of RX or TX should be enabled");
769 } 770 }
770 771
771 // TODO: better calculation, including error checking and OVER8 if possible. 772 #[cfg(not(usart_v4))]
772 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier; 773 static DIVS: [(u16, ()); 1] = [(1, ())];
774
775 #[cfg(usart_v4)]
776 static DIVS: [(u16, vals::Presc); 12] = [
777 (1, vals::Presc::DIV1),
778 (2, vals::Presc::DIV2),
779 (4, vals::Presc::DIV4),
780 (6, vals::Presc::DIV6),
781 (8, vals::Presc::DIV8),
782 (10, vals::Presc::DIV10),
783 (12, vals::Presc::DIV12),
784 (16, vals::Presc::DIV16),
785 (32, vals::Presc::DIV32),
786 (64, vals::Presc::DIV64),
787 (128, vals::Presc::DIV128),
788 (256, vals::Presc::DIV256),
789 ];
790
791 let (mul, brr_min, brr_max) = match kind {
792 #[cfg(any(usart_v3, usart_v4))]
793 Kind::Lpuart => (256, 0x300, 0x10_0000),
794 Kind::Uart => (1, 0x10, 0x1_0000),
795 };
796
797 #[cfg(not(usart_v1))]
798 let mut over8 = false;
799 let mut found = false;
800 for &(presc, _presc_val) in &DIVS {
801 let denom = (config.baudrate * presc as u32) as u64;
802 let div = (pclk_freq.0 as u64 * mul + (denom / 2)) / denom;
803 trace!("USART: presc={} div={:08x}", presc, div);
804
805 if div < brr_min {
806 #[cfg(not(usart_v1))]
807 if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
808 over8 = true;
809 let div = div as u32;
810 unsafe {
811 r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07)));
812 #[cfg(usart_v4)]
813 r.presc().write(|w| w.set_prescaler(_presc_val));
814 }
815 found = true;
816 break;
817 }
818 panic!("USART: baudrate too high");
819 }
820
821 if div < brr_max {
822 unsafe {
823 r.brr().write_value(regs::Brr(div as u32));
824 #[cfg(usart_v4)]
825 r.presc().write(|w| w.set_prescaler(_presc_val));
826 }
827 found = true;
828 break;
829 }
830 }
831
832 assert!(found, "USART: baudrate too low");
773 833
774 unsafe { 834 unsafe {
775 r.brr().write_value(regs::Brr(div));
776 r.cr2().write(|w| { 835 r.cr2().write(|w| {
777 w.set_stop(match config.stop_bits { 836 w.set_stop(match config.stop_bits {
778 StopBits::STOP0P5 => vals::Stop::STOP0P5, 837 StopBits::STOP0P5 => vals::Stop::STOP0P5,
@@ -801,6 +860,8 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32, enable
801 Parity::ParityEven => vals::Ps::EVEN, 860 Parity::ParityEven => vals::Ps::EVEN,
802 _ => vals::Ps::EVEN, 861 _ => vals::Ps::EVEN,
803 }); 862 });
863 #[cfg(not(usart_v1))]
864 w.set_over8(vals::Over8(over8 as _));
804 }); 865 });
805 } 866 }
806} 867}
@@ -986,43 +1047,45 @@ mod rx_ringbuffered;
986#[cfg(not(gpdma))] 1047#[cfg(not(gpdma))]
987pub use rx_ringbuffered::RingBufferedUartRx; 1048pub use rx_ringbuffered::RingBufferedUartRx;
988 1049
989#[cfg(usart_v1)] 1050use self::sealed::Kind;
1051
1052#[cfg(any(usart_v1, usart_v2))]
990fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { 1053fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
991 r.dr().ptr() as _ 1054 r.dr().ptr() as _
992} 1055}
993 1056
994#[cfg(usart_v1)] 1057#[cfg(any(usart_v1, usart_v2))]
995fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { 1058fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
996 r.dr().ptr() as _ 1059 r.dr().ptr() as _
997} 1060}
998 1061
999#[cfg(usart_v1)] 1062#[cfg(any(usart_v1, usart_v2))]
1000fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> { 1063fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> {
1001 r.sr() 1064 r.sr()
1002} 1065}
1003 1066
1004#[cfg(usart_v1)] 1067#[cfg(any(usart_v1, usart_v2))]
1005#[allow(unused)] 1068#[allow(unused)]
1006unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) { 1069unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
1007 // On v1 the flags are cleared implicitly by reads and writes to DR. 1070 // On v1 the flags are cleared implicitly by reads and writes to DR.
1008} 1071}
1009 1072
1010#[cfg(usart_v2)] 1073#[cfg(any(usart_v3, usart_v4))]
1011fn tdr(r: Regs) -> *mut u8 { 1074fn tdr(r: Regs) -> *mut u8 {
1012 r.tdr().ptr() as _ 1075 r.tdr().ptr() as _
1013} 1076}
1014 1077
1015#[cfg(usart_v2)] 1078#[cfg(any(usart_v3, usart_v4))]
1016fn rdr(r: Regs) -> *mut u8 { 1079fn rdr(r: Regs) -> *mut u8 {
1017 r.rdr().ptr() as _ 1080 r.rdr().ptr() as _
1018} 1081}
1019 1082
1020#[cfg(usart_v2)] 1083#[cfg(any(usart_v3, usart_v4))]
1021fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> { 1084fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> {
1022 r.isr() 1085 r.isr()
1023} 1086}
1024 1087
1025#[cfg(usart_v2)] 1088#[cfg(any(usart_v3, usart_v4))]
1026#[allow(unused)] 1089#[allow(unused)]
1027unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { 1090unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
1028 r.icr().write(|w| *w = regs::Icr(sr.0)); 1091 r.icr().write(|w| *w = regs::Icr(sr.0));
@@ -1033,6 +1096,13 @@ pub(crate) mod sealed {
1033 1096
1034 use super::*; 1097 use super::*;
1035 1098
1099 #[derive(Clone, Copy, PartialEq, Eq)]
1100 pub enum Kind {
1101 Uart,
1102 #[cfg(any(usart_v3, usart_v4))]
1103 Lpuart,
1104 }
1105
1036 pub struct State { 1106 pub struct State {
1037 pub rx_waker: AtomicWaker, 1107 pub rx_waker: AtomicWaker,
1038 pub tx_waker: AtomicWaker, 1108 pub tx_waker: AtomicWaker,
@@ -1048,7 +1118,7 @@ pub(crate) mod sealed {
1048 } 1118 }
1049 1119
1050 pub trait BasicInstance: crate::rcc::RccPeripheral { 1120 pub trait BasicInstance: crate::rcc::RccPeripheral {
1051 const MULTIPLIER: u32; 1121 const KIND: Kind;
1052 type Interrupt: crate::interrupt::Interrupt; 1122 type Interrupt: crate::interrupt::Interrupt;
1053 1123
1054 fn regs() -> Regs; 1124 fn regs() -> Regs;
@@ -1077,10 +1147,10 @@ pin_trait!(DePin, BasicInstance);
1077dma_trait!(TxDma, BasicInstance); 1147dma_trait!(TxDma, BasicInstance);
1078dma_trait!(RxDma, BasicInstance); 1148dma_trait!(RxDma, BasicInstance);
1079 1149
1080macro_rules! impl_lpuart { 1150macro_rules! impl_usart {
1081 ($inst:ident, $irq:ident, $mul:expr) => { 1151 ($inst:ident, $irq:ident, $kind:expr) => {
1082 impl sealed::BasicInstance for crate::peripherals::$inst { 1152 impl sealed::BasicInstance for crate::peripherals::$inst {
1083 const MULTIPLIER: u32 = $mul; 1153 const KIND: Kind = $kind;
1084 type Interrupt = crate::interrupt::$irq; 1154 type Interrupt = crate::interrupt::$irq;
1085 1155
1086 fn regs() -> Regs { 1156 fn regs() -> Regs {
@@ -1104,21 +1174,19 @@ macro_rules! impl_lpuart {
1104} 1174}
1105 1175
1106foreach_interrupt!( 1176foreach_interrupt!(
1107 ($inst:ident, lpuart, $block:ident, $signal_name:ident, $irq:ident) => { 1177 ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => {
1108 impl_lpuart!($inst, $irq, 256); 1178 impl_usart!($inst, $irq, Kind::Lpuart);
1109 }; 1179 };
1110 1180
1111 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { 1181 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
1112 impl_lpuart!($inst, $irq, 1); 1182 impl_usart!($inst, $irq, Kind::Uart);
1113 1183
1114 impl sealed::FullInstance for peripherals::$inst { 1184 impl sealed::FullInstance for peripherals::$inst {
1115
1116 fn regs_uart() -> crate::pac::usart::Usart { 1185 fn regs_uart() -> crate::pac::usart::Usart {
1117 crate::pac::$inst 1186 crate::pac::$inst
1118 } 1187 }
1119 } 1188 }
1120 1189
1121 impl FullInstance for peripherals::$inst { 1190 impl FullInstance for peripherals::$inst {}
1122 }
1123 }; 1191 };
1124); 1192);
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index 1b075b8fd..5fea7034b 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -4,15 +4,13 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::gpio::{AnyPin, Pin}; 6use embassy_rp::gpio::{AnyPin, Pin};
7use embassy_rp::pio::{ 7use embassy_rp::peripherals::PIO0;
8 Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, 8use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection};
9 Sm1, Sm2,
10};
11use embassy_rp::pio_instr_util; 9use embassy_rp::pio_instr_util;
12use embassy_rp::relocate::RelocatedProgram; 10use embassy_rp::relocate::RelocatedProgram;
13use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
14 12
15fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) { 13fn setup_pio_task_sm0(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 0>, pin: AnyPin) {
16 // Setup sm0 14 // Setup sm0
17 15
18 // Send data serially to pin 16 // Send data serially to pin
@@ -40,7 +38,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
40} 38}
41 39
42#[embassy_executor::task] 40#[embassy_executor::task]
43async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) { 41async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) {
44 sm.set_enable(true); 42 sm.set_enable(true);
45 43
46 let mut v = 0x0f0caffa; 44 let mut v = 0x0f0caffa;
@@ -51,7 +49,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
51 } 49 }
52} 50}
53 51
54fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) { 52fn setup_pio_task_sm1(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 1>) {
55 // Setupm sm1 53 // Setupm sm1
56 54
57 // Read 0b10101 repeatedly until ISR is full 55 // Read 0b10101 repeatedly until ISR is full
@@ -70,7 +68,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
70} 68}
71 69
72#[embassy_executor::task] 70#[embassy_executor::task]
73async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { 71async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) {
74 sm.set_enable(true); 72 sm.set_enable(true);
75 loop { 73 loop {
76 let rx = sm.wait_pull().await; 74 let rx = sm.wait_pull().await;
@@ -78,7 +76,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
78 } 76 }
79} 77}
80 78
81fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) { 79fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 2>) {
82 // Setup sm2 80 // Setup sm2
83 81
84 // Repeatedly trigger IRQ 3 82 // Repeatedly trigger IRQ 3
@@ -102,7 +100,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
102} 100}
103 101
104#[embassy_executor::task] 102#[embassy_executor::task]
105async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { 103async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, 2>) {
106 sm.set_enable(true); 104 sm.set_enable(true);
107 loop { 105 loop {
108 sm.wait_irq(3).await; 106 sm.wait_irq(3).await;
@@ -115,11 +113,17 @@ async fn main(spawner: Spawner) {
115 let p = embassy_rp::init(Default::default()); 113 let p = embassy_rp::init(Default::default());
116 let pio = p.PIO0; 114 let pio = p.PIO0;
117 115
118 let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); 116 let Pio {
119 117 mut common,
120 setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); 118 mut sm0,
121 setup_pio_task_sm1(&mut pio0, &mut sm1); 119 mut sm1,
122 setup_pio_task_sm2(&mut pio0, &mut sm2); 120 mut sm2,
121 ..
122 } = Pio::new(pio);
123
124 setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade());
125 setup_pio_task_sm1(&mut common, &mut sm1);
126 setup_pio_task_sm2(&mut common, &mut sm2);
123 spawner.spawn(pio_task_sm0(sm0)).unwrap(); 127 spawner.spawn(pio_task_sm0(sm0)).unwrap();
124 spawner.spawn(pio_task_sm1(sm1)).unwrap(); 128 spawner.spawn(pio_task_sm1(sm1)).unwrap();
125 spawner.spawn(pio_task_sm2(sm2)).unwrap(); 129 spawner.spawn(pio_task_sm2(sm2)).unwrap();
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 7d4919f75..0f1f6df12 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -4,7 +4,7 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; 7use embassy_rp::pio::{Pio, PioStateMachine, ShiftDirection};
8use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
9use embassy_rp::{pio_instr_util, Peripheral}; 9use embassy_rp::{pio_instr_util, Peripheral};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +19,11 @@ fn swap_nibbles(v: u32) -> u32 {
19async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
20 let p = embassy_rp::init(Default::default()); 20 let p = embassy_rp::init(Default::default());
21 let pio = p.PIO0; 21 let pio = p.PIO0;
22 let (mut pio0, mut sm, ..) = pio.split(); 22 let Pio {
23 mut common,
24 sm0: mut sm,
25 ..
26 } = Pio::new(pio);
23 27
24 let prg = pio_proc::pio_asm!( 28 let prg = pio_proc::pio_asm!(
25 ".origin 0", 29 ".origin 0",
@@ -34,7 +38,7 @@ async fn main(_spawner: Spawner) {
34 ); 38 );
35 39
36 let relocated = RelocatedProgram::new(&prg.program); 40 let relocated = RelocatedProgram::new(&prg.program);
37 pio0.write_instr(relocated.origin() as usize, relocated.code()); 41 common.write_instr(relocated.origin() as usize, relocated.code());
38 pio_instr_util::exec_jmp(&mut sm, relocated.origin()); 42 pio_instr_util::exec_jmp(&mut sm, relocated.origin());
39 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); 43 sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
40 let pio::Wrap { source, target } = relocated.wrap(); 44 let pio::Wrap { source, target } = relocated.wrap();
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
new file mode 100644
index 000000000..59b4c1f52
--- /dev/null
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -0,0 +1,243 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use core::fmt::Write;
6
7use embassy_executor::Spawner;
8use embassy_rp::dma::{AnyChannel, Channel};
9use embassy_rp::gpio::Pin;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection};
12use embassy_rp::pwm::{Config, Pwm};
13use embassy_rp::relocate::RelocatedProgram;
14use embassy_rp::{into_ref, Peripheral, PeripheralRef};
15use embassy_time::{Duration, Instant, Timer};
16use {defmt_rtt as _, panic_probe as _};
17
18#[embassy_executor::main]
19async fn main(_spawner: Spawner) {
20 // this test assumes a 2x16 HD44780 display attached as follow:
21 // rs = PIN0
22 // rw = PIN1
23 // e = PIN2
24 // db4 = PIN3
25 // db5 = PIN4
26 // db6 = PIN5
27 // db7 = PIN6
28 // additionally a pwm signal for a bias voltage charge pump is provided on pin 15,
29 // allowing direct connection of the display to the RP2040 without level shifters.
30 let p = embassy_rp::init(Default::default());
31
32 let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, {
33 let mut c = Config::default();
34 c.divider = 125.into();
35 c.top = 100;
36 c.compare_b = 50;
37 c
38 });
39
40 let mut hd = HD44780::new(
41 p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6,
42 )
43 .await;
44
45 loop {
46 struct Buf<const N: usize>([u8; N], usize);
47 impl<const N: usize> Write for Buf<N> {
48 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
49 for b in s.as_bytes() {
50 if self.1 >= N {
51 return Err(core::fmt::Error);
52 }
53 self.0[self.1] = *b;
54 self.1 += 1;
55 }
56 Ok(())
57 }
58 }
59 let mut buf = Buf([0; 16], 0);
60 write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap();
61 hd.add_line(&buf.0[0..buf.1]).await;
62 Timer::after(Duration::from_secs(1)).await;
63 }
64}
65
66pub struct HD44780<'l> {
67 dma: PeripheralRef<'l, AnyChannel>,
68 sm: PioStateMachineInstance<'l, PIO0, 0>,
69
70 buf: [u8; 40],
71}
72
73impl<'l> HD44780<'l> {
74 pub async fn new(
75 pio: impl Peripheral<P = PIO0> + 'l,
76 dma: impl Peripheral<P = impl Channel> + 'l,
77 rs: impl Pin,
78 rw: impl Pin,
79 e: impl Pin,
80 db4: impl Pin,
81 db5: impl Pin,
82 db6: impl Pin,
83 db7: impl Pin,
84 ) -> HD44780<'l> {
85 into_ref!(dma);
86
87 let db7pin = db7.pin();
88 let Pio {
89 mut common, mut sm0, ..
90 } = Pio::new(pio);
91
92 // takes command words (<wait:24> <command:4> <0:4>)
93 let prg = pio_proc::pio_asm!(
94 r#"
95 .side_set 1 opt
96
97 loop:
98 out x, 24
99 delay:
100 jmp x--, delay
101 out pins, 4 side 1
102 out null, 4 side 0
103 jmp !osre, loop
104 irq 0
105 "#,
106 );
107
108 let rs = common.make_pio_pin(rs);
109 let rw = common.make_pio_pin(rw);
110 let e = common.make_pio_pin(e);
111 let db4 = common.make_pio_pin(db4);
112 let db5 = common.make_pio_pin(db5);
113 let db6 = common.make_pio_pin(db6);
114 let db7 = common.make_pio_pin(db7);
115
116 sm0.set_set_pins(&[&rs, &rw]);
117 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11);
118 sm0.set_set_pins(&[&e]);
119 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1);
120 sm0.set_set_pins(&[&db4, &db5, &db6, &db7]);
121 embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111);
122
123 let relocated = RelocatedProgram::new(&prg.program);
124 common.write_instr(relocated.origin() as usize, relocated.code());
125 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
126 sm0.set_clkdiv(125 * 256);
127 let pio::Wrap { source, target } = relocated.wrap();
128 sm0.set_wrap(source, target);
129 sm0.set_side_enable(true);
130 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
131 sm0.set_sideset_base_pin(&e);
132 sm0.set_sideset_count(2);
133 sm0.set_out_shift_dir(ShiftDirection::Left);
134 sm0.set_fifo_join(FifoJoin::TxOnly);
135 sm0.set_autopull(true);
136 sm0.set_pull_threshold(32);
137
138 sm0.set_enable(true);
139 // init to 8 bit thrice
140 sm0.push_tx((50000 << 8) | 0x30);
141 sm0.push_tx((5000 << 8) | 0x30);
142 sm0.push_tx((200 << 8) | 0x30);
143 // init 4 bit
144 sm0.push_tx((200 << 8) | 0x20);
145 // set font and lines
146 sm0.push_tx((50 << 8) | 0x20);
147 sm0.push_tx(0b1100_0000);
148
149 sm0.wait_irq(0).await;
150 sm0.set_enable(false);
151
152 // takes command sequences (<rs:1> <count:7>, data...)
153 // many side sets are only there to free up a delay bit!
154 let prg = pio_proc::pio_asm!(
155 r#"
156 .origin 7
157 .side_set 1
158
159 .wrap_target
160 pull side 0
161 out x 1 side 0 ; !rs
162 out y 7 side 0 ; #data - 1
163
164 ; rs/rw to e: >= 60ns
165 ; e high time: >= 500ns
166 ; e low time: >= 500ns
167 ; read data valid after e falling: ~5ns
168 ; write data hold after e falling: ~10ns
169
170 loop:
171 pull side 0
172 jmp !x data side 0
173 command:
174 set pins 0b00 side 0
175 jmp shift side 0
176 data:
177 set pins 0b01 side 0
178 shift:
179 out pins 4 side 1 [9]
180 nop side 0 [9]
181 out pins 4 side 1 [9]
182 mov osr null side 0 [7]
183 out pindirs 4 side 0
184 set pins 0b10 side 0
185 busy:
186 nop side 1 [9]
187 jmp pin more side 0 [9]
188 mov osr ~osr side 1 [9]
189 nop side 0 [4]
190 out pindirs 4 side 0
191 jmp y-- loop side 0
192 .wrap
193 more:
194 nop side 1 [9]
195 jmp busy side 0 [9]
196 "#
197 );
198
199 let relocated = RelocatedProgram::new(&prg.program);
200 common.write_instr(relocated.origin() as usize, relocated.code());
201 embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
202 let pio::Wrap { source, target } = relocated.wrap();
203 sm0.set_clkdiv(8 * 256); // ~64ns/insn
204 sm0.set_side_enable(false);
205 sm0.set_jmp_pin(db7pin);
206 sm0.set_wrap(source, target);
207 sm0.set_set_pins(&[&rs, &rw]);
208 sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
209 sm0.set_sideset_base_pin(&e);
210 sm0.set_sideset_count(1);
211 sm0.set_out_shift_dir(ShiftDirection::Left);
212 sm0.set_fifo_join(FifoJoin::TxOnly);
213
214 sm0.set_enable(true);
215
216 // display on and cursor on and blinking, reset display
217 sm0.dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await;
218
219 Self {
220 dma: dma.map_into(),
221 sm: sm0,
222 buf: [0x20; 40],
223 }
224 }
225
226 pub async fn add_line(&mut self, s: &[u8]) {
227 // move cursor to 0:0, prepare 16 characters
228 self.buf[..3].copy_from_slice(&[0x80, 0x80, 15]);
229 // move line 2 up
230 self.buf.copy_within(22..38, 3);
231 // move cursor to 1:0, prepare 16 characters
232 self.buf[19..22].copy_from_slice(&[0x80, 0xc0, 15]);
233 // file line 2 with spaces
234 self.buf[22..38].fill(0x20);
235 // copy input line
236 let len = s.len().min(16);
237 self.buf[22..22 + len].copy_from_slice(&s[0..len]);
238 // set cursor to 1:15
239 self.buf[38..].copy_from_slice(&[0x80, 0xcf]);
240
241 self.sm.dma_push(self.dma.reborrow(), &self.buf).await;
242 }
243}
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs
index 041e8ae11..0975559d7 100644
--- a/examples/rp/src/bin/ws2812-pio.rs
+++ b/examples/rp/src/bin/ws2812-pio.rs
@@ -6,20 +6,19 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::gpio::{self, Pin}; 7use embassy_rp::gpio::{self, Pin};
8use embassy_rp::pio::{ 8use embassy_rp::pio::{
9 FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, 9 FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection,
10 ShiftDirection, SmInstance,
11}; 10};
12use embassy_rp::pio_instr_util; 11use embassy_rp::pio_instr_util;
13use embassy_rp::relocate::RelocatedProgram; 12use embassy_rp::relocate::RelocatedProgram;
14use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
15use smart_leds::RGB8; 14use smart_leds::RGB8;
16use {defmt_rtt as _, panic_probe as _}; 15use {defmt_rtt as _, panic_probe as _};
17pub struct Ws2812<P: PioInstance, S: SmInstance> { 16pub struct Ws2812<'d, P: PioInstance, const S: usize> {
18 sm: PioStateMachineInstance<P, S>, 17 sm: PioStateMachineInstance<'d, P, S>,
19} 18}
20 19
21impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { 20impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> {
22 pub fn new(mut pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self { 21 pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self {
23 // Setup sm0 22 // Setup sm0
24 23
25 // prepare the PIO program 24 // prepare the PIO program
@@ -116,7 +115,7 @@ async fn main(_spawner: Spawner) {
116 info!("Start"); 115 info!("Start");
117 let p = embassy_rp::init(Default::default()); 116 let p = embassy_rp::init(Default::default());
118 117
119 let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); 118 let Pio { common, sm0, .. } = Pio::new(p.PIO0);
120 119
121 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit 120 // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
122 // feather boards for the 2040 both have one built in. 121 // feather boards for the 2040 both have one built in.
@@ -125,7 +124,7 @@ async fn main(_spawner: Spawner) {
125 124
126 // For the thing plus, use pin 8 125 // For the thing plus, use pin 8
127 // For the feather, use pin 16 126 // For the feather, use pin 16
128 let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); 127 let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade());
129 128
130 // Loop forever making RGB values and pushing them out to the WS2812. 129 // Loop forever making RGB values and pushing them out to the WS2812.
131 loop { 130 loop {
diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs
new file mode 100644
index 000000000..6c13ccaae
--- /dev/null
+++ b/tests/rp/src/bin/gpio_multicore.rs
@@ -0,0 +1,63 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{info, unwrap};
6use embassy_executor::Executor;
7use embassy_executor::_export::StaticCell;
8use embassy_rp::gpio::{Input, Level, Output, Pull};
9use embassy_rp::multicore::{spawn_core1, Stack};
10use embassy_rp::peripherals::{PIN_0, PIN_1};
11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
12use embassy_sync::channel::Channel;
13use {defmt_rtt as _, panic_probe as _};
14
15static mut CORE1_STACK: Stack<1024> = Stack::new();
16static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
17static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
18static CHANNEL0: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
19static CHANNEL1: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
20
21#[cortex_m_rt::entry]
22fn main() -> ! {
23 let p = embassy_rp::init(Default::default());
24 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || {
25 let executor1 = EXECUTOR1.init(Executor::new());
26 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1))));
27 });
28 let executor0 = EXECUTOR0.init(Executor::new());
29 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0))));
30}
31
32#[embassy_executor::task]
33async fn core0_task(p: PIN_0) {
34 info!("CORE0 is running");
35
36 let mut pin = Output::new(p, Level::Low);
37
38 CHANNEL0.send(()).await;
39 CHANNEL1.recv().await;
40
41 pin.set_high();
42
43 CHANNEL1.recv().await;
44
45 info!("Test OK");
46 cortex_m::asm::bkpt();
47}
48
49#[embassy_executor::task]
50async fn core1_task(p: PIN_1) {
51 info!("CORE1 is running");
52
53 CHANNEL0.recv().await;
54
55 let mut pin = Input::new(p, Pull::Down);
56 let wait = pin.wait_for_rising_edge();
57
58 CHANNEL1.send(()).await;
59
60 wait.await;
61
62 CHANNEL1.send(()).await;
63}
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
index 92aa205c9..52f42e582 100644
--- a/tests/rp/src/bin/uart_dma.rs
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -53,10 +53,6 @@ async fn main(_spawner: Spawner) {
53 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); 53 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
54 let mut irq = interrupt::take!(UART0_IRQ); 54 let mut irq = interrupt::take!(UART0_IRQ);
55 55
56 // TODO
57 // nuclear error reporting. just abort the entire transfer and invalidate the
58 // dma buffer, buffered buffer, fifo etc.
59
60 // We can't send too many bytes, they have to fit in the FIFO. 56 // We can't send too many bytes, they have to fit in the FIFO.
61 // This is because we aren't sending+receiving at the same time. 57 // This is because we aren't sending+receiving at the same time.
62 { 58 {
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 5cd949661..83bf1e9c9 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -3,6 +3,7 @@ edition = "2021"
3name = "embassy-stm32-tests" 3name = "embassy-stm32-tests"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6autobins = false
6 7
7[features] 8[features]
8stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill 9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill
diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs
index 3e67a7392..7ae311778 100644
--- a/tests/stm32/build.rs
+++ b/tests/stm32/build.rs
@@ -6,15 +6,16 @@ fn main() -> Result<(), Box<dyn Error>> {
6 let out = PathBuf::from(env::var("OUT_DIR").unwrap()); 6 let out = PathBuf::from(env::var("OUT_DIR").unwrap());
7 fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap(); 7 fs::write(out.join("link_ram.x"), include_bytes!("link_ram.x")).unwrap();
8 println!("cargo:rustc-link-search={}", out.display()); 8 println!("cargo:rustc-link-search={}", out.display());
9 println!("cargo:rerun-if-changed=link_ram.x");
10
11 println!("cargo:rustc-link-arg-bins=--nmagic"); 9 println!("cargo:rustc-link-arg-bins=--nmagic");
12 10
13 // too little RAM to run from RAM. 11 // too little RAM to run from RAM.
14 #[cfg(any(feature = "stm32c031c6"))] 12 if cfg!(any(feature = "stm32f103c8", feature = "stm32c031c6")) {
15 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 13 println!("cargo:rustc-link-arg-bins=-Tlink.x");
16 #[cfg(not(any(feature = "stm32c031c6")))] 14 println!("cargo:rerun-if-changed=link.x");
17 println!("cargo:rustc-link-arg-bins=-Tlink_ram.x"); 15 } else {
16 println!("cargo:rustc-link-arg-bins=-Tlink_ram.x");
17 println!("cargo:rerun-if-changed=link_ram.x");
18 }
18 19
19 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 20 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
20 21
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs
index 0f5e563b1..a87ac3237 100644
--- a/tests/stm32/src/bin/spi.rs
+++ b/tests/stm32/src/bin/spi.rs
@@ -35,7 +35,6 @@ async fn main(_spawner: Spawner) {
35 #[cfg(feature = "stm32c031c6")] 35 #[cfg(feature = "stm32c031c6")]
36 let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6); 36 let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6);
37 37
38 info!("asdfa;");
39 let mut spi = Spi::new( 38 let mut spi = Spi::new(
40 spi, 39 spi,
41 sck, // Arduino D13 40 sck, // Arduino D13
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index cca8c42ee..bda2ce9c2 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -9,6 +9,7 @@ use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt; 10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
12use embassy_time::{Duration, Instant};
12use example_common::*; 13use example_common::*;
13 14
14#[embassy_executor::main] 15#[embassy_executor::main]
@@ -19,36 +20,76 @@ async fn main(_spawner: Spawner) {
19 // Arduino pins D0 and D1 20 // Arduino pins D0 and D1
20 // They're connected together with a 1K resistor. 21 // They're connected together with a 1K resistor.
21 #[cfg(feature = "stm32f103c8")] 22 #[cfg(feature = "stm32f103c8")]
22 let (tx, rx, usart, irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1)); 23 let (mut tx, mut rx, mut usart, mut irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1));
23 #[cfg(feature = "stm32g491re")] 24 #[cfg(feature = "stm32g491re")]
24 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1)); 25 let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
25 #[cfg(feature = "stm32g071rb")] 26 #[cfg(feature = "stm32g071rb")]
26 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1)); 27 let (mut tx, mut rx, mut usart, mut irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
27 #[cfg(feature = "stm32f429zi")] 28 #[cfg(feature = "stm32f429zi")]
28 let (tx, rx, usart, irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6)); 29 let (mut tx, mut rx, mut usart, mut irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6));
29 #[cfg(feature = "stm32wb55rg")] 30 #[cfg(feature = "stm32wb55rg")]
30 let (tx, rx, usart, irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1)); 31 let (mut tx, mut rx, mut usart, mut irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1));
31 #[cfg(feature = "stm32h755zi")] 32 #[cfg(feature = "stm32h755zi")]
32 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1)); 33 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
33 #[cfg(feature = "stm32u585ai")] 34 #[cfg(feature = "stm32u585ai")]
34 let (tx, rx, usart, irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3)); 35 let (mut tx, mut rx, mut usart, mut irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3));
35 #[cfg(feature = "stm32h563zi")] 36 #[cfg(feature = "stm32h563zi")]
36 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.LPUART1, interrupt::take!(LPUART1)); 37 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.LPUART1, interrupt::take!(LPUART1));
37 #[cfg(feature = "stm32c031c6")] 38 #[cfg(feature = "stm32c031c6")]
38 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1)); 39 let (mut tx, mut rx, mut usart, mut irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
39 40
40 let config = Config::default(); 41 {
41 let mut usart = Uart::new(usart, rx, tx, irq, NoDma, NoDma, config); 42 let config = Config::default();
43 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
42 44
43 // We can't send too many bytes, they have to fit in the FIFO. 45 // We can't send too many bytes, they have to fit in the FIFO.
44 // This is because we aren't sending+receiving at the same time. 46 // This is because we aren't sending+receiving at the same time.
45 47
46 let data = [0xC0, 0xDE]; 48 let data = [0xC0, 0xDE];
47 usart.blocking_write(&data).unwrap(); 49 usart.blocking_write(&data).unwrap();
48 50
49 let mut buf = [0; 2]; 51 let mut buf = [0; 2];
50 usart.blocking_read(&mut buf).unwrap(); 52 usart.blocking_read(&mut buf).unwrap();
51 assert_eq!(buf, data); 53 assert_eq!(buf, data);
54 }
55
56 // Test that baudrate divider is calculated correctly.
57 // Do it by comparing the time it takes to send a known number of bytes.
58 for baudrate in [
59 300,
60 9600,
61 115200,
62 250_000,
63 337_934,
64 #[cfg(not(feature = "stm32f103c8"))]
65 1_000_000,
66 #[cfg(not(feature = "stm32f103c8"))]
67 2_000_000,
68 ] {
69 info!("testing baudrate {}", baudrate);
70
71 let mut config = Config::default();
72 config.baudrate = baudrate;
73 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
74
75 let n = (baudrate as usize / 100).max(64);
76
77 let start = Instant::now();
78 for _ in 0..n {
79 usart.blocking_write(&[0x00]).unwrap();
80 }
81 let dur = Instant::now() - start;
82 let want_dur = Duration::from_micros(n as u64 * 10 * 1_000_000 / (baudrate as u64));
83 let fuzz = want_dur / 5;
84 if dur < want_dur - fuzz || dur > want_dur + fuzz {
85 defmt::panic!(
86 "bad duration for baudrate {}: got {:?} want {:?}",
87 baudrate,
88 dur,
89 want_dur
90 );
91 }
92 }
52 93
53 info!("Test OK"); 94 info!("Test OK");
54 cortex_m::asm::bkpt(); 95 cortex_m::asm::bkpt();
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index de6cd41d1..62444f0a8 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -94,6 +94,9 @@ async fn main(_spawner: Spawner) {
94 let rx_fut = async { 94 let rx_fut = async {
95 rx.read(&mut rx_buf).await.unwrap(); 95 rx.read(&mut rx_buf).await.unwrap();
96 }; 96 };
97
98 // note: rx needs to be polled first, to workaround this bug:
99 // https://github.com/embassy-rs/embassy/issues/1426
97 join(rx_fut, tx_fut).await; 100 join(rx_fut, tx_fut).await;
98 101
99 assert_eq!(tx_buf, rx_buf); 102 assert_eq!(tx_buf, rx_buf);
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
index 2c4a8fdf4..9d75dbe55 100644
--- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs
+++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs
@@ -145,13 +145,16 @@ async fn main(spawner: Spawner) {
145 145
146#[embassy_executor::task] 146#[embassy_executor::task]
147async fn transmit_task(mut tx: UartTx<'static, board::Uart, board::TxDma>) { 147async fn transmit_task(mut tx: UartTx<'static, board::Uart, board::TxDma>) {
148 // workaround https://github.com/embassy-rs/embassy/issues/1426
149 Timer::after(Duration::from_millis(100) as _).await;
150
148 let mut rng = ChaCha8Rng::seed_from_u64(1337); 151 let mut rng = ChaCha8Rng::seed_from_u64(1337);
149 152
150 info!("Starting random transmissions into void..."); 153 info!("Starting random transmissions into void...");
151 154
152 let mut i: u8 = 0; 155 let mut i: u8 = 0;
153 loop { 156 loop {
154 let mut buf = [0; 32]; 157 let mut buf = [0; 256];
155 let len = 1 + (rng.next_u32() as usize % buf.len()); 158 let len = 1 + (rng.next_u32() as usize % buf.len());
156 for b in &mut buf[..len] { 159 for b in &mut buf[..len] {
157 *b = i; 160 *b = i;
@@ -172,7 +175,7 @@ async fn receive_task(mut rx: RingBufferedUartRx<'static, board::Uart, board::Rx
172 let mut i = 0; 175 let mut i = 0;
173 let mut expected = 0; 176 let mut expected = 0;
174 loop { 177 loop {
175 let mut buf = [0; 100]; 178 let mut buf = [0; 256];
176 let max_len = 1 + (rng.next_u32() as usize % buf.len()); 179 let max_len = 1 + (rng.next_u32() as usize % buf.len());
177 let received = match rx.read(&mut buf[..max_len]).await { 180 let received = match rx.read(&mut buf[..max_len]).await {
178 Ok(r) => r, 181 Ok(r) => r,
diff --git a/tests/stm32/src/example_common.rs b/tests/stm32/src/example_common.rs
index a4f8668c7..3d150da60 100644
--- a/tests/stm32/src/example_common.rs
+++ b/tests/stm32/src/example_common.rs
@@ -16,5 +16,10 @@ pub fn config() -> Config {
16 config.rcc.pll1.q_ck = Some(Hertz(100_000_000)); 16 config.rcc.pll1.q_ck = Some(Hertz(100_000_000));
17 } 17 }
18 18
19 #[cfg(feature = "stm32u585ai")]
20 {
21 config.rcc.mux = embassy_stm32::rcc::ClockSrc::MSI(embassy_stm32::rcc::MSIRange::Range48mhz);
22 }
23
19 config 24 config
20} 25}