aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-mspm0/build.rs3
-rw-r--r--embassy-mspm0/src/i2c.rs45
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
292impl core::fmt::Display for Error { 295impl 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
308impl core::error::Error for Error {} 312impl core::error::Error for Error {}
309 313
310/// mspm0g, mspm0c, mspm0l, msps00 have 8-bytes FIFO
311pub const FIFO_SIZE: usize = 8;
312
313/// I2C Driver. 314/// I2C Driver.
314pub struct I2c<'d, M: Mode> { 315pub 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 {
1003pub(crate) struct Info { 1014pub(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
1008pub(crate) struct State { 1020pub(crate) struct State {
@@ -1070,7 +1082,7 @@ pub(crate) trait SealedInstance {
1070} 1082}
1071 1083
1072macro_rules! impl_i2c_instance { 1084macro_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 }