aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <[email protected]>2022-10-02 15:08:58 -0700
committerJeremy Fitzhardinge <[email protected]>2022-10-02 15:09:14 -0700
commite8bb8faa23c1e8b78285646ca7e711bafe990e20 (patch)
tree2e506e2500aeec609732057089b62b485c2e3693
parent09afece93d0dccb750a0dbc9c63282d3dca55e48 (diff)
rp i2c: allow blocking ops on async contexts
-rw-r--r--embassy-rp/src/i2c.rs210
1 files changed, 105 insertions, 105 deletions
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index f62cf0b86..e01692dc1 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -68,106 +68,6 @@ impl<'d, T: Instance> I2c<'d, T, Blocking> {
68 into_ref!(scl, sda); 68 into_ref!(scl, sda);
69 Self::new_inner(peri, scl.map_into(), sda.map_into(), config) 69 Self::new_inner(peri, scl.map_into(), sda.map_into(), config)
70 } 70 }
71
72 fn read_blocking_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> {
73 if buffer.is_empty() {
74 return Err(Error::InvalidReadBufferLength);
75 }
76
77 let p = T::regs();
78 let lastindex = buffer.len() - 1;
79 for (i, byte) in buffer.iter_mut().enumerate() {
80 let first = i == 0;
81 let last = i == lastindex;
82
83 // NOTE(unsafe) We have &mut self
84 unsafe {
85 // wait until there is space in the FIFO to write the next byte
86 while Self::tx_fifo_full() {}
87
88 p.ic_data_cmd().write(|w| {
89 w.set_restart(restart && first);
90 w.set_stop(send_stop && last);
91
92 w.set_cmd(true);
93 });
94
95 while Self::rx_fifo_len() == 0 {
96 self.read_and_clear_abort_reason()?;
97 }
98
99 *byte = p.ic_data_cmd().read().dat();
100 }
101 }
102
103 Ok(())
104 }
105
106 fn write_blocking_internal(&mut self, bytes: &[u8], send_stop: bool) -> Result<(), Error> {
107 if bytes.is_empty() {
108 return Err(Error::InvalidWriteBufferLength);
109 }
110
111 let p = T::regs();
112
113 for (i, byte) in bytes.iter().enumerate() {
114 let last = i == bytes.len() - 1;
115
116 // NOTE(unsafe) We have &mut self
117 unsafe {
118 p.ic_data_cmd().write(|w| {
119 w.set_stop(send_stop && last);
120 w.set_dat(*byte);
121 });
122
123 // Wait until the transmission of the address/data from the
124 // internal shift register has completed. For this to function
125 // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The
126 // TX_EMPTY_CTRL flag was set in i2c_init.
127 while !p.ic_raw_intr_stat().read().tx_empty() {}
128
129 let abort_reason = self.read_and_clear_abort_reason();
130
131 if abort_reason.is_err() || (send_stop && last) {
132 // If the transaction was aborted or if it completed
133 // successfully wait until the STOP condition has occured.
134
135 while !p.ic_raw_intr_stat().read().stop_det() {}
136
137 p.ic_clr_stop_det().read().clr_stop_det();
138 }
139
140 // Note the hardware issues a STOP automatically on an abort
141 // condition. Note also the hardware clears RX FIFO as well as
142 // TX on abort, ecause we set hwparam
143 // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0.
144 abort_reason?;
145 }
146 }
147 Ok(())
148 }
149
150 // =========================
151 // Blocking public API
152 // =========================
153
154 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
155 Self::setup(address.into())?;
156 self.read_blocking_internal(buffer, true, true)
157 // Automatic Stop
158 }
159
160 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
161 Self::setup(address.into())?;
162 self.write_blocking_internal(bytes, true)
163 }
164
165 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
166 Self::setup(address.into())?;
167 self.write_blocking_internal(bytes, false)?;
168 self.read_blocking_internal(buffer, true, true)
169 // Automatic Stop
170 }
171} 71}
172 72
173static I2C_WAKER: AtomicWaker = AtomicWaker::new(); 73static I2C_WAKER: AtomicWaker = AtomicWaker::new();
@@ -406,7 +306,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
406 self.read_async_internal(buffer, false, true).await 306 self.read_async_internal(buffer, false, true).await
407 } 307 }
408 308
409 pub async fn write_async(&mut self, addr: u16, bytes : impl IntoIterator<Item = u8>) -> Result<(), Error> { 309 pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator<Item = u8>) -> Result<(), Error> {
410 Self::setup(addr)?; 310 Self::setup(addr)?;
411 self.write_async_internal(bytes, true).await 311 self.write_async_internal(bytes, true).await
412 } 312 }
@@ -581,12 +481,112 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
581 } 481 }
582 } 482 }
583 } 483 }
484
485 fn read_blocking_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> {
486 if buffer.is_empty() {
487 return Err(Error::InvalidReadBufferLength);
488 }
489
490 let p = T::regs();
491 let lastindex = buffer.len() - 1;
492 for (i, byte) in buffer.iter_mut().enumerate() {
493 let first = i == 0;
494 let last = i == lastindex;
495
496 // NOTE(unsafe) We have &mut self
497 unsafe {
498 // wait until there is space in the FIFO to write the next byte
499 while Self::tx_fifo_full() {}
500
501 p.ic_data_cmd().write(|w| {
502 w.set_restart(restart && first);
503 w.set_stop(send_stop && last);
504
505 w.set_cmd(true);
506 });
507
508 while Self::rx_fifo_len() == 0 {
509 self.read_and_clear_abort_reason()?;
510 }
511
512 *byte = p.ic_data_cmd().read().dat();
513 }
514 }
515
516 Ok(())
517 }
518
519 fn write_blocking_internal(&mut self, bytes: &[u8], send_stop: bool) -> Result<(), Error> {
520 if bytes.is_empty() {
521 return Err(Error::InvalidWriteBufferLength);
522 }
523
524 let p = T::regs();
525
526 for (i, byte) in bytes.iter().enumerate() {
527 let last = i == bytes.len() - 1;
528
529 // NOTE(unsafe) We have &mut self
530 unsafe {
531 p.ic_data_cmd().write(|w| {
532 w.set_stop(send_stop && last);
533 w.set_dat(*byte);
534 });
535
536 // Wait until the transmission of the address/data from the
537 // internal shift register has completed. For this to function
538 // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The
539 // TX_EMPTY_CTRL flag was set in i2c_init.
540 while !p.ic_raw_intr_stat().read().tx_empty() {}
541
542 let abort_reason = self.read_and_clear_abort_reason();
543
544 if abort_reason.is_err() || (send_stop && last) {
545 // If the transaction was aborted or if it completed
546 // successfully wait until the STOP condition has occured.
547
548 while !p.ic_raw_intr_stat().read().stop_det() {}
549
550 p.ic_clr_stop_det().read().clr_stop_det();
551 }
552
553 // Note the hardware issues a STOP automatically on an abort
554 // condition. Note also the hardware clears RX FIFO as well as
555 // TX on abort, ecause we set hwparam
556 // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0.
557 abort_reason?;
558 }
559 }
560 Ok(())
561 }
562
563 // =========================
564 // Blocking public API
565 // =========================
566
567 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
568 Self::setup(address.into())?;
569 self.read_blocking_internal(buffer, true, true)
570 // Automatic Stop
571 }
572
573 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
574 Self::setup(address.into())?;
575 self.write_blocking_internal(bytes, true)
576 }
577
578 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
579 Self::setup(address.into())?;
580 self.write_blocking_internal(bytes, false)?;
581 self.read_blocking_internal(buffer, true, true)
582 // Automatic Stop
583 }
584} 584}
585 585
586mod eh02 { 586mod eh02 {
587 use super::*; 587 use super::*;
588 588
589 impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, Blocking> { 589 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Read for I2c<'d, T, M> {
590 type Error = Error; 590 type Error = Error;
591 591
592 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 592 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
@@ -594,7 +594,7 @@ mod eh02 {
594 } 594 }
595 } 595 }
596 596
597 impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, Blocking> { 597 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::Write for I2c<'d, T, M> {
598 type Error = Error; 598 type Error = Error;
599 599
600 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { 600 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
@@ -602,7 +602,7 @@ mod eh02 {
602 } 602 }
603 } 603 }
604 604
605 impl<'d, T: Instance> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, Blocking> { 605 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::i2c::WriteRead for I2c<'d, T, M> {
606 type Error = Error; 606 type Error = Error;
607 607
608 fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { 608 fn write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
@@ -635,7 +635,7 @@ mod eh1 {
635 type Error = Error; 635 type Error = Error;
636 } 636 }
637 637
638 impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, Blocking> { 638 impl<'d, T: Instance, M: Mode> embedded_hal_1::i2c::I2c for I2c<'d, T, M> {
639 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { 639 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
640 self.blocking_read(address, buffer) 640 self.blocking_read(address, buffer)
641 } 641 }