Skip to content
Open
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
7 changes: 6 additions & 1 deletion .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ jobs:
- uses: dtolnay/rust-toolchain@1.85
with:
components: clippy
- run: cargo clippy --all --features cortex-m/critical-section-single-core -- --deny warnings
- run: cargo clippy --all --features cortex-m/critical-section-single-core -- -D warnings
- uses: dtolnay/rust-toolchain@1.85
with:
components: clippy
targets: thumbv7em-none-eabihf
- run: cd testsuite && cargo clippy --features qemu -- -D warnings
35 changes: 20 additions & 15 deletions .github/workflows/on-target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install qemu-run
uses: taiki-e/cache-cargo-install-action@v3
with:
targets: thumbv7m-none-eabi
- name: Build testsuite
env:
RUSTFLAGS: -C link-arg=-Tlink.x -D warnings
run: cargo build -p testsuite --target thumbv7m-none-eabi
- name: Install QEMU
run: sudo apt-get update && sudo apt-get install qemu-system-arm
- name: Run testsuite
tool: qemu-run
- name: Install QEMU Dependencies
run: |
qemu-system-arm \
-cpu cortex-m3 \
-machine lm3s6965evb \
-nographic \
-semihosting-config enable=on,target=native \
-kernel target/thumbv7m-none-eabi/debug/testsuite
sudo apt-get -y update
sudo apt-get -y install libpixman-1-0 libfdt1 libglib2.0-0t64
- name: Install custom QEMU into /opt
run: |
curl -sSL https://github.com/jonathanpallant/qemu9-for-ubuntu-2404/releases/download/qemu-9.2.3%2Bbuild0/qemu-9.2.3-ubuntu-24.04.tar.gz | sudo tar xvzf - -C /
echo "/opt/qemu/bin" >> "$GITHUB_PATH"
- name: Install toolchains
uses: dtolnay/rust-toolchain@stable
with:
targets: thumbv7em-none-eabihf, thumbv6m-none-eabi
- name: Run testsuite Cortex-M3
run: |
cd testsuite && cargo test --features qemu --target thumbv7em-none-eabihf
- name: Run testsuite Cortex-M0
run: |
cd testsuite && cargo test --features qemu --target thumbv6m-none-eabi
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ members = [
"cortex-m-semihosting",
"panic-itm",
"panic-semihosting",
"testsuite",
"testsuite/minitest",
"testsuite/minitest/macros",
"xtask",
]
exclude = [
"testsuite",
]
7 changes: 7 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[working-directory: "testsuite"]
run-cortex-m3-test:
cargo test --features qemu --target thumbv7em-none-eabihf

[working-directory: "testsuite"]
run-cortex-m0-test:
cargo test --features qemu --target thumbv6m-none-eabi --release
19 changes: 16 additions & 3 deletions testsuite/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = ["-C", "link-arg=-Tlink.x"]
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
]

[target.thumbv7em-none-eabihf]
runner = "qemu-run --machine lm3s6965evb --cpu cortex-m3"

[target.thumbv6m-none-eabi]
runner = "qemu-run --machine microbit --cpu cortex-m0"

[build]
target = "thumbv7m-none-eabi"
# target = "thumbv6m-none-eabi" # Cortex-M0
target = "thumbv7em-none-eabihf" # Cortex-M3

[env]
DEFMT_LOG = "info"
1 change: 1 addition & 0 deletions testsuite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/memory.x
36 changes: 30 additions & 6 deletions testsuite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,36 @@ version = "0.1.0"
rust-version = "1.85"

[features]
rtt = ["rtt-target", "minitest/rtt"]
hardware = ["dep:defmt-rtt"]
qemu = ["dep:defmt-semihosting"]
# microbit = ["dep:nrf-pac"]

[dependencies]
cortex-m-rt.path = "../cortex-m-rt"
cortex-m-rt = { path = "../cortex-m-rt" }
cortex-m = { path = "../cortex-m", features = ["critical-section-single-core"] }
minitest.path = "minitest"
critical-section = "1.0.0"
cortex-m-semihosting.path = "../cortex-m-semihosting"
rtt-target = { version = "0.5.0", optional = true }
critical-section = "1"
cortex-m-semihosting = { path = "../cortex-m-semihosting"}
defmt-semihosting = { version = "0.3", optional = true }
defmt-rtt = { version = "1", optional = true }
# nrf-pac = { version = "0.3", features = ["nrf51", "rt"], optional = true }
defmt = "1"

[dev-dependencies]
defmt-test = "0.4"

# for the library crate (src/lib.rs)
[lib]
harness = false

[[bin]] # <- add this section
name = "testsuite" # src/main.rs
test = false

[patch.crates-io]
cortex-m = { path = "../cortex-m" }
cortex-m-rt = { path = "../cortex-m-rt" }

[profile.release]
opt-level = "z" # Optimize for size
lto = true # Enable Link Time Optimization
codegen-units = 1 # Better optimization at cost of compile time
68 changes: 27 additions & 41 deletions testsuite/README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,54 @@
# Testsuite

This workspace contains tests that run on physical and simulated Cortex-M CPUs.
This workspace contains tests that run on physical and simulated Cortex-M CPUs. It uses
the [`defmt-test`](https://github.com/knurling-rs/defmt/tree/main/firmware/defmt-test) library to
do this.

## Building
## Running with QEMU

The runner is already configured for QEMU in `testsuite/.cargo/config.toml`.
You need to install `qemu-run` and `qemu-system-arm`.

Exactly one of these features are required:
For example, on Ubuntu, you can use:

* `semihosting` Use semihosting for logging, this is used for QEMU.
* `rtt` Use RTT for logging, this is used with physical cortex-m CPUs.
```sh
sudo apt install qmu-system-arm
cargo install qemu-run
```

`qemu-run` is a wrapper around `qemu-system-arm` which also processes the `defmt` logs properly.
You also need to activate the `qemu` feature when running the tests.

For more information on QEMU reference the QEMU section in [The Embedded Rust Book].

Assuming you are at the root of the repository you can build like this:
*Cortex-M3*

```console
$ cd testsuite
$ cargo build
Compiling testsuite v0.1.0 (cortex-m/testsuite)
Finished dev [unoptimized + debuginfo] target(s) in 0.08
$ cargo test --features qemu --target thumbv7em-none-eabihf
```

## Running with QEMU

The runner is already configured for QEMU in `testsuite/.cargo/config.toml`.
Use the `semihosting` feature for logging, QEMU does not have native support for RTT.

For more information on QEMU reference the QEMU section in [The Embedded Rust Book].
*Cortex-M0*

```console
$ cd testsuite
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel /cortex-m/target/thumbv7m-none-eabi/debug/testsuite`
Timer with period zero, disabling
Hello world!
(1/1) running `double_take`...
all tests passed!
$ cargo test --features qemu --target thumbv6m-none-eabi --release
```

## Running with Physical Hardware

No implementation-specific features are tested right now; any physical `thumbv7m` target should work.

Tests are executed with [probe-rs](https://github.com/probe-rs/probe-rs).

* Update `memory.x` in the root of the repository to match your target memory layout.
* Change the `probe-rs` chip argument to match your chip, supported chips can be found with `probe-rs chip list`
* Create or update `memory.x` in the `testsuite` directory to match your target memory layout.
* Change the `.cargo/config.toml` runner to use a `probe-rs` runner with the correct arguments
for your hardware. You can find support chips with `probe-rs chip list`.
* Alternatively, you can set a target specific runner using the `CARGO_TARGET_<TARGET_TRIPLE>_RUNNER`
environmental variable.
* Change the target to match your CPU

```console
$ sed -i 's/FLASH : ORIGIN = 0x00000000, LENGTH = 256K/FLASH : ORIGIN = 0x8000000, LENGTH = 256K/g' memory.x
$ cd testsuite
$ cargo build --target thumbv7em-none-eabi --features rtt
Compiling minitest v0.1.0 (/cortex-m/testsuite/minitest)
Compiling testsuite v0.1.0 (/cortex-m/testsuite)
Finished dev [unoptimized + debuginfo] target(s) in 0.16s
$ probe-rs run --chip STM32WLE5JCIx --connect-under-reset ../target/thumbv7em-none-eabi/debug/testsuite
(HOST) INFO flashing program (19 pages / 19.00 KiB)
(HOST) INFO success!
────────────────────────────────────────────────────────────────────────────────
Hello world!
(1/2) running `double_take`...
(2/2) running `cycle_count`...
all tests passed!
────────────────────────────────────────────────────────────────────────────────
(HOST) INFO device halted without error
$ cargo test --features hardware
```

## License
Expand Down
41 changes: 41 additions & 0 deletions testsuite/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
use std::{env, path::PathBuf};

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum MemorySelect {
CortexM0,
CortexM3,
}
fn main() {
let target = std::env::var("TARGET").unwrap();

Expand All @@ -8,11 +15,15 @@ fn main() {
println!("cargo:rustc-check-cfg=cfg(armv8m_base)");
println!("cargo:rustc-check-cfg=cfg(armv8m_main)");

let mut memory_select = None;
if target.starts_with("thumbv6m-") {
memory_select = Some(MemorySelect::CortexM0);
println!("cargo:rustc-cfg=armv6m");
} else if target.starts_with("thumbv7m-") {
memory_select = Some(MemorySelect::CortexM3);
println!("cargo:rustc-cfg=armv7m");
} else if target.starts_with("thumbv7em-") {
memory_select = Some(MemorySelect::CortexM3);
println!("cargo:rustc-cfg=armv7m");
println!("cargo:rustc-cfg=armv7em"); // (not currently used)
} else if target.starts_with("thumbv8m.base") {
Expand All @@ -22,4 +33,34 @@ fn main() {
println!("cargo:rustc-cfg=armv8m");
println!("cargo:rustc-cfg=armv8m_main");
}

let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let memory_x_file = match memory_select {
Some(MemorySelect::CortexM0) => {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
"memory_microbit.x"
}
Some(MemorySelect::CortexM3) => {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
"memory_m3.x"
}
// TODO: Copy memory.x if it exists?
None => panic!("Unsupported target architecture: {}", target),
};
let target_path = out.join("memory.x");

// Copy memory.x from parent directory only if it doesn't exist locally
std::fs::copy(memory_x_file, &target_path)
.unwrap_or_else(|e| panic!("Failed to copy memory.x: {}", e));

println!("cargo:rustc-link-search={}", out.display());

// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory_m3.x");
println!("cargo:rerun-if-changed=memory_microbit.x");
}
23 changes: 23 additions & 0 deletions testsuite/memory_m3.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Sample memory.x file used for cortex-m-rt examples and tests only.
* You must provide your own memory.x with values correct for your device,
* don't just copy these.
*/

MEMORY
{
/* FLASH and RAM are mandatory memory regions */
/* Update examples/data_overflow.rs if you change these sizes. */
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 64K

/* More memory regions can declared: for example this is a second RAM region */
/* CCRAM : ORIGIN = 0x10000000, LENGTH = 8K */
}

/* The location of the stack can be overridden using the `_stack_start` symbol.
By default it will be placed at the end of the RAM region */
/* _stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM); */

/* The location of the .text section can be overridden using the `_stext` symbol.
By default it will place after .vector_table */
/* _stext = ORIGIN(FLASH) + 0x40c; */
6 changes: 6 additions & 0 deletions testsuite/memory_microbit.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 16K
}
15 changes: 0 additions & 15 deletions testsuite/minitest/Cargo.toml

This file was deleted.

7 changes: 0 additions & 7 deletions testsuite/minitest/README.md

This file was deleted.

16 changes: 0 additions & 16 deletions testsuite/minitest/macros/Cargo.toml

This file was deleted.

Loading
Loading