checkpoint
diff --git a/target/ast1060-evb/entry.rs b/target/ast1060-evb/entry.rs index ea9dee9..e747c81 100644 --- a/target/ast1060-evb/entry.rs +++ b/target/ast1060-evb/entry.rs
@@ -69,7 +69,7 @@ // Default stub handlers for peripherals not yet implemented default_handler!( fmc, gpio, hace, - i2c, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c8, i2c9, i2c10, i2c11, i2c12, i2c13, + i2c, i2c1, i2c3, i2c4, i2c5, i2c6, i2c7, i2c8, i2c9, i2c10, i2c11, i2c12, i2c13, i2cfilter, i3c, i3c1, i3c2, i3c3, scu, sgpiom, @@ -78,6 +78,44 @@ uart, uartdma, wdt ); +// ── I2C2 Interrupt Handler ── +// Handles I2C2 interrupts for both master and slave mode. +// This ISR clears the hardware interrupt status and lets the kernel wake the I2C server task. +// +// The AST1060 I2C controller supports simultaneous master and slave operation on the same +// bus, with separate interrupt status registers: +// - I2CM14: Master Interrupt Status Register +// - I2CS24: Slave Interrupt Status Register + +#[unsafe(no_mangle)] +pub extern "C" fn i2c2() { + // SAFETY: This is called from interrupt context. We only read/write I2C2 interrupt status + // registers, which is safe as this ISR is the exclusive owner of these operations. + unsafe { + // Steal I2C2 peripheral to access interrupt status registers + let i2c2 = ast1060_pac::I2c2::steal(); + + // Check and clear master mode interrupt status (I2CM14) + let master_int_sts = i2c2.i2cm14().read().bits(); + if master_int_sts != 0 { + // Clear master interrupt status bits by writing them back + // (AST1060 I2C uses write-1-to-clear for interrupt status) + i2c2.i2cm14().write(|w| w.bits(master_int_sts)); + } + + // Check and clear slave mode interrupt status (I2CS24) + let slave_int_sts = i2c2.i2cs24().read().bits(); + if slave_int_sts != 0 { + // Clear slave interrupt status bits by writing them back + i2c2.i2cs24().write(|w| w.bits(slave_int_sts)); + } + } + + // The kernel will deliver this interrupt to the I2C server task via the I2C2_IRQ handle. + // No explicit kernel notification needed - the hardware interrupt automatically triggers + // the kernel's interrupt delivery mechanism to wake tasks waiting on this IRQ. +} + mod console_backend { unsafe extern "Rust" { pub fn console_backend_init();
diff --git a/target/ast1060-evb/i2c/i2c_client_test.rs b/target/ast1060-evb/i2c/i2c_client_test.rs index 49b118b..899ad37 100644 --- a/target/ast1060-evb/i2c/i2c_client_test.rs +++ b/target/ast1060-evb/i2c/i2c_client_test.rs
@@ -101,7 +101,7 @@ // ============================================================================ /// Probe ADT7490 — device must ACK at 0x2E. -fn test_probe_adt7490(client: &mut IpcI2cClient, results: &mut TestResults) { +fn _test_probe_adt7490(client: &mut IpcI2cClient, results: &mut TestResults) { let addr = match I2cAddress::new(ADT7490_ADDR) { Ok(a) => a, Err(_) => { @@ -194,7 +194,7 @@ /// /// Uses the combined write-read IPC operation (repeated start) which /// exercises a different code path than separate write + read. -fn test_write_read_device_id(client: &mut IpcI2cClient, results: &mut TestResults) { +fn _test_write_read_device_id(client: &mut IpcI2cClient, results: &mut TestResults) { let addr = match I2cAddress::new(ADT7490_ADDR) { Ok(a) => a, Err(_) => { @@ -218,7 +218,7 @@ } /// Probe a vacant address — must return `Ok(false)` (NAK). -fn test_probe_vacant(client: &mut IpcI2cClient, results: &mut TestResults) { +fn _test_probe_vacant(client: &mut IpcI2cClient, results: &mut TestResults) { // 0x7F is unlikely to be populated on the EVB let addr = match I2cAddress::new(0x7F) { Ok(a) => a, @@ -389,10 +389,10 @@ pw_log::info!("Bus: I2C2 Addr: 0x42"); pw_log::info!("========================================"); - test_probe_adt7490(&mut client, &mut results); +// test_probe_adt7490(&mut client, &mut results); test_register_reads(&mut client, &mut results); - test_write_read_device_id(&mut client, &mut results); - test_probe_vacant(&mut client, &mut results); +// test_write_read_device_id(&mut client, &mut results); +// test_probe_vacant(&mut client, &mut results); // pw_log::info!("========================================"); // pw_log::info!("I2C Slave Tests (IPC slave path, I2C2)");
diff --git a/target/ast1060-evb/i2c/target.rs b/target/ast1060-evb/i2c/target.rs index 33d19ac..ae94503 100644 --- a/target/ast1060-evb/i2c/target.rs +++ b/target/ast1060-evb/i2c/target.rs
@@ -9,7 +9,6 @@ #![no_std] #![no_main] -use cortex_m_semihosting::debug::{EXIT_FAILURE, EXIT_SUCCESS, exit}; use target_common::{TargetInterface, declare_target}; use {console_backend as _, entry as _}; @@ -26,11 +25,6 @@ fn shutdown(code: u32) -> ! { pw_log::info!("Shutting down with code {}", code as u32); - let status = match code { - 0 => EXIT_SUCCESS, - _ => EXIT_FAILURE, - }; - exit(status); #[expect(clippy::empty_loop)] loop {} }