aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-06-25 23:45:01 +0000
committerGitHub <[email protected]>2022-06-25 23:45:01 +0000
commitffc32d3ddb5840b476a473c0248e32f7b9a8a212 (patch)
tree1133ce22c290e669d85d35b639ba6421dfcb9d3b
parentc460af62e0648850484368d5d4984ddf9a2ade7a (diff)
parent0beea82f407d961b43f8923b37c00e87a34eaf13 (diff)
Merge #833
833: nrf/uart: add support for tx-only and rx-only uart. r=Dirbaio a=Dirbaio Allow creating UarteRx/UarteTx directly. This allows using uart unidirectionally (rx-only or tx-only), without having to 'waste' a pin for the unused direction. Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-nrf/src/uarte.rs176
1 files changed, 149 insertions, 27 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index f626c62a5..459c56c8e 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -19,9 +19,10 @@ use core::task::Poll;
19 19
20use embassy_hal_common::drop::OnDrop; 20use embassy_hal_common::drop::OnDrop;
21use embassy_hal_common::unborrow; 21use embassy_hal_common::unborrow;
22use futures::future::poll_fn; // Re-export SVD variants to allow user to directly set values. 22use futures::future::poll_fn;
23pub use pac::uarte0::baudrate::BAUDRATE_A as Baudrate; 23use pac::uarte0::RegisterBlock;
24pub use pac::uarte0::config::PARITY_A as Parity; 24// Re-export SVD variants to allow user to directly set values.
25pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
25 26
26use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 27use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
27use crate::gpio::sealed::Pin as _; 28use crate::gpio::sealed::Pin as _;
@@ -32,6 +33,7 @@ use crate::timer::{Frequency, Instance as TimerInstance, Timer};
32use crate::util::slice_in_ram_or; 33use crate::util::slice_in_ram_or;
33use crate::{pac, Unborrow}; 34use crate::{pac, Unborrow};
34 35
36#[derive(Clone)]
35#[non_exhaustive] 37#[non_exhaustive]
36pub struct Config { 38pub struct Config {
37 pub parity: Parity, 39 pub parity: Parity,
@@ -144,37 +146,18 @@ impl<'d, T: Instance> Uarte<'d, T> {
144 } 146 }
145 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 147 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
146 148
147 // Configure 149 irq.set_handler(Self::on_interrupt);
150 irq.unpend();
151 irq.enable();
152
148 let hardware_flow_control = match (rts.is_some(), cts.is_some()) { 153 let hardware_flow_control = match (rts.is_some(), cts.is_some()) {
149 (false, false) => false, 154 (false, false) => false,
150 (true, true) => true, 155 (true, true) => true,
151 _ => panic!("RTS and CTS pins must be either both set or none set."), 156 _ => panic!("RTS and CTS pins must be either both set or none set."),
152 }; 157 };
153 r.config.write(|w| { 158 configure(r, config, hardware_flow_control);
154 w.hwfc().bit(hardware_flow_control);
155 w.parity().variant(config.parity);
156 w
157 });
158 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
159
160 // Disable all interrupts
161 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
162
163 // Reset rxstarted, txstarted. These are used by drop to know whether a transfer was
164 // stopped midway or not.
165 r.events_rxstarted.reset();
166 r.events_txstarted.reset();
167
168 irq.set_handler(Self::on_interrupt);
169 irq.unpend();
170 irq.enable();
171
172 // Enable
173 apply_workaround_for_enable_anomaly(&r);
174 r.enable.write(|w| w.enable().enabled());
175 159
176 let s = T::state(); 160 let s = T::state();
177
178 s.tx_rx_refcount.store(2, Ordering::Relaxed); 161 s.tx_rx_refcount.store(2, Ordering::Relaxed);
179 162
180 Self { 163 Self {
@@ -238,7 +221,87 @@ impl<'d, T: Instance> Uarte<'d, T> {
238 } 221 }
239} 222}
240 223
224fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) {
225 r.config.write(|w| {
226 w.hwfc().bit(hardware_flow_control);
227 w.parity().variant(config.parity);
228 w
229 });
230 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
231
232 // Disable all interrupts
233 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
234
235 // Reset rxstarted, txstarted. These are used by drop to know whether a transfer was
236 // stopped midway or not.
237 r.events_rxstarted.reset();
238 r.events_txstarted.reset();
239
240 // Enable
241 apply_workaround_for_enable_anomaly(&r);
242 r.enable.write(|w| w.enable().enabled());
243}
244
241impl<'d, T: Instance> UarteTx<'d, T> { 245impl<'d, T: Instance> UarteTx<'d, T> {
246 /// Create a new tx-only UARTE without hardware flow control
247 pub fn new(
248 uarte: impl Unborrow<Target = T> + 'd,
249 irq: impl Unborrow<Target = T::Interrupt> + 'd,
250 txd: impl Unborrow<Target = impl GpioPin> + 'd,
251 config: Config,
252 ) -> Self {
253 unborrow!(txd);
254 Self::new_inner(uarte, irq, txd.degrade(), None, config)
255 }
256
257 /// Create a new tx-only UARTE with hardware flow control (RTS/CTS)
258 pub fn new_with_rtscts(
259 uarte: impl Unborrow<Target = T> + 'd,
260 irq: impl Unborrow<Target = T::Interrupt> + 'd,
261 txd: impl Unborrow<Target = impl GpioPin> + 'd,
262 cts: impl Unborrow<Target = impl GpioPin> + 'd,
263 config: Config,
264 ) -> Self {
265 unborrow!(txd, cts);
266 Self::new_inner(uarte, irq, txd.degrade(), Some(cts.degrade()), config)
267 }
268
269 fn new_inner(
270 _uarte: impl Unborrow<Target = T> + 'd,
271 irq: impl Unborrow<Target = T::Interrupt> + 'd,
272 txd: AnyPin,
273 cts: Option<AnyPin>,
274 config: Config,
275 ) -> Self {
276 unborrow!(irq);
277
278 let r = T::regs();
279
280 txd.set_high();
281 txd.conf().write(|w| w.dir().output().drive().s0s1());
282 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
283
284 if let Some(pin) = &cts {
285 pin.conf().write(|w| w.input().connect().drive().h0h1());
286 }
287 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
288
289 r.psel.rxd.write(|w| w.connect().disconnected());
290 r.psel.rts.write(|w| w.connect().disconnected());
291
292 let hardware_flow_control = cts.is_some();
293 configure(r, config, hardware_flow_control);
294
295 irq.set_handler(Uarte::<T>::on_interrupt);
296 irq.unpend();
297 irq.enable();
298
299 let s = T::state();
300 s.tx_rx_refcount.store(1, Ordering::Relaxed);
301
302 Self { phantom: PhantomData }
303 }
304
242 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 305 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
243 match self.write_from_ram(buffer).await { 306 match self.write_from_ram(buffer).await {
244 Ok(_) => Ok(()), 307 Ok(_) => Ok(()),
@@ -372,6 +435,65 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> {
372} 435}
373 436
374impl<'d, T: Instance> UarteRx<'d, T> { 437impl<'d, T: Instance> UarteRx<'d, T> {
438 /// Create a new rx-only UARTE without hardware flow control
439 pub fn new(
440 uarte: impl Unborrow<Target = T> + 'd,
441 irq: impl Unborrow<Target = T::Interrupt> + 'd,
442 rxd: impl Unborrow<Target = impl GpioPin> + 'd,
443 config: Config,
444 ) -> Self {
445 unborrow!(rxd);
446 Self::new_inner(uarte, irq, rxd.degrade(), None, config)
447 }
448
449 /// Create a new rx-only UARTE with hardware flow control (RTS/CTS)
450 pub fn new_with_rtscts(
451 uarte: impl Unborrow<Target = T> + 'd,
452 irq: impl Unborrow<Target = T::Interrupt> + 'd,
453 rxd: impl Unborrow<Target = impl GpioPin> + 'd,
454 rts: impl Unborrow<Target = impl GpioPin> + 'd,
455 config: Config,
456 ) -> Self {
457 unborrow!(rxd, rts);
458 Self::new_inner(uarte, irq, rxd.degrade(), Some(rts.degrade()), config)
459 }
460
461 fn new_inner(
462 _uarte: impl Unborrow<Target = T> + 'd,
463 irq: impl Unborrow<Target = T::Interrupt> + 'd,
464 rxd: AnyPin,
465 rts: Option<AnyPin>,
466 config: Config,
467 ) -> Self {
468 unborrow!(irq);
469
470 let r = T::regs();
471
472 rxd.conf().write(|w| w.input().connect().drive().h0h1());
473 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
474
475 if let Some(pin) = &rts {
476 pin.set_high();
477 pin.conf().write(|w| w.dir().output().drive().h0h1());
478 }
479 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
480
481 r.psel.txd.write(|w| w.connect().disconnected());
482 r.psel.cts.write(|w| w.connect().disconnected());
483
484 irq.set_handler(Uarte::<T>::on_interrupt);
485 irq.unpend();
486 irq.enable();
487
488 let hardware_flow_control = rts.is_some();
489 configure(r, config, hardware_flow_control);
490
491 let s = T::state();
492 s.tx_rx_refcount.store(1, Ordering::Relaxed);
493
494 Self { phantom: PhantomData }
495 }
496
375 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 497 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
376 if buffer.len() == 0 { 498 if buffer.len() == 0 {
377 return Err(Error::BufferZeroLength); 499 return Err(Error::BufferZeroLength);