Files
embassy/examples/stm32g0/src/bin/i2c_master.rs
2023-10-21 12:11:32 +02:00

207 lines
7.8 KiB
Rust

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use core::fmt::{self, Write};
use embassy_executor::Spawner;
use embassy_stm32::dma::NoDma;
use embassy_stm32::i2c::{Error, I2c};
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>;
});
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 uart = usart::Uart::new(
p.USART1,
p.PB7,
p.PB6,
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 test. Master role. Connect another device in slave role to the bus."
)
.unwrap();
let mut i2c = I2c::new(
p.I2C1,
p.PB8,
p.PB9,
Irqs,
NoDma,
NoDma,
Hertz(100_000),
Default::default(),
);
Timer::after(Duration::from_millis(1000)).await;
// start of the acutal test
let mut counter = 0;
loop {
counter += 1;
writeln!(&mut writer, "Loop counter: {:?}", counter).unwrap();
let mut buf_20 = [0_u8; 20];
let mut buf_64 = [0_u8; 64];
let mut buf_65 = [0_u8; 65];
writeln!(&mut writer, "Start of test\n\r").unwrap();
for i in 0..buf_20.len() {
buf_20[i] = 0x20 + (i as u8)
}
for i in 0..buf_64.len() {
buf_64[i] = 0x40 + (i as u8)
}
for i in 0..buf_65.len() {
buf_65[i] = 0x60 + (i as u8)
}
// test 1: slave address 0x61 should not be addressable
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) {
Ok(_) => writeln!(&mut writer, "Test 0x41 passed\n\r").unwrap(),
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(&mut writer, "Test 0x41 failed. Error: {:?}", err).unwrap(),
};
Timer::after(Duration::from_millis(10)).await;
// 0x42 edge case master write exact 64 bytes: must succeed on master and slave
match i2c.blocking_write(0x42, &buf_64) {
Ok(_) => writeln!(&mut writer, "Test 0x42 passed. Master write exact 64 bytes\n\r").unwrap(),
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(&mut writer, "Test 0x42 failed. Got error: {:?}\r\n", err).unwrap(),
};
Timer::after(Duration::from_millis(10)).await;
// 0x43 edge case master write exact 65 bytes: 1 too many must fail on master and slave
match i2c.blocking_write(0x43, &buf_65) {
Ok(_) => writeln!(&mut writer, "Test 0x43 Failed. Expected a Nack\n\r").unwrap(),
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(
&mut writer,
"Test 0x43 passed: Got error NACK du to buffer of 1 too big {:?}\r\n",
err
)
.unwrap(),
};
Timer::after(Duration::from_millis(10)).await;
match i2c.blocking_read(0x48, &mut buf_20) {
Ok(_) => {
writeln!(&mut writer, "Test 0x48 failed. Read expected to fail!\n\r").unwrap();
}
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(
&mut writer,
"Test 0x48 Ok. First time, slave did not yet prepare a buffer Error: {:?}\r\n",
err
)
.unwrap(),
};
Timer::after(Duration::from_millis(10)).await;
match i2c.blocking_read(0x49, &mut buf_20) {
Ok(_) => {
writeln!(&mut writer, "Test 0x49 Read Ok\n\r").unwrap();
print_buffer(&mut writer, &buf_20);
}
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(&mut writer, "Test 0x49 Error: {:?}\r\n", err).unwrap(),
};
Timer::after(Duration::from_millis(10)).await;
match i2c.blocking_read(0x4A, &mut buf_64) {
Ok(_) => {
writeln!(&mut writer, "Test 0x4A failed. Expected was a NACK error\n\r").unwrap();
print_buffer(&mut writer, &buf_64);
}
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(&mut writer, "Test 0x4A passed. Expected to fail. Error: {:?}\r\n", err).unwrap(),
};
Timer::after(Duration::from_millis(10)).await;
match i2c.blocking_read(0x4B, &mut buf_64) {
Ok(_) => {
writeln!(&mut writer, "Test 0x4B passed\n\r").unwrap();
print_buffer(&mut writer, &buf_64);
}
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(&mut writer, "Test 0x4B failed. Error: {:?}\r\n", err).unwrap(),
};
/*
match i2c.blocking_write_read(0x44, &buf_20, &mut buf_64) {
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_rcv.len() {
writeln!(&mut writer, "{}", buf_rcv[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;
// 0x4F test end and slave will present results
let mut result: [u8; 2] = [0, 0];
match i2c.blocking_read(0x4F, &mut result) {
Ok(_) => writeln!(
&mut writer,
"Result of the whole test as reported by the slave count/errors: {}/{}\r\n",
result[0], result[1]
)
.unwrap(),
Err(Error::Timeout) => writeln!(&mut writer, "Operation timed out\n\r").unwrap(),
Err(err) => writeln!(&mut writer, "Test 0x4F unexpected error: {:?}\r\n", err).unwrap(),
};
writeln!(&mut writer, "\n\r").unwrap();
Timer::after(Duration::from_millis(10_000)).await;
}
fn print_buffer(writer: &mut SerialWriter, buf: &[u8]) {
for i in 0..buf.len() {
write!(writer, " {:2x} ", buf[i]).unwrap();
}
writeln!(writer, "\n\r\n\r").unwrap()
}
}