moved some generic components
This commit is contained in:
@ -5,8 +5,8 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
cortex-a-rt = { path = "../../cortex-r-a/cortex-a-rt", optional = true, features = ["vfp-dp"] }
|
||||
cortex-r-a = { path = "../../cortex-r-a/cortex-r-a", optional = true }
|
||||
cortex-r-a = { path = "../../cortex-r-a/cortex-r-a" }
|
||||
|
||||
[features]
|
||||
default = ["rt"]
|
||||
rt = ["dep:cortex-a-rt", "dep:cortex-r-a"]
|
||||
rt = ["dep:cortex-a-rt"]
|
||||
|
@ -2,37 +2,38 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::process::Command;
|
||||
|
||||
pub use zynq_rt::mmu::*;
|
||||
use zynq7000_rt::mmu::ONE_MB;
|
||||
pub use zynq7000_rt::mmu::segments::*;
|
||||
|
||||
fn main() {
|
||||
let file_path = "src/mmu_table.rs";
|
||||
let file = File::create(file_path).expect("Failed to create file");
|
||||
|
||||
let mut offset = 0;
|
||||
let attr_ddr = stringify!(SECTION_ATTRS_DDR);
|
||||
let attr_unassigned = stringify!(SECTION_ATTRS_UNASSIGNED_RESERVED);
|
||||
let attr_fpga_slaves = stringify!(SECTION_ATTRS_FPGA_SLAVES);
|
||||
let attr_shared_dev = stringify!(SECTION_ATTRS_SHAREABLE_DEVICE);
|
||||
let attr_sram = stringify!(SECTION_ATTRS_SRAM);
|
||||
let attr_qspi = stringify!(SECTION_ATTRS_QSPI_XIP);
|
||||
let attr_ocm_high = stringify!(SECTION_ATTRS_OCM_MAPPED_HIGH);
|
||||
let attr_ddr = stringify!(section_attrs::DDR);
|
||||
let attr_unassigned = stringify!(section_attrs::UNASSIGNED_RESERVED);
|
||||
let attr_fpga_slaves = stringify!(section_attrs::FPGA_SLAVES);
|
||||
let attr_shared_dev = stringify!(section_attrs::SHAREABLE_DEVICE);
|
||||
let attr_sram = stringify!(section_attrs::SRAM);
|
||||
let attr_qspi = stringify!(section_attrs::QSPI_XIP);
|
||||
let attr_ocm_high = stringify!(section_attrs::OCM_MAPPED_HIGH);
|
||||
|
||||
assert_eq!(
|
||||
1 + SEGMENTS_DDR_FULL_ACCESSIBLE
|
||||
+ SEGMENTS_FPGA_SLAVE
|
||||
+ SEGMENTS_FPGA_SLAVE
|
||||
+ SEGMENTS_UNASSIGNED_0
|
||||
+ SEGMENTS_IO_PERIPHS
|
||||
+ SEGMENTS_UNASSIGNED_1
|
||||
+ SEGMENTS_NAND
|
||||
+ SEGMENTS_NOR
|
||||
+ SEGMENTS_SRAM
|
||||
1 + DDR_FULL_ACCESSIBLE
|
||||
+ FPGA_SLAVE
|
||||
+ FPGA_SLAVE
|
||||
+ UNASSIGNED_0
|
||||
+ IO_PERIPHS
|
||||
+ UNASSIGNED_1
|
||||
+ NAND
|
||||
+ NOR
|
||||
+ SRAM
|
||||
+ SEGMENTS_UNASSIGNED_2
|
||||
+ SEGMENTS_AMBA_APB
|
||||
+ SEGMENTS_UNASSIGNED_3
|
||||
+ SEGMENTS_QSPI_XIP
|
||||
+ SEGMENTS_UNASSIGNED_4
|
||||
+ SEGMENTS_OCM_MAPPED_HIGH,
|
||||
+ AMBA_APB
|
||||
+ UNASSIGNED_3
|
||||
+ QSPI_XIP
|
||||
+ UNASSIGNED_4
|
||||
+ OCM_MAPPED_HIGH,
|
||||
4096
|
||||
);
|
||||
let mut buf_writer = std::io::BufWriter::new(file);
|
||||
@ -41,7 +42,8 @@ fn main() {
|
||||
"//! This file is auto-generated by table-gen.rs. Do not edit it!"
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(buf_writer, "use crate::mmu::*;").unwrap();
|
||||
writeln!(buf_writer, "use cortex_r_a::mmu::L1Section;").unwrap();
|
||||
writeln!(buf_writer, "use crate::mmu::{{section_attrs, L1Table}};").unwrap();
|
||||
writeln!(buf_writer, "").unwrap();
|
||||
|
||||
writeln!(buf_writer, "/// MMU Level 1 Page table.").unwrap();
|
||||
@ -66,18 +68,13 @@ fn main() {
|
||||
|
||||
offset += ONE_MB;
|
||||
writeln!(buf_writer, "// DDR memory (0x00100000 - 0x4000_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_DDR_FULL_ACCESSIBLE {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, SECTION_ATTRS_DDR).0,",
|
||||
offset
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..DDR_FULL_ACCESSIBLE {
|
||||
writeln!(buf_writer, "L1Section::new({}, {}).0,", offset, attr_ddr).unwrap();
|
||||
offset += ONE_MB;
|
||||
}
|
||||
|
||||
writeln!(buf_writer, "// FPGA slave 0 (0x4000_0000 - 0x8000_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_FPGA_SLAVE {
|
||||
for _ in 0..FPGA_SLAVE {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -88,7 +85,7 @@ fn main() {
|
||||
}
|
||||
|
||||
writeln!(buf_writer, "// FPGA slave 1 (0x8000_0000 - 0xC000_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_FPGA_SLAVE {
|
||||
for _ in 0..FPGA_SLAVE {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -103,7 +100,7 @@ fn main() {
|
||||
"// Unassigned/Reserved (0xC000_0000 - 0xE000_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_UNASSIGNED_0 {
|
||||
for _ in 0..UNASSIGNED_0 {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -118,7 +115,7 @@ fn main() {
|
||||
"// Segments IO peripherals (0xE000_0000 - 0xE030_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_IO_PERIPHS {
|
||||
for _ in 0..IO_PERIPHS {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -133,7 +130,7 @@ fn main() {
|
||||
"// Unassigned/Reserved (0xE030_0000 - 0xE100_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_UNASSIGNED_1 {
|
||||
for _ in 0..UNASSIGNED_1 {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -144,7 +141,7 @@ fn main() {
|
||||
}
|
||||
|
||||
writeln!(buf_writer, "// NAND (0xE100_0000 - 0xE200_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_NAND {
|
||||
for _ in 0..NAND {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -155,7 +152,7 @@ fn main() {
|
||||
}
|
||||
|
||||
writeln!(buf_writer, "// NOR (0xE200_0000 - 0xE400_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_NOR {
|
||||
for _ in 0..NOR {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -166,7 +163,7 @@ fn main() {
|
||||
}
|
||||
|
||||
writeln!(buf_writer, "// SRAM (0xE400_0000 - 0xE600_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_SRAM {
|
||||
for _ in 0..SRAM {
|
||||
writeln!(buf_writer, "L1Section::new({}, {}).0,", offset, attr_sram).unwrap();
|
||||
offset += ONE_MB;
|
||||
}
|
||||
@ -176,7 +173,7 @@ fn main() {
|
||||
"// Unassigned/Reserved (0xE600_0000 - 0xF800_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_UNASSIGNED_2 {
|
||||
for _ in 0..SEGMENTS_UNASSIGNED_2 {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -191,7 +188,7 @@ fn main() {
|
||||
"// AMBA APB peripherals (0xF800_0000 - 0xF900_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_AMBA_APB {
|
||||
for _ in 0..AMBA_APB {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -206,7 +203,7 @@ fn main() {
|
||||
"// Unassigned/Reserved (0xF900_0000 - 0xFC00_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_UNASSIGNED_3 {
|
||||
for _ in 0..UNASSIGNED_3 {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -217,7 +214,7 @@ fn main() {
|
||||
}
|
||||
|
||||
writeln!(buf_writer, "// QSPI XIP (0xFC00_0000 - 0xFE00_0000)").unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_QSPI_XIP {
|
||||
for _ in 0..QSPI_XIP {
|
||||
writeln!(buf_writer, "L1Section::new({}, {}).0,", offset, attr_qspi).unwrap();
|
||||
offset += ONE_MB;
|
||||
}
|
||||
@ -227,7 +224,7 @@ fn main() {
|
||||
"// Unassiged/Reserved (0xFE00_0000 - 0xFFF0_0000)"
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_UNASSIGNED_4 {
|
||||
for _ in 0..UNASSIGNED_4 {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
@ -239,7 +236,7 @@ fn main() {
|
||||
|
||||
writeln!(buf_writer, "// OCM High (0xFFF0_0000 - 0xFFFF_FFFF)").unwrap();
|
||||
let mut offset_u64 = offset as u64;
|
||||
for _ in 0..zynq_rt::mmu::SEGMENTS_OCM_MAPPED_HIGH {
|
||||
for _ in 0..OCM_MAPPED_HIGH {
|
||||
writeln!(
|
||||
buf_writer,
|
||||
"L1Section::new({}, {}).0,",
|
||||
|
@ -4,7 +4,7 @@
|
||||
//! [provided by Xilinx](https://github.com/Xilinx/embeddedsw/tree/master/lib/bsp/standalone/src/arm/cortexa9/gcc).
|
||||
#![no_std]
|
||||
|
||||
#[cfg(feature="rt")]
|
||||
pub mod rt;
|
||||
pub mod mmu;
|
||||
mod mmu_table;
|
||||
#[cfg(feature = "rt")]
|
||||
pub mod rt;
|
||||
|
@ -23,297 +23,145 @@
|
||||
//! of 1 MB, it is not possible to define separate regions for them. For region
|
||||
//! 0xFFF00000 - 0xFFFFFFFF, 0xFFF00000 to 0xFFFB0000 is reserved but due to 1MB
|
||||
//! granual size, it is not possible to define separate region for it.
|
||||
|
||||
use crate::mmu_table::MMU_L1_PAGE_TABLE;
|
||||
|
||||
pub const OFFSET_DDR: usize = 0;
|
||||
pub const OFFSET_DDR_ALL_ACCESSIBLE: usize = 0x10_0000;
|
||||
|
||||
pub const OFFSET_FPGA_SLAVE_0: usize = 0x4000_0000;
|
||||
pub const OFFSET_FPGA_SLAVE_1_START: usize = 0x8000_0000;
|
||||
pub const OFFSET_FPGA_SLAVE_1_END: usize = 0xC000_0000;
|
||||
|
||||
pub const OFFSET_IO_PERIPHERALS_START: usize = 0xE000_0000;
|
||||
pub const OFFSET_IO_PERIPHERALS_END: usize = 0xE030_0000;
|
||||
|
||||
pub const OFFSET_NAND_MEMORY: usize = 0xE100_0000;
|
||||
pub const OFFSET_NOR_MEMORY: usize = 0xE200_0000;
|
||||
pub const OFFSET_SRAM_MEMORY: usize = 0xE400_0000;
|
||||
pub const OFFSET_SMC_MEMORIES_END: usize = 0xE600_0000;
|
||||
|
||||
/// 0xf8000c00 to 0xf8000fff, 0xf8010000 to 0xf88fffff and
|
||||
/// 0xf8f03000 to 0xf8ffffff are reserved but due to granual size of
|
||||
/// 1MB, it is not possible to define separate regions for them.
|
||||
pub const OFFSET_AMBA_APB_START: usize = 0xF800_0000;
|
||||
pub const OFFSET_AMBA_APB_END: usize = 0xF900_0000;
|
||||
|
||||
pub const OFFSET_QSPI_XIP_START: usize = 0xFC00_0000;
|
||||
pub const OFFSET_QSPI_XIP_END: usize = 0xFE00_0000;
|
||||
|
||||
/// 0xfff00000 to 0xfffb0000 is reserved but due to granual size of
|
||||
/// 1MB, it is not possible to define separate region for it
|
||||
pub const OFFSET_OCM_MAPPED_HIGH_START: usize = 0xFFF0_0000;
|
||||
pub const OFFSET_OCM_MAPPED_HIGH_END: u64 = 0x1_0000_0000;
|
||||
|
||||
pub const MAX_DDR_SIZE: usize = 0x4000_0000;
|
||||
pub const ONE_MB: usize = 0x10_0000;
|
||||
/// First 1 MB of DDR has special treatment, access is dependant on SCU/OCM state.
|
||||
/// Refer to Zynq TRM UG585 p.106 for more details.
|
||||
pub const SEGMENTS_DDR_FULL_ACCESSIBLE: usize = (MAX_DDR_SIZE - ONE_MB) / ONE_MB;
|
||||
pub const SEGMENTS_FPGA_SLAVE: usize = (OFFSET_FPGA_SLAVE_1_START - OFFSET_FPGA_SLAVE_0) / ONE_MB;
|
||||
pub const SEGMENTS_UNASSIGNED_0: usize =
|
||||
(OFFSET_IO_PERIPHERALS_START - OFFSET_FPGA_SLAVE_1_END) / ONE_MB;
|
||||
pub const SEGMENTS_IO_PERIPHS: usize =
|
||||
(OFFSET_IO_PERIPHERALS_END - OFFSET_IO_PERIPHERALS_START) / ONE_MB;
|
||||
pub const SEGMENTS_UNASSIGNED_1: usize = (OFFSET_NAND_MEMORY - OFFSET_IO_PERIPHERALS_END) / ONE_MB;
|
||||
pub const SEGMENTS_NAND: usize = (OFFSET_NOR_MEMORY - OFFSET_NAND_MEMORY) / ONE_MB;
|
||||
pub const SEGMENTS_NOR: usize = (OFFSET_SRAM_MEMORY - OFFSET_NOR_MEMORY) / ONE_MB;
|
||||
pub const SEGMENTS_SRAM: usize = (OFFSET_SMC_MEMORIES_END - OFFSET_SRAM_MEMORY) / ONE_MB;
|
||||
pub const SEGMENTS_UNASSIGNED_2: usize = (OFFSET_AMBA_APB_START - OFFSET_SMC_MEMORIES_END) / ONE_MB;
|
||||
pub const SEGMENTS_AMBA_APB: usize = (OFFSET_AMBA_APB_END - OFFSET_AMBA_APB_START) / ONE_MB;
|
||||
pub const SEGMENTS_UNASSIGNED_3: usize = (OFFSET_QSPI_XIP_START - OFFSET_AMBA_APB_END) / ONE_MB;
|
||||
pub const SEGMENTS_QSPI_XIP: usize = (OFFSET_QSPI_XIP_END - OFFSET_QSPI_XIP_START) / ONE_MB;
|
||||
pub const SEGMENTS_UNASSIGNED_4: usize =
|
||||
(OFFSET_OCM_MAPPED_HIGH_START - OFFSET_QSPI_XIP_END) / ONE_MB;
|
||||
pub const SEGMENTS_OCM_MAPPED_HIGH: usize =
|
||||
((OFFSET_OCM_MAPPED_HIGH_END - OFFSET_OCM_MAPPED_HIGH_START as u64) / ONE_MB as u64) as usize;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
pub enum AccessPermissions {
|
||||
PermissionFault = 0b000,
|
||||
PrivilegedOnly = 0b001,
|
||||
NoUserWrite = 0b010,
|
||||
FullAccess = 0b011,
|
||||
_Reserved1 = 0b100,
|
||||
PrivilegedReadOnly = 0b101,
|
||||
ReadOnly = 0b110,
|
||||
_Reserved2 = 0b111,
|
||||
pub mod offsets {
|
||||
pub const OFFSET_DDR: usize = 0;
|
||||
pub const OFFSET_DDR_ALL_ACCESSIBLE: usize = 0x10_0000;
|
||||
|
||||
pub const OFFSET_FPGA_SLAVE_0: usize = 0x4000_0000;
|
||||
pub const OFFSET_FPGA_SLAVE_1_START: usize = 0x8000_0000;
|
||||
pub const OFFSET_FPGA_SLAVE_1_END: usize = 0xC000_0000;
|
||||
|
||||
pub const OFFSET_IO_PERIPHERALS_START: usize = 0xE000_0000;
|
||||
pub const OFFSET_IO_PERIPHERALS_END: usize = 0xE030_0000;
|
||||
|
||||
pub const OFFSET_NAND_MEMORY: usize = 0xE100_0000;
|
||||
pub const OFFSET_NOR_MEMORY: usize = 0xE200_0000;
|
||||
pub const OFFSET_SRAM_MEMORY: usize = 0xE400_0000;
|
||||
pub const OFFSET_SMC_MEMORIES_END: usize = 0xE600_0000;
|
||||
|
||||
/// 0xf8000c00 to 0xf8000fff, 0xf8010000 to 0xf88fffff and
|
||||
/// 0xf8f03000 to 0xf8ffffff are reserved but due to granual size of
|
||||
/// 1MB, it is not possible to define separate regions for them.
|
||||
pub const OFFSET_AMBA_APB_START: usize = 0xF800_0000;
|
||||
pub const OFFSET_AMBA_APB_END: usize = 0xF900_0000;
|
||||
|
||||
pub const OFFSET_QSPI_XIP_START: usize = 0xFC00_0000;
|
||||
pub const OFFSET_QSPI_XIP_END: usize = 0xFE00_0000;
|
||||
|
||||
/// 0xfff00000 to 0xfffb0000 is reserved but due to granual size of
|
||||
/// 1MB, it is not possible to define separate region for it
|
||||
pub const OFFSET_OCM_MAPPED_HIGH_START: usize = 0xFFF0_0000;
|
||||
pub const OFFSET_OCM_MAPPED_HIGH_END: u64 = 0x1_0000_0000;
|
||||
}
|
||||
pub mod segments {
|
||||
pub use super::offsets::*;
|
||||
use super::{MAX_DDR_SIZE, ONE_MB};
|
||||
|
||||
/// First 1 MB of DDR has special treatment, access is dependant on SCU/OCM state.
|
||||
/// Refer to Zynq TRM UG585 p.106 for more details.
|
||||
pub const DDR_FULL_ACCESSIBLE: usize = (MAX_DDR_SIZE - ONE_MB) / ONE_MB;
|
||||
pub const FPGA_SLAVE: usize = (OFFSET_FPGA_SLAVE_1_START - OFFSET_FPGA_SLAVE_0) / ONE_MB;
|
||||
pub const UNASSIGNED_0: usize =
|
||||
(OFFSET_IO_PERIPHERALS_START - OFFSET_FPGA_SLAVE_1_END) / ONE_MB;
|
||||
pub const IO_PERIPHS: usize =
|
||||
(OFFSET_IO_PERIPHERALS_END - OFFSET_IO_PERIPHERALS_START) / ONE_MB;
|
||||
pub const UNASSIGNED_1: usize = (OFFSET_NAND_MEMORY - OFFSET_IO_PERIPHERALS_END) / ONE_MB;
|
||||
pub const NAND: usize = (OFFSET_NOR_MEMORY - OFFSET_NAND_MEMORY) / ONE_MB;
|
||||
pub const NOR: usize = (OFFSET_SRAM_MEMORY - OFFSET_NOR_MEMORY) / ONE_MB;
|
||||
pub const SRAM: usize = (OFFSET_SMC_MEMORIES_END - OFFSET_SRAM_MEMORY) / ONE_MB;
|
||||
pub const SEGMENTS_UNASSIGNED_2: usize =
|
||||
(OFFSET_AMBA_APB_START - OFFSET_SMC_MEMORIES_END) / ONE_MB;
|
||||
pub const AMBA_APB: usize = (OFFSET_AMBA_APB_END - OFFSET_AMBA_APB_START) / ONE_MB;
|
||||
pub const UNASSIGNED_3: usize = (OFFSET_QSPI_XIP_START - OFFSET_AMBA_APB_END) / ONE_MB;
|
||||
pub const QSPI_XIP: usize = (OFFSET_QSPI_XIP_END - OFFSET_QSPI_XIP_START) / ONE_MB;
|
||||
pub const UNASSIGNED_4: usize = (OFFSET_OCM_MAPPED_HIGH_START - OFFSET_QSPI_XIP_END) / ONE_MB;
|
||||
pub const OCM_MAPPED_HIGH: usize = ((OFFSET_OCM_MAPPED_HIGH_END
|
||||
- OFFSET_OCM_MAPPED_HIGH_START as u64)
|
||||
/ ONE_MB as u64) as usize;
|
||||
}
|
||||
|
||||
impl AccessPermissions {
|
||||
const fn ap(&self) -> u8 {
|
||||
(*self as u8) & 0b11
|
||||
}
|
||||
pub mod section_attrs {
|
||||
use cortex_r_a::mmu::{
|
||||
AccessPermissions, CacheableMemoryAttribute, MemoryRegionAttributes, SectionAttributes,
|
||||
};
|
||||
|
||||
const fn apx(&self) -> bool {
|
||||
(*self as u8) > (AccessPermissions::FullAccess as u8)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
pub enum L1EntryType {
|
||||
/// Access generates an abort exception. Indicates an unmapped virtual address.
|
||||
Fault = 0b00,
|
||||
/// Entry points to a L2 translation table, allowing 1 MB of memory to be further divided
|
||||
PageTable = 0b01,
|
||||
/// Maps a 1 MB region to a physical address.
|
||||
Section = 0b10,
|
||||
/// Special 1MB section entry which requires 16 entries in the translation table.
|
||||
Supersection = 0b11,
|
||||
}
|
||||
|
||||
/// The ARM Cortex-A architecture reference manual p.1363 specifies these attributes in more detail.
|
||||
///
|
||||
/// The B (Bufferable), C (Cacheable), and TEX (Type extension) bit names are inherited from
|
||||
/// earlier versions of the architecture. These names no longer adequately describe the function
|
||||
/// of the B, C, and TEX bits.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct MemoryRegionAttributesRaw {
|
||||
/// TEX bits
|
||||
type_extensions: u8,
|
||||
c: bool,
|
||||
b: bool,
|
||||
}
|
||||
|
||||
impl MemoryRegionAttributesRaw {
|
||||
pub const fn new(type_extensions: u8, c: bool, b: bool) -> Self {
|
||||
Self {
|
||||
type_extensions,
|
||||
c,
|
||||
b,
|
||||
pub const DDR: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: true,
|
||||
access: AccessPermissions::FullAccess,
|
||||
// Manager domain
|
||||
domain: 0b1111,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::CacheableMemory {
|
||||
inner: CacheableMemoryAttribute::WriteBackWriteAlloc,
|
||||
outer: CacheableMemoryAttribute::WriteBackWriteAlloc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum CacheableMemoryAttribute {
|
||||
NonCacheable = 0b00,
|
||||
WriteBackWriteAlloc = 0b01,
|
||||
WriteThroughNoWriteAlloc = 0b10,
|
||||
WriteBackNoWriteAlloc = 0b11,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum MemoryRegionAttributes {
|
||||
StronglyOrdered,
|
||||
ShareableDevice,
|
||||
OuterAndInnerWriteThroughNoWriteAlloc,
|
||||
OuterAndInnerWriteBackNoWriteAlloc,
|
||||
OuterAndInnerNonCacheable,
|
||||
OuterAndInnerWriteBackWriteAlloc,
|
||||
NonShareableDevice,
|
||||
CacheableMemory {
|
||||
inner: CacheableMemoryAttribute,
|
||||
outer: CacheableMemoryAttribute,
|
||||
},
|
||||
}
|
||||
|
||||
impl MemoryRegionAttributes {
|
||||
pub const fn as_raw(&self) -> MemoryRegionAttributesRaw {
|
||||
match self {
|
||||
MemoryRegionAttributes::StronglyOrdered => {
|
||||
MemoryRegionAttributesRaw::new(0b000, false, false)
|
||||
}
|
||||
MemoryRegionAttributes::ShareableDevice => {
|
||||
MemoryRegionAttributesRaw::new(0b000, false, true)
|
||||
}
|
||||
MemoryRegionAttributes::OuterAndInnerWriteThroughNoWriteAlloc => {
|
||||
MemoryRegionAttributesRaw::new(0b000, true, false)
|
||||
}
|
||||
MemoryRegionAttributes::OuterAndInnerWriteBackNoWriteAlloc => {
|
||||
MemoryRegionAttributesRaw::new(0b000, true, true)
|
||||
}
|
||||
MemoryRegionAttributes::OuterAndInnerNonCacheable => {
|
||||
MemoryRegionAttributesRaw::new(0b001, false, false)
|
||||
}
|
||||
MemoryRegionAttributes::OuterAndInnerWriteBackWriteAlloc => {
|
||||
MemoryRegionAttributesRaw::new(0b001, true, true)
|
||||
}
|
||||
MemoryRegionAttributes::NonShareableDevice => {
|
||||
MemoryRegionAttributesRaw::new(0b010, false, false)
|
||||
}
|
||||
MemoryRegionAttributes::CacheableMemory { inner, outer } => {
|
||||
MemoryRegionAttributesRaw::new(
|
||||
1 << 2 | (*outer as u8),
|
||||
(*inner as u8 & 0b10) != 0,
|
||||
(*inner as u8 & 0b01) != 0,
|
||||
)
|
||||
}
|
||||
.as_raw(),
|
||||
};
|
||||
pub const FPGA_SLAVES: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::StronglyOrdered.as_raw(),
|
||||
};
|
||||
pub const SHAREABLE_DEVICE: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::ShareableDevice.as_raw(),
|
||||
};
|
||||
pub const SRAM: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::OuterAndInnerWriteBackNoWriteAlloc.as_raw(),
|
||||
};
|
||||
pub const QSPI_XIP: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::OuterAndInnerWriteThroughNoWriteAlloc.as_raw(),
|
||||
};
|
||||
pub const OCM_MAPPED_HIGH: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::CacheableMemory {
|
||||
inner: CacheableMemoryAttribute::WriteThroughNoWriteAlloc,
|
||||
outer: CacheableMemoryAttribute::NonCacheable,
|
||||
}
|
||||
}
|
||||
.as_raw(),
|
||||
};
|
||||
pub const UNASSIGNED_RESERVED: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::PermissionFault,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::StronglyOrdered.as_raw(),
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SectionAttributes {
|
||||
/// NG bit
|
||||
non_global: bool,
|
||||
/// Implementation defined bit.
|
||||
p_bit: bool,
|
||||
shareable: bool,
|
||||
/// AP bits
|
||||
access: AccessPermissions,
|
||||
memory_attrs: MemoryRegionAttributesRaw,
|
||||
domain: u8,
|
||||
/// xN bit.
|
||||
execute_never: bool,
|
||||
}
|
||||
|
||||
/// 1 MB section translation entry, mapping a 1 MB region to a physical address.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct L1Section(pub u32);
|
||||
|
||||
impl L1Section {
|
||||
/// The physical base address. The uppermost 12 bits define which 1 MB of virtual address
|
||||
/// space are being accessed. They will be stored in the L1 section table. This address
|
||||
/// MUST be aligned to 1 MB. This code will panic if this is not the case.
|
||||
pub const fn new(phys_base: u32, section_attrs: SectionAttributes) -> Self {
|
||||
// Must be aligned to 1 MB
|
||||
if phys_base & 0x000F_FFFF != 0 {
|
||||
panic!("physical base address for L1 section must be aligned to 1 MB");
|
||||
}
|
||||
let higher_bits = phys_base >> 20;
|
||||
let raw = (higher_bits << 20)
|
||||
| ((section_attrs.non_global as u32) << 17)
|
||||
| ((section_attrs.shareable as u32) << 16)
|
||||
| ((section_attrs.access.apx() as u32) << 15)
|
||||
| ((section_attrs.memory_attrs.type_extensions as u32) << 12)
|
||||
| ((section_attrs.access.ap() as u32) << 10)
|
||||
| ((section_attrs.p_bit as u32) << 9)
|
||||
| ((section_attrs.domain as u32) << 5)
|
||||
| ((section_attrs.execute_never as u32) << 4)
|
||||
| ((section_attrs.memory_attrs.c as u32) << 3)
|
||||
| ((section_attrs.memory_attrs.b as u32) << 2)
|
||||
| L1EntryType::Section as u32;
|
||||
L1Section(raw)
|
||||
}
|
||||
}
|
||||
|
||||
pub const SECTION_ATTRS_DDR: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: true,
|
||||
access: AccessPermissions::FullAccess,
|
||||
// Manager domain
|
||||
domain: 0b1111,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::CacheableMemory {
|
||||
inner: CacheableMemoryAttribute::WriteBackWriteAlloc,
|
||||
outer: CacheableMemoryAttribute::WriteBackWriteAlloc,
|
||||
}
|
||||
.as_raw(),
|
||||
};
|
||||
|
||||
pub const SECTION_ATTRS_FPGA_SLAVES: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::StronglyOrdered.as_raw(),
|
||||
};
|
||||
pub const SECTION_ATTRS_SHAREABLE_DEVICE: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::ShareableDevice.as_raw(),
|
||||
};
|
||||
pub const SECTION_ATTRS_SRAM: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::OuterAndInnerWriteBackNoWriteAlloc.as_raw(),
|
||||
};
|
||||
pub const SECTION_ATTRS_QSPI_XIP: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::OuterAndInnerWriteThroughNoWriteAlloc.as_raw(),
|
||||
};
|
||||
pub const SECTION_ATTRS_OCM_MAPPED_HIGH: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::FullAccess,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::CacheableMemory {
|
||||
inner: CacheableMemoryAttribute::WriteThroughNoWriteAlloc,
|
||||
outer: CacheableMemoryAttribute::NonCacheable,
|
||||
}
|
||||
.as_raw(),
|
||||
};
|
||||
pub const SECTION_ATTRS_UNASSIGNED_RESERVED: SectionAttributes = SectionAttributes {
|
||||
non_global: false,
|
||||
p_bit: false,
|
||||
shareable: false,
|
||||
access: AccessPermissions::PermissionFault,
|
||||
domain: 0b0000,
|
||||
execute_never: false,
|
||||
memory_attrs: MemoryRegionAttributes::StronglyOrdered.as_raw(),
|
||||
};
|
||||
|
||||
pub const NUM_L1_PAGE_TABLE_ENTRIES: usize = 4096;
|
||||
|
||||
#[repr(C, align(16384))]
|
||||
@ -327,8 +175,9 @@ pub struct L1Table(pub(crate) [u32; NUM_L1_PAGE_TABLE_ENTRIES]);
|
||||
/// called once in the boot code before enabling the MMU, and it should be called while the MMU is
|
||||
/// disabled.
|
||||
#[unsafe(no_mangle)]
|
||||
#[cfg(feature = "rt")]
|
||||
unsafe extern "C" fn load_mmu_table() {
|
||||
let table_base = &MMU_L1_PAGE_TABLE.0 as *const _ as u32;
|
||||
let table_base = &crate::mmu_table::MMU_L1_PAGE_TABLE.0 as *const _ as u32;
|
||||
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
//! [provided by Xilinx](https://github.com/Xilinx/embeddedsw/blob/master/lib/bsp/standalone/src/arm/cortexa9/gcc/boot.S)
|
||||
//! as possible. The boot routine includes stack, MMU, cache and .bss/.data section initialization.
|
||||
use cortex_a_rt as _;
|
||||
use cortex_r_a::register::{cpsr::ProcessorMode, Cpsr};
|
||||
use cortex_r_a::register::{Cpsr, cpsr::ProcessorMode};
|
||||
|
||||
// Start-up code for Armv7-A
|
||||
//
|
||||
|
Reference in New Issue
Block a user