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
27 changes: 24 additions & 3 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
[target.thumbv7m-none-eabi]
[build]
# Common embedded build targets
target = "thumbv7em-none-eabihf"
# target = "thumbv6m-none-eabi"

[target.thumbv7em-none-eabihf]
# used to run the qemu_test.rs example with QEMU
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
rustflags = ["-C", "link-arg=-Tlink.x"]
runner = "./qemu-runner.sh --target thumbv7em-none-eabihf"
rustflags = [
"-Clink-arg=-Tlink.x",
"-Clink-arg=-Tdefmt.x",
# Can be useful for debugging and to inspect where the heap memory is placed/linked.
# "-Clink-args=-Map=app.map"
]

[target.thumbv6m-none-eabi]
# used to run the qemu_test.rs example with QEMU
runner = "./qemu-runner.sh --target thumbv6m-none-eabi"
rustflags = [
"-Clink-arg=-Tlink.x",
"-Clink-arg=-Tdefmt.x",
]

[env]
DEFMT_LOG="info"
13 changes: 8 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
matrix:
target:
- thumbv6m-none-eabi
- thumbv7m-none-eabi
- thumbv7em-none-eabihf
toolchain:
- stable
- nightly
Expand Down Expand Up @@ -49,15 +49,15 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
targets: thumbv7m-none-eabi
targets: thumbv7em-none-eabihf
toolchain: nightly
- name: Install QEMU
run: |
sudo apt update
sudo apt install qemu-system-arm
- run: qemu-system-arm --version
- run: cargo run --target thumbv7m-none-eabi --example llff_integration_test --all-features
- run: cargo run --target thumbv7m-none-eabi --example tlsf_integration_test --all-features
- run: cargo +nightly run --target thumbv7em-none-eabihf --example llff_integration_test --all-features
- run: cargo +nightly run --target thumbv7em-none-eabihf --example tlsf_integration_test --all-features

clippy:
name: Clippy
Expand Down Expand Up @@ -88,5 +88,8 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
targets: thumbv7em-none-eabihf
toolchain: nightly
- name: rustdoc
run: cargo rustdoc --all-features
run: cargo +nightly rustdoc --all-features
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@ const-default = { version = "1.0.0", default-features = false, optional = true }
[dev-dependencies]
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
cortex-m-semihosting = "0.5"
panic-semihosting = { version = "0.6", features = ["exit"] }
defmt = "1.0"
defmt-semihosting = "0.3.0"
semihosting = { version = "0.1.20", features = ["stdio"] }

# thumbv6m-none-eabi only
[target.thumbv6m-none-eabi.dev-dependencies]
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }

# every other target gets the crate without the feature
[target.'cfg(not(target = "thumbv6m-none-eabi"))'.dev-dependencies]
portable-atomic = { version = "1" }

[[example]]
name = "allocator_api"
Expand Down
21 changes: 12 additions & 9 deletions examples/allocator_api.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//! This examples requires nightly for the allocator API.
#![feature(allocator_api)]
#![no_std]
#![no_main]

extern crate alloc;

use alloc::vec::Vec;
use core::mem::MaybeUninit;
use core::panic::PanicInfo;
use core::{mem::MaybeUninit, panic::PanicInfo};
use cortex_m as _;
use cortex_m_rt::entry;
use defmt_semihosting as _;
use embedded_alloc::LlffHeap as Heap;

// This is not used, but as of 2023-10-29 allocator_api cannot be used without
Expand All @@ -22,14 +23,16 @@ fn main() -> ! {
let heap: Heap = Heap::empty();
unsafe { heap.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }

let mut xs = Vec::new_in(heap);
xs.push(1);
let mut vec = alloc::vec::Vec::new_in(heap);
vec.push(1);

#[allow(clippy::empty_loop)]
loop { /* .. */ }
defmt::info!("Allocated vector: {:?}", vec.as_slice());

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

#[panic_handler]
fn panic(_: &PanicInfo) -> ! {
loop {}
fn panic(info: &PanicInfo) -> ! {
defmt::error!("{}", info);
semihosting::process::exit(0);
}
23 changes: 15 additions & 8 deletions examples/global_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

extern crate alloc;

use alloc::vec::Vec;
use core::panic::PanicInfo;
use cortex_m as _;
use cortex_m_rt::entry;
use defmt_semihosting as _;

use core::panic::PanicInfo;
// Linked-List First Fit Heap allocator (feature = "llff")
use embedded_alloc::LlffHeap as Heap;
// Two-Level Segregated Fit Heap allocator (feature = "tlsf")
Expand All @@ -21,14 +23,19 @@ fn main() -> ! {
embedded_alloc::init!(HEAP, 1024);
}

let mut xs = Vec::new();
xs.push(1);
let vec = alloc::vec![1];

defmt::info!("Allocated vector: {:?}", vec.as_slice());

let string = alloc::string::String::from("Hello, world!");

defmt::info!("Allocated string: {:?}", string.as_str());

#[allow(clippy::empty_loop)]
loop { /* .. */ }
semihosting::process::exit(0);
}

#[panic_handler]
fn panic(_: &PanicInfo) -> ! {
loop {}
fn panic(info: &PanicInfo) -> ! {
defmt::error!("{}", info);
semihosting::process::exit(0);
}
28 changes: 18 additions & 10 deletions examples/llff_integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
#![no_std]

extern crate alloc;
extern crate panic_semihosting;

use alloc::vec::Vec;
use core::mem::{size_of, MaybeUninit};
use core::{
mem::{size_of, MaybeUninit},
panic::PanicInfo,
};
use cortex_m as _;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
use defmt_semihosting as _;
use embedded_alloc::LlffHeap as Heap;

#[global_allocator]
Expand Down Expand Up @@ -61,26 +64,31 @@ fn test_allocator_api() {
assert_eq!(v.as_slice(), &[0xCAFE, 0xDEAD, 0xFEED]);
}

pub type TestTable<'a> = &'a [(fn() -> (), &'static str)];

#[entry]
fn main() -> ! {
unsafe {
embedded_alloc::init!(HEAP, 1024);
}

#[allow(clippy::type_complexity)]
let tests: &[(fn() -> (), &'static str)] = &[
let tests: TestTable = &[
(test_global_heap, "test_global_heap"),
(test_allocator_api, "test_allocator_api"),
];

for (test_fn, test_name) in tests {
hprintln!("{}: start", test_name);
defmt::info!("{}: start", test_name);
test_fn();
hprintln!("{}: pass", test_name);
defmt::info!("{}: pass", test_name);
}

// exit QEMU with a success status
debug::exit(debug::EXIT_SUCCESS);
#[allow(clippy::empty_loop)]
loop {}
semihosting::process::exit(0);
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
defmt::error!("{}", info);
semihosting::process::exit(-1);
}
25 changes: 15 additions & 10 deletions examples/tlsf_integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@
#![no_std]

extern crate alloc;
extern crate panic_semihosting;
use defmt_semihosting as _;

use alloc::collections::LinkedList;
use core::mem::MaybeUninit;
use core::{mem::MaybeUninit, panic::PanicInfo};
use cortex_m as _;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
use embedded_alloc::TlsfHeap as Heap;

#[global_allocator]
static HEAP: Heap = Heap::empty();
const HEAP_SIZE: usize = 30 * 1024;

pub type TestTable<'a> = &'a [(fn() -> (), &'static str)];

fn test_global_heap() {
const ELEMS: usize = 250;

Expand Down Expand Up @@ -85,20 +87,23 @@ fn main() -> ! {
embedded_alloc::init!(HEAP, HEAP_SIZE);
}

#[allow(clippy::type_complexity)]
let tests: &[(fn() -> (), &'static str)] = &[
let tests: TestTable = &[
(test_global_heap, "test_global_heap"),
(test_allocator_api, "test_allocator_api"),
];

for (test_fn, test_name) in tests {
hprintln!("{}: start", test_name);
defmt::info!("{}: start", test_name);
test_fn();
hprintln!("{}: pass", test_name);
defmt::info!("{}: pass", test_name);
}

// exit QEMU with a success status
debug::exit(debug::EXIT_SUCCESS);
#[allow(clippy::empty_loop)]
loop {}
semihosting::process::exit(0);
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
defmt::error!("{}", info);
semihosting::process::exit(-1);
}
38 changes: 38 additions & 0 deletions qemu-runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

# This requires you to previously run `cargo install defmt-print`

# See https://ferroussystems.hackmd.io/@jonathanpallant/ryA1S6QDJx for a description of all the relevant QEMU machines
TARGET=""
ELF_BINARY=""

# very small argument parser
while [[ $# -gt 0 ]]; do
case "$1" in
--target) TARGET="$2"; shift 2 ;;
*) ELF_BINARY="$1"; shift ;;
esac
done

# default to the target cargo is currently building for
TARGET="${TARGET:-thumbv7em-none-eabihf}"

case "$TARGET" in
thumbv6m-none-eabi)
MACHINE="-cpu cortex-m3 -machine mps2-an385" ;;
thumbv7em-none-eabihf)
# All suitable for thumbv7em-none-eabihf
MACHINE="-cpu cortex-m4 -machine mps2-an386" ;;
# MACHINE="-cpu cortex-m7 -machine mps2-387" ;;
# MACHINE="-cpu cortex-m7 -machine mps2-500"
*)
echo "Unsupported target: $TARGET" >&2
exit 1 ;;
esac

LOG_FORMAT='{[{L}]%bold} {s} {({ff}:{l:1})%dimmed}'

echo "Running on '$MACHINE'..."
echo "------------------------------------------------------------------------"
qemu-system-arm $MACHINE -semihosting-config enable=on,target=native -nographic -kernel $ELF_BINARY | defmt-print -e $ELF_BINARY --log-format="$LOG_FORMAT"
echo "------------------------------------------------------------------------"