diff options
| author | Mathias <[email protected]> | 2022-09-29 10:00:13 +0200 |
|---|---|---|
| committer | Mathias <[email protected]> | 2022-09-29 10:00:13 +0200 |
| commit | 7ee7109508b463f98ea9ae08e061aeaca28016e6 (patch) | |
| tree | 50723244067224c6c32603e21fbe8ec36c76898e /embassy-rp/src | |
| parent | 18dc0dea636daa6e48aa9208b5a74cdfedc8b513 (diff) | |
| parent | 77ece3f903735b50f265ddd43520c50e0f28c1a1 (diff) | |
Rebase on master
Diffstat (limited to 'embassy-rp/src')
| -rw-r--r-- | embassy-rp/src/i2c.rs | 556 | ||||
| -rw-r--r-- | embassy-rp/src/intrinsics.rs | 20 | ||||
| -rw-r--r-- | embassy-rp/src/lib.rs | 4 | ||||
| -rw-r--r-- | embassy-rp/src/rom_data.rs | 2 | ||||
| -rw-r--r-- | embassy-rp/src/uart/buffered.rs | 489 | ||||
| -rw-r--r-- | embassy-rp/src/uart/mod.rs (renamed from embassy-rp/src/uart.rs) | 92 | ||||
| -rw-r--r-- | embassy-rp/src/usb.rs | 28 |
7 files changed, 1167 insertions, 24 deletions
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs new file mode 100644 index 000000000..9596d661d --- /dev/null +++ b/embassy-rp/src/i2c.rs | |||
| @@ -0,0 +1,556 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | ||
| 4 | use pac::i2c; | ||
| 5 | |||
| 6 | use crate::dma::AnyChannel; | ||
| 7 | use crate::gpio::sealed::Pin; | ||
| 8 | use crate::gpio::AnyPin; | ||
| 9 | use crate::{pac, peripherals, Peripheral}; | ||
| 10 | |||
| 11 | /// I2C error abort reason | ||
| 12 | #[derive(Debug)] | ||
| 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 14 | pub enum AbortReason { | ||
| 15 | /// A bus operation was not acknowledged, e.g. due to the addressed device | ||
| 16 | /// not being available on the bus or the device not being ready to process | ||
| 17 | /// requests at the moment | ||
| 18 | NoAcknowledge, | ||
| 19 | /// The arbitration was lost, e.g. electrical problems with the clock signal | ||
| 20 | ArbitrationLoss, | ||
| 21 | Other(u32), | ||
| 22 | } | ||
| 23 | |||
| 24 | /// I2C error | ||
| 25 | #[derive(Debug)] | ||
| 26 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 27 | pub enum Error { | ||
| 28 | /// I2C abort with error | ||
| 29 | Abort(AbortReason), | ||
| 30 | /// User passed in a read buffer that was 0 length | ||
| 31 | InvalidReadBufferLength, | ||
| 32 | /// User passed in a write buffer that was 0 length | ||
| 33 | InvalidWriteBufferLength, | ||
| 34 | /// Target i2c address is out of range | ||
| 35 | AddressOutOfRange(u16), | ||
| 36 | /// Target i2c address is reserved | ||
| 37 | AddressReserved(u16), | ||
| 38 | } | ||
| 39 | |||
| 40 | #[non_exhaustive] | ||
| 41 | #[derive(Copy, Clone)] | ||
| 42 | pub struct Config { | ||
| 43 | pub frequency: u32, | ||
| 44 | } | ||
| 45 | |||
| 46 | impl Default for Config { | ||
| 47 | fn default() -> Self { | ||
| 48 | Self { frequency: 100_000 } | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | const FIFO_SIZE: u8 = 16; | ||
| 53 | |||
| 54 | pub struct I2c<'d, T: Instance, M: Mode> { | ||
| 55 | _tx_dma: Option<PeripheralRef<'d, AnyChannel>>, | ||
| 56 | _rx_dma: Option<PeripheralRef<'d, AnyChannel>>, | ||
| 57 | _dma_buf: [u16; 256], | ||
| 58 | phantom: PhantomData<(&'d mut T, M)>, | ||
| 59 | } | ||
| 60 | |||
| 61 | impl<'d, T: Instance> I2c<'d, T, Blocking> { | ||
| 62 | pub fn new_blocking( | ||
| 63 | _peri: impl Peripheral<P = T> + 'd, | ||
| 64 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, | ||
| 65 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, | ||
| 66 | config: Config, | ||
| 67 | ) -> Self { | ||
| 68 | into_ref!(scl, sda); | ||
| 69 | Self::new_inner(_peri, scl.map_into(), sda.map_into(), None, None, config) | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | impl<'d, T: Instance, M: Mode> I2c<'d, T, M> { | ||
| 74 | fn new_inner( | ||
| 75 | _peri: impl Peripheral<P = T> + 'd, | ||
| 76 | scl: PeripheralRef<'d, AnyPin>, | ||
| 77 | sda: PeripheralRef<'d, AnyPin>, | ||
| 78 | _tx_dma: Option<PeripheralRef<'d, AnyChannel>>, | ||
| 79 | _rx_dma: Option<PeripheralRef<'d, AnyChannel>>, | ||
| 80 | config: Config, | ||
| 81 | ) -> Self { | ||
| 82 | into_ref!(_peri); | ||
| 83 | |||
| 84 | assert!(config.frequency <= 1_000_000); | ||
| 85 | assert!(config.frequency > 0); | ||
| 86 | |||
| 87 | let p = T::regs(); | ||
| 88 | |||
| 89 | unsafe { | ||
| 90 | p.ic_enable().write(|w| w.set_enable(false)); | ||
| 91 | |||
| 92 | // Select controller mode & speed | ||
| 93 | p.ic_con().modify(|w| { | ||
| 94 | // Always use "fast" mode (<= 400 kHz, works fine for standard | ||
| 95 | // mode too) | ||
| 96 | w.set_speed(i2c::vals::Speed::FAST); | ||
| 97 | w.set_master_mode(true); | ||
| 98 | w.set_ic_slave_disable(true); | ||
| 99 | w.set_ic_restart_en(true); | ||
| 100 | w.set_tx_empty_ctrl(true); | ||
| 101 | }); | ||
| 102 | |||
| 103 | // Set FIFO watermarks to 1 to make things simpler. This is encoded | ||
| 104 | // by a register value of 0. | ||
| 105 | p.ic_tx_tl().write(|w| w.set_tx_tl(0)); | ||
| 106 | p.ic_rx_tl().write(|w| w.set_rx_tl(0)); | ||
| 107 | |||
| 108 | // Configure SCL & SDA pins | ||
| 109 | scl.io().ctrl().write(|w| w.set_funcsel(3)); | ||
| 110 | sda.io().ctrl().write(|w| w.set_funcsel(3)); | ||
| 111 | |||
| 112 | scl.pad_ctrl().write(|w| { | ||
| 113 | w.set_schmitt(true); | ||
| 114 | w.set_ie(true); | ||
| 115 | w.set_od(false); | ||
| 116 | w.set_pue(true); | ||
| 117 | w.set_pde(false); | ||
| 118 | }); | ||
| 119 | sda.pad_ctrl().write(|w| { | ||
| 120 | w.set_schmitt(true); | ||
| 121 | w.set_ie(true); | ||
| 122 | w.set_od(false); | ||
| 123 | w.set_pue(true); | ||
| 124 | w.set_pde(false); | ||
| 125 | }); | ||
| 126 | |||
| 127 | // Configure baudrate | ||
| 128 | |||
| 129 | // There are some subtleties to I2C timing which we are completely | ||
| 130 | // ignoring here See: | ||
| 131 | // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69 | ||
| 132 | let clk_base = crate::clocks::clk_peri_freq(); | ||
| 133 | |||
| 134 | let period = (clk_base + config.frequency / 2) / config.frequency; | ||
| 135 | let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low | ||
| 136 | let hcnt = period - lcnt; // and 2/5 (40%) of the period high | ||
| 137 | |||
| 138 | // Check for out-of-range divisors: | ||
| 139 | assert!(hcnt <= 0xffff); | ||
| 140 | assert!(lcnt <= 0xffff); | ||
| 141 | assert!(hcnt >= 8); | ||
| 142 | assert!(lcnt >= 8); | ||
| 143 | |||
| 144 | // Per I2C-bus specification a device in standard or fast mode must | ||
| 145 | // internally provide a hold time of at least 300ns for the SDA | ||
| 146 | // signal to bridge the undefined region of the falling edge of SCL. | ||
| 147 | // A smaller hold time of 120ns is used for fast mode plus. | ||
| 148 | let sda_tx_hold_count = if config.frequency < 1_000_000 { | ||
| 149 | // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s / | ||
| 150 | // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't | ||
| 151 | // fit in uint. Add 1 to avoid division truncation. | ||
| 152 | ((clk_base * 3) / 10_000_000) + 1 | ||
| 153 | } else { | ||
| 154 | // fast mode plus requires a clk_base > 32MHz | ||
| 155 | assert!(clk_base >= 32_000_000); | ||
| 156 | |||
| 157 | // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s / | ||
| 158 | // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't | ||
| 159 | // fit in uint. Add 1 to avoid division truncation. | ||
| 160 | ((clk_base * 3) / 25_000_000) + 1 | ||
| 161 | }; | ||
| 162 | assert!(sda_tx_hold_count <= lcnt - 2); | ||
| 163 | |||
| 164 | p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16)); | ||
| 165 | p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16)); | ||
| 166 | p.ic_fs_spklen() | ||
| 167 | .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 })); | ||
| 168 | p.ic_sda_hold() | ||
| 169 | .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16)); | ||
| 170 | |||
| 171 | // Enable I2C block | ||
| 172 | p.ic_enable().write(|w| w.set_enable(true)); | ||
| 173 | } | ||
| 174 | |||
| 175 | Self { | ||
| 176 | _tx_dma, | ||
| 177 | _rx_dma, | ||
| 178 | _dma_buf: [0; 256], | ||
| 179 | phantom: PhantomData, | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | fn setup(addr: u16) -> Result<(), Error> { | ||
| 184 | if addr >= 0x80 { | ||
| 185 | return Err(Error::AddressOutOfRange(addr)); | ||
| 186 | } | ||
| 187 | |||
| 188 | if i2c_reserved_addr(addr) { | ||
| 189 | return Err(Error::AddressReserved(addr)); | ||
| 190 | } | ||
| 191 | |||
| 192 | let p = T::regs(); | ||
| 193 | unsafe { | ||
| 194 | p.ic_enable().write(|w| w.set_enable(false)); | ||
| 195 | p.ic_tar().write(|w| w.set_ic_tar(addr)); | ||
| 196 | p.ic_enable().write(|w| w.set_enable(true)); | ||
| 197 | } | ||
| 198 | Ok(()) | ||
| 199 | } | ||
| 200 | |||
| 201 | fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> { | ||
| 202 | let p = T::regs(); | ||
| 203 | unsafe { | ||
| 204 | let abort_reason = p.ic_tx_abrt_source().read(); | ||
| 205 | if abort_reason.0 != 0 { | ||
| 206 | // Note clearing the abort flag also clears the reason, and this | ||
| 207 | // instance of flag is clear-on-read! Note also the | ||
| 208 | // IC_CLR_TX_ABRT register always reads as 0. | ||
| 209 | p.ic_clr_tx_abrt().read(); | ||
| 210 | |||
| 211 | let reason = if abort_reason.abrt_7b_addr_noack() | ||
| 212 | | abort_reason.abrt_10addr1_noack() | ||
| 213 | | abort_reason.abrt_10addr2_noack() | ||
| 214 | { | ||
| 215 | AbortReason::NoAcknowledge | ||
| 216 | } else if abort_reason.arb_lost() { | ||
| 217 | AbortReason::ArbitrationLoss | ||
| 218 | } else { | ||
| 219 | AbortReason::Other(abort_reason.0) | ||
| 220 | }; | ||
| 221 | |||
| 222 | Err(Error::Abort(reason)) | ||
| 223 | } else { | ||
| 224 | Ok(()) | ||
| 225 | } | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | fn read_blocking_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> { | ||
| 230 | if buffer.is_empty() { | ||
| 231 | return Err(Error::InvalidReadBufferLength); | ||
| 232 | } | ||
| 233 | |||
| 234 | let p = T::regs(); | ||
| 235 | let lastindex = buffer.len() - 1; | ||
| 236 | for (i, byte) in buffer.iter_mut().enumerate() { | ||
| 237 | let first = i == 0; | ||
| 238 | let last = i == lastindex; | ||
| 239 | |||
| 240 | // NOTE(unsafe) We have &mut self | ||
| 241 | unsafe { | ||
| 242 | // wait until there is space in the FIFO to write the next byte | ||
| 243 | while p.ic_txflr().read().txflr() == FIFO_SIZE {} | ||
| 244 | |||
| 245 | p.ic_data_cmd().write(|w| { | ||
| 246 | w.set_restart(restart && first); | ||
| 247 | w.set_stop(send_stop && last); | ||
| 248 | |||
| 249 | w.set_cmd(true); | ||
| 250 | }); | ||
| 251 | |||
| 252 | while p.ic_rxflr().read().rxflr() == 0 { | ||
| 253 | self.read_and_clear_abort_reason()?; | ||
| 254 | } | ||
| 255 | |||
| 256 | *byte = p.ic_data_cmd().read().dat(); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | Ok(()) | ||
| 261 | } | ||
| 262 | |||
| 263 | fn write_blocking_internal(&mut self, bytes: &[u8], send_stop: bool) -> Result<(), Error> { | ||
| 264 | if bytes.is_empty() { | ||
| 265 | return Err(Error::InvalidWriteBufferLength); | ||
| 266 | } | ||
| 267 | |||
| 268 | let p = T::regs(); | ||
| 269 | |||
| 270 | for (i, byte) in bytes.iter().enumerate() { | ||
| 271 | let last = i == bytes.len() - 1; | ||
| 272 | |||
| 273 | // NOTE(unsafe) We have &mut self | ||
| 274 | unsafe { | ||
| 275 | p.ic_data_cmd().write(|w| { | ||
| 276 | w.set_stop(send_stop && last); | ||
| 277 | w.set_dat(*byte); | ||
| 278 | }); | ||
| 279 | |||
| 280 | // Wait until the transmission of the address/data from the | ||
| 281 | // internal shift register has completed. For this to function | ||
| 282 | // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The | ||
| 283 | // TX_EMPTY_CTRL flag was set in i2c_init. | ||
| 284 | while !p.ic_raw_intr_stat().read().tx_empty() {} | ||
| 285 | |||
| 286 | let abort_reason = self.read_and_clear_abort_reason(); | ||
| 287 | |||
| 288 | if abort_reason.is_err() || (send_stop && last) { | ||
| 289 | // If the transaction was aborted or if it completed | ||
| 290 | // successfully wait until the STOP condition has occured. | ||
| 291 | |||
| 292 | while !p.ic_raw_intr_stat().read().stop_det() {} | ||
| 293 | |||
| 294 | p.ic_clr_stop_det().read().clr_stop_det(); | ||
| 295 | } | ||
| 296 | |||
| 297 | // Note the hardware issues a STOP automatically on an abort | ||
| 298 | // condition. Note also the hardware clears RX FIFO as well as | ||
| 299 | // TX on abort, ecause we set hwparam | ||
| 300 | // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0. | ||
| 301 | abort_reason?; | ||
| 302 | } | ||
| 303 | } | ||
| 304 | Ok(()) | ||
| 305 | } | ||
| 306 | |||
| 307 | // ========================= | ||
| 308 | // Blocking public API | ||
| 309 | // ========================= | ||
| 310 | |||
| 311 | pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 312 | Self::setup(address.into())?; | ||
| 313 | self.read_blocking_internal(buffer, true, true) | ||
| 314 | // Automatic Stop | ||
| 315 | } | ||
| 316 | |||
| 317 | pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> { | ||
| 318 | Self::setup(address.into())?; | ||
| 319 | self.write_blocking_internal(bytes, true) | ||
| 320 | } | ||
| 321 | |||
| 322 | pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { | ||
| 323 | Self::setup(address.into())?; | ||
| 324 | self.write_blocking_internal(bytes, false)?; | ||
| 325 | self.read_blocking_internal(buffer, true, true) | ||
| 326 | // Automatic Stop | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | mod eh02 { | ||
| 331 | use super::*; | ||
| 332 | |||
| 333 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> { | ||
| 334 | type Error = Error; | ||
| 335 | |||
| 336 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
| 337 | self.blocking_read(address, buffer) | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> { | ||
| 342 | type Error = Error; | ||
| 343 | |||
| 344 | fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { | ||
| 345 | self.blocking_write(address, bytes) | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> { | ||
| 350 | type Error = Error; | ||
| 351 | |||
| 352 | fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
| 353 | self.blocking_write_read(address, bytes, buffer) | ||
| 354 | } | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | #[cfg(feature = "unstable-traits")] | ||
| 359 | mod eh1 { | ||
| 360 | use super::*; | ||
| 361 | |||
| 362 | impl embedded_hal_1::i2c::Error for Error { | ||
| 363 | fn kind(&self) -> embedded_hal_1::i2c::ErrorKind { | ||
| 364 | match *self { | ||
| 365 | Self::Abort(AbortReason::ArbitrationLoss) => embedded_hal_1::i2c::ErrorKind::ArbitrationLoss, | ||
| 366 | Self::Abort(AbortReason::NoAcknowledge) => { | ||
| 367 | embedded_hal_1::i2c::ErrorKind::NoAcknowledge(embedded_hal_1::i2c::NoAcknowledgeSource::Address) | ||
| 368 | } | ||
| 369 | Self::Abort(AbortReason::Other(_)) => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 370 | Self::InvalidReadBufferLength => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 371 | Self::InvalidWriteBufferLength => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 372 | Self::AddressOutOfRange(_) => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 373 | Self::AddressReserved(_) => embedded_hal_1::i2c::ErrorKind::Other, | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::ErrorType for I2c<'d, T, M> { | ||
| 379 | type Error = Error; | ||
| 380 | } | ||
| 381 | |||
| 382 | impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::blocking::I2c for I2c<'d, T, M> { | ||
| 383 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
| 384 | self.blocking_read(address, buffer) | ||
| 385 | } | ||
| 386 | |||
| 387 | fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 388 | self.blocking_write(address, buffer) | ||
| 389 | } | ||
| 390 | |||
| 391 | fn write_iter<B>(&mut self, address: u8, bytes: B) -> Result<(), Self::Error> | ||
| 392 | where | ||
| 393 | B: IntoIterator<Item = u8>, | ||
| 394 | { | ||
| 395 | let mut peekable = bytes.into_iter().peekable(); | ||
| 396 | Self::setup(address.into())?; | ||
| 397 | |||
| 398 | while let Some(tx) = peekable.next() { | ||
| 399 | self.write_blocking_internal(&[tx], peekable.peek().is_none())?; | ||
| 400 | } | ||
| 401 | Ok(()) | ||
| 402 | } | ||
| 403 | |||
| 404 | fn write_iter_read<B>(&mut self, address: u8, bytes: B, buffer: &mut [u8]) -> Result<(), Self::Error> | ||
| 405 | where | ||
| 406 | B: IntoIterator<Item = u8>, | ||
| 407 | { | ||
| 408 | let peekable = bytes.into_iter().peekable(); | ||
| 409 | Self::setup(address.into())?; | ||
| 410 | |||
| 411 | for tx in peekable { | ||
| 412 | self.write_blocking_internal(&[tx], false)? | ||
| 413 | } | ||
| 414 | self.read_blocking_internal(buffer, true, true) | ||
| 415 | } | ||
| 416 | |||
| 417 | fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
| 418 | self.blocking_write_read(address, wr_buffer, rd_buffer) | ||
| 419 | } | ||
| 420 | |||
| 421 | fn transaction<'a>( | ||
| 422 | &mut self, | ||
| 423 | address: u8, | ||
| 424 | operations: &mut [embedded_hal_1::i2c::blocking::Operation<'a>], | ||
| 425 | ) -> Result<(), Self::Error> { | ||
| 426 | Self::setup(address.into())?; | ||
| 427 | for i in 0..operations.len() { | ||
| 428 | let last = i == operations.len() - 1; | ||
| 429 | match &mut operations[i] { | ||
| 430 | embedded_hal_1::i2c::blocking::Operation::Read(buf) => { | ||
| 431 | self.read_blocking_internal(buf, false, last)? | ||
| 432 | } | ||
| 433 | embedded_hal_1::i2c::blocking::Operation::Write(buf) => self.write_blocking_internal(buf, last)?, | ||
| 434 | } | ||
| 435 | } | ||
| 436 | Ok(()) | ||
| 437 | } | ||
| 438 | |||
| 439 | fn transaction_iter<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> | ||
| 440 | where | ||
| 441 | O: IntoIterator<Item = embedded_hal_1::i2c::blocking::Operation<'a>>, | ||
| 442 | { | ||
| 443 | Self::setup(address.into())?; | ||
| 444 | let mut peekable = operations.into_iter().peekable(); | ||
| 445 | while let Some(operation) = peekable.next() { | ||
| 446 | let last = peekable.peek().is_none(); | ||
| 447 | match operation { | ||
| 448 | embedded_hal_1::i2c::blocking::Operation::Read(buf) => { | ||
| 449 | self.read_blocking_internal(buf, false, last)? | ||
| 450 | } | ||
| 451 | embedded_hal_1::i2c::blocking::Operation::Write(buf) => self.write_blocking_internal(buf, last)?, | ||
| 452 | } | ||
| 453 | } | ||
| 454 | Ok(()) | ||
| 455 | } | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | fn i2c_reserved_addr(addr: u16) -> bool { | ||
| 460 | (addr & 0x78) == 0 || (addr & 0x78) == 0x78 | ||
| 461 | } | ||
| 462 | |||
| 463 | mod sealed { | ||
| 464 | use embassy_cortex_m::interrupt::Interrupt; | ||
| 465 | |||
| 466 | pub trait Instance { | ||
| 467 | const TX_DREQ: u8; | ||
| 468 | const RX_DREQ: u8; | ||
| 469 | |||
| 470 | type Interrupt: Interrupt; | ||
| 471 | |||
| 472 | fn regs() -> crate::pac::i2c::I2c; | ||
| 473 | } | ||
| 474 | |||
| 475 | pub trait Mode {} | ||
| 476 | |||
| 477 | pub trait SdaPin<T: Instance> {} | ||
| 478 | pub trait SclPin<T: Instance> {} | ||
| 479 | } | ||
| 480 | |||
| 481 | pub trait Mode: sealed::Mode {} | ||
| 482 | |||
| 483 | macro_rules! impl_mode { | ||
| 484 | ($name:ident) => { | ||
| 485 | impl sealed::Mode for $name {} | ||
| 486 | impl Mode for $name {} | ||
| 487 | }; | ||
| 488 | } | ||
| 489 | |||
| 490 | pub struct Blocking; | ||
| 491 | pub struct Async; | ||
| 492 | |||
| 493 | impl_mode!(Blocking); | ||
| 494 | impl_mode!(Async); | ||
| 495 | |||
| 496 | pub trait Instance: sealed::Instance {} | ||
| 497 | |||
| 498 | macro_rules! impl_instance { | ||
| 499 | ($type:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => { | ||
| 500 | impl sealed::Instance for peripherals::$type { | ||
| 501 | const TX_DREQ: u8 = $tx_dreq; | ||
| 502 | const RX_DREQ: u8 = $rx_dreq; | ||
| 503 | |||
| 504 | type Interrupt = crate::interrupt::$irq; | ||
| 505 | |||
| 506 | fn regs() -> pac::i2c::I2c { | ||
| 507 | pac::$type | ||
| 508 | } | ||
| 509 | } | ||
| 510 | impl Instance for peripherals::$type {} | ||
| 511 | }; | ||
| 512 | } | ||
| 513 | |||
| 514 | impl_instance!(I2C0, I2C0_IRQ, 32, 33); | ||
| 515 | impl_instance!(I2C1, I2C1_IRQ, 34, 35); | ||
| 516 | |||
| 517 | pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {} | ||
| 518 | pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {} | ||
| 519 | |||
| 520 | macro_rules! impl_pin { | ||
| 521 | ($pin:ident, $instance:ident, $function:ident) => { | ||
| 522 | impl sealed::$function<peripherals::$instance> for peripherals::$pin {} | ||
| 523 | impl $function<peripherals::$instance> for peripherals::$pin {} | ||
| 524 | }; | ||
| 525 | } | ||
| 526 | |||
| 527 | impl_pin!(PIN_0, I2C0, SdaPin); | ||
| 528 | impl_pin!(PIN_1, I2C0, SclPin); | ||
| 529 | impl_pin!(PIN_2, I2C1, SdaPin); | ||
| 530 | impl_pin!(PIN_3, I2C1, SclPin); | ||
| 531 | impl_pin!(PIN_4, I2C0, SdaPin); | ||
| 532 | impl_pin!(PIN_5, I2C0, SclPin); | ||
| 533 | impl_pin!(PIN_6, I2C1, SdaPin); | ||
| 534 | impl_pin!(PIN_7, I2C1, SclPin); | ||
| 535 | impl_pin!(PIN_8, I2C0, SdaPin); | ||
| 536 | impl_pin!(PIN_9, I2C0, SclPin); | ||
| 537 | impl_pin!(PIN_10, I2C1, SdaPin); | ||
| 538 | impl_pin!(PIN_11, I2C1, SclPin); | ||
| 539 | impl_pin!(PIN_12, I2C0, SdaPin); | ||
| 540 | impl_pin!(PIN_13, I2C0, SclPin); | ||
| 541 | impl_pin!(PIN_14, I2C1, SdaPin); | ||
| 542 | impl_pin!(PIN_15, I2C1, SclPin); | ||
| 543 | impl_pin!(PIN_16, I2C0, SdaPin); | ||
| 544 | impl_pin!(PIN_17, I2C0, SclPin); | ||
| 545 | impl_pin!(PIN_18, I2C1, SdaPin); | ||
| 546 | impl_pin!(PIN_19, I2C1, SclPin); | ||
| 547 | impl_pin!(PIN_20, I2C0, SdaPin); | ||
| 548 | impl_pin!(PIN_21, I2C0, SclPin); | ||
| 549 | impl_pin!(PIN_22, I2C1, SdaPin); | ||
| 550 | impl_pin!(PIN_23, I2C1, SclPin); | ||
| 551 | impl_pin!(PIN_24, I2C0, SdaPin); | ||
| 552 | impl_pin!(PIN_25, I2C0, SclPin); | ||
| 553 | impl_pin!(PIN_26, I2C1, SdaPin); | ||
| 554 | impl_pin!(PIN_27, I2C1, SclPin); | ||
| 555 | impl_pin!(PIN_28, I2C0, SdaPin); | ||
| 556 | impl_pin!(PIN_29, I2C0, SclPin); | ||
diff --git a/embassy-rp/src/intrinsics.rs b/embassy-rp/src/intrinsics.rs index 9e6624cf0..67e8202a4 100644 --- a/embassy-rp/src/intrinsics.rs +++ b/embassy-rp/src/intrinsics.rs | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | // Credit: taken from `rp-hal` (also licensed Apache+MIT) | ||
| 3 | // https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/intrinsics.rs | ||
| 2 | 4 | ||
| 3 | /// Generate a series of aliases for an intrinsic function. | 5 | /// Generate a series of aliases for an intrinsic function. |
| 4 | macro_rules! intrinsics_aliases { | 6 | macro_rules! intrinsics_aliases { |
| @@ -14,7 +16,7 @@ macro_rules! intrinsics_aliases { | |||
| 14 | $alias:ident | 16 | $alias:ident |
| 15 | $($rest:ident)* | 17 | $($rest:ident)* |
| 16 | ) => { | 18 | ) => { |
| 17 | #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] | 19 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] |
| 18 | intrinsics! { | 20 | intrinsics! { |
| 19 | extern $abi fn $alias( $($argname: $ty),* ) -> $ret { | 21 | extern $abi fn $alias( $($argname: $ty),* ) -> $ret { |
| 20 | $name($($argname),*) | 22 | $name($($argname),*) |
| @@ -32,7 +34,7 @@ macro_rules! intrinsics_aliases { | |||
| 32 | $alias:ident | 34 | $alias:ident |
| 33 | $($rest:ident)* | 35 | $($rest:ident)* |
| 34 | ) => { | 36 | ) => { |
| 35 | #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] | 37 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] |
| 36 | intrinsics! { | 38 | intrinsics! { |
| 37 | unsafe extern $abi fn $alias( $($argname: $ty),* ) -> $ret { | 39 | unsafe extern $abi fn $alias( $($argname: $ty),* ) -> $ret { |
| 38 | $name($($argname),*) | 40 | $name($($argname),*) |
| @@ -52,7 +54,7 @@ macro_rules! intrinsics_aliases { | |||
| 52 | /// is to abstract anything special that needs to be done to override an | 54 | /// is to abstract anything special that needs to be done to override an |
| 53 | /// intrinsic function. Intrinsic generation is disabled for non-ARM targets | 55 | /// intrinsic function. Intrinsic generation is disabled for non-ARM targets |
| 54 | /// so things like CI and docs generation do not have problems. Additionally | 56 | /// so things like CI and docs generation do not have problems. Additionally |
| 55 | /// they can be disabled with the crate feature `disable-intrinsics` for | 57 | /// they can be disabled by disabling the crate feature `intrinsics` for |
| 56 | /// testing or comparing performance. | 58 | /// testing or comparing performance. |
| 57 | /// | 59 | /// |
| 58 | /// Like the compiler-builtins macro, it accepts a series of functions that | 60 | /// Like the compiler-builtins macro, it accepts a series of functions that |
| @@ -211,13 +213,13 @@ macro_rules! intrinsics { | |||
| 211 | 213 | ||
| 212 | $($rest:tt)* | 214 | $($rest:tt)* |
| 213 | ) => { | 215 | ) => { |
| 214 | #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] | 216 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] |
| 215 | $(#[$($attr)*])* | 217 | $(#[$($attr)*])* |
| 216 | extern $abi fn $name( $($argname: $ty),* ) -> $ret { | 218 | extern $abi fn $name( $($argname: $ty),* ) -> $ret { |
| 217 | $($body)* | 219 | $($body)* |
| 218 | } | 220 | } |
| 219 | 221 | ||
| 220 | #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] | 222 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] |
| 221 | mod $name { | 223 | mod $name { |
| 222 | #[no_mangle] | 224 | #[no_mangle] |
| 223 | $(#[$($attr)*])* | 225 | $(#[$($attr)*])* |
| @@ -228,7 +230,7 @@ macro_rules! intrinsics { | |||
| 228 | 230 | ||
| 229 | // Not exported, but defined so the actual implementation is | 231 | // Not exported, but defined so the actual implementation is |
| 230 | // considered used | 232 | // considered used |
| 231 | #[cfg(not(all(target_arch = "arm", not(feature = "disable-intrinsics"))))] | 233 | #[cfg(not(all(target_arch = "arm", feature = "intrinsics")))] |
| 232 | #[allow(dead_code)] | 234 | #[allow(dead_code)] |
| 233 | fn $name( $($argname: $ty),* ) -> $ret { | 235 | fn $name( $($argname: $ty),* ) -> $ret { |
| 234 | $($body)* | 236 | $($body)* |
| @@ -245,13 +247,13 @@ macro_rules! intrinsics { | |||
| 245 | 247 | ||
| 246 | $($rest:tt)* | 248 | $($rest:tt)* |
| 247 | ) => { | 249 | ) => { |
| 248 | #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] | 250 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] |
| 249 | $(#[$($attr)*])* | 251 | $(#[$($attr)*])* |
| 250 | unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { | 252 | unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { |
| 251 | $($body)* | 253 | $($body)* |
| 252 | } | 254 | } |
| 253 | 255 | ||
| 254 | #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] | 256 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] |
| 255 | mod $name { | 257 | mod $name { |
| 256 | #[no_mangle] | 258 | #[no_mangle] |
| 257 | $(#[$($attr)*])* | 259 | $(#[$($attr)*])* |
| @@ -262,7 +264,7 @@ macro_rules! intrinsics { | |||
| 262 | 264 | ||
| 263 | // Not exported, but defined so the actual implementation is | 265 | // Not exported, but defined so the actual implementation is |
| 264 | // considered used | 266 | // considered used |
| 265 | #[cfg(not(all(target_arch = "arm", not(feature = "disable-intrinsics"))))] | 267 | #[cfg(not(all(target_arch = "arm", feature = "intrinsics")))] |
| 266 | #[allow(dead_code)] | 268 | #[allow(dead_code)] |
| 267 | unsafe fn $name( $($argname: $ty),* ) -> $ret { | 269 | unsafe fn $name( $($argname: $ty),* ) -> $ret { |
| 268 | $($body)* | 270 | $($body)* |
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index ce013b09c..445639618 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -8,6 +8,7 @@ mod intrinsics; | |||
| 8 | 8 | ||
| 9 | pub mod dma; | 9 | pub mod dma; |
| 10 | pub mod gpio; | 10 | pub mod gpio; |
| 11 | pub mod i2c; | ||
| 11 | pub mod interrupt; | 12 | pub mod interrupt; |
| 12 | pub mod rom_data; | 13 | pub mod rom_data; |
| 13 | pub mod rtc; | 14 | pub mod rtc; |
| @@ -76,6 +77,9 @@ embassy_hal_common::peripherals! { | |||
| 76 | SPI0, | 77 | SPI0, |
| 77 | SPI1, | 78 | SPI1, |
| 78 | 79 | ||
| 80 | I2C0, | ||
| 81 | I2C1, | ||
| 82 | |||
| 79 | DMA_CH0, | 83 | DMA_CH0, |
| 80 | DMA_CH1, | 84 | DMA_CH1, |
| 81 | DMA_CH2, | 85 | DMA_CH2, |
diff --git a/embassy-rp/src/rom_data.rs b/embassy-rp/src/rom_data.rs index 93a3632a5..8e953dcf2 100644 --- a/embassy-rp/src/rom_data.rs +++ b/embassy-rp/src/rom_data.rs | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | //! > on the device, as well as highly optimized versions of certain key | 7 | //! > on the device, as well as highly optimized versions of certain key |
| 8 | //! > functionality that would otherwise have to take up space in most user | 8 | //! > functionality that would otherwise have to take up space in most user |
| 9 | //! > binaries. | 9 | //! > binaries. |
| 10 | // Credit: taken from `rp-hal` (also licensed Apache+MIT) | ||
| 11 | // https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/rom_data.rs | ||
| 10 | 12 | ||
| 11 | /// A bootrom function table code. | 13 | /// A bootrom function table code. |
| 12 | pub type RomFnTableCode = [u8; 2]; | 14 | pub type RomFnTableCode = [u8; 2]; |
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs new file mode 100644 index 000000000..87e16f0eb --- /dev/null +++ b/embassy-rp/src/uart/buffered.rs | |||
| @@ -0,0 +1,489 @@ | |||
| 1 | use core::future::{poll_fn, Future}; | ||
| 2 | use core::task::{Poll, Waker}; | ||
| 3 | |||
| 4 | use atomic_polyfill::{compiler_fence, Ordering}; | ||
| 5 | use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; | ||
| 6 | use embassy_hal_common::ring_buffer::RingBuffer; | ||
| 7 | use embassy_sync::waitqueue::WakerRegistration; | ||
| 8 | |||
| 9 | use super::*; | ||
| 10 | |||
| 11 | pub struct State<'d, T: Instance>(StateStorage<FullStateInner<'d, T>>); | ||
| 12 | impl<'d, T: Instance> State<'d, T> { | ||
| 13 | pub const fn new() -> Self { | ||
| 14 | Self(StateStorage::new()) | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | pub struct RxState<'d, T: Instance>(StateStorage<RxStateInner<'d, T>>); | ||
| 19 | impl<'d, T: Instance> RxState<'d, T> { | ||
| 20 | pub const fn new() -> Self { | ||
| 21 | Self(StateStorage::new()) | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | pub struct TxState<'d, T: Instance>(StateStorage<TxStateInner<'d, T>>); | ||
| 26 | impl<'d, T: Instance> TxState<'d, T> { | ||
| 27 | pub const fn new() -> Self { | ||
| 28 | Self(StateStorage::new()) | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | struct RxStateInner<'d, T: Instance> { | ||
| 33 | phantom: PhantomData<&'d mut T>, | ||
| 34 | |||
| 35 | waker: WakerRegistration, | ||
| 36 | buf: RingBuffer<'d>, | ||
| 37 | } | ||
| 38 | |||
| 39 | struct TxStateInner<'d, T: Instance> { | ||
| 40 | phantom: PhantomData<&'d mut T>, | ||
| 41 | |||
| 42 | waker: WakerRegistration, | ||
| 43 | buf: RingBuffer<'d>, | ||
| 44 | } | ||
| 45 | |||
| 46 | struct FullStateInner<'d, T: Instance> { | ||
| 47 | rx: RxStateInner<'d, T>, | ||
| 48 | tx: TxStateInner<'d, T>, | ||
| 49 | } | ||
| 50 | |||
| 51 | unsafe impl<'d, T: Instance> Send for RxStateInner<'d, T> {} | ||
| 52 | unsafe impl<'d, T: Instance> Sync for RxStateInner<'d, T> {} | ||
| 53 | |||
| 54 | unsafe impl<'d, T: Instance> Send for TxStateInner<'d, T> {} | ||
| 55 | unsafe impl<'d, T: Instance> Sync for TxStateInner<'d, T> {} | ||
| 56 | |||
| 57 | unsafe impl<'d, T: Instance> Send for FullStateInner<'d, T> {} | ||
| 58 | unsafe impl<'d, T: Instance> Sync for FullStateInner<'d, T> {} | ||
| 59 | |||
| 60 | pub struct BufferedUart<'d, T: Instance> { | ||
| 61 | inner: PeripheralMutex<'d, FullStateInner<'d, T>>, | ||
| 62 | } | ||
| 63 | |||
| 64 | pub struct BufferedUartRx<'d, T: Instance> { | ||
| 65 | inner: PeripheralMutex<'d, RxStateInner<'d, T>>, | ||
| 66 | } | ||
| 67 | |||
| 68 | pub struct BufferedUartTx<'d, T: Instance> { | ||
| 69 | inner: PeripheralMutex<'d, TxStateInner<'d, T>>, | ||
| 70 | } | ||
| 71 | |||
| 72 | impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} | ||
| 73 | impl<'d, T: Instance> Unpin for BufferedUartRx<'d, T> {} | ||
| 74 | impl<'d, T: Instance> Unpin for BufferedUartTx<'d, T> {} | ||
| 75 | |||
| 76 | impl<'d, T: Instance> BufferedUart<'d, T> { | ||
| 77 | pub fn new<M: Mode>( | ||
| 78 | state: &'d mut State<'d, T>, | ||
| 79 | _uart: Uart<'d, T, M>, | ||
| 80 | irq: impl Peripheral<P = T::Interrupt> + 'd, | ||
| 81 | tx_buffer: &'d mut [u8], | ||
| 82 | rx_buffer: &'d mut [u8], | ||
| 83 | ) -> BufferedUart<'d, T> { | ||
| 84 | into_ref!(irq); | ||
| 85 | |||
| 86 | let r = T::regs(); | ||
| 87 | unsafe { | ||
| 88 | r.uartimsc().modify(|w| { | ||
| 89 | w.set_rxim(true); | ||
| 90 | w.set_rtim(true); | ||
| 91 | w.set_txim(true); | ||
| 92 | }); | ||
| 93 | } | ||
| 94 | |||
| 95 | Self { | ||
| 96 | inner: PeripheralMutex::new(irq, &mut state.0, move || FullStateInner { | ||
| 97 | tx: TxStateInner { | ||
| 98 | phantom: PhantomData, | ||
| 99 | waker: WakerRegistration::new(), | ||
| 100 | buf: RingBuffer::new(tx_buffer), | ||
| 101 | }, | ||
| 102 | rx: RxStateInner { | ||
| 103 | phantom: PhantomData, | ||
| 104 | waker: WakerRegistration::new(), | ||
| 105 | buf: RingBuffer::new(rx_buffer), | ||
| 106 | }, | ||
| 107 | }), | ||
| 108 | } | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | impl<'d, T: Instance> BufferedUartRx<'d, T> { | ||
| 113 | pub fn new<M: Mode>( | ||
| 114 | state: &'d mut RxState<'d, T>, | ||
| 115 | _uart: UartRx<'d, T, M>, | ||
| 116 | irq: impl Peripheral<P = T::Interrupt> + 'd, | ||
| 117 | rx_buffer: &'d mut [u8], | ||
| 118 | ) -> BufferedUartRx<'d, T> { | ||
| 119 | into_ref!(irq); | ||
| 120 | |||
| 121 | let r = T::regs(); | ||
| 122 | unsafe { | ||
| 123 | r.uartimsc().modify(|w| { | ||
| 124 | w.set_rxim(true); | ||
| 125 | w.set_rtim(true); | ||
| 126 | }); | ||
| 127 | } | ||
| 128 | |||
| 129 | Self { | ||
| 130 | inner: PeripheralMutex::new(irq, &mut state.0, move || RxStateInner { | ||
| 131 | phantom: PhantomData, | ||
| 132 | |||
| 133 | buf: RingBuffer::new(rx_buffer), | ||
| 134 | waker: WakerRegistration::new(), | ||
| 135 | }), | ||
| 136 | } | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | impl<'d, T: Instance> BufferedUartTx<'d, T> { | ||
| 141 | pub fn new<M: Mode>( | ||
| 142 | state: &'d mut TxState<'d, T>, | ||
| 143 | _uart: UartTx<'d, T, M>, | ||
| 144 | irq: impl Peripheral<P = T::Interrupt> + 'd, | ||
| 145 | tx_buffer: &'d mut [u8], | ||
| 146 | ) -> BufferedUartTx<'d, T> { | ||
| 147 | into_ref!(irq); | ||
| 148 | |||
| 149 | let r = T::regs(); | ||
| 150 | unsafe { | ||
| 151 | r.uartimsc().modify(|w| { | ||
| 152 | w.set_txim(true); | ||
| 153 | }); | ||
| 154 | } | ||
| 155 | |||
| 156 | Self { | ||
| 157 | inner: PeripheralMutex::new(irq, &mut state.0, move || TxStateInner { | ||
| 158 | phantom: PhantomData, | ||
| 159 | |||
| 160 | buf: RingBuffer::new(tx_buffer), | ||
| 161 | waker: WakerRegistration::new(), | ||
| 162 | }), | ||
| 163 | } | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | impl<'d, T: Instance> PeripheralState for FullStateInner<'d, T> | ||
| 168 | where | ||
| 169 | Self: 'd, | ||
| 170 | { | ||
| 171 | type Interrupt = T::Interrupt; | ||
| 172 | fn on_interrupt(&mut self) { | ||
| 173 | self.rx.on_interrupt(); | ||
| 174 | self.tx.on_interrupt(); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | impl<'d, T: Instance> RxStateInner<'d, T> | ||
| 179 | where | ||
| 180 | Self: 'd, | ||
| 181 | { | ||
| 182 | fn read(&mut self, buf: &mut [u8], waker: &Waker) -> (Poll<Result<usize, Error>>, bool) { | ||
| 183 | // We have data ready in buffer? Return it. | ||
| 184 | let mut do_pend = false; | ||
| 185 | let data = self.buf.pop_buf(); | ||
| 186 | if !data.is_empty() { | ||
| 187 | let len = data.len().min(buf.len()); | ||
| 188 | buf[..len].copy_from_slice(&data[..len]); | ||
| 189 | |||
| 190 | if self.buf.is_full() { | ||
| 191 | do_pend = true; | ||
| 192 | } | ||
| 193 | self.buf.pop(len); | ||
| 194 | |||
| 195 | return (Poll::Ready(Ok(len)), do_pend); | ||
| 196 | } | ||
| 197 | |||
| 198 | self.waker.register(waker); | ||
| 199 | (Poll::Pending, do_pend) | ||
| 200 | } | ||
| 201 | |||
| 202 | fn fill_buf<'a>(&mut self, waker: &Waker) -> Poll<Result<&'a [u8], Error>> { | ||
| 203 | // We have data ready in buffer? Return it. | ||
| 204 | let buf = self.buf.pop_buf(); | ||
| 205 | if !buf.is_empty() { | ||
| 206 | let buf: &[u8] = buf; | ||
| 207 | // Safety: buffer lives as long as uart | ||
| 208 | let buf: &[u8] = unsafe { core::mem::transmute(buf) }; | ||
| 209 | return Poll::Ready(Ok(buf)); | ||
| 210 | } | ||
| 211 | |||
| 212 | self.waker.register(waker); | ||
| 213 | Poll::Pending | ||
| 214 | } | ||
| 215 | |||
| 216 | fn consume(&mut self, amt: usize) -> bool { | ||
| 217 | let full = self.buf.is_full(); | ||
| 218 | self.buf.pop(amt); | ||
| 219 | full | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | impl<'d, T: Instance> PeripheralState for RxStateInner<'d, T> | ||
| 224 | where | ||
| 225 | Self: 'd, | ||
| 226 | { | ||
| 227 | type Interrupt = T::Interrupt; | ||
| 228 | fn on_interrupt(&mut self) { | ||
| 229 | let r = T::regs(); | ||
| 230 | unsafe { | ||
| 231 | let ris = r.uartris().read(); | ||
| 232 | // Clear interrupt flags | ||
| 233 | r.uarticr().modify(|w| { | ||
| 234 | w.set_rxic(true); | ||
| 235 | w.set_rtic(true); | ||
| 236 | }); | ||
| 237 | |||
| 238 | if ris.peris() { | ||
| 239 | warn!("Parity error"); | ||
| 240 | r.uarticr().modify(|w| { | ||
| 241 | w.set_peic(true); | ||
| 242 | }); | ||
| 243 | } | ||
| 244 | if ris.feris() { | ||
| 245 | warn!("Framing error"); | ||
| 246 | r.uarticr().modify(|w| { | ||
| 247 | w.set_feic(true); | ||
| 248 | }); | ||
| 249 | } | ||
| 250 | if ris.beris() { | ||
| 251 | warn!("Break error"); | ||
| 252 | r.uarticr().modify(|w| { | ||
| 253 | w.set_beic(true); | ||
| 254 | }); | ||
| 255 | } | ||
| 256 | if ris.oeris() { | ||
| 257 | warn!("Overrun error"); | ||
| 258 | r.uarticr().modify(|w| { | ||
| 259 | w.set_oeic(true); | ||
| 260 | }); | ||
| 261 | } | ||
| 262 | |||
| 263 | if !r.uartfr().read().rxfe() { | ||
| 264 | let buf = self.buf.push_buf(); | ||
| 265 | if !buf.is_empty() { | ||
| 266 | buf[0] = r.uartdr().read().data(); | ||
| 267 | self.buf.push(1); | ||
| 268 | } else { | ||
| 269 | warn!("RX buffer full, discard received byte"); | ||
| 270 | } | ||
| 271 | |||
| 272 | if self.buf.is_full() { | ||
| 273 | self.waker.wake(); | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | if ris.rtris() { | ||
| 278 | self.waker.wake(); | ||
| 279 | }; | ||
| 280 | } | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | impl<'d, T: Instance> TxStateInner<'d, T> | ||
| 285 | where | ||
| 286 | Self: 'd, | ||
| 287 | { | ||
| 288 | fn write(&mut self, buf: &[u8], waker: &Waker) -> (Poll<Result<usize, Error>>, bool) { | ||
| 289 | let empty = self.buf.is_empty(); | ||
| 290 | let tx_buf = self.buf.push_buf(); | ||
| 291 | if tx_buf.is_empty() { | ||
| 292 | self.waker.register(waker); | ||
| 293 | return (Poll::Pending, empty); | ||
| 294 | } | ||
| 295 | |||
| 296 | let n = core::cmp::min(tx_buf.len(), buf.len()); | ||
| 297 | tx_buf[..n].copy_from_slice(&buf[..n]); | ||
| 298 | self.buf.push(n); | ||
| 299 | |||
| 300 | (Poll::Ready(Ok(n)), empty) | ||
| 301 | } | ||
| 302 | |||
| 303 | fn flush(&mut self, waker: &Waker) -> Poll<Result<(), Error>> { | ||
| 304 | if !self.buf.is_empty() { | ||
| 305 | self.waker.register(waker); | ||
| 306 | return Poll::Pending; | ||
| 307 | } | ||
| 308 | |||
| 309 | Poll::Ready(Ok(())) | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | impl<'d, T: Instance> PeripheralState for TxStateInner<'d, T> | ||
| 314 | where | ||
| 315 | Self: 'd, | ||
| 316 | { | ||
| 317 | type Interrupt = T::Interrupt; | ||
| 318 | fn on_interrupt(&mut self) { | ||
| 319 | let r = T::regs(); | ||
| 320 | unsafe { | ||
| 321 | let buf = self.buf.pop_buf(); | ||
| 322 | if !buf.is_empty() { | ||
| 323 | r.uartimsc().modify(|w| { | ||
| 324 | w.set_txim(true); | ||
| 325 | }); | ||
| 326 | r.uartdr().write(|w| w.set_data(buf[0].into())); | ||
| 327 | self.buf.pop(1); | ||
| 328 | self.waker.wake(); | ||
| 329 | } else { | ||
| 330 | // Disable interrupt until we have something to transmit again | ||
| 331 | r.uartimsc().modify(|w| { | ||
| 332 | w.set_txim(false); | ||
| 333 | }); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | impl embedded_io::Error for Error { | ||
| 340 | fn kind(&self) -> embedded_io::ErrorKind { | ||
| 341 | embedded_io::ErrorKind::Other | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> { | ||
| 346 | type Error = Error; | ||
| 347 | } | ||
| 348 | |||
| 349 | impl<'d, T: Instance> embedded_io::Io for BufferedUartRx<'d, T> { | ||
| 350 | type Error = Error; | ||
| 351 | } | ||
| 352 | |||
| 353 | impl<'d, T: Instance> embedded_io::Io for BufferedUartTx<'d, T> { | ||
| 354 | type Error = Error; | ||
| 355 | } | ||
| 356 | |||
| 357 | impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> { | ||
| 358 | type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 359 | where | ||
| 360 | Self: 'a; | ||
| 361 | |||
| 362 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 363 | poll_fn(move |cx| { | ||
| 364 | let (res, do_pend) = self.inner.with(|state| { | ||
| 365 | compiler_fence(Ordering::SeqCst); | ||
| 366 | state.rx.read(buf, cx.waker()) | ||
| 367 | }); | ||
| 368 | |||
| 369 | if do_pend { | ||
| 370 | self.inner.pend(); | ||
| 371 | } | ||
| 372 | |||
| 373 | res | ||
| 374 | }) | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUartRx<'d, T> { | ||
| 379 | type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 380 | where | ||
| 381 | Self: 'a; | ||
| 382 | |||
| 383 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 384 | poll_fn(move |cx| { | ||
| 385 | let (res, do_pend) = self.inner.with(|state| { | ||
| 386 | compiler_fence(Ordering::SeqCst); | ||
| 387 | state.read(buf, cx.waker()) | ||
| 388 | }); | ||
| 389 | |||
| 390 | if do_pend { | ||
| 391 | self.inner.pend(); | ||
| 392 | } | ||
| 393 | |||
| 394 | res | ||
| 395 | }) | ||
| 396 | } | ||
| 397 | } | ||
| 398 | |||
| 399 | impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T> { | ||
| 400 | type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> | ||
| 401 | where | ||
| 402 | Self: 'a; | ||
| 403 | |||
| 404 | fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> { | ||
| 405 | poll_fn(move |cx| { | ||
| 406 | self.inner.with(|state| { | ||
| 407 | compiler_fence(Ordering::SeqCst); | ||
| 408 | state.rx.fill_buf(cx.waker()) | ||
| 409 | }) | ||
| 410 | }) | ||
| 411 | } | ||
| 412 | |||
| 413 | fn consume(&mut self, amt: usize) { | ||
| 414 | let signal = self.inner.with(|state| state.rx.consume(amt)); | ||
| 415 | if signal { | ||
| 416 | self.inner.pend(); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 421 | impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUartRx<'d, T> { | ||
| 422 | type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> | ||
| 423 | where | ||
| 424 | Self: 'a; | ||
| 425 | |||
| 426 | fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> { | ||
| 427 | poll_fn(move |cx| { | ||
| 428 | self.inner.with(|state| { | ||
| 429 | compiler_fence(Ordering::SeqCst); | ||
| 430 | state.fill_buf(cx.waker()) | ||
| 431 | }) | ||
| 432 | }) | ||
| 433 | } | ||
| 434 | |||
| 435 | fn consume(&mut self, amt: usize) { | ||
| 436 | let signal = self.inner.with(|state| state.consume(amt)); | ||
| 437 | if signal { | ||
| 438 | self.inner.pend(); | ||
| 439 | } | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> { | ||
| 444 | type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 445 | where | ||
| 446 | Self: 'a; | ||
| 447 | |||
| 448 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 449 | poll_fn(move |cx| { | ||
| 450 | let (poll, empty) = self.inner.with(|state| state.tx.write(buf, cx.waker())); | ||
| 451 | if empty { | ||
| 452 | self.inner.pend(); | ||
| 453 | } | ||
| 454 | poll | ||
| 455 | }) | ||
| 456 | } | ||
| 457 | |||
| 458 | type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> | ||
| 459 | where | ||
| 460 | Self: 'a; | ||
| 461 | |||
| 462 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 463 | poll_fn(move |cx| self.inner.with(|state| state.tx.flush(cx.waker()))) | ||
| 464 | } | ||
| 465 | } | ||
| 466 | |||
| 467 | impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T> { | ||
| 468 | type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> | ||
| 469 | where | ||
| 470 | Self: 'a; | ||
| 471 | |||
| 472 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 473 | poll_fn(move |cx| { | ||
| 474 | let (poll, empty) = self.inner.with(|state| state.write(buf, cx.waker())); | ||
| 475 | if empty { | ||
| 476 | self.inner.pend(); | ||
| 477 | } | ||
| 478 | poll | ||
| 479 | }) | ||
| 480 | } | ||
| 481 | |||
| 482 | type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> | ||
| 483 | where | ||
| 484 | Self: 'a; | ||
| 485 | |||
| 486 | fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { | ||
| 487 | poll_fn(move |cx| self.inner.with(|state| state.flush(cx.waker()))) | ||
| 488 | } | ||
| 489 | } | ||
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart/mod.rs index 987b716b4..567c79db3 100644 --- a/embassy-rp/src/uart.rs +++ b/embassy-rp/src/uart/mod.rs | |||
| @@ -346,6 +346,11 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> { | |||
| 346 | w.set_fen(true); | 346 | w.set_fen(true); |
| 347 | }); | 347 | }); |
| 348 | 348 | ||
| 349 | r.uartifls().write(|w| { | ||
| 350 | w.set_rxiflsel(0b000); | ||
| 351 | w.set_txiflsel(0b000); | ||
| 352 | }); | ||
| 353 | |||
| 349 | r.uartcr().write(|w| { | 354 | r.uartcr().write(|w| { |
| 350 | w.set_uarten(true); | 355 | w.set_uarten(true); |
| 351 | w.set_rxe(true); | 356 | w.set_rxe(true); |
| @@ -423,9 +428,11 @@ mod eh02 { | |||
| 423 | 428 | ||
| 424 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> { | 429 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> { |
| 425 | type Error = Error; | 430 | type Error = Error; |
| 431 | |||
| 426 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 432 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 427 | self.blocking_write(buffer) | 433 | self.blocking_write(buffer) |
| 428 | } | 434 | } |
| 435 | |||
| 429 | fn bflush(&mut self) -> Result<(), Self::Error> { | 436 | fn bflush(&mut self) -> Result<(), Self::Error> { |
| 430 | self.blocking_flush() | 437 | self.blocking_flush() |
| 431 | } | 438 | } |
| @@ -433,6 +440,7 @@ mod eh02 { | |||
| 433 | 440 | ||
| 434 | impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> { | 441 | impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> { |
| 435 | type Error = Error; | 442 | type Error = Error; |
| 443 | |||
| 436 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 444 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 437 | embedded_hal_02::serial::Read::read(&mut self.rx) | 445 | embedded_hal_02::serial::Read::read(&mut self.rx) |
| 438 | } | 446 | } |
| @@ -440,9 +448,11 @@ mod eh02 { | |||
| 440 | 448 | ||
| 441 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> { | 449 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> { |
| 442 | type Error = Error; | 450 | type Error = Error; |
| 451 | |||
| 443 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 452 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 444 | self.blocking_write(buffer) | 453 | self.blocking_write(buffer) |
| 445 | } | 454 | } |
| 455 | |||
| 446 | fn bflush(&mut self) -> Result<(), Self::Error> { | 456 | fn bflush(&mut self) -> Result<(), Self::Error> { |
| 447 | self.blocking_flush() | 457 | self.blocking_flush() |
| 448 | } | 458 | } |
| @@ -475,6 +485,75 @@ mod eh1 { | |||
| 475 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> { | 485 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> { |
| 476 | type Error = Error; | 486 | type Error = Error; |
| 477 | } | 487 | } |
| 488 | |||
| 489 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Read for UartRx<'d, T, M> { | ||
| 490 | fn read(&mut self) -> nb::Result<u8, Self::Error> { | ||
| 491 | let r = T::regs(); | ||
| 492 | unsafe { | ||
| 493 | let dr = r.uartdr().read(); | ||
| 494 | |||
| 495 | if dr.oe() { | ||
| 496 | Err(nb::Error::Other(Error::Overrun)) | ||
| 497 | } else if dr.be() { | ||
| 498 | Err(nb::Error::Other(Error::Break)) | ||
| 499 | } else if dr.pe() { | ||
| 500 | Err(nb::Error::Other(Error::Parity)) | ||
| 501 | } else if dr.fe() { | ||
| 502 | Err(nb::Error::Other(Error::Framing)) | ||
| 503 | } else if dr.fe() { | ||
| 504 | Ok(dr.data()) | ||
| 505 | } else { | ||
| 506 | Err(nb::Error::WouldBlock) | ||
| 507 | } | ||
| 508 | } | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::blocking::Write for UartTx<'d, T, M> { | ||
| 513 | fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 514 | self.blocking_write(buffer) | ||
| 515 | } | ||
| 516 | |||
| 517 | fn flush(&mut self) -> Result<(), Self::Error> { | ||
| 518 | self.blocking_flush() | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Write for UartTx<'d, T, M> { | ||
| 523 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | ||
| 524 | self.blocking_write(&[char]).map_err(nb::Error::Other) | ||
| 525 | } | ||
| 526 | |||
| 527 | fn flush(&mut self) -> nb::Result<(), Self::Error> { | ||
| 528 | self.blocking_flush().map_err(nb::Error::Other) | ||
| 529 | } | ||
| 530 | } | ||
| 531 | |||
| 532 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Read for Uart<'d, T, M> { | ||
| 533 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | ||
| 534 | embedded_hal_02::serial::Read::read(&mut self.rx) | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::blocking::Write for Uart<'d, T, M> { | ||
| 539 | fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | ||
| 540 | self.blocking_write(buffer) | ||
| 541 | } | ||
| 542 | |||
| 543 | fn flush(&mut self) -> Result<(), Self::Error> { | ||
| 544 | self.blocking_flush() | ||
| 545 | } | ||
| 546 | } | ||
| 547 | |||
| 548 | impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Write for Uart<'d, T, M> { | ||
| 549 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | ||
| 550 | self.blocking_write(&[char]).map_err(nb::Error::Other) | ||
| 551 | } | ||
| 552 | |||
| 553 | fn flush(&mut self) -> nb::Result<(), Self::Error> { | ||
| 554 | self.blocking_flush().map_err(nb::Error::Other) | ||
| 555 | } | ||
| 556 | } | ||
| 478 | } | 557 | } |
| 479 | 558 | ||
| 480 | #[cfg(all( | 559 | #[cfg(all( |
| @@ -532,6 +611,11 @@ mod eha { | |||
| 532 | } | 611 | } |
| 533 | } | 612 | } |
| 534 | 613 | ||
| 614 | #[cfg(feature = "nightly")] | ||
| 615 | mod buffered; | ||
| 616 | #[cfg(feature = "nightly")] | ||
| 617 | pub use buffered::*; | ||
| 618 | |||
| 535 | mod sealed { | 619 | mod sealed { |
| 536 | use super::*; | 620 | use super::*; |
| 537 | 621 | ||
| @@ -541,6 +625,8 @@ mod sealed { | |||
| 541 | const TX_DREQ: u8; | 625 | const TX_DREQ: u8; |
| 542 | const RX_DREQ: u8; | 626 | const RX_DREQ: u8; |
| 543 | 627 | ||
| 628 | type Interrupt: crate::interrupt::Interrupt; | ||
| 629 | |||
| 544 | fn regs() -> pac::uart::Uart; | 630 | fn regs() -> pac::uart::Uart; |
| 545 | } | 631 | } |
| 546 | pub trait TxPin<T: Instance> {} | 632 | pub trait TxPin<T: Instance> {} |
| @@ -572,6 +658,8 @@ macro_rules! impl_instance { | |||
| 572 | const TX_DREQ: u8 = $tx_dreq; | 658 | const TX_DREQ: u8 = $tx_dreq; |
| 573 | const RX_DREQ: u8 = $rx_dreq; | 659 | const RX_DREQ: u8 = $rx_dreq; |
| 574 | 660 | ||
| 661 | type Interrupt = crate::interrupt::$irq; | ||
| 662 | |||
| 575 | fn regs() -> pac::uart::Uart { | 663 | fn regs() -> pac::uart::Uart { |
| 576 | pac::$inst | 664 | pac::$inst |
| 577 | } | 665 | } |
| @@ -580,8 +668,8 @@ macro_rules! impl_instance { | |||
| 580 | }; | 668 | }; |
| 581 | } | 669 | } |
| 582 | 670 | ||
| 583 | impl_instance!(UART0, UART0, 20, 21); | 671 | impl_instance!(UART0, UART0_IRQ, 20, 21); |
| 584 | impl_instance!(UART1, UART1, 22, 23); | 672 | impl_instance!(UART1, UART1_IRQ, 22, 23); |
| 585 | 673 | ||
| 586 | pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} | 674 | pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} |
| 587 | pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} | 675 | pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} |
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index a7ec5fb79..0a904aab3 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs | |||
| @@ -7,8 +7,10 @@ use core::task::Poll; | |||
| 7 | use atomic_polyfill::compiler_fence; | 7 | use atomic_polyfill::compiler_fence; |
| 8 | use embassy_hal_common::into_ref; | 8 | use embassy_hal_common::into_ref; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; | 10 | use embassy_usb_driver as driver; |
| 11 | use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; | 11 | use embassy_usb_driver::{ |
| 12 | Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, | ||
| 13 | }; | ||
| 12 | 14 | ||
| 13 | use crate::interrupt::{Interrupt, InterruptExt}; | 15 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 14 | use crate::{pac, peripherals, Peripheral, RegExt}; | 16 | use crate::{pac, peripherals, Peripheral, RegExt}; |
| @@ -204,8 +206,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 204 | ); | 206 | ); |
| 205 | 207 | ||
| 206 | let alloc = match D::dir() { | 208 | let alloc = match D::dir() { |
| 207 | UsbDirection::Out => &mut self.ep_out, | 209 | Direction::Out => &mut self.ep_out, |
| 208 | UsbDirection::In => &mut self.ep_in, | 210 | Direction::In => &mut self.ep_in, |
| 209 | }; | 211 | }; |
| 210 | 212 | ||
| 211 | let index = alloc.iter_mut().enumerate().find(|(i, ep)| { | 213 | let index = alloc.iter_mut().enumerate().find(|(i, ep)| { |
| @@ -254,7 +256,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 254 | }; | 256 | }; |
| 255 | 257 | ||
| 256 | match D::dir() { | 258 | match D::dir() { |
| 257 | UsbDirection::Out => unsafe { | 259 | Direction::Out => unsafe { |
| 258 | T::dpram().ep_out_control(index - 1).write(|w| { | 260 | T::dpram().ep_out_control(index - 1).write(|w| { |
| 259 | w.set_enable(false); | 261 | w.set_enable(false); |
| 260 | w.set_buffer_address(addr); | 262 | w.set_buffer_address(addr); |
| @@ -262,7 +264,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 262 | w.set_endpoint_type(ep_type_reg); | 264 | w.set_endpoint_type(ep_type_reg); |
| 263 | }) | 265 | }) |
| 264 | }, | 266 | }, |
| 265 | UsbDirection::In => unsafe { | 267 | Direction::In => unsafe { |
| 266 | T::dpram().ep_in_control(index - 1).write(|w| { | 268 | T::dpram().ep_in_control(index - 1).write(|w| { |
| 267 | w.set_enable(false); | 269 | w.set_enable(false); |
| 268 | w.set_buffer_address(addr); | 270 | w.set_buffer_address(addr); |
| @@ -429,14 +431,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 429 | 431 | ||
| 430 | let n = ep_addr.index(); | 432 | let n = ep_addr.index(); |
| 431 | match ep_addr.direction() { | 433 | match ep_addr.direction() { |
| 432 | UsbDirection::In => unsafe { | 434 | Direction::In => unsafe { |
| 433 | T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); | 435 | T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); |
| 434 | T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { | 436 | T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { |
| 435 | w.set_pid(0, true); // first packet is DATA0, but PID is flipped before | 437 | w.set_pid(0, true); // first packet is DATA0, but PID is flipped before |
| 436 | }); | 438 | }); |
| 437 | EP_IN_WAKERS[n].wake(); | 439 | EP_IN_WAKERS[n].wake(); |
| 438 | }, | 440 | }, |
| 439 | UsbDirection::Out => unsafe { | 441 | Direction::Out => unsafe { |
| 440 | T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); | 442 | T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); |
| 441 | 443 | ||
| 442 | T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { | 444 | T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { |
| @@ -474,14 +476,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 474 | } | 476 | } |
| 475 | 477 | ||
| 476 | trait Dir { | 478 | trait Dir { |
| 477 | fn dir() -> UsbDirection; | 479 | fn dir() -> Direction; |
| 478 | fn waker(i: usize) -> &'static AtomicWaker; | 480 | fn waker(i: usize) -> &'static AtomicWaker; |
| 479 | } | 481 | } |
| 480 | 482 | ||
| 481 | pub enum In {} | 483 | pub enum In {} |
| 482 | impl Dir for In { | 484 | impl Dir for In { |
| 483 | fn dir() -> UsbDirection { | 485 | fn dir() -> Direction { |
| 484 | UsbDirection::In | 486 | Direction::In |
| 485 | } | 487 | } |
| 486 | 488 | ||
| 487 | #[inline] | 489 | #[inline] |
| @@ -492,8 +494,8 @@ impl Dir for In { | |||
| 492 | 494 | ||
| 493 | pub enum Out {} | 495 | pub enum Out {} |
| 494 | impl Dir for Out { | 496 | impl Dir for Out { |
| 495 | fn dir() -> UsbDirection { | 497 | fn dir() -> Direction { |
| 496 | UsbDirection::Out | 498 | Direction::Out |
| 497 | } | 499 | } |
| 498 | 500 | ||
| 499 | #[inline] | 501 | #[inline] |
