diff options
| author | Barnaby Walters <[email protected]> | 2023-11-20 01:29:02 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-11-24 23:55:46 +0100 |
| commit | 3efc3eee5700d2a39e397f1b1b821885301c0862 (patch) | |
| tree | 074c3a461d39e5295553ef30ec5c272f995a72f3 /embassy-stm32 | |
| parent | bc65b8f7ec1df181c793846b7c0657f689963d3a (diff) | |
stm32/i2c: implement async i2c v1.
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 404 |
1 files changed, 381 insertions, 23 deletions
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 03f07c4fe..b62ee8246 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -1,10 +1,14 @@ | |||
| 1 | use core::future::poll_fn; | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 3 | use core::task::Poll; | ||
| 2 | 4 | ||
| 3 | use embassy_embedded_hal::SetConfig; | 5 | use embassy_embedded_hal::SetConfig; |
| 6 | use embassy_futures::select::{select, Either}; | ||
| 7 | use embassy_hal_internal::drop::OnDrop; | ||
| 4 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 5 | 9 | ||
| 6 | use super::*; | 10 | use super::*; |
| 7 | use crate::dma::NoDma; | 11 | use crate::dma::{NoDma, Transfer}; |
| 8 | use crate::gpio::sealed::AFType; | 12 | use crate::gpio::sealed::AFType; |
| 9 | use crate::gpio::Pull; | 13 | use crate::gpio::Pull; |
| 10 | use crate::interrupt::typelevel::Interrupt; | 14 | use crate::interrupt::typelevel::Interrupt; |
| @@ -13,7 +17,17 @@ use crate::time::Hertz; | |||
| 13 | use crate::{interrupt, Peripheral}; | 17 | use crate::{interrupt, Peripheral}; |
| 14 | 18 | ||
| 15 | pub unsafe fn on_interrupt<T: Instance>() { | 19 | pub unsafe fn on_interrupt<T: Instance>() { |
| 16 | // todo | 20 | let regs = T::regs(); |
| 21 | // i2c v2 only woke the task on transfer complete interrupts. v1 uses interrupts for a bunch of | ||
| 22 | // other stuff, so we wake the task on every interrupt. | ||
| 23 | T::state().waker.wake(); | ||
| 24 | critical_section::with(|_| { | ||
| 25 | // Clear event interrupt flag. | ||
| 26 | regs.cr2().modify(|w| { | ||
| 27 | w.set_itevten(false); | ||
| 28 | w.set_iterren(false); | ||
| 29 | }); | ||
| 30 | }); | ||
| 17 | } | 31 | } |
| 18 | 32 | ||
| 19 | #[non_exhaustive] | 33 | #[non_exhaustive] |
| @@ -98,40 +112,58 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 98 | } | 112 | } |
| 99 | } | 113 | } |
| 100 | 114 | ||
| 101 | fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> { | 115 | fn check_and_clear_error_flags() -> Result<i2c::regs::Sr1, Error> { |
| 102 | // Note that flags should only be cleared once they have been registered. If flags are | 116 | // Note that flags should only be cleared once they have been registered. If flags are |
| 103 | // cleared otherwise, there may be an inherent race condition and flags may be missed. | 117 | // cleared otherwise, there may be an inherent race condition and flags may be missed. |
| 104 | let sr1 = T::regs().sr1().read(); | 118 | let sr1 = T::regs().sr1().read(); |
| 105 | 119 | ||
| 106 | if sr1.timeout() { | 120 | if sr1.timeout() { |
| 107 | T::regs().sr1().modify(|reg| reg.set_timeout(false)); | 121 | T::regs().sr1().write(|reg| { |
| 122 | reg.0 = !0; | ||
| 123 | reg.set_timeout(false); | ||
| 124 | }); | ||
| 108 | return Err(Error::Timeout); | 125 | return Err(Error::Timeout); |
| 109 | } | 126 | } |
| 110 | 127 | ||
| 111 | if sr1.pecerr() { | 128 | if sr1.pecerr() { |
| 112 | T::regs().sr1().modify(|reg| reg.set_pecerr(false)); | 129 | T::regs().sr1().write(|reg| { |
| 130 | reg.0 = !0; | ||
| 131 | reg.set_pecerr(false); | ||
| 132 | }); | ||
| 113 | return Err(Error::Crc); | 133 | return Err(Error::Crc); |
| 114 | } | 134 | } |
| 115 | 135 | ||
| 116 | if sr1.ovr() { | 136 | if sr1.ovr() { |
| 117 | T::regs().sr1().modify(|reg| reg.set_ovr(false)); | 137 | T::regs().sr1().write(|reg| { |
| 138 | reg.0 = !0; | ||
| 139 | reg.set_ovr(false); | ||
| 140 | }); | ||
| 118 | return Err(Error::Overrun); | 141 | return Err(Error::Overrun); |
| 119 | } | 142 | } |
| 120 | 143 | ||
| 121 | if sr1.af() { | 144 | if sr1.af() { |
| 122 | T::regs().sr1().modify(|reg| reg.set_af(false)); | 145 | T::regs().sr1().write(|reg| { |
| 146 | reg.0 = !0; | ||
| 147 | reg.set_af(false); | ||
| 148 | }); | ||
| 123 | return Err(Error::Nack); | 149 | return Err(Error::Nack); |
| 124 | } | 150 | } |
| 125 | 151 | ||
| 126 | if sr1.arlo() { | 152 | if sr1.arlo() { |
| 127 | T::regs().sr1().modify(|reg| reg.set_arlo(false)); | 153 | T::regs().sr1().write(|reg| { |
| 154 | reg.0 = !0; | ||
| 155 | reg.set_arlo(false); | ||
| 156 | }); | ||
| 128 | return Err(Error::Arbitration); | 157 | return Err(Error::Arbitration); |
| 129 | } | 158 | } |
| 130 | 159 | ||
| 131 | // The errata indicates that BERR may be incorrectly detected. It recommends ignoring and | 160 | // The errata indicates that BERR may be incorrectly detected. It recommends ignoring and |
| 132 | // clearing the BERR bit instead. | 161 | // clearing the BERR bit instead. |
| 133 | if sr1.berr() { | 162 | if sr1.berr() { |
| 134 | T::regs().sr1().modify(|reg| reg.set_berr(false)); | 163 | T::regs().sr1().write(|reg| { |
| 164 | reg.0 = !0; | ||
| 165 | reg.set_berr(false); | ||
| 166 | }); | ||
| 135 | } | 167 | } |
| 136 | 168 | ||
| 137 | Ok(sr1) | 169 | Ok(sr1) |
| @@ -150,13 +182,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 150 | }); | 182 | }); |
| 151 | 183 | ||
| 152 | // Wait until START condition was generated | 184 | // Wait until START condition was generated |
| 153 | while !self.check_and_clear_error_flags()?.start() { | 185 | while !Self::check_and_clear_error_flags()?.start() { |
| 154 | check_timeout()?; | 186 | check_timeout()?; |
| 155 | } | 187 | } |
| 156 | 188 | ||
| 157 | // Also wait until signalled we're master and everything is waiting for us | 189 | // Also wait until signalled we're master and everything is waiting for us |
| 158 | while { | 190 | while { |
| 159 | self.check_and_clear_error_flags()?; | 191 | Self::check_and_clear_error_flags()?; |
| 160 | 192 | ||
| 161 | let sr2 = T::regs().sr2().read(); | 193 | let sr2 = T::regs().sr2().read(); |
| 162 | !sr2.msl() && !sr2.busy() | 194 | !sr2.msl() && !sr2.busy() |
| @@ -170,7 +202,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 170 | // Wait until address was sent | 202 | // Wait until address was sent |
| 171 | // Wait for the address to be acknowledged | 203 | // Wait for the address to be acknowledged |
| 172 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. | 204 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. |
| 173 | while !self.check_and_clear_error_flags()?.addr() { | 205 | while !Self::check_and_clear_error_flags()?.addr() { |
| 174 | check_timeout()?; | 206 | check_timeout()?; |
| 175 | } | 207 | } |
| 176 | 208 | ||
| @@ -190,7 +222,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 190 | // Wait until we're ready for sending | 222 | // Wait until we're ready for sending |
| 191 | while { | 223 | while { |
| 192 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. | 224 | // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. |
| 193 | !self.check_and_clear_error_flags()?.txe() | 225 | !Self::check_and_clear_error_flags()?.txe() |
| 194 | } { | 226 | } { |
| 195 | check_timeout()?; | 227 | check_timeout()?; |
| 196 | } | 228 | } |
| @@ -201,7 +233,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 201 | // Wait until byte is transferred | 233 | // Wait until byte is transferred |
| 202 | while { | 234 | while { |
| 203 | // Check for any potential error conditions. | 235 | // Check for any potential error conditions. |
| 204 | !self.check_and_clear_error_flags()?.btf() | 236 | !Self::check_and_clear_error_flags()?.btf() |
| 205 | } { | 237 | } { |
| 206 | check_timeout()?; | 238 | check_timeout()?; |
| 207 | } | 239 | } |
| @@ -212,7 +244,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 212 | fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { | 244 | fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> { |
| 213 | while { | 245 | while { |
| 214 | // Check for any potential error conditions. | 246 | // Check for any potential error conditions. |
| 215 | self.check_and_clear_error_flags()?; | 247 | Self::check_and_clear_error_flags()?; |
| 216 | 248 | ||
| 217 | !T::regs().sr1().read().rxne() | 249 | !T::regs().sr1().read().rxne() |
| 218 | } { | 250 | } { |
| @@ -237,7 +269,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 237 | }); | 269 | }); |
| 238 | 270 | ||
| 239 | // Wait until START condition was generated | 271 | // Wait until START condition was generated |
| 240 | while !self.check_and_clear_error_flags()?.start() { | 272 | while !Self::check_and_clear_error_flags()?.start() { |
| 241 | check_timeout()?; | 273 | check_timeout()?; |
| 242 | } | 274 | } |
| 243 | 275 | ||
| @@ -254,7 +286,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 254 | 286 | ||
| 255 | // Wait until address was sent | 287 | // Wait until address was sent |
| 256 | // Wait for the address to be acknowledged | 288 | // Wait for the address to be acknowledged |
| 257 | while !self.check_and_clear_error_flags()?.addr() { | 289 | while !Self::check_and_clear_error_flags()?.addr() { |
| 258 | check_timeout()?; | 290 | check_timeout()?; |
| 259 | } | 291 | } |
| 260 | 292 | ||
| @@ -332,26 +364,352 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 332 | 364 | ||
| 333 | // Async | 365 | // Async |
| 334 | 366 | ||
| 335 | pub async fn write(&mut self, _address: u8, _write: &[u8]) -> Result<(), Error> | 367 | #[inline] // pretty sure this should always be inlined |
| 368 | fn enable_interrupts() -> () { | ||
| 369 | T::regs().cr2().modify(|w| { | ||
| 370 | w.set_iterren(true); | ||
| 371 | w.set_itevten(true); | ||
| 372 | }); | ||
| 373 | } | ||
| 374 | |||
| 375 | async fn write_with_stop(&mut self, address: u8, write: &[u8], send_stop: bool) -> Result<(), Error> | ||
| 336 | where | 376 | where |
| 337 | TXDMA: crate::i2c::TxDma<T>, | 377 | TXDMA: crate::i2c::TxDma<T>, |
| 338 | { | 378 | { |
| 339 | todo!() | 379 | let dma_transfer = unsafe { |
| 380 | let regs = T::regs(); | ||
| 381 | regs.cr2().modify(|w| { | ||
| 382 | // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2 register. | ||
| 383 | w.set_dmaen(true); | ||
| 384 | w.set_itbufen(false); | ||
| 385 | }); | ||
| 386 | // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to this address from the memory after each TxE event. | ||
| 387 | let dst = regs.dr().as_ptr() as *mut u8; | ||
| 388 | |||
| 389 | let ch = &mut self.tx_dma; | ||
| 390 | let request = ch.request(); | ||
| 391 | Transfer::new_write(ch, request, write, dst, Default::default()) | ||
| 392 | }; | ||
| 393 | |||
| 394 | let on_drop = OnDrop::new(|| { | ||
| 395 | let regs = T::regs(); | ||
| 396 | regs.cr2().modify(|w| { | ||
| 397 | w.set_dmaen(false); | ||
| 398 | w.set_iterren(false); | ||
| 399 | w.set_itevten(false); | ||
| 400 | }) | ||
| 401 | }); | ||
| 402 | |||
| 403 | Self::enable_interrupts(); | ||
| 404 | |||
| 405 | // Send a START condition | ||
| 406 | T::regs().cr1().modify(|reg| { | ||
| 407 | reg.set_start(true); | ||
| 408 | }); | ||
| 409 | |||
| 410 | let state = T::state(); | ||
| 411 | |||
| 412 | // Wait until START condition was generated | ||
| 413 | poll_fn(|cx| { | ||
| 414 | state.waker.register(cx.waker()); | ||
| 415 | |||
| 416 | match Self::check_and_clear_error_flags() { | ||
| 417 | Err(e) => Poll::Ready(Err(e)), | ||
| 418 | Ok(sr1) => { | ||
| 419 | if sr1.start() { | ||
| 420 | Poll::Ready(Ok(())) | ||
| 421 | } else { | ||
| 422 | Poll::Pending | ||
| 423 | } | ||
| 424 | } | ||
| 425 | } | ||
| 426 | }) | ||
| 427 | .await?; | ||
| 428 | |||
| 429 | // Also wait until signalled we're master and everything is waiting for us | ||
| 430 | Self::enable_interrupts(); | ||
| 431 | poll_fn(|cx| { | ||
| 432 | state.waker.register(cx.waker()); | ||
| 433 | |||
| 434 | match Self::check_and_clear_error_flags() { | ||
| 435 | Err(e) => Poll::Ready(Err(e)), | ||
| 436 | Ok(_) => { | ||
| 437 | let sr2 = T::regs().sr2().read(); | ||
| 438 | if !sr2.msl() && !sr2.busy() { | ||
| 439 | Poll::Pending | ||
| 440 | } else { | ||
| 441 | Poll::Ready(Ok(())) | ||
| 442 | } | ||
| 443 | } | ||
| 444 | } | ||
| 445 | }) | ||
| 446 | .await?; | ||
| 447 | |||
| 448 | // Set up current address, we're trying to talk to | ||
| 449 | Self::enable_interrupts(); | ||
| 450 | T::regs().dr().write(|reg| reg.set_dr(address << 1)); | ||
| 451 | |||
| 452 | poll_fn(|cx| { | ||
| 453 | state.waker.register(cx.waker()); | ||
| 454 | match Self::check_and_clear_error_flags() { | ||
| 455 | Err(e) => Poll::Ready(Err(e)), | ||
| 456 | Ok(sr1) => { | ||
| 457 | if sr1.addr() { | ||
| 458 | // Clear the ADDR condition by reading SR2. | ||
| 459 | T::regs().sr2().read(); | ||
| 460 | Poll::Ready(Ok(())) | ||
| 461 | } else { | ||
| 462 | Poll::Pending | ||
| 463 | } | ||
| 464 | } | ||
| 465 | } | ||
| 466 | }) | ||
| 467 | .await?; | ||
| 468 | Self::enable_interrupts(); | ||
| 469 | let poll_error = poll_fn(|cx| { | ||
| 470 | state.waker.register(cx.waker()); | ||
| 471 | |||
| 472 | match Self::check_and_clear_error_flags() { | ||
| 473 | // Unclear why the Err turbofish is necessary here? The compiler didn’t require it in the other | ||
| 474 | // identical poll_fn check_and_clear matches. | ||
| 475 | Err(e) => Poll::Ready(Err::<T, Error>(e)), | ||
| 476 | Ok(_) => Poll::Pending, | ||
| 477 | } | ||
| 478 | }); | ||
| 479 | |||
| 480 | // Wait for either the DMA transfer to successfully finish, or an I2C error to occur. | ||
| 481 | match select(dma_transfer, poll_error).await { | ||
| 482 | Either::Second(Err(e)) => Err(e), | ||
| 483 | _ => Ok(()), | ||
| 484 | }?; | ||
| 485 | |||
| 486 | // The I2C transfer itself will take longer than the DMA transfer, so wait for that to finish too. | ||
| 487 | |||
| 488 | // 18.3.8 “Master transmitter: In the interrupt routine after the EOT interrupt, disable DMA | ||
| 489 | // requests then wait for a BTF event before programming the Stop condition.” | ||
| 490 | |||
| 491 | // TODO: If this has to be done “in the interrupt routine after the EOT interrupt”, where to put it? | ||
| 492 | T::regs().cr2().modify(|w| { | ||
| 493 | w.set_dmaen(false); | ||
| 494 | }); | ||
| 495 | |||
| 496 | Self::enable_interrupts(); | ||
| 497 | poll_fn(|cx| { | ||
| 498 | state.waker.register(cx.waker()); | ||
| 499 | |||
| 500 | match Self::check_and_clear_error_flags() { | ||
| 501 | Err(e) => Poll::Ready(Err(e)), | ||
| 502 | Ok(sr1) => { | ||
| 503 | if sr1.btf() { | ||
| 504 | if send_stop { | ||
| 505 | T::regs().cr1().modify(|w| { | ||
| 506 | w.set_stop(true); | ||
| 507 | }); | ||
| 508 | } | ||
| 509 | |||
| 510 | Poll::Ready(Ok(())) | ||
| 511 | } else { | ||
| 512 | Poll::Pending | ||
| 513 | } | ||
| 514 | } | ||
| 515 | } | ||
| 516 | }) | ||
| 517 | .await?; | ||
| 518 | |||
| 519 | drop(on_drop); | ||
| 520 | |||
| 521 | // Fallthrough is success | ||
| 522 | Ok(()) | ||
| 340 | } | 523 | } |
| 341 | 524 | ||
| 342 | pub async fn read(&mut self, _address: u8, _buffer: &mut [u8]) -> Result<(), Error> | 525 | pub async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Error> |
| 526 | where | ||
| 527 | TXDMA: crate::i2c::TxDma<T>, | ||
| 528 | { | ||
| 529 | self.write_with_stop(address, write, true).await?; | ||
| 530 | |||
| 531 | // Wait for STOP condition to transmit. | ||
| 532 | Self::enable_interrupts(); | ||
| 533 | poll_fn(|cx| { | ||
| 534 | T::state().waker.register(cx.waker()); | ||
| 535 | // TODO: error interrupts are enabled here, should we additional check for and return errors? | ||
| 536 | if T::regs().cr1().read().stop() { | ||
| 537 | Poll::Pending | ||
| 538 | } else { | ||
| 539 | Poll::Ready(Ok(())) | ||
| 540 | } | ||
| 541 | }) | ||
| 542 | .await?; | ||
| 543 | |||
| 544 | Ok(()) | ||
| 545 | } | ||
| 546 | |||
| 547 | pub async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> | ||
| 343 | where | 548 | where |
| 344 | RXDMA: crate::i2c::RxDma<T>, | 549 | RXDMA: crate::i2c::RxDma<T>, |
| 345 | { | 550 | { |
| 346 | todo!() | 551 | let state = T::state(); |
| 552 | let buffer_len = buffer.len(); | ||
| 553 | |||
| 554 | let dma_transfer = unsafe { | ||
| 555 | let regs = T::regs(); | ||
| 556 | regs.cr2().modify(|w| { | ||
| 557 | // DMA mode can be enabled for transmission by setting the DMAEN bit in the I2C_CR2 register. | ||
| 558 | w.set_itbufen(false); | ||
| 559 | w.set_dmaen(true); | ||
| 560 | }); | ||
| 561 | // Set the I2C_DR register address in the DMA_SxPAR register. The data will be moved to this address from the memory after each TxE event. | ||
| 562 | let src = regs.dr().as_ptr() as *mut u8; | ||
| 563 | |||
| 564 | let ch = &mut self.rx_dma; | ||
| 565 | let request = ch.request(); | ||
| 566 | Transfer::new_read(ch, request, src, buffer, Default::default()) | ||
| 567 | }; | ||
| 568 | |||
| 569 | let on_drop = OnDrop::new(|| { | ||
| 570 | let regs = T::regs(); | ||
| 571 | regs.cr2().modify(|w| { | ||
| 572 | w.set_dmaen(false); | ||
| 573 | w.set_iterren(false); | ||
| 574 | w.set_itevten(false); | ||
| 575 | }) | ||
| 576 | }); | ||
| 577 | |||
| 578 | Self::enable_interrupts(); | ||
| 579 | |||
| 580 | // Send a START condition and set ACK bit | ||
| 581 | T::regs().cr1().modify(|reg| { | ||
| 582 | reg.set_start(true); | ||
| 583 | reg.set_ack(true); | ||
| 584 | }); | ||
| 585 | |||
| 586 | // Wait until START condition was generated | ||
| 587 | poll_fn(|cx| { | ||
| 588 | state.waker.register(cx.waker()); | ||
| 589 | |||
| 590 | match Self::check_and_clear_error_flags() { | ||
| 591 | Err(e) => Poll::Ready(Err(e)), | ||
| 592 | Ok(sr1) => { | ||
| 593 | if sr1.start() { | ||
| 594 | Poll::Ready(Ok(())) | ||
| 595 | } else { | ||
| 596 | Poll::Pending | ||
| 597 | } | ||
| 598 | } | ||
| 599 | } | ||
| 600 | }) | ||
| 601 | .await?; | ||
| 602 | |||
| 603 | // Also wait until signalled we're master and everything is waiting for us | ||
| 604 | Self::enable_interrupts(); | ||
| 605 | poll_fn(|cx| { | ||
| 606 | state.waker.register(cx.waker()); | ||
| 607 | |||
| 608 | // blocking read didn’t have a check_and_clear call here, but blocking write did so | ||
| 609 | // I’m adding it here in case that was an oversight. | ||
| 610 | match Self::check_and_clear_error_flags() { | ||
| 611 | Err(e) => Poll::Ready(Err(e)), | ||
| 612 | Ok(_) => { | ||
| 613 | let sr2 = T::regs().sr2().read(); | ||
| 614 | if !sr2.msl() && !sr2.busy() { | ||
| 615 | Poll::Pending | ||
| 616 | } else { | ||
| 617 | Poll::Ready(Ok(())) | ||
| 618 | } | ||
| 619 | } | ||
| 620 | } | ||
| 621 | }) | ||
| 622 | .await?; | ||
| 623 | |||
| 624 | // Set up current address, we're trying to talk to | ||
| 625 | T::regs().dr().write(|reg| reg.set_dr((address << 1) + 1)); | ||
| 626 | |||
| 627 | // Wait for the address to be acknowledged | ||
| 628 | |||
| 629 | Self::enable_interrupts(); | ||
| 630 | poll_fn(|cx| { | ||
| 631 | state.waker.register(cx.waker()); | ||
| 632 | |||
| 633 | match Self::check_and_clear_error_flags() { | ||
| 634 | Err(e) => Poll::Ready(Err(e)), | ||
| 635 | Ok(sr1) => { | ||
| 636 | if sr1.addr() { | ||
| 637 | // 18.3.8: When a single byte must be received: the NACK must be programmed during EV6 | ||
| 638 | // event, i.e. program ACK=0 when ADDR=1, before clearing ADDR flag. | ||
| 639 | if buffer_len == 1 { | ||
| 640 | T::regs().cr1().modify(|w| { | ||
| 641 | w.set_ack(false); | ||
| 642 | }); | ||
| 643 | } | ||
| 644 | Poll::Ready(Ok(())) | ||
| 645 | } else { | ||
| 646 | Poll::Pending | ||
| 647 | } | ||
| 648 | } | ||
| 649 | } | ||
| 650 | }) | ||
| 651 | .await?; | ||
| 652 | |||
| 653 | // Clear ADDR condition by reading SR2 | ||
| 654 | T::regs().sr2().read(); | ||
| 655 | |||
| 656 | // 18.3.8: When a single byte must be received: [snip] Then the | ||
| 657 | // user can program the STOP condition either after clearing ADDR flag, or in the | ||
| 658 | // DMA Transfer Complete interrupt routine. | ||
| 659 | if buffer_len == 1 { | ||
| 660 | T::regs().cr1().modify(|w| { | ||
| 661 | w.set_stop(true); | ||
| 662 | }); | ||
| 663 | } else { | ||
| 664 | // If, in the I2C_CR2 register, the LAST bit is set, I2C | ||
| 665 | // automatically sends a NACK after the next byte following EOT_1. The user can | ||
| 666 | // generate a Stop condition in the DMA Transfer Complete interrupt routine if enabled. | ||
| 667 | T::regs().cr2().modify(|w| { | ||
| 668 | w.set_last(true); | ||
| 669 | }) | ||
| 670 | } | ||
| 671 | |||
| 672 | // Wait for bytes to be received, or an error to occur. | ||
| 673 | Self::enable_interrupts(); | ||
| 674 | let poll_error = poll_fn(|cx| { | ||
| 675 | state.waker.register(cx.waker()); | ||
| 676 | |||
| 677 | match Self::check_and_clear_error_flags() { | ||
| 678 | Err(e) => Poll::Ready(Err::<T, Error>(e)), | ||
| 679 | _ => Poll::Pending, | ||
| 680 | } | ||
| 681 | }); | ||
| 682 | |||
| 683 | match select(dma_transfer, poll_error).await { | ||
| 684 | Either::Second(Err(e)) => Err(e), | ||
| 685 | _ => Ok(()), | ||
| 686 | }?; | ||
| 687 | |||
| 688 | // Wait for the STOP to be sent (STOP bit cleared). | ||
| 689 | Self::enable_interrupts(); | ||
| 690 | poll_fn(|cx| { | ||
| 691 | state.waker.register(cx.waker()); | ||
| 692 | // TODO: error interrupts are enabled here, should we additional check for and return errors? | ||
| 693 | if T::regs().cr1().read().stop() { | ||
| 694 | Poll::Pending | ||
| 695 | } else { | ||
| 696 | Poll::Ready(Ok(())) | ||
| 697 | } | ||
| 698 | }) | ||
| 699 | .await?; | ||
| 700 | drop(on_drop); | ||
| 701 | |||
| 702 | // Fallthrough is success | ||
| 703 | Ok(()) | ||
| 347 | } | 704 | } |
| 348 | 705 | ||
| 349 | pub async fn write_read(&mut self, _address: u8, _write: &[u8], _read: &mut [u8]) -> Result<(), Error> | 706 | pub async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> |
| 350 | where | 707 | where |
| 351 | RXDMA: crate::i2c::RxDma<T>, | 708 | RXDMA: crate::i2c::RxDma<T>, |
| 352 | TXDMA: crate::i2c::TxDma<T>, | 709 | TXDMA: crate::i2c::TxDma<T>, |
| 353 | { | 710 | { |
| 354 | todo!() | 711 | self.write_with_stop(address, write, false).await?; |
| 712 | self.read(address, read).await | ||
| 355 | } | 713 | } |
| 356 | } | 714 | } |
| 357 | 715 | ||
