diff options
| -rw-r--r-- | embassy-nrf/src/twis.rs | 141 | ||||
| -rw-r--r-- | examples/nrf/src/bin/twis.rs | 2 |
2 files changed, 77 insertions, 66 deletions
diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs index 8c9cb54ea..769522877 100644 --- a/embassy-nrf/src/twis.rs +++ b/embassy-nrf/src/twis.rs | |||
| @@ -24,8 +24,8 @@ use crate::{gpio, pac, Peripheral}; | |||
| 24 | 24 | ||
| 25 | #[non_exhaustive] | 25 | #[non_exhaustive] |
| 26 | pub struct Config { | 26 | pub struct Config { |
| 27 | pub addr0: u8, | 27 | pub address0: u8, |
| 28 | pub addr1: Option<u8>, | 28 | pub address1: Option<u8>, |
| 29 | pub orc: u8, | 29 | pub orc: u8, |
| 30 | pub sda_high_drive: bool, | 30 | pub sda_high_drive: bool, |
| 31 | pub sda_pullup: bool, | 31 | pub sda_pullup: bool, |
| @@ -36,8 +36,8 @@ pub struct Config { | |||
| 36 | impl Default for Config { | 36 | impl Default for Config { |
| 37 | fn default() -> Self { | 37 | fn default() -> Self { |
| 38 | Self { | 38 | Self { |
| 39 | addr0: 0x55, | 39 | address0: 0x55, |
| 40 | addr1: None, | 40 | address1: None, |
| 41 | orc: 0x00, | 41 | orc: 0x00, |
| 42 | scl_high_drive: false, | 42 | scl_high_drive: false, |
| 43 | sda_pullup: false, | 43 | sda_pullup: false, |
| @@ -134,10 +134,10 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 134 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); | 134 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); |
| 135 | 135 | ||
| 136 | // Set address | 136 | // Set address |
| 137 | r.address[0].write(|w| unsafe { w.address().bits(config.addr0) }); | 137 | r.address[0].write(|w| unsafe { w.address().bits(config.address0) }); |
| 138 | r.config.modify(|_r, w| w.address0().enabled()); | 138 | r.config.modify(|_r, w| w.address0().enabled()); |
| 139 | if let Some(addr1) = config.addr1 { | 139 | if let Some(address1) = config.address1 { |
| 140 | r.address[1].write(|w| unsafe { w.address().bits(addr1) }); | 140 | r.address[1].write(|w| unsafe { w.address().bits(address1) }); |
| 141 | r.config.modify(|_r, w| w.address1().enabled()); | 141 | r.config.modify(|_r, w| w.address1().enabled()); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| @@ -242,7 +242,13 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 242 | .write(|w| w.overflow().bit(true).overread().bit(true).dnack().bit(true)); | 242 | .write(|w| w.overflow().bit(true).overread().bit(true).dnack().bit(true)); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | /// Wait for stop or error | 245 | /// Returns matched address for latest command. |
| 246 | pub fn address_match(&self) -> u8 { | ||
| 247 | let r = T::regs(); | ||
| 248 | r.address[r.match_.read().bits() as usize].read().address().bits() | ||
| 249 | } | ||
| 250 | |||
| 251 | /// Wait for read, write, stop or error | ||
| 246 | fn blocking_listen_wait(&mut self) -> Result<Status, Error> { | 252 | fn blocking_listen_wait(&mut self) -> Result<Status, Error> { |
| 247 | let r = T::regs(); | 253 | let r = T::regs(); |
| 248 | loop { | 254 | loop { |
| @@ -267,7 +273,7 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 267 | } | 273 | } |
| 268 | } | 274 | } |
| 269 | 275 | ||
| 270 | /// Wait for stop or error | 276 | /// Wait for stop, repeated start or error |
| 271 | fn blocking_listen_wait_end(&mut self, status: Status) -> Result<Command, Error> { | 277 | fn blocking_listen_wait_end(&mut self, status: Status) -> Result<Command, Error> { |
| 272 | let r = T::regs(); | 278 | let r = T::regs(); |
| 273 | loop { | 279 | loop { |
| @@ -294,7 +300,7 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 294 | } | 300 | } |
| 295 | 301 | ||
| 296 | /// Wait for stop or error | 302 | /// Wait for stop or error |
| 297 | fn blocking_wait(&mut self) -> Result<(), Error> { | 303 | fn blocking_wait(&mut self) -> Result<usize, Error> { |
| 298 | let r = T::regs(); | 304 | let r = T::regs(); |
| 299 | loop { | 305 | loop { |
| 300 | // stop if an error occured | 306 | // stop if an error occured |
| @@ -311,12 +317,42 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 311 | } | 317 | } |
| 312 | } else if r.events_stopped.read().bits() != 0 { | 318 | } else if r.events_stopped.read().bits() != 0 { |
| 313 | r.events_stopped.reset(); | 319 | r.events_stopped.reset(); |
| 314 | return Ok(()); | 320 | let n = r.txd.amount.read().bits() as usize; |
| 321 | return Ok(n); | ||
| 315 | } | 322 | } |
| 316 | } | 323 | } |
| 317 | } | 324 | } |
| 318 | 325 | ||
| 319 | /// Wait for stop or error | 326 | /// Wait for stop or error with timeout |
| 327 | #[cfg(feature = "time")] | ||
| 328 | fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<usize, Error> { | ||
| 329 | let r = T::regs(); | ||
| 330 | let deadline = Instant::now() + timeout; | ||
| 331 | loop { | ||
| 332 | // stop if an error occured | ||
| 333 | if r.events_error.read().bits() != 0 { | ||
| 334 | r.events_error.reset(); | ||
| 335 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 336 | let errorsrc = r.errorsrc.read(); | ||
| 337 | if errorsrc.overread().is_detected() { | ||
| 338 | return Err(Error::OverRead); | ||
| 339 | } else if errorsrc.dnack().is_received() { | ||
| 340 | return Err(Error::DataNack); | ||
| 341 | } else { | ||
| 342 | return Err(Error::Bus); | ||
| 343 | } | ||
| 344 | } else if r.events_stopped.read().bits() != 0 { | ||
| 345 | r.events_stopped.reset(); | ||
| 346 | let n = r.txd.amount.read().bits() as usize; | ||
| 347 | return Ok(n); | ||
| 348 | } else if Instant::now() > deadline { | ||
| 349 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 350 | return Err(Error::Timeout); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | /// Wait for read, write, stop or error with timeout | ||
| 320 | #[cfg(feature = "time")] | 356 | #[cfg(feature = "time")] |
| 321 | fn blocking_listen_wait_timeout(&mut self, timeout: Duration) -> Result<Status, Error> { | 357 | fn blocking_listen_wait_timeout(&mut self, timeout: Duration) -> Result<Status, Error> { |
| 322 | let r = T::regs(); | 358 | let r = T::regs(); |
| @@ -347,7 +383,7 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 347 | } | 383 | } |
| 348 | } | 384 | } |
| 349 | 385 | ||
| 350 | /// Wait for stop or error | 386 | /// Wait for stop, repeated start or error with timeout |
| 351 | #[cfg(feature = "time")] | 387 | #[cfg(feature = "time")] |
| 352 | fn blocking_listen_wait_end_timeout(&mut self, status: Status, timeout: Duration) -> Result<Command, Error> { | 388 | fn blocking_listen_wait_end_timeout(&mut self, status: Status, timeout: Duration) -> Result<Command, Error> { |
| 353 | let r = T::regs(); | 389 | let r = T::regs(); |
| @@ -379,35 +415,7 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 379 | } | 415 | } |
| 380 | 416 | ||
| 381 | /// Wait for stop or error | 417 | /// Wait for stop or error |
| 382 | #[cfg(feature = "time")] | 418 | fn async_wait(&mut self) -> impl Future<Output = Result<usize, Error>> { |
| 383 | fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<(), Error> { | ||
| 384 | let r = T::regs(); | ||
| 385 | let deadline = Instant::now() + timeout; | ||
| 386 | loop { | ||
| 387 | // stop if an error occured | ||
| 388 | if r.events_error.read().bits() != 0 { | ||
| 389 | r.events_error.reset(); | ||
| 390 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 391 | let errorsrc = r.errorsrc.read(); | ||
| 392 | if errorsrc.overread().is_detected() { | ||
| 393 | return Err(Error::OverRead); | ||
| 394 | } else if errorsrc.dnack().is_received() { | ||
| 395 | return Err(Error::DataNack); | ||
| 396 | } else { | ||
| 397 | return Err(Error::Bus); | ||
| 398 | } | ||
| 399 | } else if r.events_stopped.read().bits() != 0 { | ||
| 400 | r.events_stopped.reset(); | ||
| 401 | return Ok(()); | ||
| 402 | } else if Instant::now() > deadline { | ||
| 403 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 404 | return Err(Error::Timeout); | ||
| 405 | } | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | /// Wait for stop or error | ||
| 410 | fn async_wait(&mut self) -> impl Future<Output = Result<(), Error>> { | ||
| 411 | poll_fn(move |cx| { | 419 | poll_fn(move |cx| { |
| 412 | let r = T::regs(); | 420 | let r = T::regs(); |
| 413 | let s = T::state(); | 421 | let s = T::state(); |
| @@ -428,7 +436,8 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 428 | } | 436 | } |
| 429 | } else if r.events_stopped.read().bits() != 0 { | 437 | } else if r.events_stopped.read().bits() != 0 { |
| 430 | r.events_stopped.reset(); | 438 | r.events_stopped.reset(); |
| 431 | return Poll::Ready(Ok(())); | 439 | let n = r.txd.amount.read().bits() as usize; |
| 440 | return Poll::Ready(Ok(n)); | ||
| 432 | } | 441 | } |
| 433 | 442 | ||
| 434 | Poll::Pending | 443 | Poll::Pending |
| @@ -462,7 +471,7 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 462 | }) | 471 | }) |
| 463 | } | 472 | } |
| 464 | 473 | ||
| 465 | /// Wait for stop or error | 474 | /// Wait for stop, repeated start or error |
| 466 | fn async_listen_wait_end(&mut self, status: Status) -> impl Future<Output = Result<Command, Error>> { | 475 | fn async_listen_wait_end(&mut self, status: Status) -> impl Future<Output = Result<Command, Error>> { |
| 467 | poll_fn(move |cx| { | 476 | poll_fn(move |cx| { |
| 468 | let r = T::regs(); | 477 | let r = T::regs(); |
| @@ -595,25 +604,23 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 595 | } | 604 | } |
| 596 | 605 | ||
| 597 | /// Write to an I2C master. | 606 | /// Write to an I2C master. |
| 598 | /// | 607 | /// Returns the number of bytes written. |
| 599 | /// The buffer must have a length of at most 255 bytes on the nRF52832 | 608 | /// The buffer must have a length of at most 255 bytes on the nRF52832 |
| 600 | /// and at most 65535 bytes on the nRF52840. | 609 | /// and at most 65535 bytes on the nRF52840. |
| 601 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 610 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<usize, Error> { |
| 602 | self.setup_write(buffer, false)?; | 611 | self.setup_write(buffer, false)?; |
| 603 | self.blocking_wait()?; | 612 | self.blocking_wait() |
| 604 | Ok(()) | ||
| 605 | } | 613 | } |
| 606 | 614 | ||
| 607 | /// Same as [`blocking_write`](Twis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. | 615 | /// Same as [`blocking_write`](Twis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. |
| 608 | pub fn blocking_write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> { | 616 | pub fn blocking_write_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> { |
| 609 | self.setup_write_from_ram(buffer, false)?; | 617 | self.setup_write_from_ram(buffer, false)?; |
| 610 | self.blocking_wait()?; | 618 | self.blocking_wait() |
| 611 | Ok(()) | ||
| 612 | } | 619 | } |
| 613 | 620 | ||
| 614 | // =========================================== | 621 | // =========================================== |
| 615 | 622 | ||
| 616 | /// Listen for commands from an I2C master. | 623 | /// Listen for commands from an I2C master with timeout. |
| 617 | /// | 624 | /// |
| 618 | /// The buffer must have a length of at most 255 bytes on the nRF52832 | 625 | /// The buffer must have a length of at most 255 bytes on the nRF52832 |
| 619 | /// and at most 65535 bytes on the nRF52840. | 626 | /// and at most 65535 bytes on the nRF52840. |
| @@ -630,25 +637,27 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 630 | } | 637 | } |
| 631 | 638 | ||
| 632 | /// Write to an I2C master with timeout. | 639 | /// Write to an I2C master with timeout. |
| 633 | /// | 640 | /// Returns the number of bytes written. |
| 634 | /// See [`blocking_write`]. | 641 | /// See [`blocking_write`]. |
| 635 | #[cfg(feature = "time")] | 642 | #[cfg(feature = "time")] |
| 636 | pub fn blocking_write_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<(), Error> { | 643 | pub fn blocking_write_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<usize, Error> { |
| 637 | self.setup_write(buffer, false)?; | 644 | self.setup_write(buffer, false)?; |
| 638 | self.blocking_wait_timeout(timeout)?; | 645 | self.blocking_wait_timeout(timeout) |
| 639 | Ok(()) | ||
| 640 | } | 646 | } |
| 641 | 647 | ||
| 642 | /// Same as [`blocking_write`](Twis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. | 648 | /// Same as [`blocking_write`](Twis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. |
| 643 | #[cfg(feature = "time")] | 649 | #[cfg(feature = "time")] |
| 644 | pub fn blocking_write_from_ram_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<(), Error> { | 650 | pub fn blocking_write_from_ram_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<usize, Error> { |
| 645 | self.setup_write_from_ram(buffer, false)?; | 651 | self.setup_write_from_ram(buffer, false)?; |
| 646 | self.blocking_wait_timeout(timeout)?; | 652 | self.blocking_wait_timeout(timeout) |
| 647 | Ok(()) | ||
| 648 | } | 653 | } |
| 649 | 654 | ||
| 650 | // =========================================== | 655 | // =========================================== |
| 651 | 656 | ||
| 657 | /// Listen asynchronously for commands from an I2C master. | ||
| 658 | /// | ||
| 659 | /// The buffer must have a length of at most 255 bytes on the nRF52832 | ||
| 660 | /// and at most 65535 bytes on the nRF52840. | ||
| 652 | pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> { | 661 | pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> { |
| 653 | self.setup_listen(buffer, true)?; | 662 | self.setup_listen(buffer, true)?; |
| 654 | let status = self.async_listen_wait().await?; | 663 | let status = self.async_listen_wait().await?; |
| @@ -660,17 +669,19 @@ impl<'d, T: Instance> Twis<'d, T> { | |||
| 660 | Ok(Command::Read) | 669 | Ok(Command::Read) |
| 661 | } | 670 | } |
| 662 | 671 | ||
| 663 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 672 | /// Async write to an I2C master. |
| 673 | /// Returns the number of bytes written. | ||
| 674 | /// The buffer must have a length of at most 255 bytes on the nRF52832 | ||
| 675 | /// and at most 65535 bytes on the nRF52840. | ||
| 676 | pub async fn write(&mut self, buffer: &[u8]) -> Result<usize, Error> { | ||
| 664 | self.setup_write(buffer, true)?; | 677 | self.setup_write(buffer, true)?; |
| 665 | self.async_wait().await?; | 678 | self.async_wait().await |
| 666 | Ok(()) | ||
| 667 | } | 679 | } |
| 668 | 680 | ||
| 669 | /// Same as [`write`](Twis::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. | 681 | /// Same as [`write`](Twis::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. |
| 670 | pub async fn write_from_ram(&mut self, buffer: &[u8]) -> Result<(), Error> { | 682 | pub async fn write_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> { |
| 671 | self.setup_write_from_ram(buffer, true)?; | 683 | self.setup_write_from_ram(buffer, true)?; |
| 672 | self.async_wait().await?; | 684 | self.async_wait().await |
| 673 | Ok(()) | ||
| 674 | } | 685 | } |
| 675 | } | 686 | } |
| 676 | 687 | ||
diff --git a/examples/nrf/src/bin/twis.rs b/examples/nrf/src/bin/twis.rs index f85173c08..a34bb2711 100644 --- a/examples/nrf/src/bin/twis.rs +++ b/examples/nrf/src/bin/twis.rs | |||
| @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { | |||
| 17 | let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); | 17 | let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); |
| 18 | let mut config = twis::Config::default(); | 18 | let mut config = twis::Config::default(); |
| 19 | // Set i2c address | 19 | // Set i2c address |
| 20 | config.addr0 = 0x55; | 20 | config.address0 = 0x55; |
| 21 | let mut i2c = Twis::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); | 21 | let mut i2c = Twis::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); |
| 22 | 22 | ||
| 23 | info!("Listening..."); | 23 | info!("Listening..."); |
