mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-02 14:44:32 +00:00
mspm0-I2C: forward fifo size to i2c controller
This commit is contained in:
parent
934e7809b5
commit
8091155a2f
@ -549,10 +549,11 @@ fn generate_peripheral_instances() -> TokenStream {
|
|||||||
|
|
||||||
for peripheral in METADATA.peripherals {
|
for peripheral in METADATA.peripherals {
|
||||||
let peri = format_ident!("{}", peripheral.name);
|
let peri = format_ident!("{}", peripheral.name);
|
||||||
|
let fifo_size = peripheral.sys_fentries;
|
||||||
|
|
||||||
let tokens = match peripheral.kind {
|
let tokens = match peripheral.kind {
|
||||||
"uart" => Some(quote! { impl_uart_instance!(#peri); }),
|
"uart" => Some(quote! { impl_uart_instance!(#peri); }),
|
||||||
"i2c" => Some(quote! { impl_i2c_instance!(#peri); }),
|
"i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -287,6 +287,9 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Zero-length transfers are not allowed.
|
/// Zero-length transfers are not allowed.
|
||||||
ZeroLengthTransfer,
|
ZeroLengthTransfer,
|
||||||
|
|
||||||
|
/// Transfer length is over limit.
|
||||||
|
TransferLengthIsOverLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for Error {
|
impl core::fmt::Display for Error {
|
||||||
@ -299,6 +302,7 @@ impl core::fmt::Display for Error {
|
|||||||
Self::Crc => "CRC Mismatch",
|
Self::Crc => "CRC Mismatch",
|
||||||
Self::Overrun => "Buffer Overrun",
|
Self::Overrun => "Buffer Overrun",
|
||||||
Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed",
|
Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed",
|
||||||
|
Self::TransferLengthIsOverLimit => "Transfer length is over limit",
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{}", message)
|
write!(f, "{}", message)
|
||||||
@ -307,9 +311,6 @@ impl core::fmt::Display for Error {
|
|||||||
|
|
||||||
impl core::error::Error for Error {}
|
impl core::error::Error for Error {}
|
||||||
|
|
||||||
/// mspm0g, mspm0c, mspm0l, msps00 have 8-bytes FIFO
|
|
||||||
pub const FIFO_SIZE: usize = 8;
|
|
||||||
|
|
||||||
/// I2C Driver.
|
/// I2C Driver.
|
||||||
pub struct I2c<'d, M: Mode> {
|
pub struct I2c<'d, M: Mode> {
|
||||||
info: &'static Info,
|
info: &'static Info,
|
||||||
@ -461,8 +462,6 @@ impl<'d, M: Mode> I2c<'d, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn master_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> {
|
fn master_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> {
|
||||||
assert!(length <= FIFO_SIZE && length > 0);
|
|
||||||
|
|
||||||
// delay between ongoing transactions, 1000 cycles
|
// delay between ongoing transactions, 1000 cycles
|
||||||
cortex_m::asm::delay(1000);
|
cortex_m::asm::delay(1000);
|
||||||
|
|
||||||
@ -515,8 +514,6 @@ impl<'d, M: Mode> I2c<'d, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn master_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> {
|
fn master_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> {
|
||||||
assert!(length <= FIFO_SIZE && length > 0);
|
|
||||||
|
|
||||||
// Start transfer of length amount of bytes
|
// Start transfer of length amount of bytes
|
||||||
self.info.regs.controller(0).csa().modify(|w| {
|
self.info.regs.controller(0).csa().modify(|w| {
|
||||||
w.set_taddr(address as u16);
|
w.set_taddr(address as u16);
|
||||||
@ -565,8 +562,6 @@ impl<'d> I2c<'d, Blocking> {
|
|||||||
send_ack_nack: bool,
|
send_ack_nack: bool,
|
||||||
send_stop: bool,
|
send_stop: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
assert!(length <= FIFO_SIZE && length > 0);
|
|
||||||
|
|
||||||
// unless restart, Wait for the controller to be idle,
|
// unless restart, Wait for the controller to be idle,
|
||||||
if !restart {
|
if !restart {
|
||||||
while !self.info.regs.controller(0).csr().read().idle() {}
|
while !self.info.regs.controller(0).csr().read().idle() {}
|
||||||
@ -600,10 +595,16 @@ impl<'d> I2c<'d, Blocking> {
|
|||||||
restart: bool,
|
restart: bool,
|
||||||
end_w_stop: bool,
|
end_w_stop: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let read_len = read.len();
|
if read.is_empty() {
|
||||||
|
return Err(Error::ZeroLengthTransfer);
|
||||||
|
}
|
||||||
|
if read.len() > self.info.fifo_size {
|
||||||
|
return Err(Error::TransferLengthIsOverLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
let read_len = read.len();
|
||||||
let mut bytes_to_read = read_len;
|
let mut bytes_to_read = read_len;
|
||||||
for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() {
|
for (number, chunk) in read.chunks_mut(self.info.fifo_size).enumerate() {
|
||||||
bytes_to_read -= chunk.len();
|
bytes_to_read -= chunk.len();
|
||||||
// if the current transaction is the last & end_w_stop, send stop
|
// if the current transaction is the last & end_w_stop, send stop
|
||||||
let send_stop = bytes_to_read == 0 && end_w_stop;
|
let send_stop = bytes_to_read == 0 && end_w_stop;
|
||||||
@ -611,7 +612,13 @@ impl<'d> I2c<'d, Blocking> {
|
|||||||
let send_ack_nack = bytes_to_read != 0;
|
let send_ack_nack = bytes_to_read != 0;
|
||||||
|
|
||||||
if number == 0 {
|
if number == 0 {
|
||||||
self.master_blocking_read(address, chunk.len().min(FIFO_SIZE), restart, send_ack_nack, send_stop)?
|
self.master_blocking_read(
|
||||||
|
address,
|
||||||
|
chunk.len().min(self.info.fifo_size),
|
||||||
|
restart,
|
||||||
|
send_ack_nack,
|
||||||
|
send_stop,
|
||||||
|
)?
|
||||||
} else {
|
} else {
|
||||||
self.master_blocking_continue(chunk.len(), send_ack_nack, send_stop)?;
|
self.master_blocking_continue(chunk.len(), send_ack_nack, send_stop)?;
|
||||||
}
|
}
|
||||||
@ -633,9 +640,12 @@ impl<'d> I2c<'d, Blocking> {
|
|||||||
if write.is_empty() {
|
if write.is_empty() {
|
||||||
return Err(Error::ZeroLengthTransfer);
|
return Err(Error::ZeroLengthTransfer);
|
||||||
}
|
}
|
||||||
|
if write.len() > self.info.fifo_size {
|
||||||
|
return Err(Error::TransferLengthIsOverLimit);
|
||||||
|
}
|
||||||
|
|
||||||
let mut bytes_to_send = write.len();
|
let mut bytes_to_send = write.len();
|
||||||
for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() {
|
for (number, chunk) in write.chunks(self.info.fifo_size).enumerate() {
|
||||||
for byte in chunk {
|
for byte in chunk {
|
||||||
let ctrl0 = self.info.regs.controller(0).ctxdata();
|
let ctrl0 = self.info.regs.controller(0).ctxdata();
|
||||||
ctrl0.write(|w| w.set_value(*byte));
|
ctrl0.write(|w| w.set_value(*byte));
|
||||||
@ -694,7 +704,7 @@ impl<'d> I2c<'d, Async> {
|
|||||||
let ctrl = self.info.regs.controller(0);
|
let ctrl = self.info.regs.controller(0);
|
||||||
|
|
||||||
let mut bytes_to_send = write.len();
|
let mut bytes_to_send = write.len();
|
||||||
for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() {
|
for (number, chunk) in write.chunks(self.info.fifo_size).enumerate() {
|
||||||
self.info.regs.cpu_int(0).imask().modify(|w| {
|
self.info.regs.cpu_int(0).imask().modify(|w| {
|
||||||
w.set_carblost(true);
|
w.set_carblost(true);
|
||||||
w.set_cnack(true);
|
w.set_cnack(true);
|
||||||
@ -757,7 +767,7 @@ impl<'d> I2c<'d, Async> {
|
|||||||
let read_len = read.len();
|
let read_len = read.len();
|
||||||
|
|
||||||
let mut bytes_to_read = read_len;
|
let mut bytes_to_read = read_len;
|
||||||
for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() {
|
for (number, chunk) in read.chunks_mut(self.info.fifo_size).enumerate() {
|
||||||
bytes_to_read -= chunk.len();
|
bytes_to_read -= chunk.len();
|
||||||
// if the current transaction is the last & end_w_stop, send stop
|
// if the current transaction is the last & end_w_stop, send stop
|
||||||
let send_stop = bytes_to_read == 0 && end_w_stop;
|
let send_stop = bytes_to_read == 0 && end_w_stop;
|
||||||
@ -898,6 +908,7 @@ impl embedded_hal::i2c::Error for Error {
|
|||||||
Self::Crc => embedded_hal::i2c::ErrorKind::Other,
|
Self::Crc => embedded_hal::i2c::ErrorKind::Other,
|
||||||
Self::Overrun => embedded_hal::i2c::ErrorKind::Overrun,
|
Self::Overrun => embedded_hal::i2c::ErrorKind::Overrun,
|
||||||
Self::ZeroLengthTransfer => embedded_hal::i2c::ErrorKind::Other,
|
Self::ZeroLengthTransfer => embedded_hal::i2c::ErrorKind::Other,
|
||||||
|
Self::TransferLengthIsOverLimit => embedded_hal::i2c::ErrorKind::Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1003,6 +1014,7 @@ pub trait SclPin<T: Instance>: crate::gpio::Pin {
|
|||||||
pub(crate) struct Info {
|
pub(crate) struct Info {
|
||||||
pub(crate) regs: Regs,
|
pub(crate) regs: Regs,
|
||||||
pub(crate) interrupt: Interrupt,
|
pub(crate) interrupt: Interrupt,
|
||||||
|
pub fifo_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
@ -1070,7 +1082,7 @@ pub(crate) trait SealedInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_i2c_instance {
|
macro_rules! impl_i2c_instance {
|
||||||
($instance: ident) => {
|
($instance: ident, $fifo_size: expr) => {
|
||||||
impl crate::i2c::SealedInstance for crate::peripherals::$instance {
|
impl crate::i2c::SealedInstance for crate::peripherals::$instance {
|
||||||
fn info() -> &'static crate::i2c::Info {
|
fn info() -> &'static crate::i2c::Info {
|
||||||
use crate::i2c::Info;
|
use crate::i2c::Info;
|
||||||
@ -1079,6 +1091,7 @@ macro_rules! impl_i2c_instance {
|
|||||||
const INFO: Info = Info {
|
const INFO: Info = Info {
|
||||||
regs: crate::pac::$instance,
|
regs: crate::pac::$instance,
|
||||||
interrupt: crate::interrupt::typelevel::$instance::IRQ,
|
interrupt: crate::interrupt::typelevel::$instance::IRQ,
|
||||||
|
fifo_size: $fifo_size,
|
||||||
};
|
};
|
||||||
&INFO
|
&INFO
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user