chore: test FourWire with embedded-hal-mock:

- Add dev-dependencies for embedded-hal-mock
- add docs for FourWire
- add tests for SPI frames transactions

Signed-off-by: Lachezar Lechev <elpiel93@gmail.com>
This commit is contained in:
Lachezar Lechev 2023-07-12 17:57:28 +03:00
commit ed49f20ead
No known key found for this signature in database
GPG key ID: B2D641D6A2C8E742
2 changed files with 116 additions and 12 deletions

View file

@ -10,14 +10,18 @@ license = "MIT OR Apache-2.0"
readme = "README.md"
edition = "2018"
[features]
no-chip-version-assertion = []
[dependencies]
byteorder = { version = "1.3.4", default-features = false }
embedded-hal = "0.2.4"
embedded-hal = "0.2"
embedded-nal = "0.6.0"
bit_field = "0.10.1"
bit_field = "0.10"
derive-try-from-primitive = "1"
nb = "1.0.0"
defmt = { version = "0.3", optional = true }
[features]
no-chip-version-assertion = []
[dev-dependencies]
embedded-hal-mock = "0.9"
defmt = { version = "0.3" }

View file

@ -29,10 +29,13 @@ impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> FourWire<Spi, ChipSel
impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi, ChipSelect> {
type Error =
FourWireError<<Spi as Transfer<u8>>::Error, <Spi as Write<u8>>::Error, ChipSelect::Error>;
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> {
let address_phase = address.to_be_bytes();
let control_phase = block << 3;
let data_phase = data;
// set Chip select to Low, i.e. prepare to receive data
self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
let result = (|| {
self.spi
@ -44,29 +47,39 @@ impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi,
.map_err(FourWireError::TransferError)?;
Ok(())
})();
// set Chip select to High, i.e. we've finished listening
self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
// then return the result of the transmission
result
}
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> {
let address_phase = address.to_be_bytes();
let control_phase = block << 3 | WRITE_MODE_MASK;
let data_phase = data;
// set Chip select to Low, i.e. prepare to transmit
self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
let result = (|| {
self.spi
let result = self
.spi
.write(&address_phase)
.and_then(|_| self.spi.write(&[control_phase]))
.and_then(|_| self.spi.write(data_phase))
.map_err(FourWireError::WriteError)?;
Ok(())
})();
.map_err(FourWireError::WriteError);
// set Chip select to High, i.e. we've finished transmitting
self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
// then return the result of the transmission
result
}
}
// Must use map_err, ambiguity prevents From from being implemented
#[repr(u8)]
#[derive(Clone)]
pub enum FourWireError<TransferError, WriteError, ChipSelectError> {
TransferError(TransferError),
WriteError(WriteError),
@ -91,3 +104,90 @@ impl<TransferError, WriteError, ChipSelectError> fmt::Debug
// TODO Improved error rendering could be done with specialization.
// https://github.com/rust-lang/rust/issues/31844
#[cfg(test)]
mod test {
use embedded_hal::digital::v2::OutputPin;
use embedded_hal_mock::{
pin::{Mock as PinMock, State as PinState, Transaction as PinTransaction},
spi::{Mock as SpiMock, Transaction as SpiTransaction},
};
use crate::{
bus::{four_wire::WRITE_MODE_MASK, Bus},
register,
};
use super::FourWire;
#[test]
fn test_read_frame() {
let mut cs_pin = PinMock::new(&[
// we begin with pin HIGH
PinTransaction::set(PinState::High),
// When reading
PinTransaction::set(PinState::Low),
// When finished reading
PinTransaction::set(PinState::High),
]);
// initiate the pin to high.
cs_pin.set_high().expect("Should set pin to high");
let mut actual_version = [0_u8; 1];
let mut expected_version = 5;
let expectations = [
SpiTransaction::write(register::common::VERSION.to_be_bytes().to_vec()),
SpiTransaction::write(vec![register::COMMON << 3]),
SpiTransaction::transfer(actual_version.to_vec(), vec![expected_version]),
];
let mock_spi = SpiMock::new(&expectations);
let mut four_wire = FourWire::new(mock_spi, cs_pin);
four_wire.read_frame(
register::COMMON,
register::common::VERSION,
&mut actual_version,
);
assert_eq!(expected_version, actual_version[0]);
}
#[test]
fn test_write_frame() {
let mut cs_pin = PinMock::new(&[
// we begin with pin HIGH
PinTransaction::set(PinState::High),
// When reading
PinTransaction::set(PinState::Low),
// When finished reading
PinTransaction::set(PinState::High),
]);
// initiate the pin to high.
cs_pin.set_high().expect("Should set pin to high");
let socket_0_reg = 0x01_u8;
let socket_1_reg = 0x05_u8;
let source_port = 49849_u16;
let expectations = [
SpiTransaction::write(register::socketn::SOURCE_PORT.to_be_bytes().to_vec()),
SpiTransaction::write(vec![socket_1_reg << 3 | WRITE_MODE_MASK]),
SpiTransaction::write(source_port.to_be_bytes().to_vec()),
];
let mock_spi = SpiMock::new(&expectations);
let mut four_wire = FourWire::new(mock_spi, cs_pin);
four_wire.write_frame(
socket_1_reg,
register::socketn::SOURCE_PORT,
&source_port.to_be_bytes(),
);
}
}