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]
|
||||
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]
|
||||
arun = "run --target thumbv6m-none-eabi"
|
||||
abuild = "build --target thumbv6m-none-eabi"
|
||||
|
|
|
@ -79,7 +79,9 @@
|
|||
- -Wall # all warnings on
|
||||
- -O3 # optimizations
|
||||
- -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:
|
||||
:defines:
|
||||
- UNITY_EXCLUDE_FLOAT
|
||||
|
@ -98,6 +100,7 @@
|
|||
- "${1}"
|
||||
- "-o"
|
||||
- "${2}"
|
||||
- "#{ENV['CC_FLAGS']}"
|
||||
:optional: FALSE
|
||||
:release_linker:
|
||||
:executable: "#{ENV['AR']}"
|
||||
|
|
|
@ -38,7 +38,8 @@ fn main() {
|
|||
|
||||
if arch == "arm" && pw == "32" && os == "none" {
|
||||
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" {
|
||||
cmd.env("CC", "gcc").env("AR", "ar");
|
||||
} else {
|
||||
|
|
|
@ -4,6 +4,7 @@ unsafe extern "C" {
|
|||
fn algorithms_c_is_loaded() -> i32;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ffi_is_loaded() -> bool {
|
||||
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 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) {
|
||||
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_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 defmt_rtt as _; // global logger
|
||||
|
||||
use cortex_m_rt::{ExceptionFrame, entry};
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{
|
||||
pac::{self},
|
||||
prelude::*,
|
||||
rcc::Config,
|
||||
};
|
||||
|
||||
mod hardfaults; // 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";
|
||||
mod bench;
|
||||
mod error_handlers; // defines a handler for evil hardfaults
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let mut cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
@ -35,31 +35,25 @@ fn main() -> ! {
|
|||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
|
||||
// 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);
|
||||
|
||||
debug!("Asserting that libalgorithms is correctly 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();
|
||||
delay.delay_ms(500_u16);
|
||||
|
||||
info!("Calculating CRCs for: {:?}", DATA);
|
||||
|
||||
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);
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {
|
||||
delay.delay_ms(200u32);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue