use core::mem::offset_of;
use crate::hwcore::addr::MmioAddr;
use crate::hwcore::regs::access::{Ro, Rw};
#[repr(C)]
pub struct GpioRegs {
pub moder: Rw<u32>,
pub otyper: Rw<u32>,
pub ospeedr: Rw<u32>,
pub pupdr: Rw<u32>,
pub idr: Ro<u32>,
pub odr: Rw<u32>,
pub bsrr: Rw<u32>,
pub lckr: Rw<u32>,
pub afrl: Rw<u32>,
pub afrh: Rw<u32>,
pub brr: Rw<u32>,
}
const _: () = assert!(offset_of!(GpioRegs, moder) == 0x00);
const _: () = assert!(offset_of!(GpioRegs, otyper) == 0x04);
const _: () = assert!(offset_of!(GpioRegs, ospeedr) == 0x08);
const _: () = assert!(offset_of!(GpioRegs, pupdr) == 0x0C);
const _: () = assert!(offset_of!(GpioRegs, idr) == 0x10);
const _: () = assert!(offset_of!(GpioRegs, odr) == 0x14);
const _: () = assert!(offset_of!(GpioRegs, bsrr) == 0x18);
const _: () = assert!(offset_of!(GpioRegs, lckr) == 0x1C);
const _: () = assert!(offset_of!(GpioRegs, afrl) == 0x20);
const _: () = assert!(offset_of!(GpioRegs, afrh) == 0x24);
const _: () = assert!(offset_of!(GpioRegs, brr) == 0x28);
pub const GPIOA_BASE: usize = 0x5802_0000;
pub const GPIOB_BASE: usize = 0x5802_0400;
pub const GPIOC_BASE: usize = 0x5802_0800;
pub const GPIOD_BASE: usize = 0x5802_0C00;
pub const GPIOE_BASE: usize = 0x5802_1000;
pub const GPIOF_BASE: usize = 0x5802_1400;
pub const GPIOG_BASE: usize = 0x5802_1800;
pub const GPIOH_BASE: usize = 0x5802_1C00;
pub const GPIOI_BASE: usize = 0x5802_2000;
pub const GPIOJ_BASE: usize = 0x5802_2400;
pub const GPIOK_BASE: usize = 0x5802_2800;
pub struct Gpio {
base: MmioAddr<GpioRegs>,
}
impl Gpio {
pub const unsafe fn new(base: usize) -> Self {
Self {
base: unsafe { MmioAddr::new(base) },
}
}
pub const unsafe fn gpioc() -> Self {
unsafe { Self::new(GPIOC_BASE) }
}
pub const unsafe fn gpioj() -> Self {
unsafe { Self::new(GPIOJ_BASE) }
}
pub const unsafe fn gpiok() -> Self {
unsafe { Self::new(GPIOK_BASE) }
}
#[inline]
pub fn regs(&self) -> &GpioRegs {
unsafe { &*self.base.as_ptr() }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gpio_bank_spacing_is_0x400() {
assert_eq!(GPIOB_BASE - GPIOA_BASE, 0x400);
assert_eq!(GPIOK_BASE - GPIOA_BASE, 10 * 0x400);
}
#[test]
fn gpiok_idr_matches_legacy_constant() {
assert_eq!(GPIOK_BASE + offset_of!(GpioRegs, idr), 0x5802_2810);
}
#[test]
fn gpioj_bsrr_matches_legacy_constant() {
assert_eq!(GPIOJ_BASE + offset_of!(GpioRegs, bsrr), 0x5802_2418);
}
}