Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ edition = "2021"
default = []
std = []
isr-handlers = [] # Export ISR handlers with #[no_mangle] - disable for kernel integration
i2c_master = []
i2c_target = []
i3c_master = []
i3c_target = []
Expand Down
2 changes: 2 additions & 0 deletions src/i2c_core/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ pub const AST_I2CS_RX_DONE: u32 = 1 << 2;
pub const AST_I2CS_TX_NAK: u32 = 1 << 1;
/// Slave TX got ACK
pub const AST_I2CS_TX_ACK: u32 = 1 << 0;
/// Slave inactive timeout
pub const AST_I2CS_INACTIVE_TO: u32 = 1 << 15;
/// Slave packet mode done
pub const AST_I2CS_PKT_DONE: u32 = 1 << 16;
/// Slave packet mode error
Expand Down
5 changes: 5 additions & 0 deletions src/i2c_core/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

//! AST1060 I2C controller implementation

use crate::common::DummyDelay;
use embedded_hal::delay::DelayNs;

use super::timing::configure_timing;
use super::types::{I2cConfig, I2cController, I2cXferMode};
use super::{constants, error::I2cError};
Expand Down Expand Up @@ -185,12 +188,14 @@ impl<'a> Ast1060I2c<'a> {

/// Wait for completion with timeout (visible to master/transfer modules)
pub(crate) fn wait_completion(&mut self, timeout_us: u32) -> Result<(), I2cError> {
let mut delay = DummyDelay {};
let mut timeout = timeout_us;
self.completion = false;

while timeout > 0 && !self.completion {
self.handle_interrupt()?;
timeout = timeout.saturating_sub(1);
delay.delay_ns(100_000);
}

if self.completion {
Expand Down
28 changes: 21 additions & 7 deletions src/i2c_core/slave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub enum SlaveEvent {
DataReceived { len: usize },
/// Data sent to master
DataSent { len: usize },
/// Data received from master and send data to master (combined event)
DataReceivedAndSent { rx_len: usize, tx_len: usize },
/// Stop condition received
Stop,
}
Expand Down Expand Up @@ -166,11 +168,13 @@ impl Ast1060I2c<'_> {

/// Enable slave mode interrupts
fn enable_slave_interrupts(&mut self) {
let mask = constants::AST_I2CS_PKT_DONE
| constants::AST_I2CS_PKT_ERROR
| constants::AST_I2CS_RX_DONE
| constants::AST_I2CS_SLAVE_MATCH
| constants::AST_I2CS_STOP;
let mut mask = constants::AST_I2CS_PKT_DONE | constants::AST_I2CS_INACTIVE_TO;
if self.xfer_mode == I2cXferMode::BufferMode {
mask |= constants::AST_I2CM_ABNORMAL
| constants::AST_I2CM_NORMAL_STOP
| constants::AST_I2CM_RX_DONE
| constants::AST_I2CM_TX_ACK;
}

unsafe {
self.regs().i2cs20().write(|w| w.bits(mask));
Expand All @@ -181,6 +185,7 @@ impl Ast1060I2c<'_> {
fn clear_slave_interrupts(&mut self) {
unsafe {
self.regs().i2cs24().write(|w| w.bits(0xFFFF_FFFF));
let _ = self.regs().i2cs24().read().bits();
}
}

Expand Down Expand Up @@ -385,8 +390,17 @@ impl Ast1060I2c<'_> {
| constants::AST_I2CS_WAIT_TX_DMA
{
// S: rx_done | wait_tx
return Some(SlaveEvent::DataSent {
len: usize::from(self.regs().i2cc0c().read().tx_data_byte_count().bits() + 1),
return Some(SlaveEvent::DataReceivedAndSent {
rx_len: usize::from(
self.regs()
.i2cc0c()
.read()
.actual_rxd_pool_buffer_size()
.bits(),
),
tx_len: usize::from(
self.regs().i2cc0c().read().tx_data_byte_count().bits() + 1,
),
});
} else if sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_WAIT_TX_DMA {
// S: Sw | wait_tx
Expand Down
31 changes: 19 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use aspeed_ddk::tests::functional::ecdsa_test::run_ecdsa_tests;
use aspeed_ddk::tests::functional::hash_test::run_hash_tests;
use aspeed_ddk::tests::functional::hmac_test::run_hmac_tests;
use aspeed_ddk::tests::functional::i2c_core_test::run_i2c_core_tests;
use aspeed_ddk::tests::functional::i2c_master_slave_test::run_master_slave_tests;
#[cfg(any(feature = "i2c_master", feature = "i2c_target"))]
use aspeed_ddk::tests::functional::i2c_master_slave_test;
#[cfg(any(feature = "i2c_master", feature = "i2c_target"))]
use aspeed_ddk::tests::functional::i2c_test;
#[cfg(any(feature = "i3c_master", feature = "i3c_target"))]
use aspeed_ddk::tests::functional::i3c_test;
Expand Down Expand Up @@ -386,27 +388,32 @@ fn main() -> ! {
run_rsa_tests(&mut uart_controller, &mut rsa);
gpio_test::test_gpioa(&mut uart_controller);

i2c_test::test_i2c_master(&mut uart_controller);
#[cfg(feature = "i2c_target")]
i2c_test::test_i2c_slave(&mut uart_controller);
let i2c_test_hw = false;
if i2c_test_hw {
//I2C test on real hardware
#[cfg(feature = "i2c_master")]
i2c_test::test_i2c_master(&mut uart_controller);
#[cfg(feature = "i2c_target")]
i2c_test::test_i2c_slave(&mut uart_controller);
}
#[cfg(feature = "i3c_master")]
i3c_test::test_i3c_master(&mut uart_controller);
#[cfg(feature = "i3c_target")]
i3c_test::test_i3c_target(&mut uart_controller);

// Run i2c_core functional tests
run_i2c_core_tests(&mut uart_controller);
{
let i2c_core_test_hw = false;
if i2c_core_test_hw {
//I2C core test on real hardware
i2c_core::init_i2c_global();
//run_master_tests(&mut uart_controller);
#[cfg(feature = "i2c_master")]
i2c_master_slave_test::run_master_tests(&mut uart_controller);
#[cfg(feature = "i2c_target")]
run_slave_tests(&mut uart_controller);
i2c_master_slave_test::run_slave_tests(&mut uart_controller);
} else {
// Run i2c_core functional tests
run_i2c_core_tests(&mut uart_controller);
}

// Run I2C master-slave hardware integration tests
run_master_slave_tests(&mut uart_controller);

test_wdt(&mut uart_controller);
run_timer_tests(&mut uart_controller);

Expand Down
149 changes: 130 additions & 19 deletions src/tests/functional/i2c_master_slave_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ use embedded_io::Write;

/// I2C controller for master tests (I2C1 - connected to ADT7490)
const I2C_MASTER_CTRL_ID: u8 = 1;
/// I2C controller for master tests (I2C2 - connected to ast1060 i2c slave)
const I2C_MASTER2_CTRL_ID: u8 = 2;

/// I2C controller for slave tests
const I2C_SLAVE_CTRL_ID: u8 = 2;
Expand Down Expand Up @@ -124,15 +126,24 @@ impl TestResults {
/// Tests the `i2c_core` API by reading known registers from the on-board ADT7490.
/// This mirrors the original `i2c_test.rs` functionality.
pub fn run_master_tests(uart: &mut UartController<'_>) {
let _ = writeln!(uart, "\n========================================\r");
let _ = writeln!(uart, "I2C MASTER Tests (i2c_core API)\r");
let _ = writeln!(uart, "Using ADT7490 @ 0x{ADT7490_ADDRESS:02X}\r");
let _ = writeln!(uart, "========================================\n\r");

let mut results = TestResults::new();

test_adt7490_register_reads(uart, &mut results);
test_adt7490_write_read(uart, &mut results);
if false {
let _ = writeln!(uart, "\n========================================\r");
let _ = writeln!(uart, "I2C MASTER Tests (i2c_core API)\r");
let _ = writeln!(uart, "Using ADT7490 @ 0x{ADT7490_ADDRESS:02X}\r");
let _ = writeln!(uart, "========================================\n\r");

test_adt7490_register_reads(uart, &mut results);
test_adt7490_write_read(uart, &mut results);
} else {
let _ = writeln!(uart, "\n========================================\r");
let _ = writeln!(uart, "I2C MASTER Tests (i2c_core API)\r");
let _ = writeln!(uart, "Using i2c slave @ 0x{SLAVE_ADDRESS:02X}\r");
let _ = writeln!(uart, "========================================\n\r");

test_ast1060_i2c_slave_write_read(uart, &mut results);
}

let (passed, failed) = results.summary();
let _ = writeln!(uart, "\n========================================\r");
Expand Down Expand Up @@ -299,6 +310,90 @@ fn test_adt7490_write_read(uart: &mut UartController<'_>, results: &mut TestResu
}
}

/// Test write-read sequence to slave tests
fn test_ast1060_i2c_slave_write_read(uart: &mut UartController<'_>, results: &mut TestResults) {
let _ = writeln!(uart, "\n[TEST] Write-Read Sequence\r");

unsafe {
let peripherals = Peripherals::steal();
pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2C2);

// Get I2C2 registers
let i2c_regs = &peripherals.i2c2;
let buff_regs = &peripherals.i2cbuff2;

let Some(controller_id) = Controller::new(I2C_MASTER2_CTRL_ID) else {
let _ = writeln!(uart, " [FAIL] Invalid controller ID\r");
results.fail();
return;
};

let controller = I2cController {
controller: controller_id,
registers: i2c_regs,
buff_registers: buff_regs,
};

let config = I2cConfig {
speed: I2cSpeed::Standard,
xfer_mode: I2cXferMode::BufferMode,
multi_master: true,
smbus_timeout: true,
smbus_alert: false,
clock_config: ClockConfig::ast1060_default(),
};

let mut i2c = match Ast1060I2c::new(&controller, config) {
Ok(m) => m,
Err(e) => {
let _ = writeln!(uart, " [FAIL] Init error: {e:?}\r");
results.fail();
return;
}
};

// write to address 0x3d
let write_buf = [0x3D, 0xAB];

let _ = writeln!(uart, " Writing to reg 0x3D...\r");

match i2c.write(SLAVE_ADDRESS, &write_buf) {
Ok(()) => {}
Err(e) => {
let _ = writeln!(uart, " [FAIL] Write address: {e:?}\r");
results.fail();
return;
}
}

// Read Device address (0x3D)
let reg_addr = [0x3D];
let mut read_buf = [0u8; 1];

let _ = writeln!(uart, " Reading reg 0x3D...\r");

match i2c.write(SLAVE_ADDRESS, &reg_addr) {
Ok(()) => {}
Err(e) => {
let _ = writeln!(uart, " [FAIL] Write address: {e:?}\r");
results.fail();
return;
}
}
match i2c.read(SLAVE_ADDRESS, &mut read_buf) {
Ok(()) => {
let _ = writeln!(uart, " read value: 0x{:02X}\r", read_buf[0]);
let _ = writeln!(uart, " [PASS] Write-Read sequence completed\r");
results.pass();
}
Err(e) => {
let _ = writeln!(uart, " [FAIL] Read: {e:?}\r");
results.fail();
}
}
}
}

// ============================================================================
// SLAVE Tests - External Master Required
// ============================================================================
Expand Down Expand Up @@ -416,6 +511,19 @@ fn slave_event_loop(uart: &mut UartController<'_>, slave: &mut Ast1060I2c<'_>) {
let _ = slave.slave_write(&TEST_PATTERN_READ);
transaction_count += 1;
}
SlaveEvent::DataReceivedAndSent { rx_len, tx_len } => {
let _ = writeln!(
uart,
"[SLAVE] Received {rx_len} bytes, Sent {tx_len} bytes\r"
);
let mut buf = [0u8; 32];
if let Ok(n) = slave.slave_read(&mut buf) {
let _ = writeln!(uart, " Data: {:02X?}\r", &buf[..n]);
}
let _ = writeln!(uart, "sending {:02X?}\r", &TEST_PATTERN_READ[..tx_len]);
let _ = slave.slave_write(&TEST_PATTERN_READ);
transaction_count += 1;
}
SlaveEvent::Stop => {
let _ = writeln!(uart, "[SLAVE] Stop condition\r");
}
Expand Down Expand Up @@ -453,24 +561,27 @@ fn slave_event_loop(uart: &mut UartController<'_>, slave: &mut Ast1060I2c<'_>) {

/// Print test setup information
pub fn run_master_slave_tests(uart: &mut UartController<'_>) {
let _ = writeln!(uart, "\n========================================");
let _ = writeln!(uart, "I2C Hardware Integration Tests (i2c_core)");
let _ = writeln!(uart, "========================================");
let _ = writeln!(uart, "\n========================================\r");
let _ = writeln!(uart, "I2C Hardware Integration Tests (i2c_core)\r");
let _ = writeln!(uart, "========================================\r");
let _ = writeln!(uart);
let _ = writeln!(uart, "MASTER TESTS: run_master_tests()");
let _ = writeln!(uart, "MASTER TESTS: run_master_tests()\r");
let _ = writeln!(
uart,
" - Uses on-board ADT7490 temp sensor @ 0x{ADT7490_ADDRESS:02X}"
" - Uses on-board ADT7490 temp sensor @ 0x{ADT7490_ADDRESS:02X}\r"
);
let _ = writeln!(uart, " - Reads known registers and verifies defaults");
let _ = writeln!(uart, " - No external hardware needed");
let _ = writeln!(uart, " - Reads known registers and verifies defaults\r");
let _ = writeln!(uart, " - No external hardware needed\r");
let _ = writeln!(uart);
let _ = writeln!(uart, "SLAVE TESTS: run_slave_tests()");
let _ = writeln!(uart, "SLAVE TESTS: run_slave_tests()\r");
let _ = writeln!(
uart,
" - Configures AST1060 as I2C slave @ 0x{SLAVE_ADDRESS:02X}\r"
);
let _ = writeln!(
uart,
" - Configures AST1060 as I2C slave @ 0x{SLAVE_ADDRESS:02X}"
" - Requires external master (AST2600, another EVB)\r"
);
let _ = writeln!(uart, " - Requires external master (AST2600, another EVB)");
let _ = writeln!(uart, " - Start slave first, then master initiates");
let _ = writeln!(uart, "========================================\n");
let _ = writeln!(uart, " - Start slave first, then master initiates\r");
let _ = writeln!(uart, "========================================\r\n");
}
2 changes: 1 addition & 1 deletion src/tests/functional/i2c_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ static mut TEST_TARGET: DummyI2CTarget = DummyI2CTarget {
pub fn test_i2c_slave(uart: &mut UartController<'_>) {
writeln!(uart, "\r\n####### I2C slave test #######\r\n").unwrap();

let peripherals = unsafe { Peripherals::steal() };
let _peripherals = unsafe { Peripherals::steal() };
unsafe {
let uart_regs = &*ast1060_pac::Uart::ptr();
let mut dbg_uart = UartController::new(uart_regs);
Expand Down
Loading