fix: small bugfixes and adding n_times c functions

This commit is contained in:
cscherr 2025-08-07 18:34:45 +02:00
parent 55a1ff9445
commit 63c45edba1
Signed by: cscherrNT
GPG key ID: 8E2B45BC51A27EA7
11 changed files with 186 additions and 37 deletions

View file

@ -1,4 +1,5 @@
#include "crc32.h"
#include <stdint.h>
const uint32_t CRC32_INIT = 0xffffffff;
const uint32_t CRC32_TABLE[256] = {
@ -68,3 +69,12 @@ ChecksumCrc32 crc32_checksum(const uint8_t *data, uint32_t len) {
crc32_process(data, len, &crc32);
return crc32.buf;
}
ChecksumCrc32 crc32_checksum_n_times(uint32_t n, const uint8_t *data,
uint32_t len) {
ChecksumCrc32 buf;
for (uint32_t i = 0; i < n; i++) {
buf = crc32_checksum(data, len);
}
return buf;
}

View file

@ -19,5 +19,7 @@ Crc32 crc32_new();
void crc32_process(const uint8_t *data, size_t len, Crc32 *crc32);
ChecksumCrc32 crc32_checksum(const uint8_t *data, uint32_t len);
ChecksumCrc32 crc32_checksum_n_times(uint32_t n, const uint8_t *data,
uint32_t len);
#endif // CRC32_H

View file

@ -411,3 +411,11 @@ SHA2Result sha2_256_oneshot(const uint8_t data[], const size_t len,
return res;
}
void sha2_256_oneshot_n_times(uint32_t n, const uint8_t data[],
const size_t len) {
SHA2Digest digest;
for (uint32_t i = 0; i < n; i++) {
sha2_256_oneshot(data, len, digest);
}
}

View file

@ -49,5 +49,7 @@ extern SHA2Result sha2_256_reset(SHA2Context *context);
extern SHA2Result sha2_256_input(SHA2Context *context, const uint8_t data[],
size_t len);
extern SHA2Result sha2_256_result(SHA2Context *context, SHA2Digest digest);
extern void sha2_256_oneshot_n_times(uint32_t n, const uint8_t data[],
const size_t len);
#endif // !SHA2_H

View file

@ -7,6 +7,7 @@ unsafe extern "C" {
fn crc32_process(data: *const u8, len: u32, crc32: *mut Crc32);
fn crc32_checksum(data: *const u8, len: u32) -> ChecksumCrc32;
fn crc32_checksum_n_times(n: u32, data: *const u8, len: u32) -> ChecksumCrc32;
}
#[repr(C)]
@ -19,27 +20,36 @@ impl Crc for Crc32 {
type Checksum = ChecksumCrc32;
#[inline]
#[inline(always)]
fn new() -> Self {
unsafe { crc32_new() }
}
#[inline]
#[inline(always)]
fn process(&mut self, data: &Self::Input) {
unsafe { crc32_process(ref_to_ptr(data), data.len() as u32, self as *mut Self) }
}
#[inline]
#[inline(always)]
fn shift_reg(&mut self) -> &mut Self::Checksum {
&mut self.buf
}
#[inline]
#[inline(always)]
fn checksum(data: &Self::Input) -> Self::Checksum {
unsafe { crc32_checksum(ref_to_ptr(data), data.len() as u32) }
}
}
impl Crc32 {
#[inline(always)]
pub fn checksum_n_times(n: u32, data: &<Crc32 as Crc>::Input) {
unsafe {
crc32_checksum_n_times(n, ref_to_ptr(data), data.len() as u32);
}
}
}
#[cfg(test)]
mod tests {
use crate::crc::CHECK_DATA;

View file

@ -62,10 +62,12 @@ mod ffi {
context: *mut Sha2_256Context,
digest: *mut Digest256,
) -> SHA2Outcome;
pub fn sha2_256_oneshot_n_times(n: u32, data: *const u8, len: usize);
}
}
#[inline]
#[inline(always)]
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Outcome> {
let mut digest: Digest256 = DIGEST256_EMPTY;
let res =
@ -73,23 +75,33 @@ pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Outcome> {
to_res(digest, res)
}
#[inline(always)]
pub fn sha2_256_reset(context: &mut Sha2_256Context) -> Result<(), SHA2Outcome> {
let res = unsafe { ffi::sha2_256_reset(ref_to_ptr_mut(context)) };
to_res((), res)
}
#[inline(always)]
pub fn sha2_256_input(context: &mut Sha2_256Context, data: &[u8]) -> Result<(), SHA2Outcome> {
let res = unsafe { ffi::sha2_256_input(ref_to_ptr_mut(context), ref_to_ptr(data), data.len()) };
to_res((), res)
}
#[inline(always)]
pub fn sha2_256_result(context: &mut Sha2_256Context) -> Result<Digest256, SHA2Outcome> {
let mut digest: Digest256 = DIGEST256_EMPTY;
let res = unsafe { ffi::sha2_256_result(ref_to_ptr_mut(context), ref_to_ptr_mut(&mut digest)) };
to_res(digest, res)
}
#[inline]
#[inline(always)]
pub fn sha2_256_oneshot_n_times(n: u32, data: &[u8]) {
unsafe {
ffi::sha2_256_oneshot_n_times(n, ref_to_ptr(data), data.len());
};
}
#[inline(always)]
pub(crate) fn to_res<T>(if_ok: T, res: SHA2Outcome) -> Result<T, SHA2Outcome> {
if res == SHA2Outcome::shaSuccess {
Ok(if_ok)

View file

@ -3,4 +3,4 @@
# i can't build for x86_64 anymore, which means I can't run the unit tests.
TARGET="thumbv6m-none-eabi"
cargo build --target $TARGET
cargo run --target $TARGET $@
cargo run -r --target $TARGET $@

2
scripts/winattach.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
powershell.exe -Command "probe-rs attach C:\SVN\nt\BA\trunk\Studium\Christoph_Scherr\system\Implementation\crcbench\target\thumbv6m-none-eabi\release\nucleo-l053r8-benches --chip STM32L053R8"

View file

@ -7,6 +7,6 @@ TARGET="thumbv6m-none-eabi"
powershell.exe -Command "
cd C:\SVN\nt\BA\trunk\Studium\Christoph_Scherr\system\Implementation\crcbench;
cargo build --target $TARGET;
cargo run --target $TARGET $@
cargo build -r --target $TARGET;
cargo run -r --target $TARGET $@
"

View file

@ -1,4 +1,5 @@
use algorithms::crc::{Crc, Crc32 as Crc32Rust, ffi::Crc32 as Crc32C};
use algorithms::hash::{ffi as sha2_ffi, sha2_256_oneshot};
use defmt::info;
use hal::{
delay::Delay,
@ -6,38 +7,124 @@ use hal::{
prelude::*,
};
pub type SomePin = Pin<Output<PushPull>>;
pub struct MeasurePins<'a> {
pub c: &'a mut SomePin,
pub rs: &'a mut SomePin,
pub led: &'a mut SomePin,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum MeasurementKind {
Rust,
C,
}
const RUNS: u32 = 5000;
impl MeasurePins<'_> {
pub fn set_led(&mut self, state: PinState) {
self.led.set_state(state).expect("could not set led state")
}
pub fn set_for_kind(&mut self, kind: MeasurementKind, state: PinState) {
match kind {
MeasurementKind::Rust => self.rs.set_state(state),
MeasurementKind::C => self.c.set_state(state),
}
.expect("could not set rs or c pin")
}
pub fn set_all(&mut self, state: PinState) {
self.led.set_state(state).expect("could not set led state");
self.rs.set_state(state).expect("could not set rs state");
self.c.set_state(state).expect("could not set c state");
}
}
#[inline]
pub fn bench(pin: &mut Pin<Output<PushPull>>, delay: &mut Delay) {
bench_delay(pin, delay);
bench_crc(pin, delay);
pub fn bench(pins: &mut MeasurePins, delay: &mut Delay) {
bench_crc(pins, delay);
bench_sha256(pins, delay);
}
fn bench_delay(pin: &mut Pin<Output<PushPull>>, delay: &mut Delay) {
time_exec(pin, || delay.delay_ms(20u32));
time_exec(pin, || delay.delay_ms(50u32));
}
fn time_exec<F>(pin: &mut Pin<Output<PushPull>>, mut f: F)
where
fn time_exec<F>(
id: &str,
kind: MeasurementKind,
pins: &mut MeasurePins,
delay: &mut Delay,
do_loop: bool,
mut f: F,
) where
F: FnMut(),
{
info!("Running the requested function 50 times and returning the average");
const RUNS: u32 = 50;
pin.set_high().expect("could not set pun to high");
for _ in 0..RUNS {
if do_loop {
info!("Running '{}' {} times", id, RUNS);
pins.set_for_kind(kind, PinState::High);
for _ in 0..RUNS {
f();
}
pins.set_for_kind(kind, PinState::Low);
} else {
info!("Running '{}' 1 time", id);
pins.set_for_kind(kind, PinState::High);
f();
pins.set_for_kind(kind, PinState::Low);
}
pin.set_low().expect("could not set pun to low");
info!("Measurement of '{}' finished!", id);
delay.delay_ms(100_u32);
}
fn bench_crc(pin: &mut Pin<Output<PushPull>>, delay: &mut Delay) {
fn bench_crc(pins: &mut MeasurePins, delay: &mut Delay) {
const DATA: &[u8] = b"hello world AAAAAAAAAAAAAAAAAAAAAAA";
delay.delay_ms(50_u32);
time_exec(pin, || {
time_exec("crc32_rs", MeasurementKind::Rust, pins, delay, true, || {
Crc32Rust::checksum(DATA);
});
delay.delay_ms(50_u32);
time_exec(pin, || {
time_exec("crc32_c_ffi", MeasurementKind::C, pins, delay, true, || {
Crc32C::checksum(DATA);
});
time_exec(
"crc32_c_native",
MeasurementKind::C,
pins,
delay,
false,
|| {
Crc32C::checksum_n_times(RUNS, DATA);
},
);
}
fn bench_sha256(pins: &mut MeasurePins, delay: &mut Delay) {
const DATA: &[u8] = b"hello world AAAAAAAAAAAAAAAAAAAAAAA";
time_exec(
"sha256_rs",
MeasurementKind::Rust,
pins,
delay,
true,
|| {
sha2_256_oneshot(DATA).unwrap();
},
);
time_exec(
"sha256_c_ffi",
MeasurementKind::C,
pins,
delay,
true,
|| {
sha2_ffi::sha2_256_oneshot(DATA).unwrap();
},
);
time_exec(
"sha256_c_native",
MeasurementKind::C,
pins,
delay,
false,
|| {
sha2_ffi::sha2_256_oneshot_n_times(RUNS, DATA);
},
);
}

View file

@ -19,6 +19,8 @@ use hal::{
rcc::Config,
};
use crate::bench::MeasurePins;
mod bench;
mod error_handlers; // defines a handler for evil hardfaults
@ -33,9 +35,17 @@ fn main() -> ! {
// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
// the RCC register.
let gpioa = dp.GPIOA.split(&mut rcc);
let gpiob = dp.GPIOB.split(&mut rcc);
// Configure PA5 as output.
let mut led = gpioa.pa5.into_push_pull_output().downgrade();
// This is D4 on CN19 for the NCLEO L053R8 according to the user manual:
// "UM1724"
let mut measurepin_0 = gpiob.pb5.into_push_pull_output().downgrade();
// This is D5 on CN19 for the NCLEO L053R8
let mut measurepin_1 = gpiob.pb4.into_push_pull_output().downgrade();
let mut led = gpioa.pa5.into_push_pull_output().downgrade(); // this is the led
measurepin_0.set_low().unwrap();
led.set_low().unwrap();
// setup timer for measuring time of benchmarks
cp.SYST.set_reload(0x00ffffff); // max
@ -47,13 +57,19 @@ fn main() -> ! {
debug!("Asserting that libalgorithms is correctly loaded");
assert!(algorithms::ffi_is_loaded(), "ffi is not loaded?");
info!("Starting the Rust vs C benchmark");
bench::bench(&mut led, &mut delay);
info!("Benchmark done, nothing else to do");
let mut measurepins = bench::MeasurePins {
c: &mut measurepin_0,
rs: &mut measurepin_1,
led: &mut led,
};
info!("Starting the Rust vs C benchmark");
bench::bench(&mut measurepins, &mut delay);
info!("Benchmark done");
measurepins.set_all(PinState::Low);
led.set_high().unwrap();
#[allow(clippy::empty_loop)]
loop {
delay.delay_ms(200u32);
delay.delay_ms(5000u32);
}
}