Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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