//! The MMU structures live inside a dedicated shared crate so it can be used by both the Zynq //! runtime crate and teh HAL crate. #![no_std] use cortex_ar::{ asm::{dsb, isb}, cache::clean_and_invalidate_l1_cache, mmu::SectionAttributes, register::{BpIAll, TlbIAll}, }; pub const NUM_L1_PAGE_TABLE_ENTRIES: usize = 4096; #[derive(Debug, PartialEq, Eq, thiserror::Error)] #[error("address is not aligned to 1MB boundary")] pub struct AddrNotAlignedToOneMb; #[repr(C, align(16384))] pub struct L1Table(pub [u32; NUM_L1_PAGE_TABLE_ENTRIES]); impl L1Table { #[inline(always)] pub const fn as_ptr(&self) -> *const u32 { self.0.as_ptr() } #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut u32 { self.0.as_mut_ptr() } pub fn update( &mut self, addr: u32, section_attrs: SectionAttributes, ) -> Result<(), AddrNotAlignedToOneMb> { if addr & 0x000F_FFFF != 0 { return Err(AddrNotAlignedToOneMb); } let index = addr as usize / 0x10_0000; self.0[index] = (self.0[index] & 0xFFF0_0000) | section_attrs.as_raw_bits(); clean_and_invalidate_l1_cache(); TlbIAll::write(); BpIAll::write(); dsb(); isb(); Ok(()) } }