Skip to content

Commit

Permalink
Merge pull request #7 from thejpster/add-more-msrs
Browse files Browse the repository at this point in the history
Add more registers, and MPU support
  • Loading branch information
jonathanpallant authored Feb 24, 2025
2 parents c2adc89 + 54e68e3 commit 016cdf9
Show file tree
Hide file tree
Showing 246 changed files with 10,149 additions and 202 deletions.
26 changes: 24 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
- name: Build
run: |
cargo build --target ${{ matrix.target }}
cargo build --target ${{ matrix.target }} --no-default-features
cargo build --target ${{ matrix.target }} --all-features
# Build the host tools
build-host:
Expand Down Expand Up @@ -69,6 +71,8 @@ jobs:
- name: Build
run: |
cargo build --target ${{ matrix.target }} -Zbuild-std=core
cargo build --target ${{ matrix.target }} -Zbuild-std=core --no-default-features
cargo build --target ${{ matrix.target }} -Zbuild-std=core --all-features
# Gather all the above build jobs together for the purposes of getting an overall pass-fail
build-all:
Expand Down Expand Up @@ -99,6 +103,8 @@ jobs:
- name: Build docs
run: |
cargo doc --target ${{ matrix.target }}
cargo doc --target ${{ matrix.target }} --no-default-features
cargo doc --target ${{ matrix.target }} --all-features
# Build the docs for the host tools
docs-host:
Expand Down Expand Up @@ -184,6 +190,8 @@ jobs:
- name: Clippy
run: |
cargo clippy --target ${{ matrix.target }}
cargo clippy --target ${{ matrix.target }} --no-default-features
cargo clippy --target ${{ matrix.target }} --all-features
# Run clippy on the host tools
clippy-host:
Expand Down Expand Up @@ -211,8 +219,22 @@ jobs:
steps:
- run: /bin/true

# Run the unit tests
unit-test:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install rust
run: |
rustup install stable
rustup default stable
- name: Run cargo test
run: |
cargo test --manifest-path cortex-r/Cargo.toml
# Run some programs in QEMU
test:
qemu-test:
runs-on: ubuntu-24.04
needs: [build-all]
steps:
Expand All @@ -224,6 +246,6 @@ jobs:
# Gather all the above xxx-all jobs together for the purposes of getting an overall pass-fail
all:
runs-on: ubuntu-24.04
needs: [docs-all, build-all, fmt-all, test] # not gating on clippy-all
needs: [docs-all, build-all, fmt-all, unit-test, qemu-test] # not gating on clippy-all
steps:
- run: /bin/true
38 changes: 35 additions & 3 deletions cortex-r-examples/reference/registers-armv7r-none-eabi.out
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
MIDR { implementer=0x41 variant=0x1 arch=0xf part_no=0xc15 rev=0x3 }
CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=1 I=1 F=1 T=0 MODE=Ok(Sys) }
_stack_top: 0x08000000
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=0 RR=0 V=0 I=0 Z=0 SW=0 C=0 A=0 M=0 } before setting C, I and Z
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=0 RR=0 V=0 I=1 Z=1 SW=0 C=1 A=0 M=0 } after
PMSA-v7 MPUIR: Mpuir { iregions: 0, dregions: 16, non_unified: false }
DRegion 0: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 4: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 5: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 6: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 7: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 8: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 9: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 10: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 11: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAllocate, shareable: true } }
DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 4: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 5: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 6: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 7: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 8: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 9: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 10: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 11: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=1 RR=0 V=0 I=0 Z=0 SW=0 C=0 A=0 M=0 } before setting C, I and Z
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=1 RR=0 V=0 I=1 Z=1 SW=0 C=1 A=0 M=0 } after
38 changes: 35 additions & 3 deletions cortex-r-examples/reference/registers-armv7r-none-eabihf.out
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
MIDR { implementer=0x41 variant=0x1 arch=0xf part_no=0xc15 rev=0x3 }
CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=1 I=1 F=1 T=0 MODE=Ok(Sys) }
_stack_top: 0x08000000
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=0 RR=0 V=0 I=0 Z=0 SW=0 C=0 A=0 M=0 } before setting C, I and Z
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=0 RR=0 V=0 I=1 Z=1 SW=0 C=1 A=0 M=0 } after
PMSA-v7 MPUIR: Mpuir { iregions: 0, dregions: 16, non_unified: false }
DRegion 0: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 4: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 5: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 6: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 7: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 8: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 9: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 10: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 11: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 0: Region { base: 0x20000000, size: _16M, subregion_mask: 0, enabled: true, no_exec: false, mem_attr: Cacheable { outer: NonCacheable, inner: WriteThroughNoWriteAllocate, shareable: true } }
DRegion 1: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 2: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 3: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 4: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 5: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 6: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 7: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 8: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 9: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 10: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 11: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 12: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 13: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 14: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
DRegion 15: Region { base: 0x0, size: Invalid, subregion_mask: 0, enabled: false, no_exec: false, mem_attr: StronglyOrdered }
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=1 RR=0 V=0 I=0 Z=0 SW=0 C=0 A=0 M=0 } before setting C, I and Z
SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=0 FI=0 DZ=0 BR=1 RR=0 V=0 I=1 Z=1 SW=0 C=1 A=0 M=0 } after
74 changes: 74 additions & 0 deletions cortex-r-examples/src/bin/generic_timer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//! Generic-timer example for Arm Cortex-R52
#![no_std]
#![no_main]

// pull in our start-up code
use cortex_r_examples as _;

use semihosting::println;

/// The entry-point to the Rust application.
///
/// It is called by the start-up code in `cortex-m-rt`.
#[no_mangle]
pub extern "C" fn kmain() {
main();
semihosting::process::exit(0);
}

/// A placeholder function so that the workspace still builds
#[cfg(not(arm_architecture = "v8-r"))]
fn main() {
println!("No generic timers on this platform");
}

/// Let's test some timers!
#[cfg(arm_architecture = "v8-r")]
fn main() {
use cortex_r::generic_timer::{El1PhysicalTimer, El1VirtualTimer, GenericTimer};
let cntfrq = cortex_r::register::Cntfrq::read().0;
println!("cntfrq = {:.03} MHz", cntfrq as f32 / 1_000_000.0);

let delay_ticks = cntfrq * 2;

let mut pgt = unsafe { El1PhysicalTimer::new() };
let mut vgt = unsafe { El1VirtualTimer::new() };

let pgt_ref: &mut dyn GenericTimer = &mut pgt;
let vgt_ref: &mut dyn GenericTimer = &mut vgt;

for (timer, name) in [(pgt_ref, "physical"), (vgt_ref, "virtual")] {
println!("Using {} timer ************************", name);

println!("Print five, one per second...");
for i in 0..5 {
println!("i = {}", i);
timer.delay_ms(1000);
}

let now = timer.counter();
println!("{} is now: {}", name, now);
println!("Waiting for {} {} ticks to count up...", delay_ticks, name);
timer.counter_compare_set(now + delay_ticks as u64);
timer.enable(true);
while !timer.interrupt_status() {
core::hint::spin_loop();
}
println!("Matched! {} count now {}", name, timer.counter());

println!(
"Waiting for {} {} ticks to count down...",
delay_ticks, name
);
timer.countdown_set(delay_ticks);
while !timer.interrupt_status() {
core::hint::spin_loop();
}
println!(
"{} countdown hit zero! (and is now {})",
name,
timer.countdown() as i32
);
}
}
2 changes: 1 addition & 1 deletion cortex-r-examples/src/bin/gic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn dump_cpsr() {
/// Called by [`kmain`].
fn main() -> Result<(), core::fmt::Error> {
// Get the GIC address by reading CBAR
let periphbase = cortex_r::register::Cbar::read().periphbase();
let periphbase = cortex_r::register::ImpCbar::read().periphbase();
println!("Found PERIPHBASE {:010p}", periphbase);
let gicd_base = periphbase.wrapping_byte_add(GICD_BASE_OFFSET);
let gicr_base = periphbase.wrapping_byte_add(GICR_BASE_OFFSET);
Expand Down
122 changes: 114 additions & 8 deletions cortex-r-examples/src/bin/registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,135 @@ use cortex_r_examples as _;

use semihosting::println;

extern "C" {
static _stack_top: u32;
}

/// The entry-point to the Rust application.
///
/// It is called by the start-up code in `cortex-m-rt`.
#[no_mangle]
pub extern "C" fn kmain() {
chip_info();
#[cfg(arm_architecture = "v7-r")]
mpu_pmsa_v7();
#[cfg(arm_architecture = "v8-r")]
mpu_pmsa_v8();
test_changing_sctlr();
semihosting::process::exit(0);
}

fn chip_info() {
println!("{:?}", cortex_r::register::Midr::read());
println!("{:?}", cortex_r::register::Cpsr::read());
#[cfg(arm_architecture = "v8-r")]
{
println!("{:?}", cortex_r::register::Cbar::read());
println!("{:?}", cortex_r::register::ImpCbar::read());
println!("{:?}", cortex_r::register::Vbar::read());
// This only works in EL2 and start-up put us in EL1
// println!("{:?}", cortex_r::register::Hvbar::read());
}
}

#[cfg(arm_architecture = "v7-r")]
fn mpu_pmsa_v7() {
use cortex_r::{
pmsav7::{CacheablePolicy, Config, MemAttr, Mpu, Region, RegionSize},
register::Mpuir,
};

// How many regions?
let mpuir = Mpuir::read();
println!("PMSA-v7 MPUIR: {:?}", mpuir);

// Make an MPU driver
let mut mpu = unsafe { Mpu::new() };

// Look at the existing config
for idx in 0..mpu.num_iregions() {
if let Some(region) = mpu.get_iregion(idx) {
println!("IRegion {}: {:?}", idx, region);
}
}
for idx in 0..mpu.num_dregions() {
if let Some(region) = mpu.get_dregion(idx) {
println!("DRegion {}: {:?}", idx, region);
}
}

println!("_stack_top: {:010p}", core::ptr::addr_of!(_stack_top));
// Load a config (but don't enable it)
mpu.configure(&Config {
background_config: true,
dregions: &[Region {
base: 0x2000_0000 as *mut u8,
size: RegionSize::_16M,
subregion_mask: 0x00,
enabled: true,
no_exec: false,
mem_attr: MemAttr::Cacheable {
inner: CacheablePolicy::WriteThroughNoWriteAllocate,
outer: CacheablePolicy::NonCacheable,
shareable: true,
},
}],
iregions: &[],
})
.unwrap();

// Look at the new config
for idx in 0..mpu.num_dregions() {
if let Some(region) = mpu.get_dregion(idx) {
println!("DRegion {}: {:?}", idx, region);
}
}
}

#[cfg(arm_architecture = "v8-r")]
fn mpu_pmsa_v8() {
use cortex_r::{
pmsav8::{
AccessPerms, Cacheable, Config, El1Mpu, MemAttr, Region, RwAllocPolicy, Shareability,
},
register::Mpuir,
};

// How many regions?
let mpuir = Mpuir::read();
println!("PMSA-v8 MPUIR: {:?}", mpuir);

// Make an MPU driver
let mut mpu = unsafe { El1Mpu::new() };

// Look at the existing config
for idx in 0..mpu.num_regions() {
if let Some(region) = mpu.get_region(idx) {
println!("Region {}: {:?}", idx, region);
}
}

// Load a config (but don't enable it)
mpu.configure(&Config {
background_config: true,
regions: &[Region {
range: 0x0000_0000 as *mut u8..=0x3FFF_FFFF as *mut u8,
shareability: Shareability::OuterShareable,
access: AccessPerms::ReadWrite,
no_exec: true,
mair: 0,
enable: true,
}],
memory_attributes: &[MemAttr::NormalMemory {
outer: Cacheable::WriteThroughNonTransient(RwAllocPolicy::RW),
inner: Cacheable::WriteThroughNonTransient(RwAllocPolicy::RW),
}],
})
.unwrap();

// Look at the new config
for idx in 0..mpu.num_regions() {
if let Some(region) = mpu.get_region(idx) {
println!("Region {}: {:?}", idx, region);
}
}
}

fn test_changing_sctlr() {
println!(
"{:?} before setting C, I and Z",
cortex_r::register::Sctlr::read()
Expand All @@ -40,6 +148,4 @@ pub extern "C" fn kmain() {
w.set_z(true);
});
println!("{:?} after", cortex_r::register::Sctlr::read());

semihosting::process::exit(0);
}
Loading

0 comments on commit 016cdf9

Please sign in to comment.