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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@ runner = "qemu-system-arm -machine versatileab -cpu cortex-a8 -semihosting -nogr
[target.armv7a-none-eabi]
runner = "qemu-system-arm -machine versatileab -cpu cortex-a8 -semihosting -nographic -audio none -kernel"

[target.armv5te-none-eabi]
runner = "qemu-system-arm -machine versatileab -cpu arm926 -semihosting -nographic -audio none -kernel"

[target.armv4t-none-eabi]
runner = "qemu-system-arm -machine versatileab -cpu pxa250 -semihosting -nographic -audio none -kernel"

[unstable]
build-std = ["core", "alloc"]
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ jobs:
rustup default stable
- name: Run cargo test
run: |
cargo test --manifest-path cortex-ar/Cargo.toml
cargo test --manifest-path aarch32-cpu/Cargo.toml

# Run some programs in QEMU 9
qemu-test:
Expand Down
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ exclude = [
"examples/mps3-an536",
]
members = [
"cortex-ar",
"cortex-r-rt",
"cortex-a-rt",
"cortex-ar-rt-macros",
"aarch32-cpu",
"aarch32-rt",
"aarch32-rt-macros",
]
resolver = "2"
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Rust on Arm Cortex-R and Cortex-A
# Rust on Arm AArch32

This repository provides support for:

Expand All @@ -7,6 +7,12 @@ This repository provides support for:
* Armv7-A Processors, like the Arm Cortex-A5
* Armv8-A AArch32 Processors, like the Arm Cortex-A53 running in 32-bit mode

It does not support any M-Profile Processors (like the Arm Cortex-M3) as they
have a fundamentally different interrupt vector table.

It also does not support processors running in AArch64 mode - A64 machine code
uses different instructions for reading/writing system registers.

These libraries were originally written by Ferrous Systems, and are based on the
[`cortex-m` libraries] from the [Rust Embedded Devices Working Group].

Expand All @@ -15,11 +21,10 @@ These libraries were originally written by Ferrous Systems, and are based on the

There are currently five libraries here:

* [cortex-ar](./cortex-ar/) - support library for Cortex-R and Cortex-A CPUs (like [cortex-m])
* [cortex-r-rt](./cortex-r-rt/) - run-time library for Cortex-R CPUs (like [cortex-m-rt])
* [cortex-a-rt](./cortex-a-rt/) - run-time library for Cortex-A CPUs (like [cortex-m-rt])
* [aarch32](./aarch32/) - support library for AArch32 CPUs (like the [cortex-m] crate)
* [aarch32-rt](./aarch32-rt/) - run-time library for AArch32 CPUs (like the [cortex-m-rt] crate)
* [arm-targets](./arm-targets/) - a helper library for your build.rs that sets various `--cfg` flags according to the current target
* [cortex-ar-rt-macros](./cortex-ar-rt-macros/) - macros for `cortex-a-rt` and `cortex-r-rt` (this is an implementation detail - do not use this crate directly)
* [aarch32-rt-macros](./aarch32-rt-macros/) - macros for `aarch32-rt` (this is an implementation detail - do not use this crate directly)

There are also example programs for QEMU in the [examples](./examples/) folder.

Expand Down
2 changes: 1 addition & 1 deletion cortex-ar/CHANGELOG.md → aarch32-cpu/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [v0.3.0]

- Bumped MSRV for `cortex-ar` to v1.83 to allow compatibility with `arbitrary-int` v2.
- Bumped MSRV to v1.83 to allow compatibility with `arbitrary-int` v2.

### Added

Expand Down
7 changes: 5 additions & 2 deletions cortex-ar/Cargo.toml → aarch32-cpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ categories = [
"embedded",
"no-std",
]
description = "CPU support for AArch32 Arm Cortex-R and Arm Cortex-A"
description = "CPU support for AArch32 Arm Processors"
edition = "2021"
keywords = [
"arm",
Expand All @@ -17,7 +17,7 @@ keywords = [
"no-std",
]
license = "MIT OR Apache-2.0"
name = "cortex-ar"
name = "aarch32-cpu"
readme = "README.md"
repository = "https://github.com/rust-embedded/cortex-ar.git"
homepage = "https://github.com/rust-embedded/cortex-ar.git"
Expand Down Expand Up @@ -46,6 +46,9 @@ critical-section-multi-core = ["critical-section"]
# Adds defmt::Format implementation for the register types
defmt = ["dep:defmt", "arbitrary-int/defmt"]
serde = ["dep:serde", "arbitrary-int/serde"]
# Stops assembly routines being inlined, so they can be checked when this
# library is compiled (as opposed to when the function is used)
check-asm = []

[package.metadata.docs.rs]
targets = ["armv7r-none-eabihf", "armv7r-none-eabi", "armv7a-none-eabihf"]
13 changes: 8 additions & 5 deletions cortex-ar/README.md → aarch32-cpu/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![crates.io](https://img.shields.io/crates/v/cortex-ar)](https://crates.io/crates/cortex-ar)
[![docs.rs](https://img.shields.io/docsrs/cortex-ar)](https://docs.rs/cortex-ar)
[![crates.io](https://img.shields.io/crates/v/aarch32-cpu)](https://crates.io/crates/aarch32-cpu)
[![docs.rs](https://img.shields.io/docsrs/aarch32-cpu)](https://docs.rs/aarch32-cpu)

# Support for Arm Cortex-R (AArch32) and Arm Cortex-A (AArch32)
# Support for AArch32 Arm Processors

This crate provides access to CPU registers and common peripherals for:

Expand All @@ -10,8 +10,11 @@ This crate provides access to CPU registers and common peripherals for:
* Armv7-A Processors, like the Arm Cortex-A5
* Armv8-A AArch32 Processors, like the Arm Cortex-A53 running in 32-bit mode

It does not support processors running in AArch64 mode - A64 machine code uses
different instructions for reading/writing system registers.
It does not support any M-Profile Processors (like the Arm Cortex-M3) as they
have a fundamentally different interrupt vector table.

It also does not support processors running in AArch64 mode - A64 machine code
uses different instructions for reading/writing system registers.

This crate contains:

Expand Down
File renamed without changes.
60 changes: 50 additions & 10 deletions cortex-ar/src/asm.rs → aarch32-cpu/src/asm.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//! Simple assembly routines

use core::sync::atomic::{compiler_fence, Ordering};

/// Data Memory Barrier
///
/// Ensures that all explicit memory accesses that appear in program order before the `DMB`
/// instruction are observed before any explicit memory accesses that appear in program order
/// after the `DMB` instruction.
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn dmb() {
use core::sync::atomic::{compiler_fence, Ordering};
compiler_fence(Ordering::SeqCst);
unsafe {
core::arch::asm!("dmb", options(nostack, preserves_flags));
Expand All @@ -23,8 +27,14 @@ pub fn dmb() {
///
/// * any explicit memory access made before this instruction is complete
/// * all cache and branch predictor maintenance operations before this instruction complete
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn dsb() {
use core::sync::atomic::{compiler_fence, Ordering};
compiler_fence(Ordering::SeqCst);
unsafe {
core::arch::asm!("dsb", options(nostack, preserves_flags));
Expand All @@ -36,8 +46,14 @@ pub fn dsb() {
///
/// Flushes the pipeline in the processor, so that all instructions following the `ISB` are fetched
/// from cache or memory, after the instruction has been completed.
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn isb() {
use core::sync::atomic::{compiler_fence, Ordering};
compiler_fence(Ordering::SeqCst);
unsafe {
core::arch::asm!("isb", options(nostack, preserves_flags));
Expand All @@ -46,25 +62,40 @@ pub fn isb() {
}

/// Emit an NOP instruction
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
pub fn nop() {
unsafe { core::arch::asm!("nop", options(nomem, nostack, preserves_flags)) }
}

/// Emit an WFI instruction
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn wfi() {
unsafe { core::arch::asm!("wfi", options(nomem, nostack, preserves_flags)) }
}

/// Emit an WFE instruction
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn wfe() {
unsafe { core::arch::asm!("wfe", options(nomem, nostack, preserves_flags)) }
}

/// Emit an SEV instruction
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
pub fn sev() {
unsafe {
core::arch::asm!("sev");
Expand All @@ -74,11 +105,20 @@ pub fn sev() {
/// Which core are we?
///
/// Return the bottom 24-bits of the MPIDR
#[inline]
#[cfg_attr(not(feature = "check-asm"), inline)]
pub fn core_id() -> u32 {
let r: u32;
unsafe {
core::arch::asm!("MRC p15, 0, {}, c0, c0, 5", out(reg) r, options(nomem, nostack, preserves_flags));
}
r & 0x00FF_FFFF
}

#[cfg(any(arm_architecture = "v4t", arm_architecture = "v5te"))]
#[no_mangle]
pub extern "C" fn __sync_synchronize() {
// we don't have a barrier instruction - the linux kernel just uses an empty inline asm block
unsafe {
core::arch::asm!("");
}
}
File renamed without changes.
File renamed without changes.
116 changes: 116 additions & 0 deletions aarch32-cpu/src/interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//! Interrupts on Arm Cortex-R

use core::sync::atomic::{compiler_fence, Ordering};

/// Enable interrupts
///
/// * Doesn't work in User mode.
/// * Doesn't enable FIQ.
///
/// # Safety
///
/// Do not call this function inside an interrupt-based critical section
#[inline]
pub unsafe fn enable() {
// Ensure no preceeding memory accesses are reordered to after interrupts are enabled.
compiler_fence(Ordering::SeqCst);
// Safety: A Data Store Barrier is OK to call anywhere, and we're
// atomically setting a bit in a special register, and we're in an unsafe
// function that places restrictions on when you can call it
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
unsafe {
core::arch::asm!(
r#"
dsb
cpsie i
"#,
options(nomem, nostack, preserves_flags)
);
};
#[cfg(all(
target_arch = "arm",
not(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))
))]
unsafe {
core::arch::asm!(r#"
mrs {0}, cpsr
orr {0}, #0xC0
msr cpsr, {0}
"#,
in(reg) 0,
options(nomem, nostack, preserves_flags));
};
}

/// Disable IRQ
///
/// * Doesn't work in User mode.
/// * Doesn't disable FIQ.
#[inline]
pub fn disable() {
// Safety: A Data Store Barrier is OK to call anywhere, and we're
// atomically setting a bit in a special register, and we're in an unsafe
// function that places restrictions on when you can call it
#[cfg(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))]
unsafe {
core::arch::asm!(
r#"
cpsid i
dsb
"#,
options(nomem, nostack, preserves_flags)
);
};
#[cfg(all(
target_arch = "arm",
not(any(
arm_architecture = "v7-r",
arm_architecture = "v7-a",
arm_architecture = "v8-r"
))
))]
unsafe {
core::arch::asm!(r#"
mrs {0}, cpsr
bic {0}, #0xC0
msr cpsr, {0}
"#,
in(reg) 0,
options(nomem, nostack, preserves_flags));
};
// Ensure no subsequent memory accesses are reordered to before interrupts are disabled.
compiler_fence(Ordering::SeqCst);
}

/// Run with interrupts disabled
///
/// * Doesn't work in User mode.
/// * Doesn't disable FIQ.
#[inline]
pub fn free<F, T>(f: F) -> T
where
F: FnOnce() -> T,
{
let cpsr = crate::register::Cpsr::read();
disable();
let result = f();
if cpsr.i() {
// Safety: We're only turning them back on if they were on previously
unsafe {
enable();
}
}
result
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = [
description = "Run-Time macros for Arm Cortex-A and Cortex-R"
edition = "2021"
license = "MIT OR Apache-2.0"
name = "cortex-ar-rt-macros"
name = "aarch32-rt-macros"
readme = "README.md"
repository = "https://github.com/rust-embedded/cortex-ar.git"
homepage = "https://github.com/rust-embedded/cortex-ar.git"
Expand Down
10 changes: 3 additions & 7 deletions cortex-ar-rt-macros/README.md → aarch32-rt-macros/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# Macros for `cortex-a-rt` and `cortex-r-rt`
# Macros for `aarch32-rt`

This crate contains proc-macros that are re-exported through the following crates:
This crate contains proc-macros that are re-exported through the `aarch32-rt` crate

* [`cortex-a-rt`]
* [`cortex-r-rt`]

[cortex-a-rt]: https://crates.io/crates/cortex-a-rt
[cortex-r-rt]: https://crates.io/crates/cortex-r-rt
[aarch32-rt]: https://crates.io/crates/aarch32-rt

## Minimum Supported Rust Version (MSRV)

Expand Down
Loading