aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-09-29 10:00:13 +0200
committerMathias <[email protected]>2022-09-29 10:00:13 +0200
commit7ee7109508b463f98ea9ae08e061aeaca28016e6 (patch)
tree50723244067224c6c32603e21fbe8ec36c76898e /embassy-rp/src
parent18dc0dea636daa6e48aa9208b5a74cdfedc8b513 (diff)
parent77ece3f903735b50f265ddd43520c50e0f28c1a1 (diff)
Rebase on master
Diffstat (limited to 'embassy-rp/src')
-rw-r--r--embassy-rp/src/i2c.rs556
-rw-r--r--embassy-rp/src/intrinsics.rs20
-rw-r--r--embassy-rp/src/lib.rs4
-rw-r--r--embassy-rp/src/rom_data.rs2
-rw-r--r--embassy-rp/src/uart/buffered.rs489
-rw-r--r--embassy-rp/src/uart/mod.rs (renamed from embassy-rp/src/uart.rs)92
-rw-r--r--embassy-rp/src/usb.rs28
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 @@
1use core::marker::PhantomData;
2
3use embassy_hal_common::{into_ref, PeripheralRef};
4use pac::i2c;
5
6use crate::dma::AnyChannel;
7use crate::gpio::sealed::Pin;
8use crate::gpio::AnyPin;
9use crate::{pac, peripherals, Peripheral};
10
11/// I2C error abort reason
12#[derive(Debug)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14pub 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))]
27pub 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)]
42pub struct Config {
43 pub frequency: u32,
44}
45
46impl Default for Config {
47 fn default() -> Self {
48 Self { frequency: 100_000 }
49 }
50}
51
52const FIFO_SIZE: u8 = 16;
53
54pub 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
61impl<'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
73impl<'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
330mod 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")]
359mod 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
459fn i2c_reserved_addr(addr: u16) -> bool {
460 (addr & 0x78) == 0 || (addr & 0x78) == 0x78
461}
462
463mod 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
481pub trait Mode: sealed::Mode {}
482
483macro_rules! impl_mode {
484 ($name:ident) => {
485 impl sealed::Mode for $name {}
486 impl Mode for $name {}
487 };
488}
489
490pub struct Blocking;
491pub struct Async;
492
493impl_mode!(Blocking);
494impl_mode!(Async);
495
496pub trait Instance: sealed::Instance {}
497
498macro_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
514impl_instance!(I2C0, I2C0_IRQ, 32, 33);
515impl_instance!(I2C1, I2C1_IRQ, 34, 35);
516
517pub trait SdaPin<T: Instance>: sealed::SdaPin<T> + crate::gpio::Pin {}
518pub trait SclPin<T: Instance>: sealed::SclPin<T> + crate::gpio::Pin {}
519
520macro_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
527impl_pin!(PIN_0, I2C0, SdaPin);
528impl_pin!(PIN_1, I2C0, SclPin);
529impl_pin!(PIN_2, I2C1, SdaPin);
530impl_pin!(PIN_3, I2C1, SclPin);
531impl_pin!(PIN_4, I2C0, SdaPin);
532impl_pin!(PIN_5, I2C0, SclPin);
533impl_pin!(PIN_6, I2C1, SdaPin);
534impl_pin!(PIN_7, I2C1, SclPin);
535impl_pin!(PIN_8, I2C0, SdaPin);
536impl_pin!(PIN_9, I2C0, SclPin);
537impl_pin!(PIN_10, I2C1, SdaPin);
538impl_pin!(PIN_11, I2C1, SclPin);
539impl_pin!(PIN_12, I2C0, SdaPin);
540impl_pin!(PIN_13, I2C0, SclPin);
541impl_pin!(PIN_14, I2C1, SdaPin);
542impl_pin!(PIN_15, I2C1, SclPin);
543impl_pin!(PIN_16, I2C0, SdaPin);
544impl_pin!(PIN_17, I2C0, SclPin);
545impl_pin!(PIN_18, I2C1, SdaPin);
546impl_pin!(PIN_19, I2C1, SclPin);
547impl_pin!(PIN_20, I2C0, SdaPin);
548impl_pin!(PIN_21, I2C0, SclPin);
549impl_pin!(PIN_22, I2C1, SdaPin);
550impl_pin!(PIN_23, I2C1, SclPin);
551impl_pin!(PIN_24, I2C0, SdaPin);
552impl_pin!(PIN_25, I2C0, SclPin);
553impl_pin!(PIN_26, I2C1, SdaPin);
554impl_pin!(PIN_27, I2C1, SclPin);
555impl_pin!(PIN_28, I2C0, SdaPin);
556impl_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.
4macro_rules! intrinsics_aliases { 6macro_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
9pub mod dma; 9pub mod dma;
10pub mod gpio; 10pub mod gpio;
11pub mod i2c;
11pub mod interrupt; 12pub mod interrupt;
12pub mod rom_data; 13pub mod rom_data;
13pub mod rtc; 14pub 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.
12pub type RomFnTableCode = [u8; 2]; 14pub 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 @@
1use core::future::{poll_fn, Future};
2use core::task::{Poll, Waker};
3
4use atomic_polyfill::{compiler_fence, Ordering};
5use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
6use embassy_hal_common::ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::WakerRegistration;
8
9use super::*;
10
11pub struct State<'d, T: Instance>(StateStorage<FullStateInner<'d, T>>);
12impl<'d, T: Instance> State<'d, T> {
13 pub const fn new() -> Self {
14 Self(StateStorage::new())
15 }
16}
17
18pub struct RxState<'d, T: Instance>(StateStorage<RxStateInner<'d, T>>);
19impl<'d, T: Instance> RxState<'d, T> {
20 pub const fn new() -> Self {
21 Self(StateStorage::new())
22 }
23}
24
25pub struct TxState<'d, T: Instance>(StateStorage<TxStateInner<'d, T>>);
26impl<'d, T: Instance> TxState<'d, T> {
27 pub const fn new() -> Self {
28 Self(StateStorage::new())
29 }
30}
31
32struct RxStateInner<'d, T: Instance> {
33 phantom: PhantomData<&'d mut T>,
34
35 waker: WakerRegistration,
36 buf: RingBuffer<'d>,
37}
38
39struct TxStateInner<'d, T: Instance> {
40 phantom: PhantomData<&'d mut T>,
41
42 waker: WakerRegistration,
43 buf: RingBuffer<'d>,
44}
45
46struct FullStateInner<'d, T: Instance> {
47 rx: RxStateInner<'d, T>,
48 tx: TxStateInner<'d, T>,
49}
50
51unsafe impl<'d, T: Instance> Send for RxStateInner<'d, T> {}
52unsafe impl<'d, T: Instance> Sync for RxStateInner<'d, T> {}
53
54unsafe impl<'d, T: Instance> Send for TxStateInner<'d, T> {}
55unsafe impl<'d, T: Instance> Sync for TxStateInner<'d, T> {}
56
57unsafe impl<'d, T: Instance> Send for FullStateInner<'d, T> {}
58unsafe impl<'d, T: Instance> Sync for FullStateInner<'d, T> {}
59
60pub struct BufferedUart<'d, T: Instance> {
61 inner: PeripheralMutex<'d, FullStateInner<'d, T>>,
62}
63
64pub struct BufferedUartRx<'d, T: Instance> {
65 inner: PeripheralMutex<'d, RxStateInner<'d, T>>,
66}
67
68pub struct BufferedUartTx<'d, T: Instance> {
69 inner: PeripheralMutex<'d, TxStateInner<'d, T>>,
70}
71
72impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {}
73impl<'d, T: Instance> Unpin for BufferedUartRx<'d, T> {}
74impl<'d, T: Instance> Unpin for BufferedUartTx<'d, T> {}
75
76impl<'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
112impl<'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
140impl<'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
167impl<'d, T: Instance> PeripheralState for FullStateInner<'d, T>
168where
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
178impl<'d, T: Instance> RxStateInner<'d, T>
179where
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
223impl<'d, T: Instance> PeripheralState for RxStateInner<'d, T>
224where
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
284impl<'d, T: Instance> TxStateInner<'d, T>
285where
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
313impl<'d, T: Instance> PeripheralState for TxStateInner<'d, T>
314where
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
339impl embedded_io::Error for Error {
340 fn kind(&self) -> embedded_io::ErrorKind {
341 embedded_io::ErrorKind::Other
342 }
343}
344
345impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> {
346 type Error = Error;
347}
348
349impl<'d, T: Instance> embedded_io::Io for BufferedUartRx<'d, T> {
350 type Error = Error;
351}
352
353impl<'d, T: Instance> embedded_io::Io for BufferedUartTx<'d, T> {
354 type Error = Error;
355}
356
357impl<'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
378impl<'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
399impl<'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
421impl<'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
443impl<'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
467impl<'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")]
615mod buffered;
616#[cfg(feature = "nightly")]
617pub use buffered::*;
618
535mod sealed { 619mod 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
583impl_instance!(UART0, UART0, 20, 21); 671impl_instance!(UART0, UART0_IRQ, 20, 21);
584impl_instance!(UART1, UART1, 22, 23); 672impl_instance!(UART1, UART1_IRQ, 22, 23);
585 673
586pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 674pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
587pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 675pub 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;
7use atomic_polyfill::compiler_fence; 7use atomic_polyfill::compiler_fence;
8use embassy_hal_common::into_ref; 8use embassy_hal_common::into_ref;
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; 10use embassy_usb_driver as driver;
11use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 11use embassy_usb_driver::{
12 Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
13};
12 14
13use crate::interrupt::{Interrupt, InterruptExt}; 15use crate::interrupt::{Interrupt, InterruptExt};
14use crate::{pac, peripherals, Peripheral, RegExt}; 16use 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
476trait Dir { 478trait 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
481pub enum In {} 483pub enum In {}
482impl Dir for In { 484impl 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
493pub enum Out {} 495pub enum Out {}
494impl Dir for Out { 496impl 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]