Added public interfaces for vals::Dir and vals::Oamsk, so they can be used outside the crate
This commit is contained in:
parent
0fe0bc60fe
commit
26e37c673d
@ -1,5 +1,7 @@
|
||||
#![macro_use]
|
||||
|
||||
use stm32_metapac::i2c::vals;
|
||||
|
||||
use crate::interrupt;
|
||||
|
||||
#[cfg_attr(i2c_v1, path = "v1.rs")]
|
||||
@ -29,6 +31,50 @@ pub enum AddressType {
|
||||
Address2,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum Address2Mask {
|
||||
NOMASK,
|
||||
MASK1,
|
||||
MASK2,
|
||||
MASK3,
|
||||
MASK4,
|
||||
MASK5,
|
||||
MASK6,
|
||||
MASK7,
|
||||
}
|
||||
impl Address2Mask {
|
||||
#[inline(always)]
|
||||
pub const fn to_vals_impl(self) -> vals::Oamsk {
|
||||
match self {
|
||||
Address2Mask::NOMASK => vals::Oamsk::NOMASK,
|
||||
Address2Mask::MASK1 => vals::Oamsk::MASK1,
|
||||
Address2Mask::MASK2 => vals::Oamsk::MASK2,
|
||||
Address2Mask::MASK3 => vals::Oamsk::MASK3,
|
||||
Address2Mask::MASK4 => vals::Oamsk::MASK4,
|
||||
Address2Mask::MASK5 => vals::Oamsk::MASK5,
|
||||
Address2Mask::MASK6 => vals::Oamsk::MASK6,
|
||||
Address2Mask::MASK7 => vals::Oamsk::MASK7,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum Dir {
|
||||
WRITE,
|
||||
READ,
|
||||
}
|
||||
impl Dir {
|
||||
#[inline(always)]
|
||||
pub const fn to_vals_impl(self) -> vals::Dir {
|
||||
match self {
|
||||
Dir::READ => vals::Dir::READ,
|
||||
Dir::WRITE => vals::Dir::WRITE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use super::*;
|
||||
pub trait Instance: crate::rcc::RccPeripheral {
|
||||
|
@ -22,7 +22,7 @@ use crate::dma::NoDma;
|
||||
use crate::dma::Transfer;
|
||||
use crate::gpio::sealed::AFType;
|
||||
use crate::gpio::Pull;
|
||||
use crate::i2c::{AddressType, Error, Instance, SclPin, SdaPin};
|
||||
use crate::i2c::{Address2Mask, AddressType, Dir, Error, Instance, SclPin, SdaPin};
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::pac::i2c;
|
||||
use crate::time::Hertz;
|
||||
@ -48,8 +48,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
||||
});
|
||||
state_m.result = Some(Error::Bus);
|
||||
} else if isr.arlo() {
|
||||
regs.icr().write(|w| w.set_arlocf(true));
|
||||
state_m.result = Some(Error::Arbitration);
|
||||
regs.icr().write(|w| w.set_arlocf(true));
|
||||
} else if isr.nackf() {
|
||||
regs.icr().write(|w| w.set_nackcf(true));
|
||||
} else if isr.txis() {
|
||||
@ -78,9 +78,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
||||
}
|
||||
} else if isr.stopf() {
|
||||
// Clear the stop condition flag
|
||||
regs.icr().write(|w| w.set_stopcf(true));
|
||||
state_m.ready = true;
|
||||
// make a copy of the current state as result of the transaction
|
||||
state_m.transaction_result =
|
||||
(state_m.current_address, state_m.dir, state_m.get_size(), state_m.result);
|
||||
T::state().waker.wake();
|
||||
regs.icr().write(|w| w.set_stopcf(true));
|
||||
} else if isr.tcr() {
|
||||
// This condition Will only happen when reload == 1 and sbr == 1 (slave) and nbytes was written.
|
||||
// Send a NACK, set nbytes to clear tcr flag
|
||||
@ -91,10 +94,10 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
||||
} else if isr.addr() {
|
||||
// handle the slave is addressed case, first step in the transaction
|
||||
state_m.current_address = isr.addcode();
|
||||
state_m.dir = isr.dir();
|
||||
state_m.dir = if isr.dir() as u8 == 0 { Dir::WRITE } else { Dir::READ };
|
||||
state_m.result = None;
|
||||
|
||||
if state_m.dir == vals::Dir::READ {
|
||||
if state_m.dir == Dir::READ {
|
||||
// Set the nbytes START and prepare to receive bytes into `buffer`.
|
||||
regs.cr2().modify(|w| {
|
||||
// Set number of bytes to transfer: maximum as all incoming bytes will be ACK'ed
|
||||
@ -153,7 +156,7 @@ pub struct Config {
|
||||
pub scl_pullup: bool,
|
||||
pub slave_address_1: u16,
|
||||
pub slave_address_2: u8,
|
||||
pub slave_address_mask: vals::Oamsk,
|
||||
pub slave_address_mask: Address2Mask,
|
||||
pub address_11bits: bool,
|
||||
#[cfg(feature = "time")]
|
||||
pub transaction_timeout: Duration,
|
||||
@ -173,7 +176,7 @@ impl Config {
|
||||
}
|
||||
/// Slave address 2 as 7 bit address in range 0 .. 127.
|
||||
/// The mask makes all slaves within the mask addressable
|
||||
pub fn slave_address_2(&mut self, address: u8, mask: vals::Oamsk) {
|
||||
pub fn slave_address_2(&mut self, address: u8, mask: Address2Mask) {
|
||||
// assert!(address < (2 ^ 7));
|
||||
self.slave_address_2 = address;
|
||||
self.slave_address_mask = mask;
|
||||
@ -186,7 +189,7 @@ impl Default for Config {
|
||||
scl_pullup: false,
|
||||
slave_address_1: 0,
|
||||
slave_address_2: 0,
|
||||
slave_address_mask: vals::Oamsk::NOMASK,
|
||||
slave_address_mask: Address2Mask::NOMASK,
|
||||
address_11bits: false,
|
||||
#[cfg(feature = "time")]
|
||||
transaction_timeout: Duration::from_millis(100),
|
||||
@ -214,7 +217,10 @@ struct I2cStateMachine {
|
||||
address1: u16,
|
||||
ready: bool,
|
||||
current_address: u8,
|
||||
dir: vals::Dir,
|
||||
dir: Dir,
|
||||
// at the end of the transaction make a copy of the result
|
||||
// to prevent corruption if a new transaction starts immediatly
|
||||
transaction_result: (u8, Dir, u8, Option<Error>),
|
||||
}
|
||||
impl I2cStateMachine {
|
||||
pub(crate) const fn new() -> Self {
|
||||
@ -228,8 +234,9 @@ impl I2cStateMachine {
|
||||
slave_mode: false,
|
||||
address1: 0,
|
||||
current_address: 0,
|
||||
dir: vals::Dir::READ,
|
||||
dir: Dir::READ,
|
||||
ready: false,
|
||||
transaction_result: (0, Dir::READ, 0, None),
|
||||
}
|
||||
}
|
||||
fn read_byte(&mut self) -> Result<u8, Error> {
|
||||
@ -238,7 +245,7 @@ impl I2cStateMachine {
|
||||
} else {
|
||||
AddressType::Address2
|
||||
};
|
||||
self.buffers[adress_type as usize][vals::Dir::READ as usize].master_read()
|
||||
self.buffers[adress_type as usize][Dir::READ as usize].master_read()
|
||||
}
|
||||
fn write_byte(&mut self, b: u8) -> Result<(), Error> {
|
||||
let adress_type = if self.address1 == self.current_address as u16 {
|
||||
@ -246,7 +253,7 @@ impl I2cStateMachine {
|
||||
} else {
|
||||
AddressType::Address2
|
||||
};
|
||||
self.buffers[adress_type as usize][vals::Dir::WRITE as usize].master_write(b)
|
||||
self.buffers[adress_type as usize][Dir::WRITE as usize].master_write(b)
|
||||
}
|
||||
fn get_size(&self) -> u8 {
|
||||
let adress_type = if self.address1 == self.current_address as u16 {
|
||||
@ -420,7 +427,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||
reg.set_oa2en(false);
|
||||
});
|
||||
T::regs().oar2().write(|reg| {
|
||||
reg.set_oa2msk(config.slave_address_mask);
|
||||
reg.set_oa2msk(config.slave_address_mask.to_vals_impl());
|
||||
reg.set_oa2(config.slave_address_2);
|
||||
reg.set_oa2en(true);
|
||||
});
|
||||
@ -1079,6 +1086,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_address_1(&self, address7: u8) -> Result<(), Error> {
|
||||
T::regs().oar1().modify(|reg| {
|
||||
reg.set_oa1en(false);
|
||||
});
|
||||
T::regs().oar1().modify(|reg| {
|
||||
reg.set_oa1(address7 as u16);
|
||||
reg.set_oa1en(true);
|
||||
});
|
||||
T::state().mutex.lock(|f| {
|
||||
let mut state_m = f.borrow_mut();
|
||||
state_m.address1 = address7 as u16;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
pub fn slave_sbc(&self, sbc_enabled: bool) {
|
||||
// enable acknowlidge control
|
||||
T::regs().cr1().modify(|w| w.set_sbc(sbc_enabled));
|
||||
@ -1088,16 +1110,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||
pub fn slave_write_buffer(&self, buffer: &[u8], address_type: AddressType) -> Result<(), super::Error> {
|
||||
T::state().mutex.lock(|f| {
|
||||
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][Dir::READ as usize];
|
||||
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];
|
||||
let buf_r = &mut state_m.buffers[address_type as usize][Dir::READ as usize];
|
||||
buf_r.reset();
|
||||
let buf_w = &mut state_m.buffers[address_type as usize][vals::Dir::WRITE as usize];
|
||||
let buf_w = &mut state_m.buffers[address_type as usize][Dir::WRITE as usize];
|
||||
buf_w.reset();
|
||||
})
|
||||
}
|
||||
@ -1107,12 +1129,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||
pub fn slave_read_buffer(&self, buffer: &mut [u8], address_type: AddressType) -> Result<(), super::Error> {
|
||||
T::state().mutex.lock(|f| {
|
||||
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][Dir::WRITE as usize];
|
||||
buf.to_buffer(buffer)
|
||||
})
|
||||
}
|
||||
/// wait until a slave transaction is finished, and return tuple address, direction, data size and error
|
||||
pub async fn slave_transaction(&self) -> (u8, vals::Dir, u8, Option<Error>) {
|
||||
pub async fn slave_transaction(&self) -> (u8, Dir, u8, Option<Error>) {
|
||||
// async wait until addressed
|
||||
poll_fn(|cx| {
|
||||
T::state().waker.register(cx.waker());
|
||||
@ -1120,7 +1142,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
||||
let mut state_m = f.borrow_mut();
|
||||
if state_m.ready {
|
||||
state_m.ready = false;
|
||||
return Poll::Ready((state_m.current_address, state_m.dir, state_m.get_size(), state_m.result));
|
||||
return Poll::Ready(state_m.transaction_result);
|
||||
} else {
|
||||
return Poll::Pending;
|
||||
}
|
||||
|
@ -9,8 +9,7 @@ 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::i2c::{Address2Mask, Dir, Error, I2c};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::usart::UartTx;
|
||||
use embassy_stm32::{bind_interrupts, i2c, peripherals, usart};
|
||||
@ -25,7 +24,7 @@ bind_interrupts!(struct Irqs {
|
||||
macro_rules! checkIsWrite {
|
||||
($writer:ident, $direction:ident) => {
|
||||
match $direction {
|
||||
vals::Dir::WRITE => (),
|
||||
Dir::WRITE => (),
|
||||
_ => {
|
||||
write!($writer, "Error incorrect direction {:?}\r", $direction as usize).unwrap();
|
||||
continue;
|
||||
@ -36,7 +35,7 @@ macro_rules! checkIsWrite {
|
||||
macro_rules! checkIsRead {
|
||||
($writer:ident, $direction:ident) => {
|
||||
match $direction {
|
||||
vals::Dir::READ => (),
|
||||
Dir::READ => (),
|
||||
_ => {
|
||||
write!($writer, "Error incorrect direction {:?}\r", $direction as usize).unwrap();
|
||||
continue;
|
||||
@ -108,7 +107,7 @@ async fn main(spawner: Spawner) {
|
||||
|
||||
let mut config = i2c::Config::default();
|
||||
config.slave_address_7bits(0x10); // for arbitration lost test
|
||||
config.slave_address_2(0x41, vals::Oamsk::MASK4);
|
||||
config.slave_address_2(0x41, Address2Mask::MASK4);
|
||||
|
||||
let i2c = I2c::new(p.I2C1, p.PB8, p.PB9, Irqs, NoDma, NoDma, Hertz(100_000), config);
|
||||
|
||||
@ -116,9 +115,10 @@ async fn main(spawner: Spawner) {
|
||||
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 buf_1 = [0; 1];
|
||||
let mut errors = 0;
|
||||
let mut address = 0;
|
||||
let mut dir = vals::Dir::READ;
|
||||
let mut dir = Dir::READ;
|
||||
let mut tcount = 0;
|
||||
let mut counter = 0;
|
||||
let mut result: Option<Error> = None;
|
||||
@ -360,7 +360,7 @@ async fn main(spawner: Spawner) {
|
||||
tcount = 0;
|
||||
errors = 0;
|
||||
}
|
||||
0x10 => {
|
||||
0x4 => {
|
||||
// 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
|
||||
|
@ -10,12 +10,10 @@ 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::i2c::{Dir, 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 {
|
||||
@ -23,29 +21,6 @@ bind_interrupts!(struct Irqs {
|
||||
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>,
|
||||
}
|
||||
@ -106,7 +81,7 @@ async fn main(spawner: Spawner) {
|
||||
|
||||
let mut buf_2 = [0; 2];
|
||||
let mut address = 0;
|
||||
let mut dir = vals::Dir::READ;
|
||||
let mut dir = Dir::READ;
|
||||
let mut counter = 0;
|
||||
let mut result: Option<Error> = None;
|
||||
|
||||
@ -119,7 +94,7 @@ async fn main(spawner: Spawner) {
|
||||
// content for test 0x10
|
||||
buf_2[0] = 0xFF;
|
||||
buf_2[1] = 0x03;
|
||||
_ = i2c.slave_write_buffer(&mut buf_2, i2c::AddressType::MainAddress);
|
||||
_ = i2c.slave_write_buffer(&mut buf_2, i2c::AddressType::Address1);
|
||||
|
||||
writeln!(&mut writer, "Waiting for master activity\r").unwrap();
|
||||
|
||||
@ -137,7 +112,6 @@ async fn main(spawner: Spawner) {
|
||||
// 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();
|
||||
|
Loading…
Reference in New Issue
Block a user