aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-06-13 09:43:32 +0000
committerGitHub <[email protected]>2023-06-13 09:43:32 +0000
commit38891c29ea708a86ec42c6106ad2fdb1466a0cde (patch)
tree8fa89d23d08cbe22191ab0846044896c9ec742d1
parentd82c2a1c26c1498d8f18600b650967f1ba2835f3 (diff)
parentb55e618175e3af81f2b0d04bca45a96adc24a661 (diff)
Merge pull request #1549 from timokroeger/uart_rx_idle
embassy-nrf: Idle detection for RX only uarte
-rw-r--r--embassy-nrf/src/uarte.rs95
1 files changed, 51 insertions, 44 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 85a951ae0..48d57fea4 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -205,50 +205,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
205 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 205 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
206 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 206 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
207 ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) { 207 ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) {
208 let timer = Timer::new(timer); 208 (self.tx, self.rx.with_idle(timer, ppi_ch1, ppi_ch2))
209
210 into_ref!(ppi_ch1, ppi_ch2);
211
212 let r = T::regs();
213
214 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
215 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
216 //
217 // We want to stop RX if line is idle for 2 bytes worth of time
218 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
219 // This gives us the amount of 16M ticks for 20 bits.
220 let baudrate = r.baudrate.read().baudrate().variant().unwrap();
221 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
222
223 timer.set_frequency(Frequency::F16MHz);
224 timer.cc(0).write(timeout);
225 timer.cc(0).short_compare_clear();
226 timer.cc(0).short_compare_stop();
227
228 let mut ppi_ch1 = Ppi::new_one_to_two(
229 ppi_ch1.map_into(),
230 Event::from_reg(&r.events_rxdrdy),
231 timer.task_clear(),
232 timer.task_start(),
233 );
234 ppi_ch1.enable();
235
236 let mut ppi_ch2 = Ppi::new_one_to_one(
237 ppi_ch2.map_into(),
238 timer.cc(0).event_compare(),
239 Task::from_reg(&r.tasks_stoprx),
240 );
241 ppi_ch2.enable();
242
243 (
244 self.tx,
245 UarteRxWithIdle {
246 rx: self.rx,
247 timer,
248 ppi_ch1: ppi_ch1,
249 _ppi_ch2: ppi_ch2,
250 },
251 )
252 } 209 }
253 210
254 /// Return the endtx event for use with PPI 211 /// Return the endtx event for use with PPI
@@ -563,6 +520,56 @@ impl<'d, T: Instance> UarteRx<'d, T> {
563 Self { _p: uarte } 520 Self { _p: uarte }
564 } 521 }
565 522
523 /// Upgrade to an instance that supports idle line detection.
524 pub fn with_idle<U: TimerInstance>(
525 self,
526 timer: impl Peripheral<P = U> + 'd,
527 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
528 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
529 ) -> UarteRxWithIdle<'d, T, U> {
530 let timer = Timer::new(timer);
531
532 into_ref!(ppi_ch1, ppi_ch2);
533
534 let r = T::regs();
535
536 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
537 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
538 //
539 // We want to stop RX if line is idle for 2 bytes worth of time
540 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
541 // This gives us the amount of 16M ticks for 20 bits.
542 let baudrate = r.baudrate.read().baudrate().variant().unwrap();
543 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
544
545 timer.set_frequency(Frequency::F16MHz);
546 timer.cc(0).write(timeout);
547 timer.cc(0).short_compare_clear();
548 timer.cc(0).short_compare_stop();
549
550 let mut ppi_ch1 = Ppi::new_one_to_two(
551 ppi_ch1.map_into(),
552 Event::from_reg(&r.events_rxdrdy),
553 timer.task_clear(),
554 timer.task_start(),
555 );
556 ppi_ch1.enable();
557
558 let mut ppi_ch2 = Ppi::new_one_to_one(
559 ppi_ch2.map_into(),
560 timer.cc(0).event_compare(),
561 Task::from_reg(&r.tasks_stoprx),
562 );
563 ppi_ch2.enable();
564
565 UarteRxWithIdle {
566 rx: self,
567 timer,
568 ppi_ch1: ppi_ch1,
569 _ppi_ch2: ppi_ch2,
570 }
571 }
572
566 /// Read bytes until the buffer is filled. 573 /// Read bytes until the buffer is filled.
567 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 574 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
568 if buffer.len() == 0 { 575 if buffer.len() == 0 {