diff --git a/src/i2cmonitor.rs b/src/i2cmonitor.rs new file mode 100644 index 0000000..85bc2c9 --- /dev/null +++ b/src/i2cmonitor.rs @@ -0,0 +1,467 @@ +// Licensed under the Apache-2.0 license + +use crate::common::Logger; +use ast1060_pac::{I2cFilterThr, I2cFilterThr1, I2cFilterThr2, I2cFilterThr3, I2cfilter}; +use core::fmt; +use core::fmt::Write; + +//filter capability define +const AST_I2C_F_COUNT: usize = 4; +const AST_I2C_F_REMAP_SIZE: usize = 16; +const AST_I2C_F_ELEMENT_SIZE: usize = 8; +const AST_CFG_CLOCK0: u32 = 100; +const AST_CFG_CLOCK1: u32 = 400; +const PCLK_HZ: u32 = 50_000_000; + +#[derive(Debug, Copy, Clone)] +pub struct AstI2cThrData { + filter_en: bool, + wlist_en: bool, + filter_idx: [u8; AST_I2C_F_REMAP_SIZE], +} + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct AstI2cFBitmap { + pub element: [u32; AST_I2C_F_ELEMENT_SIZE], +} + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct AstI2cFMTbl { + filter_mtbl: [AstI2cFBitmap; AST_I2C_F_REMAP_SIZE + 1], +} + +/// Wraps the `I2C_filter` peripheral +pub struct I2cMonitor { + i2cfilter_glb: I2cfilter, + i2cfilter_thr0: I2cFilterThr, + i2cfilter_thr1: I2cFilterThr1, + i2cfilter_thr2: I2cFilterThr2, + i2cfilter_thr3: I2cFilterThr3, + i2cfilter_data: [AstI2cThrData; AST_I2C_F_COUNT], + logger: L, +} + +static mut I2C_FILTER_TBL: [AstI2cFMTbl; AST_I2C_F_COUNT] = [AstI2cFMTbl { + filter_mtbl: [AstI2cFBitmap { + element: [0; AST_I2C_F_ELEMENT_SIZE], + }; AST_I2C_F_REMAP_SIZE + 1], +}; AST_I2C_F_COUNT]; + +impl fmt::Debug for I2cMonitor { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("I2cMonitor") + } +} + +macro_rules! i2cf_debug { + ($logger:expr, $($arg:tt)*) => { + let mut buf: heapless::String<64> = heapless::String::new(); + let _ = write!(buf, $($arg)*); + $logger.debug(buf.as_str()); + }; +} + +macro_rules! i2cf_error { + ($logger:expr, $($arg:tt)*) => { + let mut buf: heapless::String<64> = heapless::String::new(); + let _ = write!(buf, $($arg)*); + $logger.error(buf.as_str()); + }; +} + +impl I2cMonitor { + pub fn new( + i2cfilter_glb: I2cfilter, + i2cfilter_thr0: I2cFilterThr, + i2cfilter_thr1: I2cFilterThr1, + i2cfilter_thr2: I2cFilterThr2, + i2cfilter_thr3: I2cFilterThr3, + logger: L, + ) -> Self { + Self { + i2cfilter_glb, + i2cfilter_thr0, + i2cfilter_thr1, + i2cfilter_thr2, + i2cfilter_thr3, + i2cfilter_data: [AstI2cThrData { + filter_en: false, + wlist_en: false, + filter_idx: [0; AST_I2C_F_REMAP_SIZE], + }; AST_I2C_F_COUNT], + logger, + } + } + + pub fn dump_regs(&mut self) { + i2cf_debug!(self.logger, "******* i2cf registers ******"); + i2cf_debug!( + self.logger, + "i2cfilter008 {:#x}", + self.i2cfilter_glb.i2cfilter008().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilter00c {:#x}", + self.i2cfilter_glb.i2cfilter00c().read().bits() + ); + for i in 0..AST_I2C_F_COUNT { + let thr = match i { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + i2cf_debug!(self.logger, "******* i2cf thr {i:} registers ******"); + i2cf_debug!( + self.logger, + "i2cfilterthr04 {:#x}", + thr.i2cfilterthr04().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr08 {:#x}", + thr.i2cfilterthr08().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr0c {:#x}", + thr.i2cfilterthr0c().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr10 {:#x}", + thr.i2cfilterthr10().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr14 {:#x}", + thr.i2cfilterthr14().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr18 {:#x}", + thr.i2cfilterthr18().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr20 {:#x}", + thr.i2cfilterthr20().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr24 {:#x}", + thr.i2cfilterthr24().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr40 {:#x}", + thr.i2cfilterthr40().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr44 {:#x}", + thr.i2cfilterthr44().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr48 {:#x}", + thr.i2cfilterthr48().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr4c {:#x}", + thr.i2cfilterthr4c().read().bits() + ); + i2cf_debug!( + self.logger, + "i2cfilterthr60 {:#x}", + thr.i2cfilterthr60().read().bits() + ); + } + i2cf_debug!(self.logger, "*****************************"); + } + + #[allow(clippy::similar_names)] + pub fn ast_i2c_filter_isr(&mut self) { + let sts_global: u32 = self.i2cfilter_glb.i2cfilter00c().read().bits(); + + for index in 0..AST_I2C_F_COUNT { + if sts_global & (1 << index) == 1 << index { + let count: u8; + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + let int_sts = thr.i2cfilterthr18().read().bits(); + if int_sts > 0 { + let info_wp = thr.i2cfilterthr20().read().failwpt().bits(); + let info_rp = thr.i2cfilterthr20().read().failrpt().bits(); + //calculate the information count + if info_wp > info_rp { + count = info_wp - info_rp; + } else { + count = info_wp.wrapping_add(0x10).wrapping_sub(info_rp); + } + //read back + for _i in 0..count { + //filter block number and information + let value = thr.i2cfilterthr60().read().bits(); + i2cf_debug!(self.logger, "fail log info: {value:#x}"); + } + //clear status + thr.i2cfilterthr18().write(|w| unsafe { w.bits(int_sts) }); + } + } + } + } + pub fn get_pclk(&mut self) -> u32 { + PCLK_HZ + } + pub fn close_filter(&mut self, index: usize) { + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr04().write(|w| w.en().clear_bit()); + thr.i2cfilterthr0c().write(|w| unsafe { w.bits(0x0) }); + } + + pub fn set_initial_timing(&mut self, index: usize, cfg_clock: u32) { + if cfg_clock == AST_CFG_CLOCK0 || cfg_clock == AST_CFG_CLOCK1 { + let mut timeout_count = self.get_pclk() / (cfg_clock * 3 * 1000); + + timeout_count |= timeout_count << 16; + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr10() + .write(|w| unsafe { w.bits(timeout_count) }); + } else { + i2cf_error!(self.logger, "i2c filter invalid clock"); + } + } + + pub fn clr_local_interrupt(&mut self, index: usize) { + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr18().write(|w| unsafe { w.bits(0x1) }); + } + pub fn enable_local_interrupt(&mut self, index: usize) { + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr14() + .write(|w| unsafe { w.inten().bits(0x1) }); + } + pub fn enable_global_interrupt(&mut self, index: usize) { + self.i2cfilter_glb + .i2cfilter008() + .modify(|r, w| unsafe { w.topirqen().bits(r.topirqen().bits() | (1 << index)) }); + } + //4x4 + fn clr_remap_index(&mut self, index: usize) { + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr40() + .write(|w| unsafe { w.map0().bits(0x0) }); + thr.i2cfilterthr44() + .write(|w| unsafe { w.map1().bits(0x0) }); + thr.i2cfilterthr48() + .write(|w| unsafe { w.map2().bits(0x0) }); + thr.i2cfilterthr4c() + .write(|w| unsafe { w.map3().bits(0x0) }); + self.i2cfilter_data[index].filter_idx.fill(0); + } + + //set white list buffer into device + fn set_dev_white_list_tbl(&mut self, index: usize) { + let table_ptr = unsafe { core::ptr::from_ref(&I2C_FILTER_TBL[index]) as usize }; + let table_ptr = u32::try_from(table_ptr).unwrap(); + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr08() + .write(|w| unsafe { w.addr().bits(table_ptr) }); + } + //clear white list table + fn clr_white_list_tbl(&mut self, index: usize) { + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr08().write(|w| unsafe { w.addr().bits(0) }); + + let tbl_ptr = &mut unsafe { I2C_FILTER_TBL }[index]; + //clear bitmap table + let tbl_ref: &mut AstI2cFMTbl = &mut *tbl_ptr; + for bitmap in &mut tbl_ref.filter_mtbl { + for elem in &mut bitmap.element { + *elem = 0; + } + } + } + // + pub fn ast_i2c_filter_default( + &mut self, + idx: usize, + pass: u8, + index: usize, + ) -> Result { + if idx >= AST_I2C_F_REMAP_SIZE { + return Err("Invalid filter table index"); + } + let mut value = 0; + if pass != 0 { + value = 0xffff_ffff; + } + //fill bitmap table (pass or block) + for i in 0..AST_I2C_F_ELEMENT_SIZE { + unsafe { + I2C_FILTER_TBL[index].filter_mtbl[idx].element[i] = value; + } + } + Ok(0) + } + + pub fn ast_i2c_filter_update( + &mut self, + idx: usize, + addr: u8, + table: &mut AstI2cFBitmap, + index: usize, + ) -> Result { + if idx >= AST_I2C_F_REMAP_SIZE { + return Err("Invalid filter table index"); + } + //always put mapped address in the table + self.i2cfilter_data[index].filter_idx[idx] = addr; + + //byte index + let start_index = idx & !0b11; + let addr_4bytes = u32::from_le_bytes([ + self.i2cfilter_data[index].filter_idx[start_index], + self.i2cfilter_data[index].filter_idx[start_index + 1], + self.i2cfilter_data[index].filter_idx[start_index + 2], + self.i2cfilter_data[index].filter_idx[start_index + 3], + ]); + // 4-byte address based on 4 indexes per u32/dw map[0-3] + // Write the mapped address to the correct map register + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + match idx >> 2 { + 0 => { + thr.i2cfilterthr40() + .write(|w| unsafe { w.map0().bits(addr_4bytes) }); + } + 1 => { + thr.i2cfilterthr44() + .write(|w| unsafe { w.map1().bits(addr_4bytes) }); + } + 2 => { + thr.i2cfilterthr48() + .write(|w| unsafe { w.map2().bits(addr_4bytes) }); + } + 3 => { + thr.i2cfilterthr4c() + .write(|w| unsafe { w.map3().bits(addr_4bytes) }); + } + _ => return Err("index out of range"), // This should be unreachable + } + //fill bitmap table (pass or block) + for i in 0..AST_I2C_F_ELEMENT_SIZE { + unsafe { + I2C_FILTER_TBL[index].filter_mtbl[idx].element[i] = table.element[i]; + } + } + Ok(0) + } + + //index: filter thread index + #[allow(clippy::fn_params_excessive_bools)] + pub fn ast_i2c_filter_en( + &mut self, + filter_en: bool, + wlist_en: bool, + clr_idx: bool, + clr_tbl: bool, + index: usize, + ) -> Result { + self.i2cfilter_data[index].filter_en = filter_en; + self.i2cfilter_data[index].wlist_en = wlist_en; + + if filter_en && wlist_en { + i2cf_debug!(self.logger, "ast_i2c_filter_en: set_dev_white_list_tbl"); + self.set_dev_white_list_tbl(index); + } + //clear re-map index + if clr_idx { + i2cf_debug!(self.logger, "ast_i2c_filter_en: clr_remap_index"); + self.clr_remap_index(index); + } + if clr_tbl { + i2cf_debug!(self.logger, "ast_i2c_filter_en: clr_white_list_tbl"); + self.clr_white_list_tbl(index); + } + //apply filter setting + let thr = match index { + 0 => &*self.i2cfilter_thr0, + 1 => &*self.i2cfilter_thr1, + 2 => &*self.i2cfilter_thr2, + 3 => &*self.i2cfilter_thr3, + _ => unreachable!(), + }; + thr.i2cfilterthr04().write(|w| w.en().bit(filter_en)); + thr.i2cfilterthr0c() + .write(|w| unsafe { w.cfg().bits(u32::from(wlist_en)) }); + Ok(0) + } + + //init a filter/thread + pub fn ast_i2c_filter_init(&mut self, index: usize) { + self.close_filter(index); + self.set_initial_timing(index, AST_CFG_CLOCK0); + self.clr_local_interrupt(index); + self.enable_local_interrupt(index); + self.enable_global_interrupt(index); + } +} diff --git a/src/lib.rs b/src/lib.rs index 0a0a6db..636fcb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub mod hash_owned; pub mod hmac; pub mod i2c; pub mod i2c_core; +pub mod i2cmonitor; pub mod i3c; pub mod pinctrl; pub mod rsa; diff --git a/src/main.rs b/src/main.rs index 0b2bef6..57257b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ 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; use aspeed_ddk::tests::functional::i2c_test; +use aspeed_ddk::tests::functional::i2cmonitor_test; #[cfg(any(feature = "i3c_master", feature = "i3c_target"))] use aspeed_ddk::tests::functional::i3c_test; use aspeed_ddk::tests::functional::rsa_test::run_rsa_tests; @@ -407,6 +408,19 @@ fn main() -> ! { // Run I2C master-slave hardware integration tests run_master_slave_tests(&mut uart_controller); + // test with AST1060-AST2600 DC-SCM board + if false { + { + // use to release ast2600 + spim_test::test_spim0(&mut uart_controller); + gpio_test::test_gpio_flash_power(&mut uart_controller); + gpio_test::test_gpio_bmc_reset(&mut uart_controller); + } + + // set up i2c_filter test + i2cmonitor_test::test_i2cmonitor(&mut uart_controller); + } + test_wdt(&mut uart_controller); run_timer_tests(&mut uart_controller); diff --git a/src/pinctrl.rs b/src/pinctrl.rs index 732d240..d3d9dc5 100644 --- a/src/pinctrl.rs +++ b/src/pinctrl.rs @@ -1735,6 +1735,22 @@ paste! { pub const PINCTRL_HVI3C1: &[PinctrlPin] = &[CLR_PIN_SCU418_10, CLR_PIN_SCU418_11, CLR_PIN_SCU418_18, CLR_PIN_SCU418_19, PIN_SCU4B8_10, PIN_SCU4B8_11]; pub const PINCTRL_HVI3C2: &[PinctrlPin] = &[CLR_PIN_SCU418_12, CLR_PIN_SCU418_13, CLR_PIN_SCU418_20, CLR_PIN_SCU418_21, PIN_SCU4B8_12, PIN_SCU4B8_13]; pub const PINCTRL_HVI3C3: &[PinctrlPin] = &[CLR_PIN_SCU418_14, CLR_PIN_SCU418_15, CLR_PIN_SCU418_22, CLR_PIN_SCU418_23, PIN_SCU4B8_14, PIN_SCU4B8_15]; + pub const PINCTRL_I2CF0: &[PinctrlPin] = &[CLR_PIN_SCU41C_24, CLR_PIN_SCU4BC_24, PIN_SCU69C_24, + CLR_PIN_SCU41C_30, CLR_PIN_SCU4BC_30, PIN_SCU69C_30, + CLR_PIN_SCU41C_31, CLR_PIN_SCU4BC_31, PIN_SCU69C_31, + CLR_PIN_SCU430_0, PIN_SCU6B0_0]; + pub const PINCTRL_I2CF1: &[PinctrlPin] = &[CLR_PIN_SCU41C_20, CLR_PIN_SCU4BC_20, PIN_SCU69C_20, + CLR_PIN_SCU41C_21, CLR_PIN_SCU4BC_21, PIN_SCU69C_21, + CLR_PIN_SCU41C_22, CLR_PIN_SCU4BC_22, PIN_SCU69C_22, + CLR_PIN_SCU41C_23, CLR_PIN_SCU4BC_23, PIN_SCU69C_23]; + pub const PINCTRL_I2CF2: &[PinctrlPin] = &[CLR_PIN_SCU418_28, CLR_PIN_SCU4B8_28, PIN_SCU698_28, + CLR_PIN_SCU418_29, CLR_PIN_SCU4B8_29, PIN_SCU698_29, + CLR_PIN_SCU418_30, CLR_PIN_SCU4B8_30, PIN_SCU698_30, + CLR_PIN_SCU418_31, CLR_PIN_SCU4B8_31, PIN_SCU698_31]; + pub const PINCTRL_I2CF3: &[PinctrlPin] = &[CLR_PIN_SCU430_1, PIN_SCU6B0_1, + CLR_PIN_SCU430_2, PIN_SCU6B0_2, + CLR_PIN_SCU430_3, PIN_SCU6B0_3, + CLR_PIN_SCU430_4, PIN_SCU6B0_4,]; pub const PINCTRL_GPIOA0: &[PinctrlPin] = &[CLR_PIN_SCU410_0, CLR_PIN_SCU4B0_0, CLR_PIN_SCU690_0]; pub const PINCTRL_GPIOA1: &[PinctrlPin] = &[CLR_PIN_SCU410_1, CLR_PIN_SCU4B0_1, CLR_PIN_SCU690_1]; diff --git a/src/tests/functional/i2cmonitor_test.rs b/src/tests/functional/i2cmonitor_test.rs new file mode 100644 index 0000000..5876662 --- /dev/null +++ b/src/tests/functional/i2cmonitor_test.rs @@ -0,0 +1,197 @@ +// Licensed under the Apache-2.0 license + +use crate::common::{DummyDelay, UartLogger}; +use crate::i2cmonitor::I2cMonitor; +use crate::pinctrl; +use crate::uart_core::UartController; +use ast1060_pac::{I2cFilterThr, I2cfilter, Peripherals, Scu}; +use embedded_hal::delay::DelayNs; +use embedded_io::Write; + +/* example filter bitmap + +let data_flt: [AstI2cFBitmap; 6] = [ + // block all (index 0) + AstI2cFBitmap { element: [0; 8] }, + // accept all (index 1) + AstI2cFBitmap { + element: [0xffff_ffff; 8], + }, + // block every 16 bytes (index 2) + AstI2cFBitmap { + element: [0xffff_0000; 8], + }, + // block first 16 bytes (index 3) + AstI2cFBitmap { + element: [ + 0xffff_0000, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + ], + }, + // block first 128 bytes (index 4) + AstI2cFBitmap { + element: [ + 0x0, + 0x0, + 0x0, + 0x0, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + ], + }, + // block last 128 bytes (index 5) + AstI2cFBitmap { + element: [ + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0xffff_ffff, + 0x0, + 0x0, + 0x0, + 0x0, + ], + }, +];*/ + +pub fn test_i2cmonitor(uart: &mut UartController<'_>) { + let peripherals = unsafe { Peripherals::steal() }; + let mut delay = DummyDelay {}; + let uart_regs = unsafe { &*ast1060_pac::Uart::ptr() }; + let mut dbg_uart = UartController::new(uart_regs); + let mut i2c_monitor = I2cMonitor::new( + peripherals.i2cfilter, + peripherals.i2c_filter_thr, + peripherals.i2c_filter_thr1, + peripherals.i2c_filter_thr2, + peripherals.i2c_filter_thr3, + UartLogger::new(&mut dbg_uart), + ); + + writeln!(uart, "\r\n####### I2C filter test #######\r").unwrap(); + + pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2CF0); + pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2CF1); + pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2CF2); + pinctrl::Pinctrl::apply_pinctrl_group(pinctrl::PINCTRL_I2CF3); + + // enable it if i2c is not enabled + enable_i2c_filter_register_write_access(); + + for i in 0..4 { + i2c_monitor.ast_i2c_filter_init(i); + writeln!(uart, "i2c filter {i:} init done\r").unwrap(); + i2c_monitor + .ast_i2c_filter_en(true, false, false, false, i) + .unwrap(); + writeln!(uart, "bypass i2c filter {i:}\r").unwrap(); + } + i2c_monitor.dump_regs(); + + // test i2c filter 2 (0-based) + let i2c_monitor_idx = 2; + loop { + write!( + uart, + "i2c filter {i2c_monitor_idx:} will be set to block all after 60s" + ) + .unwrap(); + for _ in 0..60 { + write!(uart, ".").unwrap(); + delay.delay_ms(100); + } + writeln!(uart, "\r\n").unwrap(); + + i2c_monitor + .ast_i2c_filter_en(true, true, false, false, i2c_monitor_idx) + .unwrap(); + writeln!(uart, "i2c filter {i2c_monitor_idx:} block all\r").unwrap(); + + write!( + uart, + "i2c filter {i2c_monitor_idx:} will be set to allow all after 60s" + ) + .unwrap(); + for _ in 0..60 { + write!(uart, ".").unwrap(); + delay.delay_ms(100); + } + writeln!(uart, "\r\n").unwrap(); + + i2c_monitor + .ast_i2c_filter_en(true, false, true, true, i2c_monitor_idx) + .unwrap(); + writeln!(uart, "i2c filter {i2c_monitor_idx:} allow all\r").unwrap(); + } +} + +// this is necessary if only test with i2c filter +fn enable_i2c_filter_register_write_access() { + let scu = unsafe { &*Scu::ptr() }; + scu.scu050().write(|w| w.rst_i2csmbus_ctrl().set_bit()); + let mut delay = DummyDelay {}; + delay.delay_ns(1_000_000); // 1ms delay + scu.scu054().write(|w| unsafe { w.bits(0x4) }); + delay.delay_ns(1_000_000); // 1ms delay +} + +pub fn test_i2cmonitor_register_write(uart: &mut UartController<'_>) { + writeln!(uart, "\r\n####### I2C filter reg write test #########\r").unwrap(); + + enable_i2c_filter_register_write_access(); + + // i2cfilter register + let p0 = unsafe { &*I2cfilter::ptr() }; + p0.i2cfilter008() + .write(|w| unsafe { w.topirqen().bits(0xf) }); + writeln!( + uart, + "i2cfilter008 {:#x}\r", + p0.i2cfilter008().read().topirqen().bits() + ) + .unwrap(); + + //i2cfilter thr register + let p1 = unsafe { &*I2cFilterThr::PTR }; + p1.i2cfilterthr08() + .write(|w| unsafe { w.bits(0x1234_abcd) }); + writeln!( + uart, + "i2cfilterthr08 {:#x}\r", + p1.i2cfilterthr08().read().bits() + ) + .unwrap(); + + p1.i2cfilterthr18().write(|w| unsafe { w.bits(0x1) }); + writeln!( + uart, + "i2cfilterthr18 {:#x}\r", + p1.i2cfilterthr18().read().bits() + ) + .unwrap(); + + p1.i2cfilterthr14().write(|w| unsafe { w.bits(0x1) }); + writeln!( + uart, + "i2cfilterthr14 {:#x}\r", + p1.i2cfilterthr14().read().bits() + ) + .unwrap(); + + writeln!( + uart, + "i2cfilterthr20 {:#x}\r", + p1.i2cfilterthr20().read().bits() + ) + .unwrap(); + + writeln!(uart, "\r\n##########################################\r").unwrap(); +} diff --git a/src/tests/functional/mod.rs b/src/tests/functional/mod.rs index 525c77a..ad2c8ba 100644 --- a/src/tests/functional/mod.rs +++ b/src/tests/functional/mod.rs @@ -7,6 +7,7 @@ pub mod hmac_test; pub mod i2c_core_test; pub mod i2c_master_slave_test; pub mod i2c_test; +pub mod i2cmonitor_test; pub mod i3c_test; pub mod rsa_test; pub mod rsa_test_vec;