Arbitration lost test is working. Still some test failing
This commit is contained in:
parent
70a64e8dcb
commit
ce066e92e7
@ -19,12 +19,16 @@ pub enum Error {
|
|||||||
Crc,
|
Crc,
|
||||||
Overrun,
|
Overrun,
|
||||||
ZeroLengthTransfer,
|
ZeroLengthTransfer,
|
||||||
Collission, // in case of slave mode, during sending data to master
|
|
||||||
BufferEmpty,
|
|
||||||
BufferFull,
|
|
||||||
BufferSize,
|
BufferSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
#[repr(usize)]
|
||||||
|
pub enum AddressType {
|
||||||
|
Address1 = 0,
|
||||||
|
Address2,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
pub trait Instance: crate::rcc::RccPeripheral {
|
pub trait Instance: crate::rcc::RccPeripheral {
|
||||||
|
@ -22,7 +22,7 @@ use crate::dma::NoDma;
|
|||||||
use crate::dma::Transfer;
|
use crate::dma::Transfer;
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Pull;
|
use crate::gpio::Pull;
|
||||||
use crate::i2c::{Error, Instance, SclPin, SdaPin};
|
use crate::i2c::{AddressType, Error, Instance, SclPin, SdaPin};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::pac::i2c;
|
use crate::pac::i2c;
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
@ -57,10 +57,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
|||||||
let b = match state_m.read_byte() {
|
let b = match state_m.read_byte() {
|
||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
state_m.result = Some(e);
|
// An extra interrupt after the last byte is sent seems to be generated always
|
||||||
regs.cr2().modify(|w| {
|
// Do not generate an error in this (overrun) case
|
||||||
w.set_nack(true);
|
match e {
|
||||||
});
|
Error::Overrun => (),
|
||||||
|
_ => state_m.result = Some(e),
|
||||||
|
}
|
||||||
0xFF
|
0xFF
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -72,10 +74,6 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
|||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
state_m.result = Some(e);
|
state_m.result = Some(e);
|
||||||
// Send a NACK
|
|
||||||
regs.cr2().modify(|w| {
|
|
||||||
w.set_nack(true);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if isr.stopf() {
|
} else if isr.stopf() {
|
||||||
@ -104,6 +102,10 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
|||||||
// during sending nbytes automatically send a ACK, stretch clock after last byte
|
// during sending nbytes automatically send a ACK, stretch clock after last byte
|
||||||
w.set_reload(vals::Reload::COMPLETED);
|
w.set_reload(vals::Reload::COMPLETED);
|
||||||
});
|
});
|
||||||
|
// restore sbc after a master_write_read transaction
|
||||||
|
T::regs().cr1().modify(|reg| {
|
||||||
|
reg.set_sbc(true);
|
||||||
|
});
|
||||||
// flush i2c tx register
|
// flush i2c tx register
|
||||||
regs.isr().write(|w| w.set_txe(true));
|
regs.isr().write(|w| w.set_txe(true));
|
||||||
// fill rx data with the first byte
|
// fill rx data with the first byte
|
||||||
@ -232,37 +234,31 @@ impl I2cStateMachine {
|
|||||||
}
|
}
|
||||||
fn read_byte(&mut self) -> Result<u8, Error> {
|
fn read_byte(&mut self) -> Result<u8, Error> {
|
||||||
let adress_type = if self.address1 == self.current_address as u16 {
|
let adress_type = if self.address1 == self.current_address as u16 {
|
||||||
AddressType::MainAddress
|
AddressType::Address1
|
||||||
} else {
|
} else {
|
||||||
AddressType::GenericAddress
|
AddressType::Address2
|
||||||
};
|
};
|
||||||
self.buffers[adress_type as usize][vals::Dir::READ as usize].master_read()
|
self.buffers[adress_type as usize][vals::Dir::READ as usize].master_read()
|
||||||
}
|
}
|
||||||
fn write_byte(&mut self, b: u8) -> Result<(), Error> {
|
fn write_byte(&mut self, b: u8) -> Result<(), Error> {
|
||||||
let adress_type = if self.address1 == self.current_address as u16 {
|
let adress_type = if self.address1 == self.current_address as u16 {
|
||||||
AddressType::MainAddress
|
AddressType::Address1
|
||||||
} else {
|
} else {
|
||||||
AddressType::GenericAddress
|
AddressType::Address2
|
||||||
};
|
};
|
||||||
self.buffers[adress_type as usize][vals::Dir::WRITE as usize].master_write(b)
|
self.buffers[adress_type as usize][vals::Dir::WRITE as usize].master_write(b)
|
||||||
}
|
}
|
||||||
fn get_size(&self) -> u8 {
|
fn get_size(&self) -> u8 {
|
||||||
let adress_type = if self.address1 == self.current_address as u16 {
|
let adress_type = if self.address1 == self.current_address as u16 {
|
||||||
AddressType::MainAddress
|
AddressType::Address1
|
||||||
} else {
|
} else {
|
||||||
AddressType::GenericAddress
|
AddressType::Address2
|
||||||
};
|
};
|
||||||
self.buffers[adress_type as usize][self.dir as usize].size
|
self.buffers[adress_type as usize][self.dir as usize].size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const BUFFER_SIZE: usize = 64;
|
const BUFFER_SIZE: usize = 64;
|
||||||
|
|
||||||
#[repr(usize)]
|
|
||||||
pub enum AddressType {
|
|
||||||
MainAddress = 0,
|
|
||||||
GenericAddress,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct I2cBuffer {
|
struct I2cBuffer {
|
||||||
buffer: [u8; BUFFER_SIZE],
|
buffer: [u8; BUFFER_SIZE],
|
||||||
index: usize,
|
index: usize,
|
||||||
@ -280,12 +276,15 @@ impl I2cBuffer {
|
|||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
self.index = 0;
|
self.index = 0;
|
||||||
self.size = 0;
|
self.size = 0;
|
||||||
|
for i in 0..self.buffer.len() {
|
||||||
|
self.buffer[i] = 0xFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// master read slave write scenario. Master can read until self.size bytes
|
/// master read slave write scenario. Master can read until self.size bytes
|
||||||
/// If no data available (self.size == 0)
|
/// If no data available (self.size == 0)
|
||||||
fn master_read(&mut self) -> Result<u8, Error> {
|
fn master_read(&mut self) -> Result<u8, Error> {
|
||||||
if self.size == 0 {
|
if self.size == 0 {
|
||||||
return Err(Error::BufferEmpty);
|
return Err(Error::ZeroLengthTransfer);
|
||||||
};
|
};
|
||||||
if self.index < self.size as usize {
|
if self.index < self.size as usize {
|
||||||
let b = self.buffer[self.index];
|
let b = self.buffer[self.index];
|
||||||
@ -303,14 +302,14 @@ impl I2cBuffer {
|
|||||||
self.size = self.index as u8;
|
self.size = self.index as u8;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BufferFull)
|
Err(Error::Overrun)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// read data into this buffer (master read, slave write)
|
// read data into this buffer (master read, slave write)
|
||||||
fn from_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
fn from_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||||
let len = buffer.len();
|
let len = buffer.len();
|
||||||
if len > self.buffer.len() {
|
if len > self.buffer.len() {
|
||||||
return Err(Error::BufferSize);
|
return Err(Error::Overrun);
|
||||||
};
|
};
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
self.buffer[i] = buffer[i];
|
self.buffer[i] = buffer[i];
|
||||||
@ -400,13 +399,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
T::regs().oar1().write(|reg| {
|
T::regs().oar1().write(|reg| {
|
||||||
reg.set_oa1en(false);
|
reg.set_oa1en(false);
|
||||||
});
|
});
|
||||||
let mode = if config.address_11bits {
|
let (mode, address) = if config.address_11bits {
|
||||||
vals::Addmode::BIT10
|
(vals::Addmode::BIT10, config.slave_address_1)
|
||||||
} else {
|
} else {
|
||||||
vals::Addmode::BIT7
|
(vals::Addmode::BIT7, config.slave_address_1 << 1)
|
||||||
};
|
};
|
||||||
T::regs().oar1().write(|reg| {
|
T::regs().oar1().write(|reg| {
|
||||||
reg.set_oa1(config.slave_address_1);
|
reg.set_oa1(address);
|
||||||
reg.set_oa1mode(mode);
|
reg.set_oa1mode(mode);
|
||||||
reg.set_oa1en(true);
|
reg.set_oa1en(true);
|
||||||
});
|
});
|
||||||
@ -1038,7 +1037,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
// =========================
|
// =========================
|
||||||
// async Slave implementation
|
// async Slave implementation
|
||||||
/// Starts listening for slave transactions
|
/// Starts listening for slave transactions
|
||||||
pub fn slave_start_listen(&mut self) -> Result<(), super::Error> {
|
pub fn slave_start_listen(&self) -> Result<(), super::Error> {
|
||||||
T::regs().cr1().modify(|reg| {
|
T::regs().cr1().modify(|reg| {
|
||||||
reg.set_addrie(true);
|
reg.set_addrie(true);
|
||||||
reg.set_txie(true);
|
reg.set_txie(true);
|
||||||
@ -1063,7 +1062,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
// slave stop listening for slave transactions and switch back to master role
|
// slave stop listening for slave transactions and switch back to master role
|
||||||
pub fn slave_stop_listen(&mut self) -> Result<(), super::Error> {
|
pub fn slave_stop_listen(&self) -> Result<(), super::Error> {
|
||||||
T::regs().cr1().modify(|reg| {
|
T::regs().cr1().modify(|reg| {
|
||||||
reg.set_addrie(false);
|
reg.set_addrie(false);
|
||||||
reg.set_txie(false);
|
reg.set_txie(false);
|
||||||
@ -1080,22 +1079,32 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn slave_sbc(&mut self, sbc_enabled: bool) {
|
pub fn slave_sbc(&self, sbc_enabled: bool) {
|
||||||
// enable acknowlidge control
|
// enable acknowlidge control
|
||||||
T::regs().cr1().modify(|w| w.set_sbc(sbc_enabled));
|
T::regs().cr1().modify(|w| w.set_sbc(sbc_enabled));
|
||||||
}
|
}
|
||||||
/// Prepare write data to master (master_read_slave_write) before transaction starts
|
/// Prepare write data to master (master_read_slave_write) before transaction starts
|
||||||
/// Will return buffersize error in case the incoming buffer is too big
|
/// Will return buffersize error in case the incoming buffer is too big
|
||||||
pub fn slave_write_buffer(&mut self, buffer: &[u8], address_type: AddressType) -> Result<(), super::Error> {
|
pub fn slave_write_buffer(&self, buffer: &[u8], address_type: AddressType) -> Result<(), super::Error> {
|
||||||
T::state().mutex.lock(|f| {
|
T::state().mutex.lock(|f| {
|
||||||
let mut state_m = f.borrow_mut();
|
let mut state_m = f.borrow_mut();
|
||||||
let buf = &mut state_m.buffers[address_type as usize][vals::Dir::READ as usize];
|
let buf = &mut state_m.buffers[address_type as usize][vals::Dir::READ as usize];
|
||||||
buf.from_buffer(buffer)
|
buf.from_buffer(buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn slave_reset_buffer(&self, address_type: AddressType) {
|
||||||
|
T::state().mutex.lock(|f| {
|
||||||
|
let mut state_m = f.borrow_mut();
|
||||||
|
let buf_r = &mut state_m.buffers[address_type as usize][vals::Dir::READ as usize];
|
||||||
|
buf_r.reset();
|
||||||
|
let buf_w = &mut state_m.buffers[address_type as usize][vals::Dir::WRITE as usize];
|
||||||
|
buf_w.reset();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Read data from master (master_write_slave_read) after transaction is finished
|
/// Read data from master (master_write_slave_read) after transaction is finished
|
||||||
/// Will fail if the size of the incoming buffer is smaller than the received bytes
|
/// Will fail if the size of the incoming buffer is smaller than the received bytes
|
||||||
pub fn slave_read_buffer(&mut self, buffer: &mut [u8], address_type: AddressType) -> Result<(), super::Error> {
|
pub fn slave_read_buffer(&self, buffer: &mut [u8], address_type: AddressType) -> Result<(), super::Error> {
|
||||||
T::state().mutex.lock(|f| {
|
T::state().mutex.lock(|f| {
|
||||||
let mut state_m = f.borrow_mut();
|
let mut state_m = f.borrow_mut();
|
||||||
let buf = &mut state_m.buffers[address_type as usize][vals::Dir::WRITE as usize];
|
let buf = &mut state_m.buffers[address_type as usize][vals::Dir::WRITE as usize];
|
||||||
@ -1103,7 +1112,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/// wait until a slave transaction is finished, and return tuple address, direction, data size and error
|
/// wait until a slave transaction is finished, and return tuple address, direction, data size and error
|
||||||
pub async fn slave_transaction(&mut self) -> (u8, vals::Dir, u8, Option<Error>) {
|
pub async fn slave_transaction(&self) -> (u8, vals::Dir, u8, Option<Error>) {
|
||||||
// async wait until addressed
|
// async wait until addressed
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().waker.register(cx.waker());
|
T::state().waker.register(cx.waker());
|
||||||
|
@ -9,6 +9,7 @@ use core::fmt::{self, Write};
|
|||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dma::NoDma;
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::i2c::{Error, I2c};
|
use embassy_stm32::i2c::{Error, I2c};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usart::UartTx;
|
use embassy_stm32::usart::UartTx;
|
||||||
@ -35,10 +36,21 @@ impl fmt::Write for SerialWriter {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn system_ticker(mut led: Output<'static, peripherals::PA6>) {
|
||||||
|
loop {
|
||||||
|
Timer::after(Duration::from_millis(200)).await;
|
||||||
|
led.set_high();
|
||||||
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
|
led.set_low();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
// let led = Output::new(p.PA5, Level::High, Speed::Low); // nucleog070rb board
|
||||||
|
let led = Output::new(p.PA6, Level::High, Speed::Low);
|
||||||
|
|
||||||
let uart = usart::Uart::new(
|
let uart = usart::Uart::new(
|
||||||
p.USART1,
|
p.USART1,
|
||||||
@ -71,19 +83,21 @@ async fn main(_spawner: Spawner) {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
Timer::after(Duration::from_millis(1000)).await;
|
Timer::after(Duration::from_millis(1000)).await;
|
||||||
|
spawner.spawn(system_ticker(led)).unwrap();
|
||||||
|
|
||||||
// start of the acutal test
|
// start of the acutal test
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
loop {
|
loop {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
writeln!(&mut writer, "Loop counter: {:?}", counter).unwrap();
|
writeln!(&mut writer, "Loop counter: {:?}\r", counter).unwrap();
|
||||||
|
|
||||||
let mut buf_20 = [0_u8; 20];
|
let mut buf_20 = [0_u8; 20];
|
||||||
let mut buf_20a = [0_u8; 20];
|
let mut buf_20a = [0_u8; 20];
|
||||||
let mut buf_64 = [0_u8; 64];
|
let mut buf_64 = [0_u8; 64];
|
||||||
let mut buf_65 = [0_u8; 65];
|
let mut buf_65 = [0_u8; 65];
|
||||||
|
let mut buf_2 = [0_u8; 2];
|
||||||
|
|
||||||
writeln!(&mut writer, "Start of test\n\r").unwrap();
|
writeln!(&mut writer, "Start of test\r").unwrap();
|
||||||
|
|
||||||
for i in 0..buf_20.len() {
|
for i in 0..buf_20.len() {
|
||||||
buf_20[i] = 0x20 + (i as u8)
|
buf_20[i] = 0x20 + (i as u8)
|
||||||
@ -94,117 +108,126 @@ async fn main(_spawner: Spawner) {
|
|||||||
for i in 0..buf_65.len() {
|
for i in 0..buf_65.len() {
|
||||||
buf_65[i] = 0x60 + (i as u8)
|
buf_65[i] = 0x60 + (i as u8)
|
||||||
}
|
}
|
||||||
// test 1: slave address 0x61 should not be addressable
|
// 0x41 good case master write 20 bytes
|
||||||
match i2c.blocking_write(0x61, &buf_20) {
|
|
||||||
Ok(_) => writeln!(&mut writer, "Test 1 failed: would expect nack\n\r").unwrap(),
|
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
|
||||||
Err(err) => writeln!(&mut writer, "Test 1 passed: expected NACK error: {:?}", err).unwrap(),
|
|
||||||
};
|
|
||||||
// 0x41 good case master write slave read: master does send 20 bytes slave receives 20 bytes
|
|
||||||
match i2c.blocking_write(0x41, &buf_20) {
|
match i2c.blocking_write(0x41, &buf_20) {
|
||||||
Ok(_) => writeln!(&mut writer, "Test 0x41 passed\n\r").unwrap(),
|
Ok(_) => writeln!(&mut writer, "Test 0x41 passed\r").unwrap(),
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x41 failed. Error: {:?}", err).unwrap(),
|
Err(err) => writeln!(&mut writer, "Test 0x41 failed. Error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
// 0x42 edge case master write exact 64 bytes: must succeed on master and slave
|
// 0x42 edge case master write exact 64 bytes: must succeed on master and slave
|
||||||
match i2c.blocking_write(0x42, &buf_64) {
|
match i2c.blocking_write(0x42, &buf_64) {
|
||||||
Ok(_) => writeln!(&mut writer, "Test 0x42 passed. Master write exact 64 bytes\n\r").unwrap(),
|
Ok(_) => writeln!(&mut writer, "Test 0x42 passed. Master write exact 64 bytes\r").unwrap(),
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x42 failed. Got error: {:?}\r\n", err).unwrap(),
|
Err(err) => writeln!(&mut writer, "Test 0x42 failed. Got error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
// 0x43 edge case master write exact 65 bytes: 1 too many must fail on master and slave
|
// 0x43 edge case master write exact 65 bytes: 1 too many must fail on master and slave
|
||||||
match i2c.blocking_write(0x43, &buf_65) {
|
match i2c.blocking_write(0x43, &buf_65) {
|
||||||
Ok(_) => writeln!(&mut writer, "Test 0x43 Failed. Expected a Nack\n\r").unwrap(),
|
Ok(_) => writeln!(&mut writer, "Test 0x43 Failed. Expected a Nack\r").unwrap(),
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(
|
Err(err) => writeln!(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
"Test 0x43 passed: Got error NACK du to buffer of 1 too big {:?}\r\n",
|
"Test 0x43 passed: Got error NACK du to buffer of 1 too big {:?}\r",
|
||||||
err
|
err
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 0x44 master write read combined transaction write 20 bytes, then read 20 bytes
|
||||||
|
match i2c.blocking_write_read(0x44, &buf_20, &mut buf_20a) {
|
||||||
|
Ok(_) => {
|
||||||
|
writeln!(&mut writer, "Test 0x44 Ok \r").unwrap();
|
||||||
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"Uppercase input should be transformed to lowercase, A -> b \r"
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
print_buffer(&mut writer, &buf_20a);
|
||||||
|
}
|
||||||
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
|
Err(err) => writeln!(&mut writer, "Test 0x44 error: {:?}\r", err).unwrap(),
|
||||||
|
};
|
||||||
|
// master read. Slave did not prepare a buffer (buffer empty) and will NACK
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
match i2c.blocking_read(0x48, &mut buf_20) {
|
match i2c.blocking_read(0x48, &mut buf_20) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
writeln!(&mut writer, "Test 0x48 failed. Read expected to fail!\n\r").unwrap();
|
writeln!(&mut writer, "Test 0x48 failed. Read expected to fail!\r").unwrap();
|
||||||
}
|
}
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(
|
Err(err) => writeln!(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
"Test 0x48 Ok. First time, slave did not yet prepare a buffer Error: {:?}\r\n",
|
"Test 0x48 Ok. First time, slave did not yet prepare a buffer Error: {:?}\r",
|
||||||
err
|
err
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
|
// master read 20 bytes good case.
|
||||||
match i2c.blocking_read(0x49, &mut buf_20) {
|
match i2c.blocking_read(0x49, &mut buf_20) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
writeln!(&mut writer, "Test 0x49 Read Ok\n\r").unwrap();
|
writeln!(&mut writer, "Test 0x49 Read Ok\r").unwrap();
|
||||||
print_buffer(&mut writer, &buf_20);
|
print_buffer(&mut writer, &buf_20);
|
||||||
}
|
}
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x49 Error: {:?}\r\n", err).unwrap(),
|
Err(err) => writeln!(&mut writer, "Test 0x49 Error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
|
// master read 64 bytes, but the slave did prepair only 20 Should fail with NACK
|
||||||
match i2c.blocking_read(0x4A, &mut buf_64) {
|
match i2c.blocking_read(0x4A, &mut buf_64) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
writeln!(&mut writer, "Test 0x4A failed. Expected was a NACK error\n\r").unwrap();
|
writeln!(&mut writer, "Test 0x4A failed. Expected was a NACK error\r").unwrap();
|
||||||
print_buffer(&mut writer, &buf_64);
|
print_buffer(&mut writer, &buf_64);
|
||||||
}
|
}
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x4A passed. Expected to fail. Error: {:?}\r\n", err).unwrap(),
|
Err(err) => writeln!(&mut writer, "Test 0x4A passed. Expected to fail. Error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
match i2c.blocking_read(0x4B, &mut buf_64) {
|
match i2c.blocking_read(0x4B, &mut buf_64) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
writeln!(&mut writer, "Test 0x4B passed\n\r").unwrap();
|
writeln!(&mut writer, "Test 0x4B passed\r").unwrap();
|
||||||
print_buffer(&mut writer, &buf_64);
|
print_buffer(&mut writer, &buf_64);
|
||||||
}
|
}
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r\n", err).unwrap(),
|
Err(err) => writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
match i2c.blocking_write_read(0x44, &buf_20, &mut buf_20a) {
|
|
||||||
Ok(_) => {
|
|
||||||
writeln!(&mut writer, "Test 0x44 Ok \n\r").unwrap();
|
|
||||||
writeln!(
|
|
||||||
&mut writer,
|
|
||||||
"Uppercase input should be transformed to lowercase, A -> b "
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for i in 0..buf_20a.len() {
|
|
||||||
writeln!(&mut writer, "{}", buf_20[i]).unwrap();
|
|
||||||
}
|
|
||||||
writeln!(&mut writer, "\n\r").unwrap()
|
|
||||||
}
|
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x44 error: {:?}", err).unwrap(),
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
// 0x4F test end and slave will present results
|
|
||||||
|
// test for arbitration lost. 2 slaves respond on address 10 one with 0xFF03, on with 0xFF04
|
||||||
|
// if both are online the one with 0xFF04 should report arbitration loss, here we read 0xFF03
|
||||||
|
match i2c.blocking_read(0x10, &mut buf_2) {
|
||||||
|
Ok(_) => {
|
||||||
|
writeln!(&mut writer, "Test 0x10 Received {:2x}:{:2x}\r", buf_2[0], buf_2[1]).unwrap();
|
||||||
|
writeln!(&mut writer, "Look in the log of the slaves to evaluate the result\r").unwrap();
|
||||||
|
}
|
||||||
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
|
Err(err) => writeln!(&mut writer, "Test 0x10 Failed: Error: {:?}", err).unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 0x4F Master does read 2 bytes with the result of the slave
|
||||||
let mut result: [u8; 2] = [0, 0];
|
let mut result: [u8; 2] = [0, 0];
|
||||||
match i2c.blocking_read(0x4F, &mut result) {
|
match i2c.blocking_read(0x4F, &mut result) {
|
||||||
Ok(_) => writeln!(
|
Ok(_) => writeln!(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
"Result of the whole test as reported by the slave count/errors: {}/{}\r\n",
|
"Result of the whole test as reported by the slave count/errors: {}/{}\r",
|
||||||
result[0], result[1]
|
result[0], result[1]
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
|
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\r").unwrap(),
|
||||||
Err(err) => writeln!(&mut writer, "Test 0x4F unexpected error: {:?}\r\n", err).unwrap(),
|
Err(err) => writeln!(&mut writer, "Test 0x4F unexpected error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
writeln!(&mut writer, "\n\r").unwrap();
|
writeln!(&mut writer, "\r").unwrap();
|
||||||
|
|
||||||
Timer::after(Duration::from_millis(10_000)).await;
|
Timer::after(Duration::from_millis(10_000)).await;
|
||||||
}
|
}
|
||||||
fn print_buffer(writer: &mut SerialWriter, buf: &[u8]) {
|
fn print_buffer(writer: &mut SerialWriter, buf: &[u8]) {
|
||||||
for i in 0..buf.len() {
|
for i in 0..buf.len() {
|
||||||
write!(writer, " {:2x} ", buf[i]).unwrap();
|
write!(writer, " {:2x} ", buf[i]).unwrap();
|
||||||
}
|
}
|
||||||
writeln!(writer, "\n\r\n\r").unwrap()
|
writeln!(writer, "\r\r").unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ impl fmt::Write for SerialWriter {
|
|||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
let mut led = Output::new(p.PA5, Level::High, Speed::Low);
|
let led = Output::new(p.PA5, Level::High, Speed::Low);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let uart = usart::Uart::new(
|
let uart = usart::Uart::new(
|
||||||
@ -107,15 +107,15 @@ async fn main(spawner: Spawner) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut config = i2c::Config::default();
|
let mut config = i2c::Config::default();
|
||||||
config.slave_address_7bits(0x4);
|
config.slave_address_7bits(0x10); // for arbitration lost test
|
||||||
config.slave_address_2(0x41, vals::Oamsk::MASK4);
|
config.slave_address_2(0x41, vals::Oamsk::MASK4);
|
||||||
writeln!(&mut writer, "After config:\r",).unwrap();
|
|
||||||
|
|
||||||
let mut i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, NoDma, NoDma, Hertz(100_000), config);
|
let i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, NoDma, NoDma, Hertz(100_000), config);
|
||||||
writeln!(&mut writer, "After i2c init\r").unwrap();
|
|
||||||
|
|
||||||
let mut buf_64 = [0; 64]; // buffer is longer than master will send: wait for STOP condition
|
let mut buf_64 = [0; 64]; // buffer is longer than master will send: wait for STOP condition
|
||||||
let mut buf_20 = [0; 20]; // buffer is shorter than master will send: wait for STOP condition
|
let mut buf_20 = [0; 20]; // buffer is shorter than master will send: wait for STOP condition
|
||||||
|
let mut buf_20a = [0; 20];
|
||||||
|
let mut buf_2 = [0; 2];
|
||||||
let mut errors = 0;
|
let mut errors = 0;
|
||||||
let mut address = 0;
|
let mut address = 0;
|
||||||
let mut dir = vals::Dir::READ;
|
let mut dir = vals::Dir::READ;
|
||||||
@ -131,19 +131,26 @@ async fn main(spawner: Spawner) {
|
|||||||
counter += 1;
|
counter += 1;
|
||||||
writeln!(&mut writer, "Loop: {}\r", counter).unwrap();
|
writeln!(&mut writer, "Loop: {}\r", counter).unwrap();
|
||||||
|
|
||||||
|
// clear master write buffers for sure
|
||||||
|
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::Address2);
|
||||||
|
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::Address1);
|
||||||
|
|
||||||
for i in 0..buf_20.len() {
|
for i in 0..buf_20.len() {
|
||||||
buf_20[i] = 0x20 + (i as u8)
|
buf_20[i] = 0x20 + (i as u8)
|
||||||
}
|
}
|
||||||
|
for i in 0..buf_20a.len() {
|
||||||
|
buf_20a[i] = 0x40 - (i as u8)
|
||||||
|
}
|
||||||
for i in 0..buf_64.len() {
|
for i in 0..buf_64.len() {
|
||||||
buf_64[i] = 0x60 + (i as u8)
|
buf_64[i] = 0x60 + (i as u8)
|
||||||
}
|
}
|
||||||
|
// content for test 0x10
|
||||||
|
buf_2[0] = 0xFF;
|
||||||
|
buf_2[1] = 0x04;
|
||||||
|
_ = i2c.slave_write_buffer(&mut buf_2, i2c::AddressType::Address1);
|
||||||
|
|
||||||
writeln!(&mut writer, "Waiting for master activity\r").unwrap();
|
writeln!(&mut writer, "Waiting for master activity\r").unwrap();
|
||||||
|
|
||||||
// clear write buffers for sure
|
|
||||||
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress);
|
|
||||||
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::MainAddress);
|
|
||||||
|
|
||||||
let (address, dir, size, result) = i2c.slave_transaction().await;
|
let (address, dir, size, result) = i2c.slave_transaction().await;
|
||||||
writeln!(
|
writeln!(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
@ -152,30 +159,85 @@ async fn main(spawner: Spawner) {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tcount += 1;
|
tcount += 1;
|
||||||
|
// preparations for the next round
|
||||||
|
match address {
|
||||||
|
0x42 => {
|
||||||
|
// prepare for test 0x44: master write read. 20a is send to the master
|
||||||
|
_ = i2c.slave_write_buffer(&mut buf_20a, i2c::AddressType::Address2);
|
||||||
|
i2c.slave_sbc(false);
|
||||||
|
}
|
||||||
|
0x43 => {
|
||||||
|
// prepare for test 0x44: master write read. 20a is send to the master
|
||||||
|
_ = i2c.slave_write_buffer(&mut buf_20a, i2c::AddressType::Address2);
|
||||||
|
i2c.slave_sbc(false);
|
||||||
|
}
|
||||||
|
0x44 => {
|
||||||
|
// prepare for test 0x48: slave does have no buffer to read
|
||||||
|
i2c.slave_reset_buffer(i2c::AddressType::Address2);
|
||||||
|
}
|
||||||
|
0x48 => {
|
||||||
|
// 0x48 master read slave write slave did not yet prepare a buffer, master will fail
|
||||||
|
// prepare buffer for test 0x49
|
||||||
|
for i in 0..buf_20.len() {
|
||||||
|
buf_20[i] = 0x48 + (i as u8)
|
||||||
|
}
|
||||||
|
_ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::Address2);
|
||||||
|
}
|
||||||
|
0x49 => {
|
||||||
|
// prepare buffer for test 0x4A
|
||||||
|
for i in 0..buf_20.len() {
|
||||||
|
buf_20[i] = 0x49 + (i as u8)
|
||||||
|
}
|
||||||
|
match i2c.slave_write_buffer(&buf_20, i2c::AddressType::Address2) {
|
||||||
|
Err(_) => writeln!(&mut writer, "Buffer error\r").unwrap(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x4A => {
|
||||||
|
// prepare buffer for test 0x4B
|
||||||
|
for i in 0..buf_64.len() {
|
||||||
|
buf_64[i] = 0x4A + (i as u8)
|
||||||
|
}
|
||||||
|
match i2c.slave_write_buffer(&buf_64, i2c::AddressType::Address2) {
|
||||||
|
Err(_) => writeln!(&mut writer, "Buffer error\r").unwrap(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x4B => {
|
||||||
|
// prepare for test 0x4F
|
||||||
|
let result: [u8; 2] = [tcount, errors];
|
||||||
|
_ = i2c.slave_write_buffer(&result, i2c::AddressType::Address2);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
match address {
|
match address {
|
||||||
0x41 => {
|
0x41 => {
|
||||||
writeln!(&mut writer, "Evaluate test 0x41.\r\n").unwrap();
|
writeln!(&mut writer, "Evaluate test 0x41: Good case master write 20 bytes\r").unwrap();
|
||||||
checkIsWrite!(writer, dir);
|
checkIsWrite!(writer, dir);
|
||||||
_ = i2c.slave_read_buffer(&mut buf_20, i2c::AddressType::GenericAddress);
|
_ = i2c.slave_read_buffer(&mut buf_20, i2c::AddressType::Address2);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
writeln!(&mut writer, "Test 0x41 passed\r\n").unwrap();
|
writeln!(&mut writer, "Test 0x41 passed\r").unwrap();
|
||||||
print_buffer(&mut writer, &buf_20);
|
print_buffer(&mut writer, &buf_20);
|
||||||
}
|
}
|
||||||
Some(err) => {
|
Some(err) => {
|
||||||
errors += 1;
|
errors += 1;
|
||||||
writeln!(&mut writer, "Test 0x41 failed. Error: {:?}\r\n", err).unwrap()
|
writeln!(&mut writer, "Test 0x41 failed. Error: {:?}\r", err).unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
0x42 => {
|
0x42 => {
|
||||||
writeln!(&mut writer, "Evaluate test 0x42.\r\n").unwrap();
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"Evaluate test 0x42: edge case master write exact 64 bytes: must succeed on master and slave\r"
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
checkIsWrite!(writer, dir);
|
checkIsWrite!(writer, dir);
|
||||||
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress);
|
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::Address2);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
writeln!(&mut writer, "Test 0x42 passed. send 64 bytes\r\n").unwrap();
|
writeln!(&mut writer, "Test 0x42 passed. send 64 bytes\r").unwrap();
|
||||||
print_buffer(&mut writer, &buf_64);
|
print_buffer(&mut writer, &buf_64);
|
||||||
}
|
}
|
||||||
Some(err) => {
|
Some(err) => {
|
||||||
@ -185,9 +247,9 @@ async fn main(spawner: Spawner) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
0x43 => {
|
0x43 => {
|
||||||
writeln!(&mut writer, "Evaluate test 0x43.\r\n").unwrap();
|
writeln!(&mut writer, "Evaluate test 0x43.edge case master write exact 65 bytes: 1 too many must fail on master and slave\r").unwrap();
|
||||||
checkIsWrite!(writer, dir);
|
checkIsWrite!(writer, dir);
|
||||||
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::GenericAddress);
|
_ = i2c.slave_read_buffer(&mut buf_64, i2c::AddressType::Address2);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
errors += 1;
|
errors += 1;
|
||||||
@ -201,9 +263,32 @@ async fn main(spawner: Spawner) {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
0x44 => {
|
||||||
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"Evaluate test 0x44: master write read combined transaction write 20 bytes, then read 20 bytes \r"
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
checkIsRead!(writer, dir);
|
||||||
|
_ = i2c.slave_read_buffer(&mut buf_20, i2c::AddressType::Address2);
|
||||||
|
match result {
|
||||||
|
None => {
|
||||||
|
writeln!(&mut writer, "Test 0x44 passed\r").unwrap();
|
||||||
|
print_buffer(&mut writer, &buf_20)
|
||||||
|
}
|
||||||
|
Some(err) => {
|
||||||
|
errors += 1;
|
||||||
|
writeln!(&mut writer, "Test 0x44 failed. Error:{:?}\r", err).unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
0x48 => {
|
0x48 => {
|
||||||
// 0x48 master read slave write slave did not yet prepare a buffer, master will fail
|
// 0x48 master read slave write slave did not yet prepare a buffer, master will fail
|
||||||
writeln!(&mut writer, "Evaluate test 0x48.\r\n").unwrap();
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"Evaluate test 0x48. master read. Slave did not prepare a buffer (buffer empty) and will NACK\r"
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
checkIsRead!(writer, dir);
|
checkIsRead!(writer, dir);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
@ -212,16 +297,9 @@ async fn main(spawner: Spawner) {
|
|||||||
}
|
}
|
||||||
Some(err) => writeln!(&mut writer, "Test 0x48 passed. Got expected error: {:?}\r", err).unwrap(),
|
Some(err) => writeln!(&mut writer, "Test 0x48 passed. Got expected error: {:?}\r", err).unwrap(),
|
||||||
};
|
};
|
||||||
// prepare buffer for test 0x49
|
|
||||||
_ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::GenericAddress);
|
|
||||||
}
|
}
|
||||||
0x49 => {
|
0x49 => {
|
||||||
// prepare buffer for test 0x4A
|
writeln!(&mut writer, "Evaluate test 0x49. master read 20 bytes good case.\r").unwrap();
|
||||||
for i in 0..buf_20.len() {
|
|
||||||
buf_20[i] = 0x50 + (i as u8)
|
|
||||||
}
|
|
||||||
_ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::GenericAddress);
|
|
||||||
writeln!(&mut writer, "Evaluate test 0x49\r\n").unwrap();
|
|
||||||
checkIsRead!(writer, dir);
|
checkIsRead!(writer, dir);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
@ -232,33 +310,22 @@ async fn main(spawner: Spawner) {
|
|||||||
writeln!(&mut writer, "Test 0x49 failed. Error: {:?}\r", err).unwrap()
|
writeln!(&mut writer, "Test 0x49 failed. Error: {:?}\r", err).unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// prepare buffer for test 0x4A
|
|
||||||
_ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::GenericAddress);
|
|
||||||
}
|
}
|
||||||
0x4A => {
|
0x4A => {
|
||||||
// 0x4A master read slave write bad case: master expects 64 does slave does prepare 20 characters
|
// 0x4A master read slave write bad case: master expects 64 does slave does prepare 20 characters
|
||||||
// prepare buffer for test 0x4B
|
writeln!(&mut writer, "Evaluate test 0x4A.master read 64 bytes, but the slave did prepair only 20 Should fail with NACK\r").unwrap();
|
||||||
for i in 0..buf_64.len() {
|
|
||||||
buf_64[i] = 0x40 + (i as u8)
|
|
||||||
}
|
|
||||||
_ = i2c.slave_write_buffer(&buf_64, i2c::AddressType::GenericAddress);
|
|
||||||
|
|
||||||
writeln!(&mut writer, "Evaluate test 0x4A.\r\n").unwrap();
|
|
||||||
checkIsRead!(writer, dir);
|
checkIsRead!(writer, dir);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
|
errors += 1;
|
||||||
writeln!(&mut writer, "Test 0x4A failed . Expected an error").unwrap();
|
writeln!(&mut writer, "Test 0x4A failed . Expected an error").unwrap();
|
||||||
}
|
}
|
||||||
Some(err) => {
|
Some(err) => writeln!(&mut writer, "Test 0x4A passed. Expected error: {:?}\r", err).unwrap(),
|
||||||
errors += 1;
|
|
||||||
writeln!(&mut writer, "Test 0x4A passed. Expected error: {:?}\r", err).unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ = i2c.slave_write_buffer(&buf_20, i2c::AddressType::GenericAddress);
|
|
||||||
}
|
}
|
||||||
0x4B => {
|
0x4B => {
|
||||||
// Master-read-slave-write Master expects 64 bytes, Should be ok
|
// Master-read-slave-write Master expects 64 bytes, Should be ok
|
||||||
writeln!(&mut writer, "Evaluate test 0x4B. .\r\n").unwrap();
|
writeln!(&mut writer, "Evaluate test 0x4B. Master read 64 bytes good case.\r").unwrap();
|
||||||
checkIsRead!(writer, dir);
|
checkIsRead!(writer, dir);
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
@ -269,14 +336,11 @@ async fn main(spawner: Spawner) {
|
|||||||
writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r", err).unwrap()
|
writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r", err).unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// prepare for test 0x4F
|
|
||||||
let result: [u8; 2] = [tcount, errors];
|
|
||||||
_ = i2c.slave_write_buffer(&result, i2c::AddressType::GenericAddress);
|
|
||||||
}
|
}
|
||||||
0x4F => {
|
0x4F => {
|
||||||
// Master-read-slave-write 2 bytes with test summary Should be ok.
|
// Master-read-slave-write 2 bytes with test summary Should be ok.
|
||||||
checkIsRead!(writer, dir);
|
checkIsRead!(writer, dir);
|
||||||
writeln!(&mut writer, "Evaluate test 0x4F.\r\n").unwrap();
|
writeln!(&mut writer, "Evaluate test 0x4F. Send test summary\r").unwrap();
|
||||||
match result {
|
match result {
|
||||||
None => {
|
None => {
|
||||||
writeln!(&mut writer, "Test 0x4F Result send to master\r").unwrap();
|
writeln!(&mut writer, "Test 0x4F Result send to master\r").unwrap();
|
||||||
@ -296,6 +360,30 @@ async fn main(spawner: Spawner) {
|
|||||||
tcount = 0;
|
tcount = 0;
|
||||||
errors = 0;
|
errors = 0;
|
||||||
}
|
}
|
||||||
|
0x10 => {
|
||||||
|
// Arbitration lost test Master does read 2 bytes on address 0x10
|
||||||
|
// this slave will send 0xFF04, the other slave will send 0xFF03
|
||||||
|
// This slave should generate a arbitration lost if the other slave is online
|
||||||
|
writeln!(&mut writer, "Evaluate test 0x10: slave arbitration lost.\r").unwrap();
|
||||||
|
checkIsRead!(writer, dir);
|
||||||
|
match result {
|
||||||
|
None => {
|
||||||
|
writeln!(&mut writer, "Test 0x10 should fail if a second slave with testcase i2c_salve_arbitration.rs is connected.\r").unwrap();
|
||||||
|
errors += 1;
|
||||||
|
}
|
||||||
|
Some(err) => writeln!(&mut writer, "Test 0x10 passed. Error: {:?}\r", err).unwrap(),
|
||||||
|
};
|
||||||
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"Test finished. nr tests/nr errors: {}/{}!\r",
|
||||||
|
tcount, errors
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
writeln!(&mut writer, "-----\r").unwrap();
|
||||||
|
tcount = 0;
|
||||||
|
errors = 0;
|
||||||
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,6 +391,6 @@ async fn main(spawner: Spawner) {
|
|||||||
for i in 0..buf.len() {
|
for i in 0..buf.len() {
|
||||||
write!(writer, " {:2x} ", buf[i]).unwrap();
|
write!(writer, " {:2x} ", buf[i]).unwrap();
|
||||||
}
|
}
|
||||||
writeln!(writer, "\n\r").unwrap()
|
writeln!(writer, "\r").unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
153
examples/stm32g0/src/bin/i2c_slave_arbitration.rs
Normal file
153
examples/stm32g0/src/bin/i2c_slave_arbitration.rs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
// test is targeted for nucleo-g070RB board
|
||||||
|
// this test will only respond to address 0x10, master read with 0xFF03
|
||||||
|
|
||||||
|
use core::fmt::{self, Write};
|
||||||
|
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::dma::NoDma;
|
||||||
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
|
use embassy_stm32::i2c::{Error, I2c};
|
||||||
|
use embassy_stm32::pac::i2c::vals;
|
||||||
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_stm32::usart::UartTx;
|
||||||
|
use embassy_stm32::{bind_interrupts, i2c, peripherals, usart};
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2C1 => i2c::InterruptHandler<peripherals::I2C1>;
|
||||||
|
USART1 => usart::InterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
macro_rules! checkIsWrite {
|
||||||
|
($writer:ident, $direction:ident) => {
|
||||||
|
match $direction {
|
||||||
|
vals::Dir::WRITE => (),
|
||||||
|
_ => {
|
||||||
|
write!($writer, "Error incorrect direction {:?}\r", $direction as usize).unwrap();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
macro_rules! checkIsRead {
|
||||||
|
($writer:ident, $direction:ident) => {
|
||||||
|
match $direction {
|
||||||
|
vals::Dir::READ => (),
|
||||||
|
_ => {
|
||||||
|
write!($writer, "Error incorrect direction {:?}\r", $direction as usize).unwrap();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SerialWriter {
|
||||||
|
tx: UartTx<'static, peripherals::USART1, peripherals::DMA1_CH1>,
|
||||||
|
}
|
||||||
|
impl SerialWriter {
|
||||||
|
pub fn new(tx: UartTx<'static, peripherals::USART1, peripherals::DMA1_CH1>) -> Self {
|
||||||
|
SerialWriter { tx }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Write for SerialWriter {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
_ = self.tx.blocking_write(s.as_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
let led = Output::new(p.PA5, Level::High, Speed::Low);
|
||||||
|
|
||||||
|
let uart = usart::Uart::new(
|
||||||
|
p.USART1,
|
||||||
|
p.PB7,
|
||||||
|
p.PB6,
|
||||||
|
Irqs,
|
||||||
|
p.DMA1_CH1,
|
||||||
|
p.DMA1_CH2,
|
||||||
|
usart::Config::default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
/*
|
||||||
|
let uart = usart::Uart::new(
|
||||||
|
p.USART2,
|
||||||
|
p.PA3,
|
||||||
|
p.PA2,
|
||||||
|
Irqs,
|
||||||
|
p.DMA1_CH1,
|
||||||
|
p.DMA1_CH2,
|
||||||
|
usart::Config::default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
*/
|
||||||
|
let (tx, _rx) = uart.split();
|
||||||
|
|
||||||
|
let mut writer = SerialWriter::new(tx);
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"i2c slave test for arbitration lost. Will respond to address 0x10\r"
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut config = i2c::Config::default();
|
||||||
|
config.slave_address_7bits(0x10); // for arbitration lost test
|
||||||
|
|
||||||
|
let i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, NoDma, NoDma, Hertz(100_000), config);
|
||||||
|
|
||||||
|
let mut buf_2 = [0; 2];
|
||||||
|
let mut address = 0;
|
||||||
|
let mut dir = vals::Dir::READ;
|
||||||
|
let mut counter = 0;
|
||||||
|
let mut result: Option<Error> = None;
|
||||||
|
|
||||||
|
// start of the actual test
|
||||||
|
i2c.slave_start_listen().unwrap();
|
||||||
|
loop {
|
||||||
|
counter += 1;
|
||||||
|
writeln!(&mut writer, "Loop: {}\r", counter).unwrap();
|
||||||
|
|
||||||
|
// content for test 0x10
|
||||||
|
buf_2[0] = 0xFF;
|
||||||
|
buf_2[1] = 0x03;
|
||||||
|
_ = i2c.slave_write_buffer(&mut buf_2, i2c::AddressType::MainAddress);
|
||||||
|
|
||||||
|
writeln!(&mut writer, "Waiting for master activity\r").unwrap();
|
||||||
|
|
||||||
|
let (address, dir, size, result) = i2c.slave_transaction().await;
|
||||||
|
writeln!(
|
||||||
|
&mut writer,
|
||||||
|
"Address: x{:2x} dir: {:?} size: x{:2x}, Result:{:?}\r",
|
||||||
|
address, dir as u8, size, result
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match address {
|
||||||
|
0x10 => {
|
||||||
|
// Arbitration lost test Master does read 2 bytes on address 0x10
|
||||||
|
// this slave will send 0xFF03, the other slave will send 0xFF04
|
||||||
|
// This slave should win , so no error here
|
||||||
|
writeln!(&mut writer, "Evaluate arbitration lost test 0x10.\r\n").unwrap();
|
||||||
|
checkIsRead!(writer, dir);
|
||||||
|
match result {
|
||||||
|
None => {
|
||||||
|
writeln!(&mut writer, "Test 0x10 Passed\n\r").unwrap();
|
||||||
|
}
|
||||||
|
Some(err) => writeln!(&mut writer, "Test 0x10 Failed. Error: {:?}\r", err).unwrap(),
|
||||||
|
};
|
||||||
|
writeln!(&mut writer, "-----\r").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user