diff options
| author | HybridChild <[email protected]> | 2025-08-11 19:56:52 +0200 |
|---|---|---|
| committer | HybridChild <[email protected]> | 2025-08-23 08:53:48 +0200 |
| commit | fd7158063d38ece65f6f3f13422b2d744e8a144f (patch) | |
| tree | b85ab3f804c51bf9564bf73d9a030fbbf0cbc40d | |
| parent | 4f7febc34eab0dd5822f313854338997f6dbf617 (diff) | |
stm32/i2c_v1: Clean up slave implementation
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 992 |
1 files changed, 470 insertions, 522 deletions
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 9022c2f5d..8f4128b45 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -32,21 +32,6 @@ impl State { | |||
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | #[derive(Debug, PartialEq)] | ||
| 36 | enum SlaveSendResult { | ||
| 37 | Acked, // Byte sent and ACK received from master | ||
| 38 | Nacked, // Byte sent but NACK received (normal end of transmission) | ||
| 39 | Stopped, // STOP condition detected | ||
| 40 | Restart, // RESTART condition detected | ||
| 41 | } | ||
| 42 | |||
| 43 | #[derive(Debug, PartialEq)] | ||
| 44 | enum SlaveReceiveResult { | ||
| 45 | Byte(u8), // Data byte received | ||
| 46 | Stop, // STOP condition detected | ||
| 47 | Restart, // RESTART condition (new ADDR) detected | ||
| 48 | } | ||
| 49 | |||
| 50 | // /!\ /!\ | 35 | // /!\ /!\ |
| 51 | // /!\ Implementation note! /!\ | 36 | // /!\ Implementation note! /!\ |
| 52 | // /!\ /!\ | 37 | // /!\ /!\ |
| @@ -387,513 +372,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 387 | } | 372 | } |
| 388 | } | 373 | } |
| 389 | 374 | ||
| 390 | impl<'d, M: Mode> I2c<'d, M, Master> { | ||
| 391 | /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) | ||
| 392 | pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { | ||
| 393 | let mut slave = I2c { | ||
| 394 | info: self.info, | ||
| 395 | state: self.state, | ||
| 396 | kernel_clock: self.kernel_clock, | ||
| 397 | tx_dma: self.tx_dma.take(), // Use take() to move ownership | ||
| 398 | rx_dma: self.rx_dma.take(), // Use take() to move ownership | ||
| 399 | #[cfg(feature = "time")] | ||
| 400 | timeout: self.timeout, | ||
| 401 | _phantom: PhantomData, | ||
| 402 | _phantom2: PhantomData, | ||
| 403 | _drop_guard: self._drop_guard, // Move the drop guard | ||
| 404 | }; | ||
| 405 | slave.init_slave(slave_addr_config); | ||
| 406 | slave | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | ||
| 411 | /// Slave configuration with v1 address setup | ||
| 412 | pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { | ||
| 413 | trace!("i2c v1 slave init: config={:?}", config); | ||
| 414 | |||
| 415 | // Disable peripheral for configuration | ||
| 416 | self.info.regs.cr1().modify(|reg| { | ||
| 417 | reg.set_pe(false); | ||
| 418 | }); | ||
| 419 | |||
| 420 | // Configure addresses with proper v1 format | ||
| 421 | self.configure_addresses(config); | ||
| 422 | |||
| 423 | // Configure general call if requested | ||
| 424 | if config.general_call { | ||
| 425 | self.info.regs.cr1().modify(|w| w.set_engc(true)); | ||
| 426 | trace!("i2c v1 slave: General call enabled"); | ||
| 427 | } | ||
| 428 | |||
| 429 | // Log final configuration before enabling | ||
| 430 | let cr1 = self.info.regs.cr1().read(); | ||
| 431 | let oar1 = self.info.regs.oar1().read(); | ||
| 432 | let oar2 = self.info.regs.oar2().read(); | ||
| 433 | trace!("i2c v1 slave: Pre-enable state - CR1={:#x}, OAR1={:#x}, OAR2={:#x}", | ||
| 434 | cr1.0, oar1.0, oar2.0); | ||
| 435 | trace!("i2c v1 slave: Address details - OAR1.ADD={:#x}, OAR1.ADDMODE={}, bit14={}", | ||
| 436 | oar1.add(), oar1.addmode() as u8, (oar1.0 >> 14) & 1); | ||
| 437 | |||
| 438 | self.info.regs.cr1().modify(|reg| { | ||
| 439 | reg.set_pe(true); // Re-enable peripheral | ||
| 440 | reg.set_ack(true); // Critical for slave to ACK its address | ||
| 441 | }); | ||
| 442 | |||
| 443 | // Verify peripheral is enabled and ready | ||
| 444 | let cr1_final = self.info.regs.cr1().read(); | ||
| 445 | trace!("i2c v1 slave: Final state - CR1={:#x}, PE={}", cr1_final.0, cr1_final.pe()); | ||
| 446 | |||
| 447 | trace!("i2c v1 slave init complete"); | ||
| 448 | } | ||
| 449 | |||
| 450 | fn configure_oa1(&mut self, addr: Address) { | ||
| 451 | match addr { | ||
| 452 | Address::SevenBit(addr) => { | ||
| 453 | trace!("i2c v1 slave: Setting OA1 7-bit address: input={:#x}", addr); | ||
| 454 | self.info.regs.oar1().write(|reg| { | ||
| 455 | // For I2C v1, the 7-bit address goes in bits [7:1] of the ADD field | ||
| 456 | // The ADD field spans bits [9:0], so we put the address in the correct position | ||
| 457 | let hw_addr = (addr as u16) << 1; // This puts address in bits [7:1], bit [0] = 0 | ||
| 458 | reg.set_add(hw_addr); | ||
| 459 | reg.set_addmode(i2c::vals::Addmode::BIT7); | ||
| 460 | }); | ||
| 461 | |||
| 462 | // CRITICAL: Set bit 14 as required by the reference manual | ||
| 463 | // "Bit 14: Should always be kept at 1 by software" | ||
| 464 | self.info.regs.oar1().modify(|reg| { | ||
| 465 | reg.0 |= 1 << 14; // Set bit 14 | ||
| 466 | }); | ||
| 467 | |||
| 468 | let oar1_verify = self.info.regs.oar1().read(); | ||
| 469 | trace!("i2c v1 slave: OA1 configured - OAR1={:#x}, stored_addr={:#x}, bit14={}", | ||
| 470 | oar1_verify.0, oar1_verify.add(), (oar1_verify.0 >> 14) & 1); | ||
| 471 | }, | ||
| 472 | Address::TenBit(addr) => { | ||
| 473 | trace!("i2c v1 slave: Setting OA1 10-bit address: {:#x}", addr); | ||
| 474 | self.info.regs.oar1().write(|reg| { | ||
| 475 | reg.set_add(addr); // For 10-bit, full address goes in ADD field | ||
| 476 | reg.set_addmode(i2c::vals::Addmode::BIT10); | ||
| 477 | }); | ||
| 478 | |||
| 479 | // Set required bit 14 for 10-bit mode too | ||
| 480 | self.info.regs.oar1().modify(|reg| { | ||
| 481 | reg.0 |= 1 << 14; // Set bit 14 | ||
| 482 | }); | ||
| 483 | |||
| 484 | let oar1_verify = self.info.regs.oar1().read(); | ||
| 485 | trace!("i2c v1 slave: OA1 10-bit configured - OAR1={:#x}, bit14={}", | ||
| 486 | oar1_verify.0, (oar1_verify.0 >> 14) & 1); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | fn configure_oa2_simple(&mut self, addr: u8) { | ||
| 492 | trace!("i2c v1 slave: Setting OA2 address: {:#x}", addr); | ||
| 493 | self.info.regs.oar2().write(|reg| { | ||
| 494 | // For OA2, the address goes in bits [7:1] of the ADD2 field | ||
| 495 | reg.set_add2(addr); // ADD2 field automatically handles bits [7:1] placement | ||
| 496 | reg.set_endual(i2c::vals::Endual::DUAL); // Enable dual addressing | ||
| 497 | }); | ||
| 498 | |||
| 499 | let oar2_verify = self.info.regs.oar2().read(); | ||
| 500 | trace!("i2c v1 slave: OA2 configured - OAR2={:#x}, ADD2={:#x}, ENDUAL={}", | ||
| 501 | oar2_verify.0, oar2_verify.add2(), oar2_verify.endual() as u8); | ||
| 502 | } | ||
| 503 | |||
| 504 | fn configure_addresses(&mut self, config: SlaveAddrConfig) { | ||
| 505 | match config.addr { | ||
| 506 | OwnAddresses::OA1(addr) => { | ||
| 507 | self.configure_oa1(addr); | ||
| 508 | // Disable OA2 if not needed | ||
| 509 | self.info.regs.oar2().write(|reg| { | ||
| 510 | reg.set_endual(i2c::vals::Endual::SINGLE); | ||
| 511 | }); | ||
| 512 | }, | ||
| 513 | OwnAddresses::OA2(oa2) => { | ||
| 514 | // v1 limitation: ignore mask, only support simple OA2 | ||
| 515 | if !matches!(oa2.mask, AddrMask::NOMASK) { | ||
| 516 | // Could log a warning here that masking is ignored in v1 | ||
| 517 | #[cfg(feature = "defmt")] | ||
| 518 | warn!("I2C v1 does not support OA2 address masking, ignoring mask setting"); | ||
| 519 | } | ||
| 520 | |||
| 521 | // Must have a default OA1 when using OA2-only mode | ||
| 522 | // Set OA1 to a reserved address that won't conflict | ||
| 523 | self.info.regs.oar1().write(|reg| { | ||
| 524 | reg.set_add(0); // Address 0x00 is reserved, safe to use | ||
| 525 | reg.set_addmode(i2c::vals::Addmode::BIT7); | ||
| 526 | }); | ||
| 527 | |||
| 528 | self.configure_oa2_simple(oa2.addr); | ||
| 529 | }, | ||
| 530 | OwnAddresses::Both { oa1, oa2 } => { | ||
| 531 | self.configure_oa1(oa1); | ||
| 532 | |||
| 533 | // Same masking limitation applies | ||
| 534 | if !matches!(oa2.mask, AddrMask::NOMASK) { | ||
| 535 | #[cfg(feature = "defmt")] | ||
| 536 | defmt::warn!("I2C v1 does not support OA2 address masking, ignoring mask setting"); | ||
| 537 | } | ||
| 538 | |||
| 539 | self.configure_oa2_simple(oa2.addr); | ||
| 540 | } | ||
| 541 | } | ||
| 542 | |||
| 543 | // Configure general call if requested | ||
| 544 | if config.general_call { | ||
| 545 | self.info.regs.cr1().modify(|w| w.set_engc(true)); | ||
| 546 | } | ||
| 547 | } | ||
| 548 | } | ||
| 549 | |||
| 550 | impl<'d, M: Mode> I2c<'d, M, MultiMaster> { | ||
| 551 | /// Listen for incoming I2C address match and return the command type | ||
| 552 | pub fn blocking_listen(&mut self) -> Result<SlaveCommand, Error> { | ||
| 553 | trace!("i2c v1 slave: blocking_listen start"); | ||
| 554 | let timeout = self.timeout(); // Get timeout internally | ||
| 555 | let result = self.blocking_listen_timeout(timeout); | ||
| 556 | trace!("i2c v1 slave: blocking_listen result={:?}", result); | ||
| 557 | result | ||
| 558 | } | ||
| 559 | |||
| 560 | /// Respond to master read request (master wants to read from us) | ||
| 561 | pub fn blocking_respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> { | ||
| 562 | trace!("i2c v1 slave: blocking_respond_to_read start, data_len={}", data.len()); | ||
| 563 | let timeout = self.timeout(); // Get timeout internally | ||
| 564 | let result = self.blocking_respond_to_read_timeout(data, timeout); | ||
| 565 | trace!("i2c v1 slave: blocking_respond_to_read result={:?}", result); | ||
| 566 | result | ||
| 567 | } | ||
| 568 | |||
| 569 | /// Respond to master write request (master wants to write to us) | ||
| 570 | pub fn blocking_respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { | ||
| 571 | trace!("i2c v1 slave: blocking_respond_to_write start, buffer_len={}", buffer.len()); | ||
| 572 | let timeout = self.timeout(); // Get timeout internally | ||
| 573 | let result = self.blocking_respond_to_write_timeout(buffer, timeout); | ||
| 574 | trace!("i2c v1 slave: blocking_respond_to_write result={:?}", result); | ||
| 575 | result | ||
| 576 | } | ||
| 577 | |||
| 578 | // Private implementation methods with Timeout parameter | ||
| 579 | fn blocking_listen_timeout(&mut self, timeout: Timeout) -> Result<SlaveCommand, Error> { | ||
| 580 | trace!("i2c v1 slave: listen_timeout start"); | ||
| 581 | |||
| 582 | // Disable interrupts for blocking operation | ||
| 583 | self.info.regs.cr2().modify(|w| { | ||
| 584 | w.set_itevten(false); | ||
| 585 | w.set_iterren(false); | ||
| 586 | }); | ||
| 587 | |||
| 588 | // Wait for address match (ADDR flag) | ||
| 589 | loop { | ||
| 590 | let sr1 = Self::check_slave_error_flags_and_get_sr1(self.info)?; | ||
| 591 | |||
| 592 | if sr1.addr() { | ||
| 593 | // Address matched! Read SR2 to get direction and clear ADDR | ||
| 594 | let sr2 = self.info.regs.sr2().read(); | ||
| 595 | let direction = if sr2.tra() { | ||
| 596 | trace!("i2c v1 slave: address match - READ direction"); | ||
| 597 | SlaveCommandKind::Read | ||
| 598 | } else { | ||
| 599 | trace!("i2c v1 slave: address match - WRITE direction"); | ||
| 600 | SlaveCommandKind::Write | ||
| 601 | }; | ||
| 602 | |||
| 603 | // Determine which address was matched | ||
| 604 | let matched_address = self.determine_matched_address(sr2)?; | ||
| 605 | trace!("i2c v1 slave: matched address={:?}", matched_address); | ||
| 606 | |||
| 607 | // ADDR is automatically cleared by reading SR1 then SR2 | ||
| 608 | return Ok(SlaveCommand { | ||
| 609 | kind: direction, | ||
| 610 | address: matched_address, | ||
| 611 | }); | ||
| 612 | } | ||
| 613 | |||
| 614 | timeout.check()?; | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | fn blocking_respond_to_read_timeout(&mut self, data: &[u8], timeout: Timeout) -> Result<usize, Error> { | ||
| 619 | trace!("i2c v1 slave: respond_to_read_timeout start, data_len={}", data.len()); | ||
| 620 | let mut bytes_sent = 0; | ||
| 621 | let mut data_exhausted = false; | ||
| 622 | |||
| 623 | loop { | ||
| 624 | // Determine what byte to send | ||
| 625 | let byte_to_send = if bytes_sent < data.len() { | ||
| 626 | // Send real data | ||
| 627 | data[bytes_sent] | ||
| 628 | } else { | ||
| 629 | // Data exhausted - send padding bytes | ||
| 630 | if !data_exhausted { | ||
| 631 | trace!("i2c v1 slave: real data exhausted, sending padding bytes"); | ||
| 632 | data_exhausted = true; | ||
| 633 | } | ||
| 634 | 0x00 // Send zeros as padding (or 0xFF, or last byte repeated) | ||
| 635 | }; | ||
| 636 | |||
| 637 | trace!("i2c v1 slave: sending byte={:#x} ({})", byte_to_send, bytes_sent); | ||
| 638 | match self.send_byte_or_nack(byte_to_send, timeout)? { | ||
| 639 | SlaveSendResult::Acked => { | ||
| 640 | bytes_sent += 1; | ||
| 641 | trace!("i2c v1 slave: byte acked, total_sent={}", bytes_sent); | ||
| 642 | // Continue sending more bytes | ||
| 643 | }, | ||
| 644 | SlaveSendResult::Nacked => { | ||
| 645 | bytes_sent += 1; // Count the NACKed byte as sent | ||
| 646 | trace!("i2c v1 slave: byte nacked by master (normal completion), total_sent={}", bytes_sent); | ||
| 647 | break; // Normal end of transmission | ||
| 648 | }, | ||
| 649 | SlaveSendResult::Stopped => { | ||
| 650 | trace!("i2c v1 slave: stop condition detected, stopping transmission"); | ||
| 651 | break; // Master sent STOP | ||
| 652 | } | ||
| 653 | SlaveSendResult::Restart => { | ||
| 654 | trace!("i2c v1 slave: restart detected, stopping transmission"); | ||
| 655 | break; // Master sent RESTART | ||
| 656 | } | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | trace!("i2c v1 slave: respond_to_read_timeout complete, bytes_sent={}", bytes_sent); | ||
| 661 | Ok(bytes_sent) // Return total bytes sent (including padding) | ||
| 662 | } | ||
| 663 | |||
| 664 | fn blocking_respond_to_write_timeout(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> { | ||
| 665 | trace!("i2c v1 slave: respond_to_write_timeout start, buffer_len={}", buffer.len()); | ||
| 666 | let mut bytes_received = 0; | ||
| 667 | let buffer_capacity = buffer.len(); | ||
| 668 | let mut overflow_detected = false; | ||
| 669 | |||
| 670 | while bytes_received < buffer_capacity { | ||
| 671 | match self.recv_byte_or_stop(timeout)? { | ||
| 672 | SlaveReceiveResult::Byte(b) => { | ||
| 673 | trace!("i2c v1 slave: received byte={:#x} ({})", b, bytes_received); | ||
| 674 | buffer[bytes_received] = b; | ||
| 675 | bytes_received += 1; | ||
| 676 | }, | ||
| 677 | SlaveReceiveResult::Stop => { | ||
| 678 | trace!("i2c v1 slave: stop condition detected, stopping reception"); | ||
| 679 | break; | ||
| 680 | }, | ||
| 681 | SlaveReceiveResult::Restart => { | ||
| 682 | trace!("i2c v1 slave: restart detected, stopping reception"); | ||
| 683 | break; | ||
| 684 | }, | ||
| 685 | } | ||
| 686 | } | ||
| 687 | |||
| 688 | // Handle buffer overflow - continue receiving but discard bytes | ||
| 689 | if bytes_received >= buffer_capacity { | ||
| 690 | loop { | ||
| 691 | match self.recv_byte_or_stop(timeout)? { | ||
| 692 | SlaveReceiveResult::Byte(b) => { | ||
| 693 | if !overflow_detected { | ||
| 694 | trace!("i2c v1 slave: buffer full, discarding excess bytes"); | ||
| 695 | overflow_detected = true; | ||
| 696 | } | ||
| 697 | trace!("i2c v1 slave: discarding overflow byte={:#x}", b); | ||
| 698 | // Byte is discarded but we still ACK it | ||
| 699 | }, | ||
| 700 | SlaveReceiveResult::Stop => { | ||
| 701 | trace!("i2c v1 slave: stop condition detected after overflow"); | ||
| 702 | break; | ||
| 703 | }, | ||
| 704 | SlaveReceiveResult::Restart => { | ||
| 705 | trace!("i2c v1 slave: restart detected after overflow"); | ||
| 706 | break; | ||
| 707 | }, | ||
| 708 | } | ||
| 709 | } | ||
| 710 | } | ||
| 711 | |||
| 712 | if overflow_detected { | ||
| 713 | trace!("i2c v1 slave: transaction complete with overflow - received {} bytes, buffer held {}", | ||
| 714 | bytes_received, buffer_capacity); | ||
| 715 | } else { | ||
| 716 | trace!("i2c v1 slave: respond_to_write_timeout complete, bytes_received={}", bytes_received); | ||
| 717 | } | ||
| 718 | |||
| 719 | Ok(bytes_received.min(buffer_capacity)) // Return stored bytes, not total received | ||
| 720 | } | ||
| 721 | |||
| 722 | fn determine_matched_address(&self, sr2: stm32_metapac::i2c::regs::Sr2) -> Result<Address, Error> { | ||
| 723 | trace!("i2c v1 slave: determine_matched_address, sr2={:#x}", sr2.0); | ||
| 724 | // Check for general call first | ||
| 725 | if sr2.gencall() { | ||
| 726 | trace!("i2c v1 slave: general call address matched"); | ||
| 727 | Ok(Address::SevenBit(0x00)) | ||
| 728 | } else if sr2.dualf() { | ||
| 729 | // OA2 was matched - verify it's actually enabled | ||
| 730 | let oar2 = self.info.regs.oar2().read(); | ||
| 731 | if oar2.endual() != i2c::vals::Endual::DUAL { | ||
| 732 | error!("i2c v1 slave: OA2 matched but not enabled - hardware inconsistency"); | ||
| 733 | return Err(Error::Bus); // Hardware inconsistency | ||
| 734 | } | ||
| 735 | trace!("i2c v1 slave: OA2 address matched: {:#x}", oar2.add2()); | ||
| 736 | Ok(Address::SevenBit(oar2.add2())) | ||
| 737 | } else { | ||
| 738 | // OA1 was matched | ||
| 739 | let oar1 = self.info.regs.oar1().read(); | ||
| 740 | match oar1.addmode() { | ||
| 741 | i2c::vals::Addmode::BIT7 => { | ||
| 742 | let addr = (oar1.add() >> 1) as u8; | ||
| 743 | trace!("i2c v1 slave: OA1 7-bit address matched: {:#x}", addr); | ||
| 744 | Ok(Address::SevenBit(addr)) | ||
| 745 | }, | ||
| 746 | i2c::vals::Addmode::BIT10 => { | ||
| 747 | trace!("i2c v1 slave: OA1 10-bit address matched: {:#x}", oar1.add()); | ||
| 748 | Ok(Address::TenBit(oar1.add())) | ||
| 749 | }, | ||
| 750 | } | ||
| 751 | } | ||
| 752 | } | ||
| 753 | |||
| 754 | /// Send a byte in slave transmitter mode and check for ACK/NACK/STOP | ||
| 755 | fn send_byte_or_nack(&mut self, byte: u8, timeout: Timeout) -> Result<SlaveSendResult, Error> { | ||
| 756 | trace!("i2c v1 slave: send_byte_or_nack start, byte={:#x}", byte); | ||
| 757 | |||
| 758 | // Wait until we're ready for sending (TXE flag set) | ||
| 759 | loop { | ||
| 760 | let sr1 = Self::check_slave_error_flags_and_get_sr1(self.info)?; | ||
| 761 | |||
| 762 | // Check for STOP condition first | ||
| 763 | if sr1.stopf() { | ||
| 764 | trace!("i2c v1 slave: STOP detected before send"); | ||
| 765 | self.info.regs.cr1().modify(|_w| {}); | ||
| 766 | return Ok(SlaveSendResult::Stopped); | ||
| 767 | } | ||
| 768 | |||
| 769 | // Check for RESTART (new ADDR) | ||
| 770 | if sr1.addr() { | ||
| 771 | trace!("i2c v1 slave: RESTART detected before send"); | ||
| 772 | return Ok(SlaveSendResult::Restart); | ||
| 773 | } | ||
| 774 | |||
| 775 | // Check for NACK (AF flag) before writing | ||
| 776 | let sr1_current = self.info.regs.sr1().read(); | ||
| 777 | if sr1_current.af() { | ||
| 778 | trace!("i2c v1 slave: NACK detected before send"); | ||
| 779 | self.info.regs.sr1().write(|reg| { | ||
| 780 | reg.0 = !0; | ||
| 781 | reg.set_af(false); | ||
| 782 | }); | ||
| 783 | return Ok(SlaveSendResult::Nacked); | ||
| 784 | } | ||
| 785 | |||
| 786 | // Check if we can send data | ||
| 787 | if sr1.txe() { | ||
| 788 | trace!("i2c v1 slave: TXE ready, sending byte"); | ||
| 789 | break; // Ready to send | ||
| 790 | } | ||
| 791 | |||
| 792 | timeout.check()?; | ||
| 793 | } | ||
| 794 | |||
| 795 | // Send the byte | ||
| 796 | self.info.regs.dr().write(|w| w.set_dr(byte)); | ||
| 797 | trace!("i2c v1 slave: byte written to DR, waiting for completion"); | ||
| 798 | |||
| 799 | // Wait for completion - but be more flexible about what constitutes "completion" | ||
| 800 | // In slave transmitter mode, we need to detect: | ||
| 801 | // 1. BTF - byte transfer finished (normal case) | ||
| 802 | // 2. AF (NACK) - master signals end of transaction | ||
| 803 | // 3. STOP - master terminates transaction | ||
| 804 | // 4. ADDR - master starts new transaction (restart) | ||
| 805 | loop { | ||
| 806 | // Get current flags without error handling that clears AF | ||
| 807 | let sr1 = self.info.regs.sr1().read(); | ||
| 808 | |||
| 809 | // Check for NACK FIRST - this is the most likely end condition | ||
| 810 | if sr1.af() { | ||
| 811 | trace!("i2c v1 slave: NACK detected after send"); | ||
| 812 | // Clear the AF flag | ||
| 813 | self.info.regs.sr1().write(|reg| { | ||
| 814 | reg.0 = !0; | ||
| 815 | reg.set_af(false); | ||
| 816 | }); | ||
| 817 | return Ok(SlaveSendResult::Nacked); | ||
| 818 | } | ||
| 819 | |||
| 820 | // Check for STOP condition | ||
| 821 | if sr1.stopf() { | ||
| 822 | trace!("i2c v1 slave: STOP detected after send"); | ||
| 823 | self.info.regs.cr1().modify(|_w| {}); | ||
| 824 | return Ok(SlaveSendResult::Stopped); | ||
| 825 | } | ||
| 826 | |||
| 827 | // Check for RESTART (new ADDR) | ||
| 828 | if sr1.addr() { | ||
| 829 | trace!("i2c v1 slave: RESTART detected after send"); | ||
| 830 | return Ok(SlaveSendResult::Restart); | ||
| 831 | } | ||
| 832 | |||
| 833 | // Check for byte transfer finished (normal ACK case) | ||
| 834 | if sr1.btf() { | ||
| 835 | trace!("i2c v1 slave: BTF set, byte transfer complete (ACK)"); | ||
| 836 | return Ok(SlaveSendResult::Acked); | ||
| 837 | } | ||
| 838 | |||
| 839 | // Check for other error conditions that should be propagated | ||
| 840 | if sr1.timeout() || sr1.ovr() || sr1.arlo() || sr1.berr() { | ||
| 841 | // Use the error handling function for these | ||
| 842 | match Self::check_and_clear_error_flags(self.info) { | ||
| 843 | Ok(_) => {}, // Shouldn't happen given the flags we checked | ||
| 844 | Err(e) => return Err(e), | ||
| 845 | } | ||
| 846 | } | ||
| 847 | |||
| 848 | timeout.check()?; | ||
| 849 | } | ||
| 850 | } | ||
| 851 | |||
| 852 | /// Receive a byte in slave receiver mode or detect STOP condition | ||
| 853 | fn recv_byte_or_stop(&mut self, timeout: Timeout) -> Result<SlaveReceiveResult, Error> { | ||
| 854 | trace!("i2c v1 slave: recv_byte_or_stop start"); | ||
| 855 | loop { | ||
| 856 | let sr1 = Self::check_slave_error_flags_and_get_sr1(self.info)?; | ||
| 857 | |||
| 858 | // Check for received data FIRST (handles race condition) | ||
| 859 | if sr1.rxne() { | ||
| 860 | let byte = self.info.regs.dr().read().dr(); | ||
| 861 | trace!("i2c v1 slave: received byte={:#x}", byte); | ||
| 862 | return Ok(SlaveReceiveResult::Byte(byte)); | ||
| 863 | } | ||
| 864 | |||
| 865 | // Check for RESTART (new ADDR) before STOP | ||
| 866 | if sr1.addr() { | ||
| 867 | trace!("i2c v1 slave: RESTART detected during receive"); | ||
| 868 | return Ok(SlaveReceiveResult::Restart); | ||
| 869 | } | ||
| 870 | |||
| 871 | // Check for STOP condition LAST | ||
| 872 | if sr1.stopf() { | ||
| 873 | trace!("i2c v1 slave: STOP detected during receive"); | ||
| 874 | self.info.regs.cr1().modify(|_w| {}); | ||
| 875 | return Ok(SlaveReceiveResult::Stop); | ||
| 876 | } | ||
| 877 | |||
| 878 | timeout.check()?; | ||
| 879 | } | ||
| 880 | } | ||
| 881 | |||
| 882 | /// Wrapper that treats AF (NACK) as normal protocol behavior in slave mode | ||
| 883 | fn check_slave_error_flags_and_get_sr1(info: &'static Info) -> Result<i2c::regs::Sr1, Error> { | ||
| 884 | match Self::check_and_clear_error_flags(info) { | ||
| 885 | Ok(sr1) => Ok(sr1), | ||
| 886 | Err(Error::Nack) => { | ||
| 887 | // AF flag was set and cleared by check_and_clear_error_flags | ||
| 888 | // In slave mode, this is normal protocol behavior, not an error | ||
| 889 | // Read SR1 again to get current state (AF should now be cleared) | ||
| 890 | Ok(info.regs.sr1().read()) | ||
| 891 | }, | ||
| 892 | Err(other_error) => Err(other_error), // Propagate real errors | ||
| 893 | } | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | 375 | impl<'d, IM: MasterMode> I2c<'d, Async, IM> { |
| 898 | async fn write_with_framing(&mut self, address: u8, write_buffer: &[u8], framing: OperationFraming) -> Result<(), Error> { | 376 | async fn write_with_framing(&mut self, address: u8, write_buffer: &[u8], framing: OperationFraming) -> Result<(), Error> { |
| 899 | self.info.regs.cr2().modify(|w| { | 377 | self.info.regs.cr2().modify(|w| { |
| @@ -1240,6 +718,476 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1240 | } | 718 | } |
| 1241 | } | 719 | } |
| 1242 | 720 | ||
| 721 | /// Result of attempting to send a byte in slave transmitter mode | ||
| 722 | #[derive(Debug, PartialEq)] | ||
| 723 | enum TransmitResult { | ||
| 724 | /// Byte sent and ACKed by master - continue transmission | ||
| 725 | Acknowledged, | ||
| 726 | /// Byte sent but NACKed by master - normal end of read transaction | ||
| 727 | NotAcknowledged, | ||
| 728 | /// STOP condition detected - master terminated transaction | ||
| 729 | Stopped, | ||
| 730 | /// RESTART condition detected - master starting new transaction | ||
| 731 | Restarted, | ||
| 732 | } | ||
| 733 | |||
| 734 | /// Result of attempting to receive a byte in slave receiver mode | ||
| 735 | #[derive(Debug, PartialEq)] | ||
| 736 | enum ReceiveResult { | ||
| 737 | /// Data byte successfully received | ||
| 738 | Data(u8), | ||
| 739 | /// STOP condition detected - end of write transaction | ||
| 740 | Stopped, | ||
| 741 | /// RESTART condition detected - master starting new transaction | ||
| 742 | Restarted, | ||
| 743 | } | ||
| 744 | |||
| 745 | impl<'d, M: Mode> I2c<'d, M, Master> { | ||
| 746 | /// Configure the I2C driver for slave operations, allowing for the driver to be used as a slave and a master (multimaster) | ||
| 747 | pub fn into_slave_multimaster(mut self, slave_addr_config: SlaveAddrConfig) -> I2c<'d, M, MultiMaster> { | ||
| 748 | let mut slave = I2c { | ||
| 749 | info: self.info, | ||
| 750 | state: self.state, | ||
| 751 | kernel_clock: self.kernel_clock, | ||
| 752 | tx_dma: self.tx_dma.take(), // Use take() to move ownership | ||
| 753 | rx_dma: self.rx_dma.take(), // Use take() to move ownership | ||
| 754 | #[cfg(feature = "time")] | ||
| 755 | timeout: self.timeout, | ||
| 756 | _phantom: PhantomData, | ||
| 757 | _phantom2: PhantomData, | ||
| 758 | _drop_guard: self._drop_guard, // Move the drop guard | ||
| 759 | }; | ||
| 760 | slave.init_slave(slave_addr_config); | ||
| 761 | slave | ||
| 762 | } | ||
| 763 | } | ||
| 764 | |||
| 765 | impl<'d, M: Mode> I2c<'d, M, MultiMaster> { | ||
| 766 | /// Listen for incoming I2C address match and return the command type | ||
| 767 | /// | ||
| 768 | /// This method blocks until the slave address is matched by a master. | ||
| 769 | /// Returns the command type (Read/Write) and the matched address. | ||
| 770 | pub fn blocking_listen(&mut self) -> Result<SlaveCommand, Error> { | ||
| 771 | trace!("I2C slave: listening for address match"); | ||
| 772 | let result = self.blocking_listen_with_timeout(self.timeout()); | ||
| 773 | trace!("I2C slave: listen result={:?}", result); | ||
| 774 | result | ||
| 775 | } | ||
| 776 | |||
| 777 | /// Respond to a master read request by transmitting data | ||
| 778 | /// | ||
| 779 | /// Sends the provided data to the master. If the master requests more bytes | ||
| 780 | /// than available, padding bytes (0x00) are sent until the master terminates | ||
| 781 | /// the transaction with NACK. | ||
| 782 | /// | ||
| 783 | /// Returns the total number of bytes transmitted (including padding). | ||
| 784 | pub fn blocking_respond_to_read(&mut self, data: &[u8]) -> Result<usize, Error> { | ||
| 785 | trace!("I2C slave: responding to read, data_len={}", data.len()); | ||
| 786 | let result = self.transmit_to_master(data, self.timeout()); | ||
| 787 | trace!("I2C slave: read response complete, result={:?}", result); | ||
| 788 | result | ||
| 789 | } | ||
| 790 | |||
| 791 | /// Respond to a master write request by receiving data | ||
| 792 | /// | ||
| 793 | /// Receives data from the master into the provided buffer. If the master | ||
| 794 | /// sends more bytes than the buffer can hold, excess bytes are acknowledged | ||
| 795 | /// but discarded. | ||
| 796 | /// | ||
| 797 | /// Returns the number of bytes stored in the buffer (not total received). | ||
| 798 | pub fn blocking_respond_to_write(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { | ||
| 799 | trace!("I2C slave: responding to write, buffer_len={}", buffer.len()); | ||
| 800 | let result = self.receive_from_master(buffer, self.timeout()); | ||
| 801 | trace!("I2C slave: write response complete, result={:?}", result); | ||
| 802 | result | ||
| 803 | } | ||
| 804 | |||
| 805 | // Private implementation methods | ||
| 806 | |||
| 807 | /// Wait for address match and determine transaction type | ||
| 808 | fn blocking_listen_with_timeout(&mut self, timeout: Timeout) -> Result<SlaveCommand, Error> { | ||
| 809 | // Ensure interrupts are disabled for blocking operation | ||
| 810 | self.disable_i2c_interrupts(); | ||
| 811 | |||
| 812 | // Wait for address match (ADDR flag) | ||
| 813 | loop { | ||
| 814 | let sr1 = Self::read_status_and_handle_errors(self.info)?; | ||
| 815 | |||
| 816 | if sr1.addr() { | ||
| 817 | // Address matched - read SR2 to get direction and clear ADDR flag | ||
| 818 | let sr2 = self.info.regs.sr2().read(); | ||
| 819 | let direction = if sr2.tra() { | ||
| 820 | SlaveCommandKind::Read | ||
| 821 | } else { | ||
| 822 | SlaveCommandKind::Write | ||
| 823 | }; | ||
| 824 | |||
| 825 | let matched_address = self.decode_matched_address(sr2)?; | ||
| 826 | trace!("I2C slave: address matched, direction={:?}, addr={:?}", direction, matched_address); | ||
| 827 | |||
| 828 | return Ok(SlaveCommand { | ||
| 829 | kind: direction, | ||
| 830 | address: matched_address, | ||
| 831 | }); | ||
| 832 | } | ||
| 833 | |||
| 834 | timeout.check()?; | ||
| 835 | } | ||
| 836 | } | ||
| 837 | |||
| 838 | /// Transmit data to master in response to read request | ||
| 839 | fn transmit_to_master(&mut self, data: &[u8], timeout: Timeout) -> Result<usize, Error> { | ||
| 840 | let mut bytes_transmitted = 0; | ||
| 841 | |||
| 842 | loop { | ||
| 843 | // Determine next byte to send | ||
| 844 | let byte_to_send = if bytes_transmitted < data.len() { | ||
| 845 | data[bytes_transmitted] | ||
| 846 | } else { | ||
| 847 | 0x00 // Send padding bytes when data is exhausted | ||
| 848 | }; | ||
| 849 | |||
| 850 | // Attempt to send the byte | ||
| 851 | match self.transmit_byte(byte_to_send, timeout)? { | ||
| 852 | TransmitResult::Acknowledged => { | ||
| 853 | bytes_transmitted += 1; | ||
| 854 | // Continue transmission | ||
| 855 | }, | ||
| 856 | TransmitResult::NotAcknowledged => { | ||
| 857 | bytes_transmitted += 1; // Count the NACKed byte | ||
| 858 | break; // Normal end of read transaction | ||
| 859 | }, | ||
| 860 | TransmitResult::Stopped | TransmitResult::Restarted => { | ||
| 861 | break; // Transaction terminated by master | ||
| 862 | } | ||
| 863 | } | ||
| 864 | } | ||
| 865 | |||
| 866 | Ok(bytes_transmitted) | ||
| 867 | } | ||
| 868 | |||
| 869 | /// Receive data from master during write request | ||
| 870 | fn receive_from_master(&mut self, buffer: &mut [u8], timeout: Timeout) -> Result<usize, Error> { | ||
| 871 | let mut bytes_stored = 0; | ||
| 872 | |||
| 873 | // Receive bytes that fit in buffer | ||
| 874 | while bytes_stored < buffer.len() { | ||
| 875 | match self.receive_byte(timeout)? { | ||
| 876 | ReceiveResult::Data(byte) => { | ||
| 877 | buffer[bytes_stored] = byte; | ||
| 878 | bytes_stored += 1; | ||
| 879 | }, | ||
| 880 | ReceiveResult::Stopped | ReceiveResult::Restarted => { | ||
| 881 | return Ok(bytes_stored); | ||
| 882 | }, | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | // Handle buffer overflow by discarding excess bytes | ||
| 887 | if bytes_stored == buffer.len() { | ||
| 888 | trace!("I2C slave: buffer full, discarding excess bytes"); | ||
| 889 | self.discard_excess_bytes(timeout)?; | ||
| 890 | } | ||
| 891 | |||
| 892 | Ok(bytes_stored) | ||
| 893 | } | ||
| 894 | |||
| 895 | /// Discard excess bytes when buffer is full | ||
| 896 | fn discard_excess_bytes(&mut self, timeout: Timeout) -> Result<(), Error> { | ||
| 897 | loop { | ||
| 898 | match self.receive_byte(timeout)? { | ||
| 899 | ReceiveResult::Data(_) => { | ||
| 900 | // Byte received and ACKed, but discarded | ||
| 901 | continue; | ||
| 902 | }, | ||
| 903 | ReceiveResult::Stopped | ReceiveResult::Restarted => { | ||
| 904 | break; // Transaction completed | ||
| 905 | }, | ||
| 906 | } | ||
| 907 | } | ||
| 908 | Ok(()) | ||
| 909 | } | ||
| 910 | |||
| 911 | /// Send a single byte and wait for master's response | ||
| 912 | fn transmit_byte(&mut self, byte: u8, timeout: Timeout) -> Result<TransmitResult, Error> { | ||
| 913 | // Wait for transmit buffer ready | ||
| 914 | self.wait_for_transmit_ready(timeout)?; | ||
| 915 | |||
| 916 | // Send the byte | ||
| 917 | self.info.regs.dr().write(|w| w.set_dr(byte)); | ||
| 918 | |||
| 919 | // Wait for transmission completion or master response | ||
| 920 | self.wait_for_transmit_completion(timeout) | ||
| 921 | } | ||
| 922 | |||
| 923 | /// Wait until transmit buffer is ready (TXE flag set) | ||
| 924 | fn wait_for_transmit_ready(&mut self, timeout: Timeout) -> Result<(), Error> { | ||
| 925 | loop { | ||
| 926 | let sr1 = Self::read_status_and_handle_errors(self.info)?; | ||
| 927 | |||
| 928 | // Check for early termination conditions | ||
| 929 | if let Some(result) = Self::check_early_termination(sr1) { | ||
| 930 | return Err(self.handle_early_termination(result)); | ||
| 931 | } | ||
| 932 | |||
| 933 | if sr1.txe() { | ||
| 934 | return Ok(()); // Ready to transmit | ||
| 935 | } | ||
| 936 | |||
| 937 | timeout.check()?; | ||
| 938 | } | ||
| 939 | } | ||
| 940 | |||
| 941 | /// Wait for byte transmission completion or master response | ||
| 942 | fn wait_for_transmit_completion(&mut self, timeout: Timeout) -> Result<TransmitResult, Error> { | ||
| 943 | loop { | ||
| 944 | let sr1 = self.info.regs.sr1().read(); | ||
| 945 | |||
| 946 | // Check flags in priority order | ||
| 947 | if sr1.af() { | ||
| 948 | self.clear_acknowledge_failure(); | ||
| 949 | return Ok(TransmitResult::NotAcknowledged); | ||
| 950 | } | ||
| 951 | |||
| 952 | if sr1.btf() { | ||
| 953 | return Ok(TransmitResult::Acknowledged); | ||
| 954 | } | ||
| 955 | |||
| 956 | if sr1.stopf() { | ||
| 957 | self.clear_stop_flag(); | ||
| 958 | return Ok(TransmitResult::Stopped); | ||
| 959 | } | ||
| 960 | |||
| 961 | if sr1.addr() { | ||
| 962 | return Ok(TransmitResult::Restarted); | ||
| 963 | } | ||
| 964 | |||
| 965 | // Check for other error conditions | ||
| 966 | self.check_for_hardware_errors(sr1)?; | ||
| 967 | |||
| 968 | timeout.check()?; | ||
| 969 | } | ||
| 970 | } | ||
| 971 | |||
| 972 | /// Receive a single byte or detect transaction termination | ||
| 973 | fn receive_byte(&mut self, timeout: Timeout) -> Result<ReceiveResult, Error> { | ||
| 974 | loop { | ||
| 975 | let sr1 = Self::read_status_and_handle_errors(self.info)?; | ||
| 976 | |||
| 977 | // Check for received data first (prioritize data over control signals) | ||
| 978 | if sr1.rxne() { | ||
| 979 | let byte = self.info.regs.dr().read().dr(); | ||
| 980 | return Ok(ReceiveResult::Data(byte)); | ||
| 981 | } | ||
| 982 | |||
| 983 | // Check for transaction termination | ||
| 984 | if sr1.addr() { | ||
| 985 | return Ok(ReceiveResult::Restarted); | ||
| 986 | } | ||
| 987 | |||
| 988 | if sr1.stopf() { | ||
| 989 | self.clear_stop_flag(); | ||
| 990 | return Ok(ReceiveResult::Stopped); | ||
| 991 | } | ||
| 992 | |||
| 993 | timeout.check()?; | ||
| 994 | } | ||
| 995 | } | ||
| 996 | |||
| 997 | /// Determine which slave address was matched based on SR2 flags | ||
| 998 | fn decode_matched_address(&self, sr2: i2c::regs::Sr2) -> Result<Address, Error> { | ||
| 999 | if sr2.gencall() { | ||
| 1000 | Ok(Address::SevenBit(0x00)) // General call address | ||
| 1001 | } else if sr2.dualf() { | ||
| 1002 | // OA2 (secondary address) was matched | ||
| 1003 | let oar2 = self.info.regs.oar2().read(); | ||
| 1004 | if oar2.endual() != i2c::vals::Endual::DUAL { | ||
| 1005 | return Err(Error::Bus); // Hardware inconsistency | ||
| 1006 | } | ||
| 1007 | Ok(Address::SevenBit(oar2.add2())) | ||
| 1008 | } else { | ||
| 1009 | // OA1 (primary address) was matched | ||
| 1010 | let oar1 = self.info.regs.oar1().read(); | ||
| 1011 | match oar1.addmode() { | ||
| 1012 | i2c::vals::Addmode::BIT7 => { | ||
| 1013 | let addr = (oar1.add() >> 1) as u8; | ||
| 1014 | Ok(Address::SevenBit(addr)) | ||
| 1015 | }, | ||
| 1016 | i2c::vals::Addmode::BIT10 => { | ||
| 1017 | Ok(Address::TenBit(oar1.add())) | ||
| 1018 | }, | ||
| 1019 | } | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | // Helper methods for hardware interaction | ||
| 1024 | |||
| 1025 | /// Read status register and handle I2C errors (except NACK in slave mode) | ||
| 1026 | fn read_status_and_handle_errors(info: &'static Info) -> Result<i2c::regs::Sr1, Error> { | ||
| 1027 | match Self::check_and_clear_error_flags(info) { | ||
| 1028 | Ok(sr1) => Ok(sr1), | ||
| 1029 | Err(Error::Nack) => { | ||
| 1030 | // In slave mode, NACK is normal protocol behavior, not an error | ||
| 1031 | Ok(info.regs.sr1().read()) | ||
| 1032 | }, | ||
| 1033 | Err(other_error) => Err(other_error), | ||
| 1034 | } | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | /// Check for conditions that cause early termination of operations | ||
| 1038 | fn check_early_termination(sr1: i2c::regs::Sr1) -> Option<TransmitResult> { | ||
| 1039 | if sr1.stopf() { | ||
| 1040 | Some(TransmitResult::Stopped) | ||
| 1041 | } else if sr1.addr() { | ||
| 1042 | Some(TransmitResult::Restarted) | ||
| 1043 | } else if sr1.af() { | ||
| 1044 | Some(TransmitResult::NotAcknowledged) | ||
| 1045 | } else { | ||
| 1046 | None | ||
| 1047 | } | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | /// Convert early termination to appropriate error | ||
| 1051 | fn handle_early_termination(&mut self, result: TransmitResult) -> Error { | ||
| 1052 | match result { | ||
| 1053 | TransmitResult::Stopped => { | ||
| 1054 | self.clear_stop_flag(); | ||
| 1055 | Error::Bus // Unexpected STOP during setup | ||
| 1056 | }, | ||
| 1057 | TransmitResult::Restarted => { | ||
| 1058 | Error::Bus // Unexpected RESTART during setup | ||
| 1059 | }, | ||
| 1060 | TransmitResult::NotAcknowledged => { | ||
| 1061 | self.clear_acknowledge_failure(); | ||
| 1062 | Error::Bus // Unexpected NACK during setup | ||
| 1063 | }, | ||
| 1064 | TransmitResult::Acknowledged => { | ||
| 1065 | unreachable!() // This should never be passed to this function | ||
| 1066 | } | ||
| 1067 | } | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | /// Check for hardware-level I2C errors during transmission | ||
| 1071 | fn check_for_hardware_errors(&self, sr1: i2c::regs::Sr1) -> Result<(), Error> { | ||
| 1072 | if sr1.timeout() || sr1.ovr() || sr1.arlo() || sr1.berr() { | ||
| 1073 | // Delegate to existing error handling | ||
| 1074 | Self::check_and_clear_error_flags(self.info)?; | ||
| 1075 | } | ||
| 1076 | Ok(()) | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | /// Disable I2C event and error interrupts for blocking operations | ||
| 1080 | fn disable_i2c_interrupts(&mut self) { | ||
| 1081 | self.info.regs.cr2().modify(|w| { | ||
| 1082 | w.set_itevten(false); | ||
| 1083 | w.set_iterren(false); | ||
| 1084 | }); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | /// Clear the acknowledge failure flag | ||
| 1088 | fn clear_acknowledge_failure(&mut self) { | ||
| 1089 | self.info.regs.sr1().write(|reg| { | ||
| 1090 | reg.0 = !0; | ||
| 1091 | reg.set_af(false); | ||
| 1092 | }); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | /// Clear the stop condition flag | ||
| 1096 | fn clear_stop_flag(&mut self) { | ||
| 1097 | self.info.regs.cr1().modify(|_w| {}); | ||
| 1098 | } | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | // Address configuration methods | ||
| 1102 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | ||
| 1103 | /// Initialize slave mode with address configuration | ||
| 1104 | pub(crate) fn init_slave(&mut self, config: SlaveAddrConfig) { | ||
| 1105 | trace!("I2C slave: initializing with config={:?}", config); | ||
| 1106 | |||
| 1107 | // Disable peripheral for configuration | ||
| 1108 | self.info.regs.cr1().modify(|reg| reg.set_pe(false)); | ||
| 1109 | |||
| 1110 | // Configure slave addresses | ||
| 1111 | self.apply_address_configuration(config); | ||
| 1112 | |||
| 1113 | // Enable peripheral with slave settings | ||
| 1114 | self.info.regs.cr1().modify(|reg| { | ||
| 1115 | reg.set_pe(true); | ||
| 1116 | reg.set_ack(true); // Enable acknowledgment for slave mode | ||
| 1117 | }); | ||
| 1118 | |||
| 1119 | trace!("I2C slave: initialization complete"); | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | /// Apply the complete address configuration for slave mode | ||
| 1123 | fn apply_address_configuration(&mut self, config: SlaveAddrConfig) { | ||
| 1124 | match config.addr { | ||
| 1125 | OwnAddresses::OA1(addr) => { | ||
| 1126 | self.configure_primary_address(addr); | ||
| 1127 | self.disable_secondary_address(); | ||
| 1128 | }, | ||
| 1129 | OwnAddresses::OA2(oa2) => { | ||
| 1130 | self.configure_default_primary_address(); | ||
| 1131 | self.configure_secondary_address(oa2.addr); // v1 ignores mask | ||
| 1132 | }, | ||
| 1133 | OwnAddresses::Both { oa1, oa2 } => { | ||
| 1134 | self.configure_primary_address(oa1); | ||
| 1135 | self.configure_secondary_address(oa2.addr); // v1 ignores mask | ||
| 1136 | } | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | // Configure general call detection | ||
| 1140 | if config.general_call { | ||
| 1141 | self.info.regs.cr1().modify(|w| w.set_engc(true)); | ||
| 1142 | } | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | /// Configure the primary address (OA1) register | ||
| 1146 | fn configure_primary_address(&mut self, addr: Address) { | ||
| 1147 | match addr { | ||
| 1148 | Address::SevenBit(addr) => { | ||
| 1149 | self.info.regs.oar1().write(|reg| { | ||
| 1150 | let hw_addr = (addr as u16) << 1; // Address in bits [7:1] | ||
| 1151 | reg.set_add(hw_addr); | ||
| 1152 | reg.set_addmode(i2c::vals::Addmode::BIT7); | ||
| 1153 | }); | ||
| 1154 | }, | ||
| 1155 | Address::TenBit(addr) => { | ||
| 1156 | self.info.regs.oar1().write(|reg| { | ||
| 1157 | reg.set_add(addr); | ||
| 1158 | reg.set_addmode(i2c::vals::Addmode::BIT10); | ||
| 1159 | }); | ||
| 1160 | } | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | // Set required bit 14 as per reference manual | ||
| 1164 | self.info.regs.oar1().modify(|reg| reg.0 |= 1 << 14); | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | /// Configure the secondary address (OA2) register | ||
| 1168 | fn configure_secondary_address(&mut self, addr: u8) { | ||
| 1169 | self.info.regs.oar2().write(|reg| { | ||
| 1170 | reg.set_add2(addr); | ||
| 1171 | reg.set_endual(i2c::vals::Endual::DUAL); | ||
| 1172 | }); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | /// Set a default primary address when using OA2-only mode | ||
| 1176 | fn configure_default_primary_address(&mut self) { | ||
| 1177 | self.info.regs.oar1().write(|reg| { | ||
| 1178 | reg.set_add(0); // Reserved address, safe to use | ||
| 1179 | reg.set_addmode(i2c::vals::Addmode::BIT7); | ||
| 1180 | }); | ||
| 1181 | self.info.regs.oar1().modify(|reg| reg.0 |= 1 << 14); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | /// Disable secondary address when not needed | ||
| 1185 | fn disable_secondary_address(&mut self) { | ||
| 1186 | self.info.regs.oar2().write(|reg| { | ||
| 1187 | reg.set_endual(i2c::vals::Endual::SINGLE); | ||
| 1188 | }); | ||
| 1189 | } | ||
| 1190 | } | ||
| 1243 | 1191 | ||
| 1244 | /// Timing configuration for I2C v1 hardware | 1192 | /// Timing configuration for I2C v1 hardware |
| 1245 | /// | 1193 | /// |
