use core::mem::offset_of;
use crate::hwcore::addr::MmioAddr;
use crate::hwcore::regs::access::{Ro, Rw};
#[repr(C)]
pub struct I2cRegs {
pub cr1: Rw<u32>,
pub cr2: Rw<u32>,
pub oar1: Rw<u32>,
pub oar2: Rw<u32>,
pub timingr: Rw<u32>,
pub timeoutr: Rw<u32>,
pub isr: Ro<u32>,
pub icr: Rw<u32>,
pub pecr: Ro<u32>,
pub rxdr: Ro<u32>,
pub txdr: Rw<u32>,
}
const _: () = assert!(offset_of!(I2cRegs, cr1) == 0x00);
const _: () = assert!(offset_of!(I2cRegs, cr2) == 0x04);
const _: () = assert!(offset_of!(I2cRegs, oar1) == 0x08);
const _: () = assert!(offset_of!(I2cRegs, oar2) == 0x0C);
const _: () = assert!(offset_of!(I2cRegs, timingr) == 0x10);
const _: () = assert!(offset_of!(I2cRegs, timeoutr) == 0x14);
const _: () = assert!(offset_of!(I2cRegs, isr) == 0x18);
const _: () = assert!(offset_of!(I2cRegs, icr) == 0x1C);
const _: () = assert!(offset_of!(I2cRegs, pecr) == 0x20);
const _: () = assert!(offset_of!(I2cRegs, rxdr) == 0x24);
const _: () = assert!(offset_of!(I2cRegs, txdr) == 0x28);
pub const I2C1_BASE: usize = 0x4000_5400;
pub const I2C2_BASE: usize = 0x4000_5800;
pub const I2C3_BASE: usize = 0x4000_5C00;
pub const I2C4_BASE: usize = 0x5800_1C00;
pub struct I2c {
base: MmioAddr<I2cRegs>,
}
impl I2c {
pub const unsafe fn new(base: usize) -> Self {
Self {
base: unsafe { MmioAddr::new(base) },
}
}
pub const unsafe fn i2c4() -> Self {
unsafe { Self::new(I2C4_BASE) }
}
#[inline]
pub fn regs(&self) -> &I2cRegs {
unsafe { &*self.base.as_ptr() }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn i2c4_base_matches_legacy_constants() {
assert_eq!(I2C4_BASE, 0x5800_1C00);
assert_eq!(I2C4_BASE + offset_of!(I2cRegs, cr1), 0x5800_1C00);
assert_eq!(I2C4_BASE + offset_of!(I2cRegs, cr2), 0x5800_1C04);
assert_eq!(I2C4_BASE + offset_of!(I2cRegs, isr), 0x5800_1C18);
assert_eq!(I2C4_BASE + offset_of!(I2cRegs, icr), 0x5800_1C1C);
assert_eq!(I2C4_BASE + offset_of!(I2cRegs, rxdr), 0x5800_1C24);
assert_eq!(I2C4_BASE + offset_of!(I2cRegs, txdr), 0x5800_1C28);
}
}