Fix inverting pins (#3312)

* Merge tests

* Add test case with inverted pins

* Connect signal before converting to AnyPin
This commit is contained in:
Dániel Buga 2025-03-31 11:40:55 +02:00 committed by GitHub
parent 9d2005841d
commit 739e203f39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 99 additions and 104 deletions

View File

@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ESP32: Enforce required pointer alignments in DMA buffers (#3296) - ESP32: Enforce required pointer alignments in DMA buffers (#3296)
- ESP32-C6: Keep ADC enabled to improve radio signal strength (#3249) - ESP32-C6: Keep ADC enabled to improve radio signal strength (#3249)
- Fix off-by-one in the allowed range of the spi clock calculations (#3266) - Fix off-by-one in the allowed range of the spi clock calculations (#3266)
- Fixed an issue where inverting a pin via the interconnect matrix was ineffective (#3312)
### Removed ### Removed

View File

@ -870,6 +870,7 @@ impl OutputConnection<'_> {
} }
pub(crate) fn connect_with_guard(self, signal: crate::gpio::OutputSignal) -> PinGuard { pub(crate) fn connect_with_guard(self, signal: crate::gpio::OutputSignal) -> PinGuard {
signal.connect_to(&self);
match self.0 { match self.0 {
OutputConnectionInner::Output(pin) => PinGuard::new(pin.pin, signal), OutputConnectionInner::Output(pin) => PinGuard::new(pin.pin, signal),
OutputConnectionInner::DirectOutput(pin) => PinGuard::new(pin.pin, signal), OutputConnectionInner::DirectOutput(pin) => PinGuard::new(pin.pin, signal),

View File

@ -135,10 +135,8 @@ impl crate::private::Sealed for PinGuard {}
impl PinGuard { impl PinGuard {
pub(crate) fn new(pin: AnyPin, signal: OutputSignal) -> Self { pub(crate) fn new(pin: AnyPin, signal: OutputSignal) -> Self {
let number = pin.number();
signal.connect_to(&pin.into_ref());
Self { Self {
pin: number, pin: pin.number(),
signal, signal,
} }
} }

View File

@ -177,10 +177,6 @@ required-features = ["embassy"]
name = "uart_regression" name = "uart_regression"
harness = false harness = false
[[test]]
name = "uart_tx_rx"
harness = false
[[test]] [[test]]
name = "uart_tx_rx_async" name = "uart_tx_rx_async"
harness = false harness = false

View File

@ -7,18 +7,27 @@
#![no_main] #![no_main]
use esp_hal::{ use esp_hal::{
gpio::{
interconnect::{InputSignal, OutputSignal},
AnyPin,
},
uart::{self, ClockSource, Uart}, uart::{self, ClockSource, Uart},
Blocking, Blocking,
}; };
use hil_test as _; use hil_test as _;
struct Context { struct Context {
uart: Uart<'static, Blocking>, uart0: Uart<'static, Blocking>,
uart1: Uart<'static, Blocking>,
rx: AnyPin,
tx: AnyPin,
} }
#[cfg(test)] #[cfg(test)]
#[embedded_test::tests(default_timeout = 3)] #[embedded_test::tests(default_timeout = 3)]
mod tests { mod tests {
use esp_hal::gpio::Pin;
use super::*; use super::*;
#[init] #[init]
@ -29,35 +38,41 @@ mod tests {
let (rx, tx) = hil_test::common_test_pins!(peripherals); let (rx, tx) = hil_test::common_test_pins!(peripherals);
let uart = Uart::new(peripherals.UART1, uart::Config::default()) let uart0 = Uart::new(peripherals.UART0, uart::Config::default()).unwrap();
.unwrap() let uart1 = Uart::new(peripherals.UART1, uart::Config::default()).unwrap();
.with_tx(tx)
.with_rx(rx);
Context { uart } Context {
uart0,
uart1,
rx: rx.degrade(),
tx: tx.degrade(),
}
} }
#[test] #[test]
fn test_send_receive(mut ctx: Context) { fn test_send_receive(ctx: Context) {
ctx.uart.write(&[0x42]).unwrap(); let mut uart = ctx.uart1.with_tx(ctx.tx).with_rx(ctx.rx);
uart.write(&[0x42]).unwrap();
let mut byte = [0u8; 1]; let mut byte = [0u8; 1];
ctx.uart.read(&mut byte).unwrap(); uart.read(&mut byte).unwrap();
assert_eq!(byte[0], 0x42); assert_eq!(byte[0], 0x42);
} }
#[test] #[test]
fn flush_waits_for_data_to_be_transmitted(mut ctx: Context) { fn flush_waits_for_data_to_be_transmitted(ctx: Context) {
let mut uart = ctx.uart1.with_tx(ctx.tx).with_rx(ctx.rx);
let bauds = [1000, 5000000]; let bauds = [1000, 5000000];
for baud in bauds { for baud in bauds {
ctx.uart uart.apply_config(&uart::Config::default().with_baudrate(baud))
.apply_config(&uart::Config::default().with_baudrate(baud))
.unwrap(); .unwrap();
for i in 0..10 { for i in 0..10 {
let mut byte = [0u8; 1]; let mut byte = [0u8; 1];
ctx.uart.write(&[i as u8]).unwrap(); uart.write(&[i as u8]).unwrap();
ctx.uart.flush().unwrap(); uart.flush().unwrap();
let read = ctx.uart.read_buffered(&mut byte).unwrap(); let read = uart.read_buffered(&mut byte).unwrap();
assert_eq!(read, 1, "Baud rate {}, iteration {}", baud, i); assert_eq!(read, 1, "Baud rate {}, iteration {}", baud, i);
assert_eq!(byte[0], i as u8, "Baud rate {}, iteration {}", baud, i); assert_eq!(byte[0], i as u8, "Baud rate {}, iteration {}", baud, i);
} }
@ -65,7 +80,9 @@ mod tests {
} }
#[test] #[test]
fn test_different_tolerance(mut ctx: Context) { fn test_different_tolerance(ctx: Context) {
let mut uart = ctx.uart1.with_tx(ctx.tx).with_rx(ctx.rx);
let configs = [ let configs = [
uart::Config::default() uart::Config::default()
.with_baudrate(19_200) .with_baudrate(19_200)
@ -76,32 +93,36 @@ mod tests {
]; ];
for config in configs { for config in configs {
ctx.uart.apply_config(&config).unwrap(); uart.apply_config(&config).unwrap();
ctx.uart.write(&[0x42]).unwrap(); uart.write(&[0x42]).unwrap();
let mut byte = [0u8; 1]; let mut byte = [0u8; 1];
ctx.uart.read(&mut byte).unwrap(); uart.read(&mut byte).unwrap();
assert_eq!(byte[0], 0x42); assert_eq!(byte[0], 0x42);
} }
} }
#[test] #[test]
fn test_send_receive_buffer(mut ctx: Context) { fn test_send_receive_buffer(ctx: Context) {
let mut uart = ctx.uart1.with_tx(ctx.tx).with_rx(ctx.rx);
const BUF_SIZE: usize = 128; // UART_FIFO_SIZE const BUF_SIZE: usize = 128; // UART_FIFO_SIZE
let data = [13; BUF_SIZE]; let data = [13; BUF_SIZE];
let written = ctx.uart.write(&data).unwrap(); let written = uart.write(&data).unwrap();
assert_eq!(written, BUF_SIZE); assert_eq!(written, BUF_SIZE);
// Calls to read may not fill the buffer, wait until read returns 0 // Calls to read may not fill the buffer, wait until read returns 0
let mut buffer = [0; BUF_SIZE]; let mut buffer = [0; BUF_SIZE];
embedded_io::Read::read_exact(&mut ctx.uart, &mut buffer).unwrap(); embedded_io::Read::read_exact(&mut uart, &mut buffer).unwrap();
assert_eq!(data, buffer); assert_eq!(data, buffer);
} }
#[test] #[test]
fn test_send_receive_different_baud_rates_and_clock_sources(mut ctx: Context) { fn test_send_receive_different_baud_rates_and_clock_sources(ctx: Context) {
let mut uart = ctx.uart1.with_tx(ctx.tx).with_rx(ctx.rx);
// The default baud rate for the UART is 115,200, so we will try to // The default baud rate for the UART is 115,200, so we will try to
// send/receive with some other common baud rates to ensure this is // send/receive with some other common baud rates to ensure this is
// working as expected. We will also using different clock sources // working as expected. We will also using different clock sources
@ -121,19 +142,62 @@ mod tests {
let mut byte_to_write = 0xA5; let mut byte_to_write = 0xA5;
for (baudrate, clock_source) in configs { for (baudrate, clock_source) in configs {
ctx.uart uart.apply_config(
.apply_config( &uart::Config::default()
&uart::Config::default() .with_baudrate(baudrate)
.with_baudrate(baudrate) .with_clock_source(clock_source),
.with_clock_source(clock_source), )
) .unwrap();
.unwrap(); uart.write(&[byte_to_write]).unwrap();
ctx.uart.write(&[byte_to_write]).unwrap();
let mut byte = [0u8; 1]; let mut byte = [0u8; 1];
ctx.uart.read(&mut byte).unwrap(); uart.read(&mut byte).unwrap();
assert_eq!(byte[0], byte_to_write); assert_eq!(byte[0], byte_to_write);
byte_to_write = !byte_to_write; byte_to_write = !byte_to_write;
} }
} }
#[test]
fn test_send_receive_inverted(ctx: Context) {
let mut uart = ctx
.uart1
.with_tx(OutputSignal::from(ctx.tx).inverted())
.with_rx(InputSignal::from(ctx.rx).inverted());
uart.write(&[0x42]).unwrap();
let mut byte = [0u8; 1];
uart.read(&mut byte).unwrap();
assert_eq!(byte[0], 0x42);
}
#[test]
fn test_split_send_receive(ctx: Context) {
let mut tx = ctx.uart0.split().1.with_tx(ctx.tx);
let mut rx = ctx.uart1.split().0.with_rx(ctx.rx);
let byte = [0x42];
tx.flush().unwrap();
tx.write(&byte).unwrap();
let mut buf = [0u8; 1];
rx.read(&mut buf).unwrap();
assert_eq!(buf[0], 0x42);
}
#[test]
fn test_split_send_receive_bytes(ctx: Context) {
let mut tx = ctx.uart0.split().1.with_tx(ctx.tx);
let mut rx = ctx.uart1.split().0.with_rx(ctx.rx);
let bytes = [0x42, 0x43, 0x44];
let mut buf = [0u8; 3];
tx.flush().unwrap();
tx.write(&bytes).unwrap();
embedded_io::Read::read_exact(&mut rx, &mut buf).unwrap();
assert_eq!(buf, bytes);
}
} }

View File

@ -1,65 +0,0 @@
//! UART TX/RX Test
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: unstable
#![no_std]
#![no_main]
use esp_hal::{
uart::{self, UartRx, UartTx},
Blocking,
};
use hil_test as _;
struct Context {
rx: UartRx<'static, Blocking>,
tx: UartTx<'static, Blocking>,
}
#[cfg(test)]
#[embedded_test::tests(default_timeout = 3)]
mod tests {
use super::*;
#[init]
fn init() -> Context {
let peripherals = esp_hal::init(esp_hal::Config::default());
let (rx, tx) = hil_test::common_test_pins!(peripherals);
let tx = UartTx::new(peripherals.UART0, uart::Config::default())
.unwrap()
.with_tx(tx);
let rx = UartRx::new(peripherals.UART1, uart::Config::default())
.unwrap()
.with_rx(rx);
Context { rx, tx }
}
#[test]
fn test_send_receive(mut ctx: Context) {
let byte = [0x42];
ctx.tx.flush().unwrap();
ctx.tx.write(&byte).unwrap();
let mut buf = [0u8; 1];
ctx.rx.read(&mut buf).unwrap();
assert_eq!(buf[0], 0x42);
}
#[test]
fn test_send_receive_bytes(mut ctx: Context) {
let bytes = [0x42, 0x43, 0x44];
let mut buf = [0u8; 3];
ctx.tx.flush().unwrap();
ctx.tx.write(&bytes).unwrap();
embedded_io::Read::read_exact(&mut ctx.rx, &mut buf).unwrap();
assert_eq!(buf, bytes);
}
}