embassy-nrf: Idle detection for RX only uarte
Introduce `with_idle()` to upgrade an `UarteRx` instance to `UarteRxWithIdle`. Use the method in the split constructor aswell.
This commit is contained in:
		
							parent
							
								
									0053a8a1a7
								
							
						
					
					
						commit
						b55e618175
					
				| @ -205,50 +205,7 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||||||
|         ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, |         ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, | ||||||
|         ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, |         ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, | ||||||
|     ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) { |     ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) { | ||||||
|         let timer = Timer::new(timer); |         (self.tx, self.rx.with_idle(timer, ppi_ch1, ppi_ch2)) | ||||||
| 
 |  | ||||||
|         into_ref!(ppi_ch1, ppi_ch2); |  | ||||||
| 
 |  | ||||||
|         let r = T::regs(); |  | ||||||
| 
 |  | ||||||
|         // BAUDRATE register values are `baudrate * 2^32 / 16000000`
 |  | ||||||
|         // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
 |  | ||||||
|         //
 |  | ||||||
|         // We want to stop RX if line is idle for 2 bytes worth of time
 |  | ||||||
|         // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
 |  | ||||||
|         // This gives us the amount of 16M ticks for 20 bits.
 |  | ||||||
|         let baudrate = r.baudrate.read().baudrate().variant().unwrap(); |  | ||||||
|         let timeout = 0x8000_0000 / (baudrate as u32 / 40); |  | ||||||
| 
 |  | ||||||
|         timer.set_frequency(Frequency::F16MHz); |  | ||||||
|         timer.cc(0).write(timeout); |  | ||||||
|         timer.cc(0).short_compare_clear(); |  | ||||||
|         timer.cc(0).short_compare_stop(); |  | ||||||
| 
 |  | ||||||
|         let mut ppi_ch1 = Ppi::new_one_to_two( |  | ||||||
|             ppi_ch1.map_into(), |  | ||||||
|             Event::from_reg(&r.events_rxdrdy), |  | ||||||
|             timer.task_clear(), |  | ||||||
|             timer.task_start(), |  | ||||||
|         ); |  | ||||||
|         ppi_ch1.enable(); |  | ||||||
| 
 |  | ||||||
|         let mut ppi_ch2 = Ppi::new_one_to_one( |  | ||||||
|             ppi_ch2.map_into(), |  | ||||||
|             timer.cc(0).event_compare(), |  | ||||||
|             Task::from_reg(&r.tasks_stoprx), |  | ||||||
|         ); |  | ||||||
|         ppi_ch2.enable(); |  | ||||||
| 
 |  | ||||||
|         ( |  | ||||||
|             self.tx, |  | ||||||
|             UarteRxWithIdle { |  | ||||||
|                 rx: self.rx, |  | ||||||
|                 timer, |  | ||||||
|                 ppi_ch1: ppi_ch1, |  | ||||||
|                 _ppi_ch2: ppi_ch2, |  | ||||||
|             }, |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Return the endtx event for use with PPI
 |     /// Return the endtx event for use with PPI
 | ||||||
| @ -563,6 +520,56 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||||||
|         Self { _p: uarte } |         Self { _p: uarte } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Upgrade to an instance that supports idle line detection.
 | ||||||
|  |     pub fn with_idle<U: TimerInstance>( | ||||||
|  |         self, | ||||||
|  |         timer: impl Peripheral<P = U> + 'd, | ||||||
|  |         ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, | ||||||
|  |         ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, | ||||||
|  |     ) -> UarteRxWithIdle<'d, T, U> { | ||||||
|  |         let timer = Timer::new(timer); | ||||||
|  | 
 | ||||||
|  |         into_ref!(ppi_ch1, ppi_ch2); | ||||||
|  | 
 | ||||||
|  |         let r = T::regs(); | ||||||
|  | 
 | ||||||
|  |         // BAUDRATE register values are `baudrate * 2^32 / 16000000`
 | ||||||
|  |         // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
 | ||||||
|  |         //
 | ||||||
|  |         // We want to stop RX if line is idle for 2 bytes worth of time
 | ||||||
|  |         // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
 | ||||||
|  |         // This gives us the amount of 16M ticks for 20 bits.
 | ||||||
|  |         let baudrate = r.baudrate.read().baudrate().variant().unwrap(); | ||||||
|  |         let timeout = 0x8000_0000 / (baudrate as u32 / 40); | ||||||
|  | 
 | ||||||
|  |         timer.set_frequency(Frequency::F16MHz); | ||||||
|  |         timer.cc(0).write(timeout); | ||||||
|  |         timer.cc(0).short_compare_clear(); | ||||||
|  |         timer.cc(0).short_compare_stop(); | ||||||
|  | 
 | ||||||
|  |         let mut ppi_ch1 = Ppi::new_one_to_two( | ||||||
|  |             ppi_ch1.map_into(), | ||||||
|  |             Event::from_reg(&r.events_rxdrdy), | ||||||
|  |             timer.task_clear(), | ||||||
|  |             timer.task_start(), | ||||||
|  |         ); | ||||||
|  |         ppi_ch1.enable(); | ||||||
|  | 
 | ||||||
|  |         let mut ppi_ch2 = Ppi::new_one_to_one( | ||||||
|  |             ppi_ch2.map_into(), | ||||||
|  |             timer.cc(0).event_compare(), | ||||||
|  |             Task::from_reg(&r.tasks_stoprx), | ||||||
|  |         ); | ||||||
|  |         ppi_ch2.enable(); | ||||||
|  | 
 | ||||||
|  |         UarteRxWithIdle { | ||||||
|  |             rx: self, | ||||||
|  |             timer, | ||||||
|  |             ppi_ch1: ppi_ch1, | ||||||
|  |             _ppi_ch2: ppi_ch2, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Read bytes until the buffer is filled.
 |     /// Read bytes until the buffer is filled.
 | ||||||
|     pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |     pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||||||
|         if buffer.len() == 0 { |         if buffer.len() == 0 { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user