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:
parent
a384a09f35
commit
ed49f20ead
2 changed files with 116 additions and 12 deletions
12
Cargo.toml
12
Cargo.toml
|
|
@ -10,14 +10,18 @@ license = "MIT OR Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
no-chip-version-assertion = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = { version = "1.3.4", default-features = false }
|
byteorder = { version = "1.3.4", default-features = false }
|
||||||
embedded-hal = "0.2.4"
|
embedded-hal = "0.2"
|
||||||
embedded-nal = "0.6.0"
|
embedded-nal = "0.6.0"
|
||||||
bit_field = "0.10.1"
|
bit_field = "0.10"
|
||||||
derive-try-from-primitive = "1"
|
derive-try-from-primitive = "1"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
|
|
||||||
[features]
|
[dev-dependencies]
|
||||||
no-chip-version-assertion = []
|
embedded-hal-mock = "0.9"
|
||||||
|
defmt = { version = "0.3" }
|
||||||
|
|
@ -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> {
|
impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi, ChipSelect> {
|
||||||
type Error =
|
type Error =
|
||||||
FourWireError<<Spi as Transfer<u8>>::Error, <Spi as Write<u8>>::Error, ChipSelect::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> {
|
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
let address_phase = address.to_be_bytes();
|
let address_phase = address.to_be_bytes();
|
||||||
let control_phase = block << 3;
|
let control_phase = block << 3;
|
||||||
let data_phase = data;
|
let data_phase = data;
|
||||||
|
|
||||||
|
// set Chip select to Low, i.e. prepare to receive data
|
||||||
self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
|
self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
|
||||||
let result = (|| {
|
let result = (|| {
|
||||||
self.spi
|
self.spi
|
||||||
|
|
@ -44,29 +47,39 @@ impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi,
|
||||||
.map_err(FourWireError::TransferError)?;
|
.map_err(FourWireError::TransferError)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// set Chip select to High, i.e. we've finished listening
|
||||||
self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
|
self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
|
||||||
|
|
||||||
|
// then return the result of the transmission
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> {
|
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> {
|
||||||
let address_phase = address.to_be_bytes();
|
let address_phase = address.to_be_bytes();
|
||||||
let control_phase = block << 3 | WRITE_MODE_MASK;
|
let control_phase = block << 3 | WRITE_MODE_MASK;
|
||||||
let data_phase = data;
|
let data_phase = data;
|
||||||
|
|
||||||
|
// set Chip select to Low, i.e. prepare to transmit
|
||||||
self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
|
self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
|
||||||
let result = (|| {
|
let result = self
|
||||||
self.spi
|
.spi
|
||||||
.write(&address_phase)
|
.write(&address_phase)
|
||||||
.and_then(|_| self.spi.write(&[control_phase]))
|
.and_then(|_| self.spi.write(&[control_phase]))
|
||||||
.and_then(|_| self.spi.write(data_phase))
|
.and_then(|_| self.spi.write(data_phase))
|
||||||
.map_err(FourWireError::WriteError)?;
|
.map_err(FourWireError::WriteError);
|
||||||
Ok(())
|
|
||||||
})();
|
// set Chip select to High, i.e. we've finished transmitting
|
||||||
self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
|
self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
|
||||||
|
|
||||||
|
// then return the result of the transmission
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must use map_err, ambiguity prevents From from being implemented
|
// Must use map_err, ambiguity prevents From from being implemented
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum FourWireError<TransferError, WriteError, ChipSelectError> {
|
pub enum FourWireError<TransferError, WriteError, ChipSelectError> {
|
||||||
TransferError(TransferError),
|
TransferError(TransferError),
|
||||||
WriteError(WriteError),
|
WriteError(WriteError),
|
||||||
|
|
@ -91,3 +104,90 @@ impl<TransferError, WriteError, ChipSelectError> fmt::Debug
|
||||||
|
|
||||||
// TODO Improved error rendering could be done with specialization.
|
// TODO Improved error rendering could be done with specialization.
|
||||||
// https://github.com/rust-lang/rust/issues/31844
|
// 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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue