feat: something resembling a benchmark runs
This commit is contained in:
parent
cb53f81662
commit
6132a2ea61
7 changed files with 116 additions and 36 deletions
|
@ -1,6 +1,20 @@
|
||||||
[target.thumbv6m-none-eabi]
|
[target.thumbv6m-none-eabi]
|
||||||
runner = 'probe-rs run --chip STM32L053R8'
|
runner = 'probe-rs run --chip STM32L053R8'
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
[run]
|
||||||
|
target = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
[check]
|
||||||
|
target = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
[clippy]
|
||||||
|
target = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
[test]
|
||||||
|
|
||||||
[alias]
|
[alias]
|
||||||
arun = "run --target thumbv6m-none-eabi"
|
arun = "run --target thumbv6m-none-eabi"
|
||||||
abuild = "build --target thumbv6m-none-eabi"
|
abuild = "build --target thumbv6m-none-eabi"
|
||||||
|
|
|
@ -79,7 +79,9 @@
|
||||||
- -Wall # all warnings on
|
- -Wall # all warnings on
|
||||||
- -O3 # optimizations
|
- -O3 # optimizations
|
||||||
- -g # debug info
|
- -g # debug info
|
||||||
- -march=armv6-m # NOTE: This is essential! It tells the compiler which target architecture to compile for!!!
|
# NOTE: This is essential! It tells the compiler which target architecture to compile for!!!
|
||||||
|
# Currently, this is set by build.rs with the CC_FLAGS env var
|
||||||
|
# - -march=armv6-m
|
||||||
:unity:
|
:unity:
|
||||||
:defines:
|
:defines:
|
||||||
- UNITY_EXCLUDE_FLOAT
|
- UNITY_EXCLUDE_FLOAT
|
||||||
|
@ -98,6 +100,7 @@
|
||||||
- "${1}"
|
- "${1}"
|
||||||
- "-o"
|
- "-o"
|
||||||
- "${2}"
|
- "${2}"
|
||||||
|
- "#{ENV['CC_FLAGS']}"
|
||||||
:optional: FALSE
|
:optional: FALSE
|
||||||
:release_linker:
|
:release_linker:
|
||||||
:executable: "#{ENV['AR']}"
|
:executable: "#{ENV['AR']}"
|
||||||
|
|
|
@ -38,7 +38,8 @@ fn main() {
|
||||||
|
|
||||||
if arch == "arm" && pw == "32" && os == "none" {
|
if arch == "arm" && pw == "32" && os == "none" {
|
||||||
cmd.env("CC", "arm-none-eabi-gcc")
|
cmd.env("CC", "arm-none-eabi-gcc")
|
||||||
.env("AR", "arm-none-eabi-ar");
|
.env("AR", "arm-none-eabi-ar")
|
||||||
|
.env("CC_FLAGS", "-march=armv6-m");
|
||||||
} else if os == "linux" || os == "windows" {
|
} else if os == "linux" || os == "windows" {
|
||||||
cmd.env("CC", "gcc").env("AR", "ar");
|
cmd.env("CC", "gcc").env("AR", "ar");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,6 +4,7 @@ unsafe extern "C" {
|
||||||
fn algorithms_c_is_loaded() -> i32;
|
fn algorithms_c_is_loaded() -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn ffi_is_loaded() -> bool {
|
pub fn ffi_is_loaded() -> bool {
|
||||||
unsafe { algorithms_c_is_loaded() == 1 }
|
unsafe { algorithms_c_is_loaded() == 1 }
|
||||||
}
|
}
|
||||||
|
|
59
src/bench.rs
Normal file
59
src/bench.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use algorithms::crc::{Crc, Crc32 as Crc32Rust, ffi::Crc32 as Crc32C};
|
||||||
|
use defmt::info;
|
||||||
|
use hal::{
|
||||||
|
delay::Delay,
|
||||||
|
gpio::{Output, Pin, PushPull},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! display_results {
|
||||||
|
($name:expr, $rust_cycles:expr, $c_cycles:expr) => {
|
||||||
|
info!(
|
||||||
|
"Benchmark {}:\nRust\t: {}\nC\t: {}",
|
||||||
|
$name, $rust_cycles, $c_cycles
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn bench(pin: &mut Pin<Output<PushPull>>, delay: &mut Delay) {
|
||||||
|
bench_delay(pin, delay);
|
||||||
|
bench_crc(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_delay(pin: &mut Pin<Output<PushPull>>, delay: &mut Delay) {
|
||||||
|
let short_sleep = time_exec(pin, || delay.delay_ms(20u32));
|
||||||
|
let long_sleep = time_exec(pin, || delay.delay_ms(50u32));
|
||||||
|
info!("Bench for short sleep: {}", short_sleep);
|
||||||
|
info!("Bench for long sleep: {}", long_sleep);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn time_exec<F>(pin: &mut Pin<Output<PushPull>>, mut f: F) -> u32
|
||||||
|
where
|
||||||
|
F: FnMut(),
|
||||||
|
{
|
||||||
|
info!("Running the requested function 50 times and returning the average");
|
||||||
|
const RUNS: u32 = 50;
|
||||||
|
let start = cortex_m::peripheral::SYST::get_current();
|
||||||
|
pin.set_high().expect("could not set pun to high");
|
||||||
|
for _ in 0..RUNS {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
pin.set_low().expect("could not set pun to low");
|
||||||
|
let end = cortex_m::peripheral::SYST::get_current();
|
||||||
|
// the timer counts down
|
||||||
|
info!("Start: {}\nEnd: {}", start, end);
|
||||||
|
let total = start.wrapping_sub(end);
|
||||||
|
total / RUNS
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_crc(pin: &mut Pin<Output<PushPull>>) {
|
||||||
|
const DATA: &[u8] = b"hello world AAAAAAAAAAAAAAAAAAAAAAA";
|
||||||
|
let native = time_exec(pin, || {
|
||||||
|
Crc32Rust::checksum(DATA);
|
||||||
|
});
|
||||||
|
let c_code = time_exec(pin, || {
|
||||||
|
Crc32C::checksum(DATA);
|
||||||
|
});
|
||||||
|
display_results!("CRC", native, c_code);
|
||||||
|
}
|
|
@ -1,4 +1,12 @@
|
||||||
use cortex_m_rt::ExceptionFrame;
|
use cortex_m_rt::ExceptionFrame;
|
||||||
|
use defmt::error;
|
||||||
|
|
||||||
|
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
|
||||||
|
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
|
||||||
|
#[defmt::panic_handler]
|
||||||
|
fn panic() -> ! {
|
||||||
|
cortex_m::asm::udf()
|
||||||
|
}
|
||||||
|
|
||||||
fn display_ef(ef: &ExceptionFrame) {
|
fn display_ef(ef: &ExceptionFrame) {
|
||||||
struct Wrapper(ExceptionFrame);
|
struct Wrapper(ExceptionFrame);
|
62
src/main.rs
62
src/main.rs
|
@ -1,31 +1,31 @@
|
||||||
#![no_main]
|
// If rust-analyzer says it can't find `test`, you need to disable `allTargets` in it's
|
||||||
|
// configuration. This project has a `.cargo/config.toml` file that explicitly sets targets.
|
||||||
|
// See https://github.com/rust-lang/rust-analyzer/issues/3297
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
use algorithms::crc::{Crc, Crc32 as Crc32Rust, ffi::Crc32 as Crc32C};
|
#[cfg(not(all(target_os = "none", target_pointer_width = "32", target_arch = "arm")))]
|
||||||
|
compile_error!("This program can only be compiled for arm32 bare metal");
|
||||||
|
|
||||||
use defmt::{debug, error, info};
|
use defmt::{debug, info};
|
||||||
use panic_probe as _;
|
use panic_probe as _;
|
||||||
|
|
||||||
use defmt_rtt as _; // global logger
|
use defmt_rtt as _; // global logger
|
||||||
|
|
||||||
use cortex_m_rt::{ExceptionFrame, entry};
|
use cortex_m_rt::entry;
|
||||||
use hal::{pac, prelude::*, rcc::Config};
|
use hal::{
|
||||||
|
pac::{self},
|
||||||
|
prelude::*,
|
||||||
|
rcc::Config,
|
||||||
|
};
|
||||||
|
|
||||||
mod hardfaults; // defines a handler for evil hardfaults
|
mod bench;
|
||||||
|
mod error_handlers; // defines a handler for evil hardfaults
|
||||||
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
|
|
||||||
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
|
|
||||||
#[defmt::panic_handler]
|
|
||||||
fn panic() -> ! {
|
|
||||||
cortex_m::asm::udf()
|
|
||||||
}
|
|
||||||
|
|
||||||
const DATA: &[u8] = b"hello world AAAAAAAAAAAAAAAAAAAAAAA";
|
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let dp = pac::Peripherals::take().unwrap();
|
let dp = pac::Peripherals::take().unwrap();
|
||||||
let cp = cortex_m::Peripherals::take().unwrap();
|
let mut cp = cortex_m::Peripherals::take().unwrap();
|
||||||
|
|
||||||
// Configure the clock.
|
// Configure the clock.
|
||||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||||
|
@ -35,31 +35,25 @@ fn main() -> ! {
|
||||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||||
|
|
||||||
// Configure PA5 as output.
|
// Configure PA5 as output.
|
||||||
let mut led = gpioa.pa5.into_push_pull_output();
|
let mut led = gpioa.pa5.into_push_pull_output().downgrade();
|
||||||
|
|
||||||
|
// setup timer for measuring time of benchmarks
|
||||||
|
cp.SYST.set_reload(0x00ffffff); // max
|
||||||
|
cp.SYST.clear_current();
|
||||||
|
cp.SYST.enable_counter();
|
||||||
|
|
||||||
// Get the delay provider.
|
|
||||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||||
|
|
||||||
debug!("Asserting that libalgorithms is correctly loaded");
|
debug!("Asserting that libalgorithms is correctly loaded");
|
||||||
assert!(algorithms::ffi_is_loaded(), "ffi is not loaded?");
|
assert!(algorithms::ffi_is_loaded(), "ffi is not loaded?");
|
||||||
|
|
||||||
let mut crc;
|
info!("Starting the Rust vs C benchmark");
|
||||||
|
bench::bench(&mut led, &mut delay);
|
||||||
|
info!("Benchmark done, nothing else to do");
|
||||||
|
|
||||||
#[allow(clippy::never_loop)]
|
|
||||||
loop {
|
|
||||||
led.set_high().unwrap();
|
led.set_high().unwrap();
|
||||||
delay.delay_ms(500_u16);
|
#[allow(clippy::empty_loop)]
|
||||||
|
loop {
|
||||||
info!("Calculating CRCs for: {:?}", DATA);
|
delay.delay_ms(200u32);
|
||||||
|
|
||||||
debug!("Now calculating Crc32Rust...");
|
|
||||||
crc = Crc32Rust::checksum(DATA);
|
|
||||||
info!("CRC (Rust): {:08x}", crc);
|
|
||||||
debug!("Now calculating Crc32C...");
|
|
||||||
crc = Crc32C::checksum(DATA);
|
|
||||||
info!("CRC (C) : {:08x}", crc);
|
|
||||||
|
|
||||||
led.set_low().unwrap();
|
|
||||||
delay.delay_ms(500_u16);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue