aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-08-26 12:50:12 +0200
committerMathias <[email protected]>2022-08-26 12:55:15 +0200
commitbd27b9080fd9019e69e84fd30894a71db9fd61b5 (patch)
tree9627c002b0b38278b296f315be73d8951d8fa0d1
parentb88ef032141e87411dabb5d90ef488f5d6af2285 (diff)
Add HIL tests of DMA & UART, and correctly set DREQ for uart DMA
-rw-r--r--embassy-rp/src/dma.rs31
-rw-r--r--embassy-rp/src/uart.rs71
-rw-r--r--tests/rp/src/bin/dma_copy_async.rs41
-rw-r--r--tests/rp/src/bin/uart.rs32
-rw-r--r--tests/rp/src/bin/uart_dma.rs32
5 files changed, 184 insertions, 23 deletions
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 694823742..75d7492e0 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -41,18 +41,38 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
41 ch: impl Peripheral<P = C> + 'a, 41 ch: impl Peripheral<P = C> + 'a,
42 from: *const W, 42 from: *const W,
43 to: &mut [W], 43 to: &mut [W],
44 dreq: u8,
44) -> Transfer<'a, C> { 45) -> Transfer<'a, C> {
45 let (ptr, len) = crate::dma::slice_ptr_parts_mut(to); 46 let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(to);
46 copy_inner(ch, from as *const u32, ptr as *mut u32, len, W::size(), false, true) 47 copy_inner(
48 ch,
49 from as *const u32,
50 to_ptr as *mut u32,
51 len,
52 W::size(),
53 false,
54 true,
55 dreq,
56 )
47} 57}
48 58
49pub unsafe fn write<'a, C: Channel, W: Word>( 59pub unsafe fn write<'a, C: Channel, W: Word>(
50 ch: impl Peripheral<P = C> + 'a, 60 ch: impl Peripheral<P = C> + 'a,
51 from: &[W], 61 from: &[W],
52 to: *mut W, 62 to: *mut W,
63 dreq: u8,
53) -> Transfer<'a, C> { 64) -> Transfer<'a, C> {
54 let (from_ptr, len) = crate::dma::slice_ptr_parts(from); 65 let (from_ptr, len) = crate::dma::slice_ptr_parts(from);
55 copy_inner(ch, from_ptr as *const u32, to as *mut u32, len, W::size(), true, false) 66 copy_inner(
67 ch,
68 from_ptr as *const u32,
69 to as *mut u32,
70 len,
71 W::size(),
72 true,
73 false,
74 dreq,
75 )
56} 76}
57 77
58pub unsafe fn copy<'a, C: Channel, W: Word>( 78pub unsafe fn copy<'a, C: Channel, W: Word>(
@@ -71,6 +91,7 @@ pub unsafe fn copy<'a, C: Channel, W: Word>(
71 W::size(), 91 W::size(),
72 true, 92 true,
73 true, 93 true,
94 vals::TreqSel::PERMANENT.0,
74 ) 95 )
75} 96}
76 97
@@ -82,6 +103,7 @@ fn copy_inner<'a, C: Channel>(
82 data_size: DataSize, 103 data_size: DataSize,
83 incr_read: bool, 104 incr_read: bool,
84 incr_write: bool, 105 incr_write: bool,
106 dreq: u8,
85) -> Transfer<'a, C> { 107) -> Transfer<'a, C> {
86 into_ref!(ch); 108 into_ref!(ch);
87 109
@@ -95,6 +117,9 @@ fn copy_inner<'a, C: Channel>(
95 compiler_fence(Ordering::SeqCst); 117 compiler_fence(Ordering::SeqCst);
96 118
97 p.ctrl_trig().write(|w| { 119 p.ctrl_trig().write(|w| {
120 // TODO: Add all DREQ options to pac vals::TreqSel, and use
121 // `set_treq:sel`
122 w.0 = ((dreq as u32) & 0x3f) << 15usize;
98 w.set_data_size(data_size); 123 w.set_data_size(data_size);
99 w.set_incr_read(incr_read); 124 w.set_incr_read(incr_read);
100 w.set_incr_write(incr_write); 125 w.set_incr_write(incr_write);
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs
index 9d94dcf21..4a3c7a0ce 100644
--- a/embassy-rp/src/uart.rs
+++ b/embassy-rp/src/uart.rs
@@ -113,7 +113,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
113 113
114 pub fn blocking_flush(&mut self) -> Result<(), Error> { 114 pub fn blocking_flush(&mut self) -> Result<(), Error> {
115 let r = T::regs(); 115 let r = T::regs();
116 unsafe { while r.uartfr().read().txff() {} } 116 unsafe { while !r.uartfr().read().txfe() {} }
117 Ok(()) 117 Ok(())
118 } 118 }
119} 119}
@@ -127,7 +127,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
127 }); 127 });
128 // If we don't assign future to a variable, the data register pointer 128 // If we don't assign future to a variable, the data register pointer
129 // is held across an await and makes the future non-Send. 129 // is held across an await and makes the future non-Send.
130 crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _) 130 crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ)
131 }; 131 };
132 transfer.await; 132 transfer.await;
133 Ok(()) 133 Ok(())
@@ -147,6 +147,10 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
147 unsafe { 147 unsafe {
148 for b in buffer { 148 for b in buffer {
149 *b = loop { 149 *b = loop {
150 if r.uartfr().read().rxfe() {
151 continue;
152 }
153
150 let dr = r.uartdr().read(); 154 let dr = r.uartdr().read();
151 155
152 if dr.oe() { 156 if dr.oe() {
@@ -157,7 +161,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
157 return Err(Error::Parity); 161 return Err(Error::Parity);
158 } else if dr.fe() { 162 } else if dr.fe() {
159 return Err(Error::Framing); 163 return Err(Error::Framing);
160 } else if dr.fe() { 164 } else {
161 break dr.data(); 165 break dr.data();
162 } 166 }
163 }; 167 };
@@ -176,7 +180,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
176 }); 180 });
177 // If we don't assign future to a variable, the data register pointer 181 // If we don't assign future to a variable, the data register pointer
178 // is held across an await and makes the future non-Send. 182 // is held across an await and makes the future non-Send.
179 crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer) 183 crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ)
180 }; 184 };
181 transfer.await; 185 transfer.await;
182 Ok(()) 186 Ok(())
@@ -282,6 +286,30 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
282 unsafe { 286 unsafe {
283 let r = T::regs(); 287 let r = T::regs();
284 288
289 tx.io().ctrl().write(|w| w.set_funcsel(2));
290 rx.io().ctrl().write(|w| w.set_funcsel(2));
291
292 tx.pad_ctrl().write(|w| {
293 w.set_ie(true);
294 });
295
296 rx.pad_ctrl().write(|w| {
297 w.set_ie(true);
298 });
299
300 if let Some(pin) = &cts {
301 pin.io().ctrl().write(|w| w.set_funcsel(2));
302 pin.pad_ctrl().write(|w| {
303 w.set_ie(true);
304 });
305 }
306 if let Some(pin) = &rts {
307 pin.io().ctrl().write(|w| w.set_funcsel(2));
308 pin.pad_ctrl().write(|w| {
309 w.set_ie(true);
310 });
311 }
312
285 let clk_base = crate::clocks::clk_peri_freq(); 313 let clk_base = crate::clocks::clk_peri_freq();
286 314
287 let baud_rate_div = (8 * clk_base) / config.baudrate; 315 let baud_rate_div = (8 * clk_base) / config.baudrate;
@@ -302,10 +330,14 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
302 330
303 let (pen, eps) = match config.parity { 331 let (pen, eps) = match config.parity {
304 Parity::ParityNone => (false, false), 332 Parity::ParityNone => (false, false),
305 Parity::ParityEven => (true, true),
306 Parity::ParityOdd => (true, false), 333 Parity::ParityOdd => (true, false),
334 Parity::ParityEven => (true, true),
307 }; 335 };
308 336
337 // PL011 needs a (dummy) line control register write to latch in the
338 // divisors. We don't want to actually change LCR contents here.
339 r.uartlcr_h().modify(|_| {});
340
309 r.uartlcr_h().write(|w| { 341 r.uartlcr_h().write(|w| {
310 w.set_wlen(config.data_bits.bits()); 342 w.set_wlen(config.data_bits.bits());
311 w.set_stp2(config.stop_bits == StopBits::STOP2); 343 w.set_stp2(config.stop_bits == StopBits::STOP2);
@@ -321,15 +353,6 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
321 w.set_ctsen(cts.is_some()); 353 w.set_ctsen(cts.is_some());
322 w.set_rtsen(rts.is_some()); 354 w.set_rtsen(rts.is_some());
323 }); 355 });
324
325 tx.io().ctrl().write(|w| w.set_funcsel(2));
326 rx.io().ctrl().write(|w| w.set_funcsel(2));
327 if let Some(pin) = &cts {
328 pin.io().ctrl().write(|w| w.set_funcsel(2));
329 }
330 if let Some(pin) = &rts {
331 pin.io().ctrl().write(|w| w.set_funcsel(2));
332 }
333 } 356 }
334 357
335 Self { 358 Self {
@@ -377,6 +400,10 @@ mod eh02 {
377 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 400 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
378 let r = T::regs(); 401 let r = T::regs();
379 unsafe { 402 unsafe {
403 if r.uartfr().read().rxfe() {
404 return Err(nb::Error::WouldBlock);
405 }
406
380 let dr = r.uartdr().read(); 407 let dr = r.uartdr().read();
381 408
382 if dr.oe() { 409 if dr.oe() {
@@ -387,10 +414,8 @@ mod eh02 {
387 Err(nb::Error::Other(Error::Parity)) 414 Err(nb::Error::Other(Error::Parity))
388 } else if dr.fe() { 415 } else if dr.fe() {
389 Err(nb::Error::Other(Error::Framing)) 416 Err(nb::Error::Other(Error::Framing))
390 } else if dr.fe() {
391 Ok(dr.data())
392 } else { 417 } else {
393 Err(nb::Error::WouldBlock) 418 Ok(dr.data())
394 } 419 }
395 } 420 }
396 } 421 }
@@ -512,6 +537,9 @@ mod sealed {
512 pub trait Mode {} 537 pub trait Mode {}
513 538
514 pub trait Instance { 539 pub trait Instance {
540 const TX_DREQ: u8;
541 const RX_DREQ: u8;
542
515 fn regs() -> pac::uart::Uart; 543 fn regs() -> pac::uart::Uart;
516 } 544 }
517 pub trait TxPin<T: Instance> {} 545 pub trait TxPin<T: Instance> {}
@@ -538,8 +566,11 @@ impl_mode!(Async);
538pub trait Instance: sealed::Instance {} 566pub trait Instance: sealed::Instance {}
539 567
540macro_rules! impl_instance { 568macro_rules! impl_instance {
541 ($inst:ident, $irq:ident) => { 569 ($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {
542 impl sealed::Instance for peripherals::$inst { 570 impl sealed::Instance for peripherals::$inst {
571 const TX_DREQ: u8 = $tx_dreq;
572 const RX_DREQ: u8 = $rx_dreq;
573
543 fn regs() -> pac::uart::Uart { 574 fn regs() -> pac::uart::Uart {
544 pac::$inst 575 pac::$inst
545 } 576 }
@@ -548,8 +579,8 @@ macro_rules! impl_instance {
548 }; 579 };
549} 580}
550 581
551impl_instance!(UART0, UART0); 582impl_instance!(UART0, UART0, 20, 21);
552impl_instance!(UART1, UART1); 583impl_instance!(UART1, UART1, 22, 23);
553 584
554pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 585pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
555pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 586pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
diff --git a/tests/rp/src/bin/dma_copy_async.rs b/tests/rp/src/bin/dma_copy_async.rs
new file mode 100644
index 000000000..c53f644bd
--- /dev/null
+++ b/tests/rp/src/bin/dma_copy_async.rs
@@ -0,0 +1,41 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::dma::copy;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 info!("Hello World!");
14
15 // Check `u8` copy
16 {
17 let data: [u8; 2] = [0xC0, 0xDE];
18 let mut buf = [0; 2];
19 unsafe { copy(p.DMA_CH0, &data, &mut buf).await };
20 assert_eq!(buf, data);
21 }
22
23 // Check `u16` copy
24 {
25 let data: [u16; 2] = [0xC0BE, 0xDEAD];
26 let mut buf = [0; 2];
27 unsafe { copy(p.DMA_CH1, &data, &mut buf).await };
28 assert_eq!(buf, data);
29 }
30
31 // Check `u32` copy
32 {
33 let data: [u32; 2] = [0xC0BEDEAD, 0xDEADAAFF];
34 let mut buf = [0; 2];
35 unsafe { copy(p.DMA_CH2, &data, &mut buf).await };
36 assert_eq!(buf, data);
37 }
38
39 info!("Test OK");
40 cortex_m::asm::bkpt();
41}
diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs
new file mode 100644
index 000000000..92f61464e
--- /dev/null
+++ b/tests/rp/src/bin/uart.rs
@@ -0,0 +1,32 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::uart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 info!("Hello World!");
14
15 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0);
16
17 let config = Config::default();
18 let mut uart = Uart::new_blocking(uart, tx, rx, config);
19
20 // We can't send too many bytes, they have to fit in the FIFO.
21 // This is because we aren't sending+receiving at the same time.
22
23 let data = [0xC0, 0xDE];
24 uart.blocking_write(&data).unwrap();
25
26 let mut buf = [0; 2];
27 uart.blocking_read(&mut buf).unwrap();
28 assert_eq!(buf, data);
29
30 info!("Test OK");
31 cortex_m::asm::bkpt();
32}
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
new file mode 100644
index 000000000..963c22707
--- /dev/null
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -0,0 +1,32 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::uart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 info!("Hello World!");
14
15 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0);
16
17 let config = Config::default();
18 let mut uart = Uart::new(uart, tx, rx, p.DMA_CH0, p.DMA_CH1, config);
19
20 // We can't send too many bytes, they have to fit in the FIFO.
21 // This is because we aren't sending+receiving at the same time.
22
23 let data = [0xC0, 0xDE];
24 uart.write(&data).await.unwrap();
25
26 let mut buf = [0; 2];
27 uart.read(&mut buf).await.unwrap();
28 assert_eq!(buf, data);
29
30 info!("Test OK");
31 cortex_m::asm::bkpt();
32}