diff options
| author | Siarhei B <[email protected]> | 2025-08-04 09:38:35 +0200 |
|---|---|---|
| committer | Siarhei B <[email protected]> | 2025-08-04 10:19:14 +0200 |
| commit | 8091155a2f0eaa64f3ca7c9da4c835c956e860e8 (patch) | |
| tree | abc95b5245de1657568f743bd5a4d9ebe40a0118 | |
| parent | 934e7809b5036047f5113a9241c6af680f9a8c4b (diff) | |
mspm0-I2C: forward fifo size to i2c controller
| -rw-r--r-- | embassy-mspm0/build.rs | 3 | ||||
| -rw-r--r-- | embassy-mspm0/src/i2c.rs | 45 |
2 files changed, 31 insertions, 17 deletions
diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 328db3926..efbe6645f 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs | |||
| @@ -549,10 +549,11 @@ fn generate_peripheral_instances() -> TokenStream { | |||
| 549 | 549 | ||
| 550 | for peripheral in METADATA.peripherals { | 550 | for peripheral in METADATA.peripherals { |
| 551 | let peri = format_ident!("{}", peripheral.name); | 551 | let peri = format_ident!("{}", peripheral.name); |
| 552 | let fifo_size = peripheral.sys_fentries; | ||
| 552 | 553 | ||
| 553 | let tokens = match peripheral.kind { | 554 | let tokens = match peripheral.kind { |
| 554 | "uart" => Some(quote! { impl_uart_instance!(#peri); }), | 555 | "uart" => Some(quote! { impl_uart_instance!(#peri); }), |
| 555 | "i2c" => Some(quote! { impl_i2c_instance!(#peri); }), | 556 | "i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }), |
| 556 | _ => None, | 557 | _ => None, |
| 557 | }; | 558 | }; |
| 558 | 559 | ||
diff --git a/embassy-mspm0/src/i2c.rs b/embassy-mspm0/src/i2c.rs index 3406623fb..7581f131e 100644 --- a/embassy-mspm0/src/i2c.rs +++ b/embassy-mspm0/src/i2c.rs | |||
| @@ -287,6 +287,9 @@ pub enum Error { | |||
| 287 | 287 | ||
| 288 | /// Zero-length transfers are not allowed. | 288 | /// Zero-length transfers are not allowed. |
| 289 | ZeroLengthTransfer, | 289 | ZeroLengthTransfer, |
| 290 | |||
| 291 | /// Transfer length is over limit. | ||
| 292 | TransferLengthIsOverLimit, | ||
| 290 | } | 293 | } |
| 291 | 294 | ||
| 292 | impl core::fmt::Display for Error { | 295 | impl core::fmt::Display for Error { |
| @@ -299,6 +302,7 @@ impl core::fmt::Display for Error { | |||
| 299 | Self::Crc => "CRC Mismatch", | 302 | Self::Crc => "CRC Mismatch", |
| 300 | Self::Overrun => "Buffer Overrun", | 303 | Self::Overrun => "Buffer Overrun", |
| 301 | Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed", | 304 | Self::ZeroLengthTransfer => "Zero-Length Transfers are not allowed", |
| 305 | Self::TransferLengthIsOverLimit => "Transfer length is over limit", | ||
| 302 | }; | 306 | }; |
| 303 | 307 | ||
| 304 | write!(f, "{}", message) | 308 | write!(f, "{}", message) |
| @@ -307,9 +311,6 @@ impl core::fmt::Display for Error { | |||
| 307 | 311 | ||
| 308 | impl core::error::Error for Error {} | 312 | impl core::error::Error for Error {} |
| 309 | 313 | ||
| 310 | /// mspm0g, mspm0c, mspm0l, msps00 have 8-bytes FIFO | ||
| 311 | pub const FIFO_SIZE: usize = 8; | ||
| 312 | |||
| 313 | /// I2C Driver. | 314 | /// I2C Driver. |
| 314 | pub struct I2c<'d, M: Mode> { | 315 | pub struct I2c<'d, M: Mode> { |
| 315 | info: &'static Info, | 316 | info: &'static Info, |
| @@ -461,8 +462,6 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 461 | } | 462 | } |
| 462 | 463 | ||
| 463 | fn master_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> { | 464 | fn master_continue(&mut self, length: usize, send_ack_nack: bool, send_stop: bool) -> Result<(), Error> { |
| 464 | assert!(length <= FIFO_SIZE && length > 0); | ||
| 465 | |||
| 466 | // delay between ongoing transactions, 1000 cycles | 465 | // delay between ongoing transactions, 1000 cycles |
| 467 | cortex_m::asm::delay(1000); | 466 | cortex_m::asm::delay(1000); |
| 468 | 467 | ||
| @@ -515,8 +514,6 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 515 | } | 514 | } |
| 516 | 515 | ||
| 517 | fn master_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> { | 516 | fn master_write(&mut self, address: u8, length: usize, send_stop: bool) -> Result<(), Error> { |
| 518 | assert!(length <= FIFO_SIZE && length > 0); | ||
| 519 | |||
| 520 | // Start transfer of length amount of bytes | 517 | // Start transfer of length amount of bytes |
| 521 | self.info.regs.controller(0).csa().modify(|w| { | 518 | self.info.regs.controller(0).csa().modify(|w| { |
| 522 | w.set_taddr(address as u16); | 519 | w.set_taddr(address as u16); |
| @@ -565,8 +562,6 @@ impl<'d> I2c<'d, Blocking> { | |||
| 565 | send_ack_nack: bool, | 562 | send_ack_nack: bool, |
| 566 | send_stop: bool, | 563 | send_stop: bool, |
| 567 | ) -> Result<(), Error> { | 564 | ) -> Result<(), Error> { |
| 568 | assert!(length <= FIFO_SIZE && length > 0); | ||
| 569 | |||
| 570 | // unless restart, Wait for the controller to be idle, | 565 | // unless restart, Wait for the controller to be idle, |
| 571 | if !restart { | 566 | if !restart { |
| 572 | while !self.info.regs.controller(0).csr().read().idle() {} | 567 | while !self.info.regs.controller(0).csr().read().idle() {} |
| @@ -600,10 +595,16 @@ impl<'d> I2c<'d, Blocking> { | |||
| 600 | restart: bool, | 595 | restart: bool, |
| 601 | end_w_stop: bool, | 596 | end_w_stop: bool, |
| 602 | ) -> Result<(), Error> { | 597 | ) -> Result<(), Error> { |
| 603 | let read_len = read.len(); | 598 | if read.is_empty() { |
| 599 | return Err(Error::ZeroLengthTransfer); | ||
| 600 | } | ||
| 601 | if read.len() > self.info.fifo_size { | ||
| 602 | return Err(Error::TransferLengthIsOverLimit); | ||
| 603 | } | ||
| 604 | 604 | ||
| 605 | let read_len = read.len(); | ||
| 605 | let mut bytes_to_read = read_len; | 606 | let mut bytes_to_read = read_len; |
| 606 | for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() { | 607 | for (number, chunk) in read.chunks_mut(self.info.fifo_size).enumerate() { |
| 607 | bytes_to_read -= chunk.len(); | 608 | bytes_to_read -= chunk.len(); |
| 608 | // if the current transaction is the last & end_w_stop, send stop | 609 | // if the current transaction is the last & end_w_stop, send stop |
| 609 | let send_stop = bytes_to_read == 0 && end_w_stop; | 610 | let send_stop = bytes_to_read == 0 && end_w_stop; |
| @@ -611,7 +612,13 @@ impl<'d> I2c<'d, Blocking> { | |||
| 611 | let send_ack_nack = bytes_to_read != 0; | 612 | let send_ack_nack = bytes_to_read != 0; |
| 612 | 613 | ||
| 613 | if number == 0 { | 614 | if number == 0 { |
| 614 | self.master_blocking_read(address, chunk.len().min(FIFO_SIZE), restart, send_ack_nack, send_stop)? | 615 | self.master_blocking_read( |
| 616 | address, | ||
| 617 | chunk.len().min(self.info.fifo_size), | ||
| 618 | restart, | ||
| 619 | send_ack_nack, | ||
| 620 | send_stop, | ||
| 621 | )? | ||
| 615 | } else { | 622 | } else { |
| 616 | self.master_blocking_continue(chunk.len(), send_ack_nack, send_stop)?; | 623 | self.master_blocking_continue(chunk.len(), send_ack_nack, send_stop)?; |
| 617 | } | 624 | } |
| @@ -633,9 +640,12 @@ impl<'d> I2c<'d, Blocking> { | |||
| 633 | if write.is_empty() { | 640 | if write.is_empty() { |
| 634 | return Err(Error::ZeroLengthTransfer); | 641 | return Err(Error::ZeroLengthTransfer); |
| 635 | } | 642 | } |
| 643 | if write.len() > self.info.fifo_size { | ||
| 644 | return Err(Error::TransferLengthIsOverLimit); | ||
| 645 | } | ||
| 636 | 646 | ||
| 637 | let mut bytes_to_send = write.len(); | 647 | let mut bytes_to_send = write.len(); |
| 638 | for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() { | 648 | for (number, chunk) in write.chunks(self.info.fifo_size).enumerate() { |
| 639 | for byte in chunk { | 649 | for byte in chunk { |
| 640 | let ctrl0 = self.info.regs.controller(0).ctxdata(); | 650 | let ctrl0 = self.info.regs.controller(0).ctxdata(); |
| 641 | ctrl0.write(|w| w.set_value(*byte)); | 651 | ctrl0.write(|w| w.set_value(*byte)); |
| @@ -694,7 +704,7 @@ impl<'d> I2c<'d, Async> { | |||
| 694 | let ctrl = self.info.regs.controller(0); | 704 | let ctrl = self.info.regs.controller(0); |
| 695 | 705 | ||
| 696 | let mut bytes_to_send = write.len(); | 706 | let mut bytes_to_send = write.len(); |
| 697 | for (number, chunk) in write.chunks(FIFO_SIZE).enumerate() { | 707 | for (number, chunk) in write.chunks(self.info.fifo_size).enumerate() { |
| 698 | self.info.regs.cpu_int(0).imask().modify(|w| { | 708 | self.info.regs.cpu_int(0).imask().modify(|w| { |
| 699 | w.set_carblost(true); | 709 | w.set_carblost(true); |
| 700 | w.set_cnack(true); | 710 | w.set_cnack(true); |
| @@ -757,7 +767,7 @@ impl<'d> I2c<'d, Async> { | |||
| 757 | let read_len = read.len(); | 767 | let read_len = read.len(); |
| 758 | 768 | ||
| 759 | let mut bytes_to_read = read_len; | 769 | let mut bytes_to_read = read_len; |
| 760 | for (number, chunk) in read.chunks_mut(FIFO_SIZE).enumerate() { | 770 | for (number, chunk) in read.chunks_mut(self.info.fifo_size).enumerate() { |
| 761 | bytes_to_read -= chunk.len(); | 771 | bytes_to_read -= chunk.len(); |
| 762 | // if the current transaction is the last & end_w_stop, send stop | 772 | // if the current transaction is the last & end_w_stop, send stop |
| 763 | let send_stop = bytes_to_read == 0 && end_w_stop; | 773 | let send_stop = bytes_to_read == 0 && end_w_stop; |
| @@ -898,6 +908,7 @@ impl embedded_hal::i2c::Error for Error { | |||
| 898 | Self::Crc => embedded_hal::i2c::ErrorKind::Other, | 908 | Self::Crc => embedded_hal::i2c::ErrorKind::Other, |
| 899 | Self::Overrun => embedded_hal::i2c::ErrorKind::Overrun, | 909 | Self::Overrun => embedded_hal::i2c::ErrorKind::Overrun, |
| 900 | Self::ZeroLengthTransfer => embedded_hal::i2c::ErrorKind::Other, | 910 | Self::ZeroLengthTransfer => embedded_hal::i2c::ErrorKind::Other, |
| 911 | Self::TransferLengthIsOverLimit => embedded_hal::i2c::ErrorKind::Other, | ||
| 901 | } | 912 | } |
| 902 | } | 913 | } |
| 903 | } | 914 | } |
| @@ -1003,6 +1014,7 @@ pub trait SclPin<T: Instance>: crate::gpio::Pin { | |||
| 1003 | pub(crate) struct Info { | 1014 | pub(crate) struct Info { |
| 1004 | pub(crate) regs: Regs, | 1015 | pub(crate) regs: Regs, |
| 1005 | pub(crate) interrupt: Interrupt, | 1016 | pub(crate) interrupt: Interrupt, |
| 1017 | pub fifo_size: usize, | ||
| 1006 | } | 1018 | } |
| 1007 | 1019 | ||
| 1008 | pub(crate) struct State { | 1020 | pub(crate) struct State { |
| @@ -1070,7 +1082,7 @@ pub(crate) trait SealedInstance { | |||
| 1070 | } | 1082 | } |
| 1071 | 1083 | ||
| 1072 | macro_rules! impl_i2c_instance { | 1084 | macro_rules! impl_i2c_instance { |
| 1073 | ($instance: ident) => { | 1085 | ($instance: ident, $fifo_size: expr) => { |
| 1074 | impl crate::i2c::SealedInstance for crate::peripherals::$instance { | 1086 | impl crate::i2c::SealedInstance for crate::peripherals::$instance { |
| 1075 | fn info() -> &'static crate::i2c::Info { | 1087 | fn info() -> &'static crate::i2c::Info { |
| 1076 | use crate::i2c::Info; | 1088 | use crate::i2c::Info; |
| @@ -1079,6 +1091,7 @@ macro_rules! impl_i2c_instance { | |||
| 1079 | const INFO: Info = Info { | 1091 | const INFO: Info = Info { |
| 1080 | regs: crate::pac::$instance, | 1092 | regs: crate::pac::$instance, |
| 1081 | interrupt: crate::interrupt::typelevel::$instance::IRQ, | 1093 | interrupt: crate::interrupt::typelevel::$instance::IRQ, |
| 1094 | fifo_size: $fifo_size, | ||
| 1082 | }; | 1095 | }; |
| 1083 | &INFO | 1096 | &INFO |
| 1084 | } | 1097 | } |
