Skip to content

Commit 979eecc

Browse files
committed
Add disable and enable tx and rx functions for RP UART
1 parent 9ab6100 commit 979eecc

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

embassy-rp/src/uart/buffered.rs

+20
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,26 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
134134
}
135135
}
136136

137+
/// Disable the UART receiver, if disabled in the middle of a reception, it will complete the current character
138+
pub fn disable_rx(&mut self) {
139+
UartRx::<'d, T, Async>::disable_inner();
140+
}
141+
142+
/// Enable the UART receiver
143+
pub fn enable_rx(&mut self) {
144+
UartRx::<'d, T, Async>::enable_inner();
145+
}
146+
147+
/// Disable the UART transmitter, if disabled in the middle of a transmission, it will complete the current character
148+
pub fn disable_tx(&mut self) {
149+
UartTx::<'d, T, Async>::disable_inner();
150+
}
151+
152+
/// Enable the UART transmitter
153+
pub fn enable_tx(&mut self) {
154+
UartTx::<'d, T, Async>::enable_inner();
155+
}
156+
137157
/// Write to UART TX buffer blocking execution until done.
138158
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<usize, Error> {
139159
self.tx.blocking_write(buffer)

embassy-rp/src/uart/mod.rs

+56
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,24 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
171171
}
172172
}
173173

174+
fn disable_inner() {
175+
T::regs().uartcr().modify(|t| t.set_txe(false));
176+
}
177+
178+
fn enable_inner() {
179+
T::regs().uartcr().modify(|t| t.set_txe(true));
180+
}
181+
182+
/// Disable the UART transmitter, if disabled in the middle of a transmission, it will complete the current character
183+
pub fn disable(&mut self) {
184+
Self::disable_inner();
185+
}
186+
187+
/// Enable the UART transmitter
188+
pub fn enable(&mut self) {
189+
Self::enable_inner();
190+
}
191+
174192
/// Transmit the provided buffer blocking execution until done.
175193
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
176194
let r = T::regs();
@@ -286,6 +304,24 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
286304
}
287305
}
288306

307+
fn disable_inner() {
308+
T::regs().uartcr().modify(|t| t.set_rxe(false));
309+
}
310+
311+
fn enable_inner() {
312+
T::regs().uartcr().modify(|t| t.set_rxe(true));
313+
}
314+
315+
/// Disable the UART receiver, if disabled in the middle of a reception, it will complete the current character
316+
pub fn disable(&mut self) {
317+
Self::disable_inner();
318+
}
319+
320+
/// Enable the UART receiver
321+
pub fn enable(&mut self) {
322+
Self::enable_inner();
323+
}
324+
289325
/// Read from UART RX blocking execution until done.
290326
pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> {
291327
while !buffer.is_empty() {
@@ -1007,6 +1043,26 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
10071043
}
10081044

10091045
impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
1046+
/// Disable the UART receiver, if disabled in the middle of a reception, it will complete the current character
1047+
pub fn disable_rx(&mut self) {
1048+
UartRx::<'d, T, M>::disable_inner();
1049+
}
1050+
1051+
/// Enable the UART receiver
1052+
pub fn enable_rx(&mut self) {
1053+
UartRx::<'d, T, M>::enable_inner();
1054+
}
1055+
1056+
/// Disable the UART transmitter, if disabled in the middle of a transmission, it will complete the current character
1057+
pub fn disable_tx(&mut self) {
1058+
UartTx::<'d, T, M>::disable_inner();
1059+
}
1060+
1061+
/// Enable the UART transmitter
1062+
pub fn enable_tx(&mut self) {
1063+
UartTx::<'d, T, M>::enable_inner();
1064+
}
1065+
10101066
/// Transmit the provided buffer blocking execution until done.
10111067
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
10121068
self.tx.blocking_write(buffer)

examples/rp/src/bin/uart_rs485.rs

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip.
2+
//!
3+
//! No specific hardware is specified in this example. Only output on pin 0 and pin 2, and input on pin 1 is tested.
4+
//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used
5+
//! with its UART port.
6+
7+
#![no_std]
8+
#![no_main]
9+
10+
use defmt::*;
11+
use embassy_executor::Spawner;
12+
use embassy_rp::bind_interrupts;
13+
use embassy_rp::gpio::{Level, Output};
14+
use embassy_rp::peripherals::UART0;
15+
use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, Config};
16+
use embedded_io_async::{Read, Write};
17+
use static_cell::StaticCell;
18+
use {defmt_rtt as _, panic_probe as _};
19+
20+
static TX_BUF: StaticCell<[u8; 32]> = StaticCell::new();
21+
static RX_BUF: StaticCell<[u8; 32]> = StaticCell::new();
22+
23+
bind_interrupts!(struct Irqs {
24+
UART0_IRQ => BufferedInterruptHandler<UART0>;
25+
});
26+
27+
#[embassy_executor::main]
28+
async fn main(_spawner: Spawner) {
29+
let p = embassy_rp::init(Default::default());
30+
let config = Config::default();
31+
let mut uart = BufferedUart::new(
32+
p.UART0,
33+
p.PIN_0,
34+
p.PIN_1,
35+
Irqs,
36+
TX_BUF.init([0; 32]),
37+
RX_BUF.init([0; 32]),
38+
config,
39+
);
40+
let mut data_enable = Output::new(p.PIN_2, Level::Low);
41+
42+
loop {
43+
// When using a UART with an RS485 bus, often a transceiver is used which has a DE/nRE pin.
44+
// Setting this DE/nRE pin high to allow transmitting data, could cause the RX pin to go low depending on the chip and hardware used.
45+
// When done transmitting data and setting the DE/nRE pin low, the RX pin would go up again which will trigger a break condition in the UART receiver.
46+
// This can be prevented by temporarily disabling the receiver of the UART, roughly as follows:
47+
uart.disable_rx();
48+
data_enable.set_high();
49+
50+
uart.write_all("hello there!\r\n".as_bytes()).await.unwrap();
51+
52+
data_enable.set_low();
53+
uart.enable_rx();
54+
55+
let mut buf = [0; 16];
56+
uart.read(&mut buf).await.unwrap();
57+
58+
info!("Rx: {:?}", buf);
59+
60+
cortex_m::asm::delay(1_000_000);
61+
}
62+
}

0 commit comments

Comments
 (0)