From bc5d7757cb2840048413547984461e9ec28d68d7 Mon Sep 17 00:00:00 2001 From: liebman Date: Sun, 22 Sep 2024 08:50:09 -0700 Subject: [PATCH] added tests to check the for the correct number of clocks during valid --- hil-test/Cargo.toml | 8 ++ hil-test/tests/parl_io_tx.rs | 181 ++++++++++++++++++++++++++++ hil-test/tests/parl_io_tx_async.rs | 182 +++++++++++++++++++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 hil-test/tests/parl_io_tx.rs create mode 100644 hil-test/tests/parl_io_tx_async.rs diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index bef22fea4dc..13e5402fc1d 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -99,6 +99,14 @@ harness = false name = "systimer" harness = false +[[test]] +name = "parl_io_tx" +harness = false + +[[test]] +name = "parl_io_tx_async" +harness = false + [[test]] name = "pcnt" harness = false diff --git a/hil-test/tests/parl_io_tx.rs b/hil-test/tests/parl_io_tx.rs new file mode 100644 index 00000000000..00e43da53ad --- /dev/null +++ b/hil-test/tests/parl_io_tx.rs @@ -0,0 +1,181 @@ +//! PARL_IO TX test + +//% CHIPS: esp32c6 esp32h2 + +#![no_std] +#![no_main] + +use esp_hal::{ + dma::{ChannelCreator, Dma, DmaPriority}, + gpio::{interconnect::InputSignal, AnyPin, Io, NoPin}, + parl_io::{ + BitPackOrder, + ClkOutPin, + ParlIoTxOnly, + SampleEdge, + TxEightBits, + TxPinConfigIncludingValidPin, + TxPinConfigWithValidPin, + TxSixteenBits, + }, + pcnt::{ + channel::{CtrlMode, EdgeMode}, + unit::Unit, + Pcnt, + }, + peripherals::PARL_IO, + prelude::*, +}; +use hil_test as _; + +struct Context { + parl_io: PARL_IO, + dma_channel: ChannelCreator<0>, + clock: AnyPin, + valid: AnyPin, + clock_loopback: InputSignal, + valid_loopback: InputSignal, + pcnt_unit: Unit<'static, 0>, +} + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + // defmt::* is load-bearing, it ensures that the assert in dma_buffers! is not + // using defmt's non-const assert. Doing so would result in a compile error. + #[allow(unused_imports)] + use defmt::{assert_eq, *}; + + use super::*; + + #[init] + fn init() -> Context { + let peripherals = esp_hal::init(esp_hal::Config::default()); + + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + let (clock, _) = hil_test::common_test_pins!(io); + let valid = io.pins.gpio0.degrade(); + let clock_loopback = clock.peripheral_input(); + let valid_loopback = valid.peripheral_input(); + let clock = clock.degrade(); + let pcnt = Pcnt::new(peripherals.PCNT); + let pcnt_unit = pcnt.unit0; + let dma = Dma::new(peripherals.DMA); + let dma_channel = dma.channel0; + + let parl_io = peripherals.PARL_IO; + + Context { + parl_io, + dma_channel, + clock, + valid, + clock_loopback, + valid_loopback, + pcnt_unit, + } + } + + #[test] + #[timeout(3)] + fn test_parl_io_tx_16bit_valid_clock_count(ctx: Context) { + const BUFFER_SIZE: usize = 64; + let tx_buffer = [0u16; BUFFER_SIZE]; + let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, 2 * BUFFER_SIZE); + + let pins = TxSixteenBits::new( + NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, + NoPin, NoPin, NoPin, ctx.valid, + ); + let mut pins = TxPinConfigIncludingValidPin::new(pins); + let mut clock_pin = ClkOutPin::new(ctx.clock); + + let pio = ParlIoTxOnly::new( + ctx.parl_io, + ctx.dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + 20.MHz(), + ) + .unwrap(); + + let mut pio = pio + .tx + .with_config( + &mut pins, + &mut clock_pin, + 0, + SampleEdge::Invert, + BitPackOrder::Msb, + ) + .unwrap(); // TODO: handle error + + // use a PCNT unit to count the negitive clock edges only when valid is high + let clock_unit = ctx.pcnt_unit; + clock_unit.channel0.set_edge_signal(ctx.clock_loopback); + clock_unit.channel0.set_ctrl_signal(ctx.valid_loopback); + clock_unit + .channel0 + .set_input_mode(EdgeMode::Increment, EdgeMode::Hold); + clock_unit + .channel0 + .set_ctrl_mode(CtrlMode::Disable, CtrlMode::Keep); + + for _ in 0..100 { + clock_unit.clear(); + let xfer = pio.write_dma(&tx_buffer).unwrap(); + xfer.wait().unwrap(); + info!("clock count: {}", clock_unit.get_value()); + assert_eq!(clock_unit.get_value(), BUFFER_SIZE as _); + } + } + + #[test] + #[timeout(3)] + fn test_parl_io_tx_8bit_valid_clock_count(ctx: Context) { + const BUFFER_SIZE: usize = 64; + let tx_buffer = [0u8; BUFFER_SIZE]; + let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, 2 * BUFFER_SIZE); + + let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin); + let mut pins = TxPinConfigWithValidPin::new(pins, ctx.valid); + let mut clock_pin = ClkOutPin::new(ctx.clock); + + let pio = ParlIoTxOnly::new( + ctx.parl_io, + ctx.dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + 20.MHz(), + ) + .unwrap(); + + let mut pio = pio + .tx + .with_config( + &mut pins, + &mut clock_pin, + 0, + SampleEdge::Invert, + BitPackOrder::Msb, + ) + .unwrap(); // TODO: handle error + + // use a PCNT unit to count the negitive clock edges only when valid is high + let clock_unit = ctx.pcnt_unit; + clock_unit.channel0.set_edge_signal(ctx.clock_loopback); + clock_unit.channel0.set_ctrl_signal(ctx.valid_loopback); + clock_unit + .channel0 + .set_input_mode(EdgeMode::Increment, EdgeMode::Hold); + clock_unit + .channel0 + .set_ctrl_mode(CtrlMode::Disable, CtrlMode::Keep); + + for _ in 0..100 { + clock_unit.clear(); + let xfer = pio.write_dma(&tx_buffer).unwrap(); + xfer.wait().unwrap(); + info!("clock count: {}", clock_unit.get_value()); + assert_eq!(clock_unit.get_value(), BUFFER_SIZE as _); + } + } +} diff --git a/hil-test/tests/parl_io_tx_async.rs b/hil-test/tests/parl_io_tx_async.rs new file mode 100644 index 00000000000..7be9979416e --- /dev/null +++ b/hil-test/tests/parl_io_tx_async.rs @@ -0,0 +1,182 @@ +//! PARL_IO TX async test + +//% CHIPS: esp32c6 esp32h2 +//% FEATURES: generic-queue + +#![no_std] +#![no_main] + +use esp_hal::{ + dma::{ChannelCreator, Dma, DmaPriority}, + gpio::{interconnect::InputSignal, AnyPin, Io, NoPin}, + parl_io::{ + BitPackOrder, + ClkOutPin, + ParlIoTxOnly, + SampleEdge, + TxEightBits, + TxPinConfigIncludingValidPin, + TxPinConfigWithValidPin, + TxSixteenBits, + }, + pcnt::{ + channel::{CtrlMode, EdgeMode}, + unit::Unit, + Pcnt, + }, + peripherals::PARL_IO, + prelude::*, +}; +use hil_test as _; + +struct Context { + parl_io: PARL_IO, + dma_channel: ChannelCreator<0>, + clock: AnyPin, + valid: AnyPin, + clock_loopback: InputSignal, + valid_loopback: InputSignal, + pcnt_unit: Unit<'static, 0>, +} + +#[cfg(test)] +#[embedded_test::tests(executor = esp_hal_embassy::Executor::new())] +mod tests { + // defmt::* is load-bearing, it ensures that the assert in dma_buffers! is not + // using defmt's non-const assert. Doing so would result in a compile error. + #[allow(unused_imports)] + use defmt::{assert_eq, *}; + + use super::*; + + #[init] + async fn init() -> Context { + let peripherals = esp_hal::init(esp_hal::Config::default()); + + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + let (clock, _) = hil_test::common_test_pins!(io); + let valid = io.pins.gpio0.degrade(); + let clock_loopback = clock.peripheral_input(); + let valid_loopback = valid.peripheral_input(); + let clock = clock.degrade(); + let pcnt = Pcnt::new(peripherals.PCNT); + let pcnt_unit = pcnt.unit0; + let dma = Dma::new(peripherals.DMA); + let dma_channel = dma.channel0; + + let parl_io = peripherals.PARL_IO; + + Context { + parl_io, + dma_channel, + clock, + valid, + clock_loopback, + valid_loopback, + pcnt_unit, + } + } + + #[test] + #[timeout(3)] + async fn test_parl_io_tx_async_16bit_valid_clock_count(ctx: Context) { + const BUFFER_SIZE: usize = 64; + let tx_buffer = [0u16; BUFFER_SIZE]; + let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, 2 * BUFFER_SIZE); + + let pins = TxSixteenBits::new( + NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, + NoPin, NoPin, NoPin, ctx.valid, + ); + let mut pins = TxPinConfigIncludingValidPin::new(pins); + let mut clock_pin = ClkOutPin::new(ctx.clock); + + let pio = ParlIoTxOnly::new( + ctx.parl_io, + ctx.dma_channel + .configure_for_async(false, DmaPriority::Priority0), + tx_descriptors, + 20.MHz(), + ) + .unwrap(); + + let mut pio = pio + .tx + .with_config( + &mut pins, + &mut clock_pin, + 0, + SampleEdge::Invert, + BitPackOrder::Msb, + ) + .unwrap(); + + // use a PCNT unit to count the negitive clock edges only when valid is high + let clock_unit = ctx.pcnt_unit; + clock_unit.channel0.set_edge_signal(ctx.clock_loopback); + clock_unit.channel0.set_ctrl_signal(ctx.valid_loopback); + clock_unit + .channel0 + .set_input_mode(EdgeMode::Increment, EdgeMode::Hold); + clock_unit + .channel0 + .set_ctrl_mode(CtrlMode::Disable, CtrlMode::Keep); + + for _ in 0..100 { + clock_unit.clear(); + pio.write_dma_async(&tx_buffer).await.unwrap(); + info!("clock count: {}", clock_unit.get_value()); + assert_eq!(clock_unit.get_value(), BUFFER_SIZE as _); + } + } + + #[test] + #[timeout(3)] + async fn test_parl_io_tx_async_8bit_valid_clock_count(ctx: Context) { + const BUFFER_SIZE: usize = 64; + let tx_buffer = [0u8; BUFFER_SIZE]; + let (_, tx_descriptors) = esp_hal::dma_descriptors!(0, 2 * BUFFER_SIZE); + + let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin); + let mut pins = TxPinConfigWithValidPin::new(pins, ctx.valid); + let mut clock_pin = ClkOutPin::new(ctx.clock); + + let pio = ParlIoTxOnly::new( + ctx.parl_io, + ctx.dma_channel + .configure_for_async(false, DmaPriority::Priority0), + tx_descriptors, + 20.MHz(), + ) + .unwrap(); + + let mut pio = pio + .tx + .with_config( + &mut pins, + &mut clock_pin, + 0, + SampleEdge::Invert, + BitPackOrder::Msb, + ) + .unwrap(); + + // use a PCNT unit to count the negitive clock edges only when valid is high + let clock_unit = ctx.pcnt_unit; + clock_unit.channel0.set_edge_signal(ctx.clock_loopback); + clock_unit.channel0.set_ctrl_signal(ctx.valid_loopback); + clock_unit + .channel0 + .set_input_mode(EdgeMode::Increment, EdgeMode::Hold); + clock_unit + .channel0 + .set_ctrl_mode(CtrlMode::Disable, CtrlMode::Keep); + + for _ in 0..100 { + clock_unit.clear(); + pio.write_dma_async(&tx_buffer).await.unwrap(); + info!("clock count: {}", clock_unit.get_value()); + assert_eq!(clock_unit.get_value(), BUFFER_SIZE as _); + } + } +}