diff options
| author | Michael van Niekerk <[email protected]> | 2023-07-28 12:56:31 +0200 |
|---|---|---|
| committer | Michael van Niekerk <[email protected]> | 2023-07-28 12:56:31 +0200 |
| commit | 146c744223056561c6be61dda791993d939d0ae0 (patch) | |
| tree | b33254aa39bace0edd09e8ac0ec3641d46bc3022 /examples | |
| parent | 6b6acc256d163be62e6970d03632eca11a287ec6 (diff) | |
Fixes as per PR
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/src/bin/pio_uart.rs | 114 |
1 files changed, 48 insertions, 66 deletions
diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs index eeb213e1b..c978f8f06 100644 --- a/examples/rp/src/bin/pio_uart.rs +++ b/examples/rp/src/bin/pio_uart.rs | |||
| @@ -19,7 +19,7 @@ use embassy_rp::peripherals::{PIO0, USB}; | |||
| 19 | use embassy_rp::pio::InterruptHandler as PioInterruptHandler; | 19 | use embassy_rp::pio::InterruptHandler as PioInterruptHandler; |
| 20 | use embassy_rp::usb::{Driver, Instance, InterruptHandler}; | 20 | use embassy_rp::usb::{Driver, Instance, InterruptHandler}; |
| 21 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 21 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 22 | use embassy_sync::channel::Channel; | 22 | use embassy_sync::pipe::Pipe; |
| 23 | use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; | 23 | use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; |
| 24 | use embassy_usb::driver::EndpointError; | 24 | use embassy_usb::driver::EndpointError; |
| 25 | use embassy_usb::{Builder, Config}; | 25 | use embassy_usb::{Builder, Config}; |
| @@ -30,11 +30,8 @@ use crate::uart::PioUart; | |||
| 30 | use crate::uart_rx::PioUartRx; | 30 | use crate::uart_rx::PioUartRx; |
| 31 | use crate::uart_tx::PioUartTx; | 31 | use crate::uart_tx::PioUartTx; |
| 32 | 32 | ||
| 33 | bind_interrupts!(struct UsbIrqs { | 33 | bind_interrupts!(struct Irqs { |
| 34 | USBCTRL_IRQ => InterruptHandler<USB>; | 34 | USBCTRL_IRQ => InterruptHandler<USB>; |
| 35 | }); | ||
| 36 | |||
| 37 | bind_interrupts!(struct PioIrqs { | ||
| 38 | PIO0_IRQ_0 => PioInterruptHandler<PIO0>; | 35 | PIO0_IRQ_0 => PioInterruptHandler<PIO0>; |
| 39 | }); | 36 | }); |
| 40 | 37 | ||
| @@ -45,7 +42,7 @@ async fn main(_spawner: Spawner) { | |||
| 45 | let p = embassy_rp::init(Default::default()); | 42 | let p = embassy_rp::init(Default::default()); |
| 46 | 43 | ||
| 47 | // Create the driver, from the HAL. | 44 | // Create the driver, from the HAL. |
| 48 | let driver = Driver::new(p.USB, UsbIrqs); | 45 | let driver = Driver::new(p.USB, Irqs); |
| 49 | 46 | ||
| 50 | // Create embassy-usb Config | 47 | // Create embassy-usb Config |
| 51 | let mut config = Config::new(0xc0de, 0xcafe); | 48 | let mut config = Config::new(0xc0de, 0xcafe); |
| @@ -90,17 +87,17 @@ async fn main(_spawner: Spawner) { | |||
| 90 | let usb_fut = usb.run(); | 87 | let usb_fut = usb.run(); |
| 91 | 88 | ||
| 92 | // PIO UART setup | 89 | // PIO UART setup |
| 93 | let uart = PioUart::new(9600, p.PIO0, p.PIN_4, p.PIN_5).await; | 90 | let uart = PioUart::new(9600, p.PIO0, p.PIN_4, p.PIN_5); |
| 94 | let (mut uart_tx, mut uart_rx) = uart.split(); | 91 | let (mut uart_tx, mut uart_rx) = uart.split(); |
| 95 | 92 | ||
| 96 | // Channels setup | 93 | // Pipe setup |
| 97 | static USB_CHANNEL_TX: Channel<ThreadModeRawMutex, u8, 20> = Channel::<ThreadModeRawMutex, u8, 20>::new(); | 94 | static USB_PIPE: Pipe<ThreadModeRawMutex, 20> = Pipe::new(); |
| 98 | let mut usb_channel_tx_send = USB_CHANNEL_TX.sender(); | 95 | let mut usb_pipe_writer = USB_PIPE.writer(); |
| 99 | let mut usb_channel_tx_recv = USB_CHANNEL_TX.receiver(); | 96 | let mut usb_pipe_reader = USB_PIPE.reader(); |
| 100 | 97 | ||
| 101 | static UART_CHANNEL_TX: Channel<ThreadModeRawMutex, u8, 20> = Channel::<ThreadModeRawMutex, u8, 20>::new(); | 98 | static UART_PIPE: Pipe<ThreadModeRawMutex, 20> = Pipe::new(); |
| 102 | let mut uart_channel_tx_send = UART_CHANNEL_TX.sender(); | 99 | let mut uart_pipe_writer = UART_PIPE.writer(); |
| 103 | let mut uart_channel_tx_recv = UART_CHANNEL_TX.receiver(); | 100 | let mut uart_pipe_reader = UART_PIPE.reader(); |
| 104 | 101 | ||
| 105 | let (mut usb_tx, mut usb_rx) = class.split(); | 102 | let (mut usb_tx, mut usb_rx) = class.split(); |
| 106 | 103 | ||
| @@ -111,8 +108,8 @@ async fn main(_spawner: Spawner) { | |||
| 111 | usb_rx.wait_connection().await; | 108 | usb_rx.wait_connection().await; |
| 112 | info!("Connected"); | 109 | info!("Connected"); |
| 113 | let _ = join( | 110 | let _ = join( |
| 114 | usb_read(&mut usb_rx, &mut uart_channel_tx_send), | 111 | usb_read(&mut usb_rx, &mut uart_pipe_writer), |
| 115 | usb_write(&mut usb_tx, &mut usb_channel_tx_recv), | 112 | usb_write(&mut usb_tx, &mut usb_pipe_reader), |
| 116 | ) | 113 | ) |
| 117 | .await; | 114 | .await; |
| 118 | info!("Disconnected"); | 115 | info!("Disconnected"); |
| @@ -120,15 +117,10 @@ async fn main(_spawner: Spawner) { | |||
| 120 | }; | 117 | }; |
| 121 | 118 | ||
| 122 | // Read + write from UART | 119 | // Read + write from UART |
| 123 | let uart_future = async { | 120 | let uart_future = join( |
| 124 | loop { | 121 | uart_read(&mut uart_rx, &mut usb_pipe_writer), |
| 125 | let _ = join( | 122 | uart_write(&mut uart_tx, &mut uart_pipe_reader), |
| 126 | uart_read(&mut uart_rx, &mut usb_channel_tx_send), | 123 | ); |
| 127 | uart_write(&mut uart_tx, &mut uart_channel_tx_recv), | ||
| 128 | ) | ||
| 129 | .await; | ||
| 130 | } | ||
| 131 | }; | ||
| 132 | 124 | ||
| 133 | // Run everything concurrently. | 125 | // Run everything concurrently. |
| 134 | // If we had made everything `'static` above instead, we could do this using separate tasks instead. | 126 | // If we had made everything `'static` above instead, we could do this using separate tasks instead. |
| @@ -146,75 +138,73 @@ impl From<EndpointError> for Disconnected { | |||
| 146 | } | 138 | } |
| 147 | } | 139 | } |
| 148 | 140 | ||
| 149 | /// Read from the USB and write it to the UART TX send channel | 141 | /// Read from the USB and write it to the UART TX pipe |
| 150 | async fn usb_read<'d, T: Instance + 'd>( | 142 | async fn usb_read<'d, T: Instance + 'd>( |
| 151 | usb_rx: &mut Receiver<'d, Driver<'d, T>>, | 143 | usb_rx: &mut Receiver<'d, Driver<'d, T>>, |
| 152 | uart_tx_send: &mut embassy_sync::channel::Sender<'d, ThreadModeRawMutex, u8, 20>, | 144 | uart_pipe_writer: &mut embassy_sync::pipe::Writer<'static, ThreadModeRawMutex, 20>, |
| 153 | ) -> Result<(), Disconnected> { | 145 | ) -> Result<(), Disconnected> { |
| 154 | let mut buf = [0; 64]; | 146 | let mut buf = [0; 64]; |
| 155 | loop { | 147 | loop { |
| 156 | let n = usb_rx.read_packet(&mut buf).await?; | 148 | let n = usb_rx.read_packet(&mut buf).await?; |
| 157 | let data = &buf[..n]; | 149 | let data = &buf[..n]; |
| 158 | trace!("USB IN: {:x}", data); | 150 | trace!("USB IN: {:x}", data); |
| 159 | for byte in data { | 151 | uart_pipe_writer.write(data).await; |
| 160 | uart_tx_send.send(*byte).await; | ||
| 161 | } | ||
| 162 | } | 152 | } |
| 163 | } | 153 | } |
| 164 | 154 | ||
| 165 | /// Read from the USB TX receive channel and write it to the USB | 155 | /// Read from the USB TX pipe and write it to the USB |
| 166 | async fn usb_write<'d, T: Instance + 'd>( | 156 | async fn usb_write<'d, T: Instance + 'd>( |
| 167 | usb_tx: &mut Sender<'d, Driver<'d, T>>, | 157 | usb_tx: &mut Sender<'d, Driver<'d, T>>, |
| 168 | usb_tx_recv: &mut embassy_sync::channel::Receiver<'d, ThreadModeRawMutex, u8, 20>, | 158 | usb_pipe_reader: &mut embassy_sync::pipe::Reader<'d, ThreadModeRawMutex, 20>, |
| 169 | ) -> Result<(), Disconnected> { | 159 | ) -> Result<(), Disconnected> { |
| 160 | let mut buf = [0; 64]; | ||
| 170 | loop { | 161 | loop { |
| 171 | let n = usb_tx_recv.recv().await; | 162 | let n = usb_pipe_reader.read(&mut buf).await; |
| 172 | let data = [n]; | 163 | let data = &buf[..n]; |
| 173 | trace!("USB OUT: {:x}", data); | 164 | trace!("USB OUT: {:x}", data); |
| 174 | usb_tx.write_packet(&data).await?; | 165 | usb_tx.write_packet(&data).await?; |
| 175 | } | 166 | } |
| 176 | } | 167 | } |
| 177 | 168 | ||
| 178 | /// Read from the UART and write it to the USB TX send channel | 169 | /// Read from the UART and write it to the USB TX pipe |
| 179 | async fn uart_read<'a>( | 170 | async fn uart_read<'a>( |
| 180 | uart_rx: &mut PioUartRx<'a>, | 171 | uart_rx: &mut PioUartRx<'a>, |
| 181 | usb_tx_send: &mut embassy_sync::channel::Sender<'a, ThreadModeRawMutex, u8, 20>, | 172 | usb_pipe_writer: &mut embassy_sync::pipe::Writer<'static, ThreadModeRawMutex, 20>, |
| 182 | ) -> Result<(), Disconnected> { | 173 | ) -> ! { |
| 183 | let mut buf = [0; 1]; | 174 | let mut buf = [0; 64]; |
| 184 | loop { | 175 | loop { |
| 185 | let n = uart_rx.read(&mut buf).await.expect("UART read error"); | 176 | let n = uart_rx.read(&mut buf).await.expect("UART read error"); |
| 186 | if n == 0 { | 177 | if n == 0 { |
| 187 | continue; | 178 | continue; |
| 188 | } | 179 | } |
| 180 | let data = &buf[..n]; | ||
| 189 | trace!("UART IN: {:x}", buf); | 181 | trace!("UART IN: {:x}", buf); |
| 190 | usb_tx_send.send(buf[0]).await; | 182 | usb_pipe_writer.write(data).await; |
| 191 | } | 183 | } |
| 192 | } | 184 | } |
| 193 | 185 | ||
| 194 | /// Read from the UART TX receive channel and write it to the UART | 186 | /// Read from the UART TX pipe and write it to the UART |
| 195 | async fn uart_write<'a>( | 187 | async fn uart_write<'a>( |
| 196 | uart_tx: &mut PioUartTx<'a>, | 188 | uart_tx: &mut PioUartTx<'a>, |
| 197 | uart_rx_recv: &mut embassy_sync::channel::Receiver<'a, ThreadModeRawMutex, u8, 20>, | 189 | uart_pipe_reader: &mut embassy_sync::pipe::Reader<'a, ThreadModeRawMutex, 20>, |
| 198 | ) -> Result<(), Disconnected> { | 190 | ) -> ! { |
| 191 | let mut buf = [0; 64]; | ||
| 199 | loop { | 192 | loop { |
| 200 | let n = uart_rx_recv.recv().await; | 193 | let n = uart_pipe_reader.read(&mut buf).await; |
| 201 | let data = [n]; | 194 | let data = &buf[..n]; |
| 202 | trace!("UART OUT: {:x}", data); | 195 | trace!("UART OUT: {:x}", data); |
| 203 | let _ = uart_tx.write(&data).await; | 196 | let _ = uart_tx.write(&data).await; |
| 204 | } | 197 | } |
| 205 | } | 198 | } |
| 206 | 199 | ||
| 207 | mod uart { | 200 | mod uart { |
| 208 | use core::fmt::Debug; | ||
| 209 | |||
| 210 | use embassy_rp::peripherals::PIO0; | 201 | use embassy_rp::peripherals::PIO0; |
| 211 | use embassy_rp::pio::{Pio, PioPin}; | 202 | use embassy_rp::pio::{Pio, PioPin}; |
| 212 | use embassy_rp::Peripheral; | 203 | use embassy_rp::Peripheral; |
| 213 | use embedded_io::ErrorKind; | ||
| 214 | 204 | ||
| 215 | use crate::uart_rx::PioUartRx; | 205 | use crate::uart_rx::PioUartRx; |
| 216 | use crate::uart_tx::PioUartTx; | 206 | use crate::uart_tx::PioUartTx; |
| 217 | use crate::PioIrqs; | 207 | use crate::Irqs; |
| 218 | 208 | ||
| 219 | pub struct PioUart<'a> { | 209 | pub struct PioUart<'a> { |
| 220 | tx: PioUartTx<'a>, | 210 | tx: PioUartTx<'a>, |
| @@ -222,7 +212,7 @@ mod uart { | |||
| 222 | } | 212 | } |
| 223 | 213 | ||
| 224 | impl<'a> PioUart<'a> { | 214 | impl<'a> PioUart<'a> { |
| 225 | pub async fn new( | 215 | pub fn new( |
| 226 | baud: u64, | 216 | baud: u64, |
| 227 | pio: impl Peripheral<P = PIO0> + 'a, | 217 | pio: impl Peripheral<P = PIO0> + 'a, |
| 228 | tx_pin: impl PioPin, | 218 | tx_pin: impl PioPin, |
| @@ -230,7 +220,7 @@ mod uart { | |||
| 230 | ) -> PioUart<'a> { | 220 | ) -> PioUart<'a> { |
| 231 | let Pio { | 221 | let Pio { |
| 232 | mut common, sm0, sm1, .. | 222 | mut common, sm0, sm1, .. |
| 233 | } = Pio::new(pio, PioIrqs); | 223 | } = Pio::new(pio, Irqs); |
| 234 | 224 | ||
| 235 | let (tx, origin) = PioUartTx::new(&mut common, sm0, tx_pin, baud, None); | 225 | let (tx, origin) = PioUartTx::new(&mut common, sm0, tx_pin, baud, None); |
| 236 | let (rx, _) = PioUartRx::new(&mut common, sm1, rx_pin, baud, Some(origin)); | 226 | let (rx, _) = PioUartRx::new(&mut common, sm1, rx_pin, baud, Some(origin)); |
| @@ -242,17 +232,11 @@ mod uart { | |||
| 242 | (self.tx, self.rx) | 232 | (self.tx, self.rx) |
| 243 | } | 233 | } |
| 244 | } | 234 | } |
| 245 | #[derive(defmt::Format, Debug)] | ||
| 246 | pub struct PioUartError {} | ||
| 247 | |||
| 248 | impl embedded_io::Error for PioUartError { | ||
| 249 | fn kind(&self) -> ErrorKind { | ||
| 250 | ErrorKind::Other | ||
| 251 | } | ||
| 252 | } | ||
| 253 | } | 235 | } |
| 254 | 236 | ||
| 255 | mod uart_tx { | 237 | mod uart_tx { |
| 238 | use core::convert::Infallible; | ||
| 239 | |||
| 256 | use embassy_rp::gpio::Level; | 240 | use embassy_rp::gpio::Level; |
| 257 | use embassy_rp::peripherals::PIO0; | 241 | use embassy_rp::peripherals::PIO0; |
| 258 | use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine}; | 242 | use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine}; |
| @@ -262,8 +246,6 @@ mod uart_tx { | |||
| 262 | use fixed::traits::ToFixed; | 246 | use fixed::traits::ToFixed; |
| 263 | use fixed_macro::types::U56F8; | 247 | use fixed_macro::types::U56F8; |
| 264 | 248 | ||
| 265 | use crate::uart::PioUartError; | ||
| 266 | |||
| 267 | pub struct PioUartTx<'a> { | 249 | pub struct PioUartTx<'a> { |
| 268 | sm_tx: StateMachine<'a, PIO0, 0>, | 250 | sm_tx: StateMachine<'a, PIO0, 0>, |
| 269 | } | 251 | } |
| @@ -328,11 +310,11 @@ mod uart_tx { | |||
| 328 | } | 310 | } |
| 329 | 311 | ||
| 330 | impl Io for PioUartTx<'_> { | 312 | impl Io for PioUartTx<'_> { |
| 331 | type Error = PioUartError; | 313 | type Error = Infallible; |
| 332 | } | 314 | } |
| 333 | 315 | ||
| 334 | impl Write for PioUartTx<'_> { | 316 | impl Write for PioUartTx<'_> { |
| 335 | async fn write(&mut self, buf: &[u8]) -> Result<usize, PioUartError> { | 317 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Infallible> { |
| 336 | for byte in buf { | 318 | for byte in buf { |
| 337 | self.write_u8(*byte).await; | 319 | self.write_u8(*byte).await; |
| 338 | } | 320 | } |
| @@ -342,6 +324,8 @@ mod uart_tx { | |||
| 342 | } | 324 | } |
| 343 | 325 | ||
| 344 | mod uart_rx { | 326 | mod uart_rx { |
| 327 | use core::convert::Infallible; | ||
| 328 | |||
| 345 | use embassy_rp::gpio::Level; | 329 | use embassy_rp::gpio::Level; |
| 346 | use embassy_rp::peripherals::PIO0; | 330 | use embassy_rp::peripherals::PIO0; |
| 347 | use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine}; | 331 | use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine}; |
| @@ -351,8 +335,6 @@ mod uart_rx { | |||
| 351 | use fixed::traits::ToFixed; | 335 | use fixed::traits::ToFixed; |
| 352 | use fixed_macro::types::U56F8; | 336 | use fixed_macro::types::U56F8; |
| 353 | 337 | ||
| 354 | use crate::uart::PioUartError; | ||
| 355 | |||
| 356 | pub struct PioUartRx<'a> { | 338 | pub struct PioUartRx<'a> { |
| 357 | sm_rx: StateMachine<'a, PIO0, 1>, | 339 | sm_rx: StateMachine<'a, PIO0, 1>, |
| 358 | } | 340 | } |
| @@ -415,11 +397,11 @@ mod uart_rx { | |||
| 415 | } | 397 | } |
| 416 | 398 | ||
| 417 | impl Io for PioUartRx<'_> { | 399 | impl Io for PioUartRx<'_> { |
| 418 | type Error = PioUartError; | 400 | type Error = Infallible; |
| 419 | } | 401 | } |
| 420 | 402 | ||
| 421 | impl Read for PioUartRx<'_> { | 403 | impl Read for PioUartRx<'_> { |
| 422 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, PioUartError> { | 404 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Infallible> { |
| 423 | let mut i = 0; | 405 | let mut i = 0; |
| 424 | while i < buf.len() { | 406 | while i < buf.len() { |
| 425 | buf[i] = self.read_u8().await; | 407 | buf[i] = self.read_u8().await; |
