Skip to content

Comments

I2c core#69

Open
rusty1968 wants to merge 18 commits intomainfrom
i2c-core
Open

I2c core#69
rusty1968 wants to merge 18 commits intomainfrom
i2c-core

Conversation

@rusty1968
Copy link
Contributor

No description provided.

rusty1968 and others added 18 commits December 26, 2025 00:37
Add i2c_core module - a bare-metal AST1060 I2C driver implementation:
- Master mode: write, read, write-read operations
- Slave mode: configure, read, write, interrupt handling
- Buffer mode: 32-byte hardware FIFO for efficient transfers
- Byte mode: Single byte polling mode for simple transfers
- Multi-master: Arbitration support for shared bus
- Bus recovery: Automatic stuck bus detection and recovery
- Timing configuration: Standard (100kHz), Fast (400kHz), Fast-plus (1MHz)
- SMBus support: Timeout detection and alert signaling

The driver provides hardware-specific methods optimized for the AST1060's
capabilities, including packet mode and structured interrupt events for
slave operation.
- Add ClockConfig struct with injected clock frequencies
- Remove direct SCU/I2C global register access from timing.rs
- Add ClockConfig::ast1060_default() for typical configuration
- Add ClockConfig::from_hardware() for system init use
- Add I2cConfig::with_hardware_clocks() convenience constructor
- Add unit tests for timing calculations

This decouples the I2C driver from SCU, enabling:
- Unit testing without hardware
- Clear ownership boundaries
- Portability across configurations
- Add i2c_core_test.rs with functional tests for timing, master, slave config
- Add target_adapter.rs for decoupled I2CTarget trait integration
- Export i2c_core module from lib.rs
- Fix all clippy warnings:
  - Add #[must_use] attributes to pure functions
  - Fix doc backticks for MHz, GHz, SMBus, type names
  - Replace unsafe From<u8> for Controller with TryFrom
  - Fix cast warnings with u32::from() and allow attributes
  - Change match to let...else patterns
  - Fix uninlined_format_args warnings
  - Add struct-level allow for excessive_bools
- Add logging adapter helpers in test code (decoupled from i2c_core)
- Document design tradeoff: embedded-hal compatibility vs compile-time validation
- Add comprehensive i2c-core-hubris-integration-design.md documenting:
  - Three-layer architecture (i2c_core → Hubris wrapper → server)
  - Interrupt vs polling architecture (master polls, slave uses IRQs)
  - Pre-kernel hardware initialization in app main.rs
  - from_initialized() performance optimization pattern
  - Future optimizations (slave pre-init, interrupt master, DMA)
  - Phase 2 completion status

- Add Ast1060I2c::from_initialized() constructor:
  - Lightweight wrapper with no hardware register writes
  - ~50x faster than new() for per-operation usage
  - Used when hardware is pre-initialized by app main.rs

- Update I2cConfig::default() to read clocks from hardware:
  - Assumes app pre-configured I2CG10 timing register
  - Add with_static_clocks() for testing with hardcoded defaults

Phase 2 of I2C migration now complete.
- Add from_initialized() for lightweight I2C instance creation without
  hardware re-initialization (~50x faster than new())
- Add design note documenting AtomicBool guard tradeoffs in init_i2c_global
- Use i2cm18 (command register) instead of i2cm14 (status register)
- Add SDA/SCL state check before attempting recovery (matches legacy)
- Remove unnecessary unsafe block by using typed accessor
- Add global.rs with init_i2c_global() for one-time hardware initialization
- Export init_i2c_global, SlaveBuffer, SlaveConfig, SlaveEvent from i2c_core
- Remove AtomicBool guard from controller.rs (caller responsibility)
- Clean up slave.rs exports (remove dead_code allows)
Adds a public enable_slave() method to complement disable_slave().
This allows re-enabling slave mode and interrupts after a previous
disable, without needing to fully reconfigure the slave address.

- configure_slave() - initial setup, sets address + enables
- disable_slave() - disables slave mode + interrupts
- enable_slave() - re-enables after disable (NEW)
- Add i2c_master_slave_test.rs using new i2c_core API
- Master tests: Read ADT7490 temp sensor registers (same as original i2c_test.rs)
- Slave tests: Configure AST1060 as I2C slave for external master
- Uses proper i2c_core types: I2cConfig, I2cController, ClockConfig::ast1060_default()
- Tests verify i2c_core API against real hardware
- Add new uart_core module with modular architecture:
  - config.rs: BaudRate, WordLength, Parity, StopBits, UartConfig
  - controller.rs: UartController hardware abstraction
  - error.rs: UartError with embedded_io::Error impl
  - fifo.rs: FifoTriggerLevel, FifoConfig
  - interrupt.rs: InterruptSource, InterruptConfig
  - line_status.rs: LineStatus bitflags
  - hal_impl.rs: embedded_io::{Read,Write}, core::fmt::Write
  - types.rs: ModemStatus, UartStats, constants

- Remove old uart.rs flat module and uart/ crate
- Update all consumers to use uart_core:
  - main.rs, astdebug.rs, common.rs
  - spi/fmccontroller.rs, spi/spicontroller.rs, spi/spitest.rs
  - All test files in tests/functional/

Key improvements:
- No delay dependency required for UartController
- Safe init() API (was unsafe)
- Builder pattern for configuration
- Better error types with Display impl
- Added core::fmt::Write for writeln! macro support
- Added nb-based non-blocking methods
- Better documentation following i2c_core patterns

BREAKING CHANGE: UartController::new() signature changed from
(Uart, &mut dyn DelayNs) to (&RegisterBlock). Config renamed to
UartConfig with different fields.
Key fixes:
- Use i2cm18 (Master Command Register) for commands, not i2cm14
- Use i2cc08 for byte mode TX/RX data (tx_byte_buffer, rx_byte_buffer)
- Use i2cc0c for buffer sizes (tx_data_byte_count, rx_pool_buffer_size)
- Byte mode: only send START+ADDR on first byte, STOP on last byte
- Buffer mode: combine all command bits in single i2cm18 write
- Add missing DMA enable constants (AST_I2CM_RX_DMA_EN, AST_I2CM_TX_DMA_EN)
- Narrow unsafe scope to inside closure for w.bits() calls
- Add references to original working code (ast1060_i2c.rs)

Register map clarifications:
- i2cm18: Master Command Register (write commands here)
- i2cm14: Interrupt Status Register (read status, write-to-clear)
- i2cc08: Byte Buffer Register (tx_byte_buffer, rx_byte_buffer)
- i2cc0c: Pool Buffer Control Register (buffer sizes)

Reference: aspeed-rust/src/i2c/ast1060_i2c.rs lines 55-100, 320-360, 960-1120
…ansfers

Buffer mode now correctly maintains a single I2C transaction across
multiple 32-byte chunks:
- First chunk: START + addr + data
- Subsequent chunks: data only (no re-addressing)
- Last chunk: data + STOP

This matches the original ast1060_i2c.rs do_i2cm_rx()/do_i2cm_tx()
continuation logic where only PKT_EN + RX/TX_CMD is used for chunks
after the first.

Previously, every chunk sent START+addr which would break devices
expecting a continuous multi-byte read/write transaction.
@rusty1968 rusty1968 requested a review from lxuxx February 17, 2026 18:31
@linux-foundation-easycla
Copy link

CLA Not Signed

@LeeTroy
Copy link
Collaborator

LeeTroy commented Feb 20, 2026

EasyCLA approval list updated and @lxuxx is included, how can we re-trigger the check?

Copy link
Collaborator

@lxuxx lxuxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested i2c as master and slave on hardware. It's good.

@lxuxx
Copy link
Collaborator

lxuxx commented Feb 20, 2026

/easycla

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants