Skip to content

Commit

Permalink
added tests to check the for the correct number of clocks during valid
Browse files Browse the repository at this point in the history
  • Loading branch information
liebman committed Sep 22, 2024
1 parent 40e5290 commit bc5d775
Show file tree
Hide file tree
Showing 3 changed files with 371 additions and 0 deletions.
8 changes: 8 additions & 0 deletions hil-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
181 changes: 181 additions & 0 deletions hil-test/tests/parl_io_tx.rs
Original file line number Diff line number Diff line change
@@ -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 _);
}
}
}
182 changes: 182 additions & 0 deletions hil-test/tests/parl_io_tx_async.rs
Original file line number Diff line number Diff line change
@@ -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 _);
}
}
}

0 comments on commit bc5d775

Please sign in to comment.