Compare commits
66 commits
Author | SHA1 | Date | |
---|---|---|---|
3493bd2024 | |||
cfc851d3fe | |||
21e77c65a9 | |||
63c45edba1 | |||
55a1ff9445 | |||
f944cce39d | |||
f162fe8734 | |||
92cdf6af78 | |||
cf3bc785ab | |||
d4e405cf07 | |||
ba9ba5aa09 | |||
416dd1660d | |||
368d790c63 | |||
078e55ef4a | |||
32643ad085 | |||
347e752e37 | |||
1e827d6b8a | |||
e78dc4a628 | |||
bb81a7dd49 | |||
11677d8fe0 | |||
afff4c8aa4 | |||
1b582ba202 | |||
3331e89179 | |||
00ced8e548 | |||
96eee72756 | |||
a0a277b80d | |||
7ef66ead56 | |||
a3f77b4f45 | |||
0fd29467a3 | |||
65690e7f43 | |||
009ed1fb50 | |||
1c4ffa19a6 | |||
6132a2ea61 | |||
cb53f81662 | |||
0f3a5f6b32 | |||
6bf1b1beb7 | |||
7808fb55e3 | |||
aaab15e72d | |||
f57aa91880 | |||
0316298825 | |||
727800ba2f | |||
bad5730a8d | |||
e8d26dd1a4 | |||
28611efedb | |||
84a7fc294b | |||
d2476c2cd6 | |||
4aef6894e5 | |||
d1120ba806 | |||
7595ba6c52 | |||
ece5923ed8 | |||
83ff767c5f | |||
c77927711d | |||
e0b79b5a22 | |||
84698796d1 | |||
ca49202052 | |||
8afd71ebe3 | |||
e2bc777410 | |||
b3ca9eeabf | |||
e83167634a | |||
a9a1fc40db | |||
ab9a5a4a55 | |||
be26f8f688 | |||
87a8b04c35 | |||
93abdfb521 | |||
41736b1d23 | |||
d1f9420703 |
71 changed files with 2949 additions and 636 deletions
|
@ -1,11 +1,16 @@
|
|||
[build]
|
||||
target = "thumbv6m-none-eabi"
|
||||
|
||||
[target.thumbv6m-none-eabi]
|
||||
runner = 'probe-rs run --chip STM32L053R8'
|
||||
|
||||
# [build]
|
||||
# target = "thumbv6m-none-eabi"
|
||||
|
||||
[alias]
|
||||
arun = "run --target thumbv6m-none-eabi"
|
||||
abuild = "build --target thumbv6m-none-eabi"
|
||||
atest = "test --target x86_64-unknown-linux-gnu"
|
||||
abench = "bench --target x86_64-unknown-linux-gnu"
|
||||
acheck = "check --target thumbv6m-none-eabi"
|
||||
aclippy = "clippy --target thumbv6m-none-eabi"
|
||||
cflash = "flash --chip STM32L053R8"
|
||||
|
||||
[env]
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,4 @@
|
|||
/target
|
||||
/.git
|
||||
scripts/copy_to_svn.sh
|
||||
scripts/copy_to_win.sh
|
||||
|
|
20
.vscode/launch.json
vendored
Executable file
20
.vscode/launch.json
vendored
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"preLaunchTask": "${defaultBuildTask}",
|
||||
"type": "probe-rs-debug",
|
||||
"request": "launch",
|
||||
"name": "probe_rs Run and Debug",
|
||||
"flashingConfig": {
|
||||
"flashingEnabled": true,
|
||||
},
|
||||
"chip": "STM32L053R8",
|
||||
"coreConfigs": [
|
||||
{
|
||||
"programBinary": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/nucleo-l053r8-benches",
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
25
.vscode/tasks.json
vendored
Executable file
25
.vscode/tasks.json
vendored
Executable file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "cargo run",
|
||||
"type": "shell",
|
||||
"command": "cargo arun",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
},
|
||||
{
|
||||
"label": "cargo build",
|
||||
"type": "shell",
|
||||
"command": "cargo build --target thumbv6m-none-eabi",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
620
Cargo.lock
generated
620
Cargo.lock
generated
|
@ -2,6 +2,25 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "algorithms"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"assert_hex",
|
||||
"criterion",
|
||||
"iai",
|
||||
"pretty_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "as-slice"
|
||||
version = "0.2.1"
|
||||
|
@ -12,10 +31,27 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
name = "assert_hex"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
checksum = "f7010f1430f0fc8ca80bdb5e5d074db68776a2e268ec6cf80b53712d3ea4bca7"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
|
@ -45,10 +81,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
|
@ -57,14 +93,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
name = "cfg-if"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.7.7"
|
||||
|
@ -98,12 +151,94 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"cast",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"csv",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf"
|
||||
dependencies = [
|
||||
"csv-core",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt"
|
||||
version = "0.3.100"
|
||||
|
@ -155,6 +290,18 @@ dependencies = [
|
|||
"defmt 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.7"
|
||||
|
@ -175,33 +322,75 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
name = "half"
|
||||
version = "1.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hd44780-driver"
|
||||
version = "0.4.0"
|
||||
name = "iai"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aab2b13fdeaed7dde9133a57c28b2cbde4a8fc8c3196b5631428aad114857d3a"
|
||||
checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"embedded-hal",
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
|
@ -218,16 +407,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||
|
||||
[[package]]
|
||||
name = "nucleo-l053r8-blink"
|
||||
version = "0.1.0"
|
||||
name = "nucleo-l053r8-benches"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"algorithms",
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"defmt 1.0.1",
|
||||
"defmt-rtt",
|
||||
"hd44780-driver",
|
||||
"heapless",
|
||||
"panic-halt",
|
||||
"panic-probe",
|
||||
"stm32l0xx-hal",
|
||||
]
|
||||
|
@ -295,10 +482,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic-halt"
|
||||
version = "1.0.0"
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
|
||||
|
||||
[[package]]
|
||||
name = "panic-probe"
|
||||
|
@ -310,6 +503,44 @@ dependencies = [
|
|||
"defmt 0.3.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
|
@ -350,6 +581,55 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rtcc"
|
||||
version = "0.3.2"
|
||||
|
@ -368,6 +648,27 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
|
@ -383,6 +684,48 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_cbor"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
|
||||
dependencies = [
|
||||
"half",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
@ -421,15 +764,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.100"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.12"
|
||||
|
@ -450,12 +802,28 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "vcell"
|
||||
version = "0.1.3"
|
||||
|
@ -476,3 +844,191 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
|
|||
dependencies = [
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
|
41
Cargo.toml
41
Cargo.toml
|
@ -1,7 +1,9 @@
|
|||
[package]
|
||||
name = "nucleo-l053r8-blink"
|
||||
version = "0.1.0"
|
||||
name = "nucleo-l053r8-benches"
|
||||
version = "0.2.0"
|
||||
edition = "2024"
|
||||
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
||||
license = "MIT"
|
||||
|
||||
|
||||
[dependencies]
|
||||
|
@ -11,32 +13,17 @@ hal = { package = "stm32l0xx-hal", version = "0.10.0", features = [
|
|||
] }
|
||||
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7.5"
|
||||
panic-halt = "1.0.0"
|
||||
hd44780-driver = "0.4.0"
|
||||
heapless = "0.8.0"
|
||||
defmt = {version="1.0.1", optional= true}
|
||||
defmt-rtt = {version="1.0.0", optional=true}
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"], optional=true }
|
||||
defmt = { version = "1.0.1" }
|
||||
defmt-rtt = { version = "1.0.0" }
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
algorithms = { path = "./crates/algorithms" }
|
||||
|
||||
[features]
|
||||
logging = ["dep:defmt", "dep:defmt-rtt", "dep:panic-probe"]
|
||||
default = ["buildscript"]
|
||||
buildscript = [] # runs build.rs
|
||||
|
||||
[[example]]
|
||||
name = "logging"
|
||||
path = "examples/logging.rs"
|
||||
required-features = ["logging"]
|
||||
[profile.release]
|
||||
debug = "full" # those are not on the board
|
||||
|
||||
[[example]]
|
||||
name = "rtc-log"
|
||||
path = "examples/rtc-log.rs"
|
||||
required-features = ["logging"]
|
||||
|
||||
[[example]]
|
||||
name = "temperature"
|
||||
path = "examples/temperature.rs"
|
||||
required-features = ["logging"]
|
||||
|
||||
[[example]]
|
||||
name = "aes_ecb"
|
||||
path = "examples/aes_ecb.rs"
|
||||
required-features = ["logging"]
|
||||
[workspace]
|
||||
members = ["", "crates/algorithms"]
|
||||
|
|
22
LICENSE
Normal file
22
LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Christoph Johannes Scherr
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
64
README.md
64
README.md
|
@ -1,16 +1,58 @@
|
|||
# Example Codes for the STM32 NUCLEO-L053R8
|
||||
# NUCLEO L053R8 Benches
|
||||
|
||||
This repository contains many example programs that are written to run on the
|
||||
NUCLEO-L053R8 Board.
|
||||
This repository contains code to measure the performance of embedded C and
|
||||
Rust code for an STM32 Microcontroller, specifically the `STM32L053R` on a
|
||||
`NUCLEO-L053R` evaluation board.
|
||||
|
||||
## Running
|
||||
It implements a variety of algorithms in both C and Rust
|
||||
(`crate/algorithms`). These Algorithm programs are then executed by the
|
||||
executable program written in Rust. C code is called using Rust's FFI with
|
||||
manually implemented bindings. To measure the actual runtime of the algorithms,
|
||||
you need to attach an oscilluscope to the configured port of the board while
|
||||
the prgrams are running.
|
||||
|
||||
Some programs require additional libraries for logging/formatting that would
|
||||
make the more basic ones not compile (or rather link) correctly. For those,
|
||||
enable the `logging` feature.
|
||||
## Building
|
||||
|
||||
See [build.sh](./scripts/build.sh).
|
||||
|
||||
## Flashing
|
||||
|
||||
See [flash.sh](./scripts/flash.sh).
|
||||
|
||||
## Host-Benchmarks
|
||||
|
||||
The algorithms have benchmarks that can run on regular consumer laptops, so that
|
||||
you can see the implementation difference on a bigger architecture like
|
||||
`x86_64`.
|
||||
|
||||
See [bench_algorithms.sh](./scripts/bench_algorithms.sh).
|
||||
|
||||
### Dependencies
|
||||
|
||||
This program requires Rust to be installed. I made it with `Rust 1.88.0`, but
|
||||
the theoretical MSRV is `Rust 1.85.1` (according to `cargo-msrv`).
|
||||
|
||||
In addition to some crates from crates.io, this project requires the following
|
||||
to be installed to compile and link to the algorithms-c implementations.
|
||||
|
||||
```bash
|
||||
cargo run --example=blinky
|
||||
cargo run --example=rtc-log --features=logging
|
||||
# etc
|
||||
```
|
||||
# on debian bookworm
|
||||
# compiler for your architecture if you want to run the unit tests
|
||||
apt install gcc
|
||||
# compiler for the target architecture
|
||||
apt install binutils-arm-none-eabi gcc-arm-none-eabi
|
||||
# ceedling is the used build system for algorithms-c, and needs to be installed with gem, the ruby package manager
|
||||
apt install ruby
|
||||
gem install ceedling
|
||||
```
|
||||
|
||||
To actually flash the program onto an STM32, you also need
|
||||
[probe-rs](https://probe.rs/docs/getting-started/installation/). I used
|
||||
`probe-rs 0.29.1`.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
For implementing the SHA-2-256 Algorithm, [this](https://sha256algorithm.com/)
|
||||
website was very helpful.
|
||||
|
||||
The algorithms themselves are mostly reference implementation of various RFCs.
|
||||
|
|
6
build.rs
6
build.rs
|
@ -1,8 +1,8 @@
|
|||
fn main() {
|
||||
println!("cargo::rerun-if-changed=Cargo.toml");
|
||||
println!("cargo::rustc-link-arg=-Tlink.x");
|
||||
#[cfg(feature = "logging")]
|
||||
#[cfg(feature = "buildscript")]
|
||||
{
|
||||
println!("cargo::rerun-if-changed=Cargo.toml");
|
||||
println!("cargo::rustc-link-arg=-Tlink.x");
|
||||
println!("cargo::rustc-link-arg=-Tdefmt.x");
|
||||
}
|
||||
}
|
||||
|
|
1
crates/algorithms/.gitignore
vendored
Executable file
1
crates/algorithms/.gitignore
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
/target
|
36
crates/algorithms/Cargo.toml
Executable file
36
crates/algorithms/Cargo.toml
Executable file
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "algorithms"
|
||||
version = "0.2.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dev-dependencies]
|
||||
assert_hex = "0.4.1"
|
||||
criterion = "0.3"
|
||||
iai = "0.1.1"
|
||||
pretty_assertions = "1.4.1"
|
||||
|
||||
[[bench]]
|
||||
name = "crc32bench"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "crc32bench_iai"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std = []
|
||||
show_internals = ["std"]
|
||||
|
||||
[[bin]]
|
||||
path = "src/bin/crc32sum.rs"
|
||||
name = "crc32sum"
|
||||
required-features = ["std"]
|
||||
|
||||
[[bin]]
|
||||
path = "src/bin/sha256sum.rs"
|
||||
name = "algsha256sum"
|
||||
required-features = ["std"]
|
5
crates/algorithms/algorithms-c/.clangd
Normal file
5
crates/algorithms/algorithms-c/.clangd
Normal file
|
@ -0,0 +1,5 @@
|
|||
SemanticTokens:
|
||||
DisabledKinds: [InactiveCode]
|
||||
CompileFlags: # Tweak the parse settings, example directory given to show format
|
||||
Add:
|
||||
- "-Wall"
|
1
crates/algorithms/algorithms-c/.gitignore
vendored
Executable file
1
crates/algorithms/algorithms-c/.gitignore
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
build*
|
27
crates/algorithms/algorithms-c/README.md
Executable file
27
crates/algorithms/algorithms-c/README.md
Executable file
|
@ -0,0 +1,27 @@
|
|||
# Algorithms-c
|
||||
|
||||
This subproject contains all C Code for the benchmarking. It is built with
|
||||
[ceedling](https://www.throwtheswitch.org/ceedling), a more modern build tool
|
||||
for C projects that also integrates well with the Unity framework.
|
||||
|
||||
## Compiler
|
||||
|
||||
To compile for STM32, you need to crosscompile
|
||||
|
||||
```
|
||||
# apt install binutils-arm-none-eabi gcc-arm-none-eabi
|
||||
```
|
||||
|
||||
Then, use your tool with an `arm-none-eabi-` prefix: `arm-none-eabi-gcc`. This
|
||||
project has been configured to use the compiler specified in `$CC` to compile modules and `$AR` to
|
||||
"link" the object files (this should be `ar` for a static library like this)
|
||||
. You can and should also give extra compiler flags in `$CC_FLAGS`.
|
||||
|
||||
```bash
|
||||
# cross-compile for STM32
|
||||
CC=arm-none-eabi-gcc AR=arm-none-eabi-ar CC_FLAGS="-march=armv6-m" ceedling release
|
||||
# compile for this computer
|
||||
CC=gcc AR=ar ceedling release
|
||||
```
|
||||
|
||||
It is critically important to define the `-march=ARCH` option when using `arm-none-eabi-gcc`, since the compiler will otherwise just assume a target architecture. In this case, it needs to be set to `armv6-m`, since the MPU is a `cortex-M0+`. This MPU does only support the thumb instruction-set, not the ARM32 set.
|
12
crates/algorithms/algorithms-c/compile_flags.txt
Normal file
12
crates/algorithms/algorithms-c/compile_flags.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
-I
|
||||
./build/vendor/unity/src/
|
||||
-I
|
||||
./build/vendor/cmock/src/
|
||||
-I
|
||||
./src/crc/
|
||||
-I
|
||||
./src/hash/
|
||||
-I
|
||||
./src/
|
||||
-I
|
||||
./test/support/
|
112
crates/algorithms/algorithms-c/project.yml
Executable file
112
crates/algorithms/algorithms-c/project.yml
Executable file
|
@ -0,0 +1,112 @@
|
|||
:project:
|
||||
:which_ceedling: gem
|
||||
:ceedling_version: 1.0.1
|
||||
:use_mocks: FALSE
|
||||
:use_backtrace: :gdb # options are :none, :simple, or :gdb
|
||||
:use_decorators: :auto # decorate Ceedling's output text. options are :auto, :all, or :none
|
||||
:build_root: build
|
||||
:test_file_prefix: test_
|
||||
:default_tasks:
|
||||
- release
|
||||
- test:all
|
||||
:test_threads: 8
|
||||
:compile_threads: 8
|
||||
:release_build: TRUE
|
||||
:version: 0.2.0
|
||||
:test_build:
|
||||
:use_assembly: FALSE
|
||||
:release_build:
|
||||
:output: libalgorithms.a
|
||||
:use_assembly: FALSE
|
||||
:artifacts: []
|
||||
:plugins:
|
||||
:load_paths: []
|
||||
:enabled:
|
||||
#- beep # beeps when finished, so you don't waste time waiting for ceedling
|
||||
- module_generator # handy for quickly creating source, header, and test templates
|
||||
#- gcov # test coverage using gcov. Requires gcc, gcov, and a coverage analyzer like gcovr
|
||||
#- bullseye # test coverage using bullseye. Requires bullseye for your platform
|
||||
#- command_hooks # write custom actions to be called at different points during the build process
|
||||
#- compile_commands_json_db # generate a compile_commands.json file
|
||||
#- dependencies # automatically fetch 3rd party libraries, etc.
|
||||
#- subprojects # managing builds and test for static libraries
|
||||
#- fake_function_framework # use FFF instead of CMock
|
||||
# Report options (You'll want to choose one stdout option, but may choose multiple stored options if desired)
|
||||
- report_build_warnings_log
|
||||
#- report_tests_gtestlike_stdout
|
||||
#- report_tests_ide_stdout
|
||||
#- report_tests_log_factory
|
||||
- report_tests_pretty_stdout
|
||||
#- report_tests_raw_output_log
|
||||
#- report_tests_teamcity_stdout
|
||||
# Specify which reports you'd like from the log factory
|
||||
:report_tests_log_factory:
|
||||
:reports:
|
||||
- json
|
||||
- junit
|
||||
- cppunit
|
||||
- html
|
||||
# override the default extensions for your system and toolchain
|
||||
:extension:
|
||||
#:header: .h
|
||||
#:source: .c
|
||||
#:assembly: .s
|
||||
#:dependencies: .d
|
||||
#:object: .o
|
||||
:executable: .out
|
||||
#:testpass: .pass
|
||||
#:testfail: .fail
|
||||
#:subprojects: .a
|
||||
:paths:
|
||||
:test:
|
||||
- +:test/**
|
||||
- -:test/support
|
||||
:source:
|
||||
- src/**
|
||||
:include:
|
||||
- src/** # In simple projects, this entry often duplicates :source
|
||||
:support:
|
||||
- test/support
|
||||
:libraries: []
|
||||
:defines:
|
||||
:test:
|
||||
- TEST # Simple list option to add symbol 'TEST' to compilation of all files in all test executables
|
||||
:release: []
|
||||
# Enable to inject name of a test as a unique compilation symbol into its respective executable build.
|
||||
:use_test_definition: FALSE
|
||||
:flags:
|
||||
:release:
|
||||
:compile:
|
||||
- -Wall # all warnings on
|
||||
- -O3 # optimizations
|
||||
- -g # debug info
|
||||
# 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
|
||||
:libraries:
|
||||
:placement: :end
|
||||
:flag: "-l${1}"
|
||||
:path_flag: "-L ${1}"
|
||||
:system: []
|
||||
:test: []
|
||||
:release: []
|
||||
:tools:
|
||||
:release_compiler:
|
||||
:executable: "#{ENV['CC']}"
|
||||
:arguments:
|
||||
- "-c"
|
||||
- "${1}"
|
||||
- "-o"
|
||||
- "${2}"
|
||||
- "#{ENV['CC_FLAGS']}"
|
||||
:optional: FALSE
|
||||
:release_linker:
|
||||
:executable: "#{ENV['AR']}"
|
||||
:arguments:
|
||||
- "-rcs"
|
||||
- "${2}"
|
||||
- "${1}"
|
||||
:optional: FALSE
|
3
crates/algorithms/algorithms-c/src/algorithms.c
Normal file
3
crates/algorithms/algorithms-c/src/algorithms.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include "algorithms.h"
|
||||
|
||||
int algorithms_c_is_loaded() { return 1; }
|
12
crates/algorithms/algorithms-c/src/algorithms.h
Normal file
12
crates/algorithms/algorithms-c/src/algorithms.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
#ifndef ALGORITHMS_H
|
||||
#define ALGORITHMS_H
|
||||
|
||||
#include "crc/crc.h"
|
||||
#include "hash/hash.h"
|
||||
|
||||
#include "stdbool.h"
|
||||
|
||||
extern int algorithms_c_is_loaded();
|
||||
|
||||
#endif // ALGORITHMS_H
|
2
crates/algorithms/algorithms-c/src/crc/crc.c
Executable file
2
crates/algorithms/algorithms-c/src/crc/crc.c
Executable file
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "crc.h"
|
6
crates/algorithms/algorithms-c/src/crc/crc.h
Executable file
6
crates/algorithms/algorithms-c/src/crc/crc.h
Executable file
|
@ -0,0 +1,6 @@
|
|||
#ifndef CRC_H
|
||||
#define CRC_H
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
#endif // CRC_H
|
80
crates/algorithms/algorithms-c/src/crc/crc32.c
Executable file
80
crates/algorithms/algorithms-c/src/crc/crc32.c
Executable file
|
@ -0,0 +1,80 @@
|
|||
#include "crc32.h"
|
||||
#include <stdint.h>
|
||||
|
||||
const uint32_t CRC32_INIT = 0xffffffff;
|
||||
const uint32_t CRC32_TABLE[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
|
||||
Crc32 crc32_new() {
|
||||
Crc32 crc32;
|
||||
crc32.buf = 0;
|
||||
return crc32;
|
||||
}
|
||||
void crc32_process(const uint8_t *data, size_t len, Crc32 *crc32) {
|
||||
#define chksum crc32->buf
|
||||
chksum = CRC32_INIT;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
chksum ^= data[i];
|
||||
chksum = (chksum >> 8) ^ CRC32_TABLE[(chksum & 0xff)];
|
||||
}
|
||||
chksum ^= CRC32_INIT;
|
||||
return;
|
||||
}
|
||||
|
||||
ChecksumCrc32 crc32_checksum(const uint8_t *data, uint32_t len) {
|
||||
Crc32 crc32 = crc32_new();
|
||||
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;
|
||||
}
|
25
crates/algorithms/algorithms-c/src/crc/crc32.h
Executable file
25
crates/algorithms/algorithms-c/src/crc/crc32.h
Executable file
|
@ -0,0 +1,25 @@
|
|||
#ifndef CRC32_H
|
||||
#define CRC32_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// it needs to be declared but not implemented, otherwise, multiple definitions
|
||||
// will occur
|
||||
extern const uint32_t CRC32_INIT;
|
||||
extern const uint32_t CRC32_TABLE[256];
|
||||
|
||||
typedef uint32_t ChecksumCrc32;
|
||||
|
||||
typedef struct Crc32 {
|
||||
ChecksumCrc32 buf;
|
||||
} Crc32;
|
||||
|
||||
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
|
10
crates/algorithms/algorithms-c/src/hash/hash.c
Executable file
10
crates/algorithms/algorithms-c/src/hash/hash.c
Executable file
|
@ -0,0 +1,10 @@
|
|||
|
||||
#include "hash.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void print_digest(const SHA2Digest digest) {
|
||||
for (size_t i = 0; i < SHA2_256_HashParts; i++) {
|
||||
fprintf(stderr, "%08x", digest[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
8
crates/algorithms/algorithms-c/src/hash/hash.h
Executable file
8
crates/algorithms/algorithms-c/src/hash/hash.h
Executable file
|
@ -0,0 +1,8 @@
|
|||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
extern void print_digest(const SHA2Digest);
|
||||
|
||||
#endif // HASH_H
|
421
crates/algorithms/algorithms-c/src/hash/sha2.c
Normal file
421
crates/algorithms/algorithms-c/src/hash/sha2.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
#include "sha2.h"
|
||||
#include "../trace.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef TEST
|
||||
// if you want to get the internals of sha2 printed, uncomment the line below
|
||||
// #define SHOW_INTERNALS
|
||||
#endif // TEST
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
#define sha2_256_show_internal_state(context) \
|
||||
TRACE("Internal State:\n\tcorrupted: %d\n\tintermediate_hash: ", \
|
||||
context->corrupted); \
|
||||
dump_hash(context); \
|
||||
TRACE("\tmessage_block_index: %d\n\tmessage_block: ", \
|
||||
context->message_block_index); \
|
||||
dump_data((uint8_t *)context->message_block, SHA2_256_BlockSize); \
|
||||
TRACE("\tcorrupted: %d\n\tcomputed: %d\n", context->corrupted, \
|
||||
context->computed);
|
||||
#else
|
||||
#define sha2_256_show_internal_state(context)
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
#define err_handler(RES) \
|
||||
if (RES) { \
|
||||
return RES; \
|
||||
}
|
||||
|
||||
static uint32_t addTemp = 0;
|
||||
#define sha2_256_add_length(context, length) \
|
||||
(addTemp = (context)->length_low, \
|
||||
(context)->corrupted = (((context)->length_low += (length)) < addTemp) && \
|
||||
(++(context)->length_high == 0) \
|
||||
? shaInputTooLong \
|
||||
: (context)->corrupted)
|
||||
|
||||
#define dump_hash(context) \
|
||||
for (int o = 0; o < SHA2_256_HashParts; o++) { \
|
||||
TRACE("%08x", context->intermediate_hash[o]); \
|
||||
} \
|
||||
TRACELN("")
|
||||
|
||||
/* Define the SHA shift, rotate left, and rotate right macros */
|
||||
#define SHA256_SHR(bits, word) ((word) >> (bits))
|
||||
#define SHA256_ROTL(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))
|
||||
#define SHA256_ROTR(bits, word) (((word) >> (bits)) | ((word) << (32 - (bits))))
|
||||
|
||||
/* Define the SHA SIGMA and sigma macros, yes these have the same name and are
|
||||
* different */
|
||||
#define SHA256_SIGMA0(word) \
|
||||
(SHA256_ROTR(2, word) ^ SHA256_ROTR(13, word) ^ SHA256_ROTR(22, word))
|
||||
#define SHA256_SIGMA1(word) \
|
||||
(SHA256_ROTR(6, word) ^ SHA256_ROTR(11, word) ^ SHA256_ROTR(25, word))
|
||||
#define SHA256_sigma0(word) \
|
||||
(SHA256_ROTR(7, word) ^ SHA256_ROTR(18, word) ^ SHA256_SHR(3, word))
|
||||
#define SHA256_sigma1(word) \
|
||||
(SHA256_ROTR(17, word) ^ SHA256_ROTR(19, word) ^ SHA256_SHR(10, word))
|
||||
|
||||
#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
|
||||
#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
|
||||
|
||||
static const uint32_t H[SHA2_256_HashParts] = {
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
||||
static const uint32_t K[SHA2_256_BlockSize] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
/*
|
||||
* Description:
|
||||
* This helper function will process the next 512 bits of the
|
||||
* message stored in the message_block array.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The SHA context to update.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
* Comments:
|
||||
* Many of the variable names in this code, especially the
|
||||
* single character names, were used because those were the
|
||||
* names used in the Secure Hash Standard.
|
||||
*/
|
||||
static void sha2_256_process_message_block(SHA2Context *context) {
|
||||
#define dump_letter(X) TRACE("%s: %08x ", STR(X), X)
|
||||
#define dump_alphabet \
|
||||
dump_letter(A) dump_letter(B) dump_letter(C) dump_letter(D) dump_letter(E) \
|
||||
dump_letter(F) dump_letter(G) dump_letter(H) TRACELN("")
|
||||
#define dump_w \
|
||||
TRACELN("Dumping W:"); \
|
||||
for (int o = 0; o < SHA2_256_BlockSize; o++) { \
|
||||
TRACE("\tW[%d]: %032b\n", o, W[o]) \
|
||||
}
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
TRACELN("before process message block");
|
||||
sha2_256_show_internal_state(context);
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
uint8_t t, t4; /* Loop counter */
|
||||
uint32_t temp1, temp2; /* Temporary word value */
|
||||
uint32_t W[SHA2_256_BlockSize]; /* Word sequence */
|
||||
uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
|
||||
|
||||
/*
|
||||
* Initialize the first 16 words in the array W
|
||||
*/
|
||||
for (t = t4 = 0; t < 16; t++, t4 += 4) {
|
||||
W[t] = (((uint32_t)context->message_block[t4]) << 24) |
|
||||
(((uint32_t)context->message_block[t4 + 1]) << 16) |
|
||||
(((uint32_t)context->message_block[t4 + 2]) << 8) |
|
||||
(((uint32_t)context->message_block[t4 + 3]));
|
||||
}
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
dump_w;
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
for (t = 16; t < SHA2_256_BlockSize; t++) {
|
||||
W[t] = SHA256_sigma1(W[t - 2]) + W[t - 7] + SHA256_sigma0(W[t - 15]) +
|
||||
W[t - 16];
|
||||
}
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
dump_w;
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
A = context->intermediate_hash[0];
|
||||
B = context->intermediate_hash[1];
|
||||
C = context->intermediate_hash[2];
|
||||
D = context->intermediate_hash[3];
|
||||
E = context->intermediate_hash[4];
|
||||
F = context->intermediate_hash[5];
|
||||
G = context->intermediate_hash[6];
|
||||
H = context->intermediate_hash[7];
|
||||
|
||||
for (t = 0; t < SHA2_256_BlockSize; t++) {
|
||||
#ifdef SHOW_INTERNALS
|
||||
TRACE("Iter: %d\t", t);
|
||||
dump_alphabet;
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
|
||||
temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
|
||||
H = G;
|
||||
G = F;
|
||||
F = E;
|
||||
E = D + temp1;
|
||||
D = C;
|
||||
C = B;
|
||||
B = A;
|
||||
A = temp1 + temp2;
|
||||
}
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
TRACE("DONE:\t")
|
||||
dump_alphabet;
|
||||
|
||||
TRACE("Intermediate hash before we add the working variables:\n");
|
||||
for (int o = 0; o < SHA2_256_HashParts; o++) {
|
||||
TRACE("\t%d:\t%032b\n", o, context->intermediate_hash[o]);
|
||||
}
|
||||
#endif // SHOW_INTERNALS
|
||||
|
||||
context->intermediate_hash[0] += A;
|
||||
context->intermediate_hash[1] += B;
|
||||
context->intermediate_hash[2] += C;
|
||||
context->intermediate_hash[3] += D;
|
||||
context->intermediate_hash[4] += E;
|
||||
context->intermediate_hash[5] += F;
|
||||
context->intermediate_hash[6] += G;
|
||||
context->intermediate_hash[7] += H;
|
||||
|
||||
context->message_block_index = 0;
|
||||
|
||||
#ifdef SHOW_INTERNALS
|
||||
TRACE("Hash data if we finish now: ");
|
||||
dump_hash(context);
|
||||
TRACELN("\nafter process message block");
|
||||
sha2_256_show_internal_state(context);
|
||||
#endif // SHOW_INTERNALS
|
||||
}
|
||||
|
||||
/*
|
||||
* Description:
|
||||
* According to the standard, the message must be padded to the next
|
||||
* even multiple of 512 bits. The first padding bit must be a '1'.
|
||||
* The last 64 bits represent the length of the original message.
|
||||
* All bits in between should be 0. This helper function will pad
|
||||
* the message according to those rules by filling the
|
||||
* Message_Block array accordingly. When it returns, it can be
|
||||
* assumed that the message digest has been computed.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to pad.
|
||||
* Pad_Byte: [in]
|
||||
* The last byte to add to the message block before the 0-padding
|
||||
* and length. This will contain the last bits of the message
|
||||
* followed by another single bit. If the message was an
|
||||
* exact multiple of 8-bits long, Pad_Byte will be 0x80.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
static void sha2_256_pad_message(SHA2Context *context, uint8_t pad_byte) {
|
||||
/*
|
||||
* Check to see if the current message block is too small to hold
|
||||
* the initial padding bits and length. If so, we will pad the
|
||||
* block, process it, and then continue padding into a second
|
||||
* block.
|
||||
*/
|
||||
if (context->message_block_index >= (SHA2_256_BlockSize - 8)) {
|
||||
context->message_block[context->message_block_index++] = pad_byte;
|
||||
while (context->message_block_index < SHA2_256_BlockSize)
|
||||
context->message_block[context->message_block_index++] = 0;
|
||||
sha2_256_process_message_block(context);
|
||||
} else
|
||||
context->message_block[context->message_block_index++] = pad_byte;
|
||||
|
||||
while (context->message_block_index < (SHA2_256_BlockSize - 8))
|
||||
context->message_block[context->message_block_index++] = 0;
|
||||
|
||||
/*
|
||||
* store the message length as the last 8 octets
|
||||
*/
|
||||
context->message_block[56] = (uint8_t)(context->length_high >> 24);
|
||||
context->message_block[57] = (uint8_t)(context->length_high >> 16);
|
||||
context->message_block[58] = (uint8_t)(context->length_high >> 8);
|
||||
context->message_block[59] = (uint8_t)(context->length_high);
|
||||
context->message_block[60] = (uint8_t)(context->length_low >> 24);
|
||||
context->message_block[61] = (uint8_t)(context->length_low >> 16);
|
||||
context->message_block[62] = (uint8_t)(context->length_low >> 8);
|
||||
context->message_block[63] = (uint8_t)(context->length_low);
|
||||
|
||||
sha2_256_process_message_block(context);
|
||||
|
||||
sha2_256_show_internal_state(context);
|
||||
}
|
||||
|
||||
static void sha2_256_finalize(SHA2Context *context, uint8_t pad_byte) {
|
||||
sha2_256_pad_message(context, pad_byte);
|
||||
}
|
||||
|
||||
/*
|
||||
* sha2_reset
|
||||
*
|
||||
* Description:
|
||||
* This function will initialize the SHA2Context in preparation
|
||||
* for computing a new SHA2 message digest.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to reset.
|
||||
*
|
||||
* Returns:
|
||||
* SHA2 Error Code.
|
||||
*
|
||||
*/
|
||||
SHA2Result sha2_256_reset(SHA2Context *context) {
|
||||
size_t i;
|
||||
|
||||
if (!context) {
|
||||
return shaNull;
|
||||
}
|
||||
|
||||
context->length_low = 0;
|
||||
context->length_high = 0;
|
||||
context->message_block_index = 0;
|
||||
|
||||
for (i = 0; i < SHA2_256_BlockSize; i++) {
|
||||
context->message_block[i] = 0;
|
||||
}
|
||||
for (i = 0; i < SHA2_256_HashParts; i++) {
|
||||
context->intermediate_hash[i] = H[i];
|
||||
}
|
||||
|
||||
context->corrupted = 0;
|
||||
context->computed = 0;
|
||||
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* sha2_input
|
||||
*
|
||||
* Description:
|
||||
* This function accepts an array of bytes as the next portion
|
||||
* of the message.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The SHA context to update
|
||||
* data: [in]
|
||||
* An array of characters representing the next portion of
|
||||
* the message.
|
||||
* length: [in]
|
||||
* The length of the message in message_array
|
||||
*
|
||||
* Returns:
|
||||
* sha Error Code.
|
||||
*
|
||||
*/
|
||||
SHA2Result sha2_256_input(SHA2Context *context, const uint8_t data[],
|
||||
size_t len) {
|
||||
sha2_256_show_internal_state(context);
|
||||
|
||||
if (!context) {
|
||||
TRACELN("Context was NULL");
|
||||
return shaNull;
|
||||
}
|
||||
if (!len)
|
||||
return shaSuccess;
|
||||
if (!data) {
|
||||
TRACELN("Data was NULL");
|
||||
return shaNull;
|
||||
}
|
||||
if (context->computed) {
|
||||
TRACELN("context was already computed");
|
||||
context->corrupted = shaStateError;
|
||||
}
|
||||
if (context->corrupted) {
|
||||
TRACELN("context is corrupted");
|
||||
return context->corrupted;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
context->message_block[context->message_block_index++] = *data;
|
||||
|
||||
if ((sha2_256_add_length(context, 8) == shaSuccess) &&
|
||||
(context->message_block_index == SHA2_256_BlockSize)) {
|
||||
TRACELN("processing the message block after inputting")
|
||||
sha2_256_process_message_block(context);
|
||||
}
|
||||
|
||||
data++;
|
||||
}
|
||||
|
||||
return context->corrupted;
|
||||
}
|
||||
|
||||
/*
|
||||
* sha2_result
|
||||
*
|
||||
* Description:
|
||||
* This function will return the 256-bit message digest
|
||||
* into the digest array provided by the caller.
|
||||
* NOTE:
|
||||
* The first octet of hash is stored in the element with index 0,
|
||||
* the last octet of hash in the element with index 31.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to use to calculate the SHA hash.
|
||||
* digest: [out]
|
||||
* Where the digest is returned.
|
||||
*
|
||||
* Returns:
|
||||
* sha Error Code.
|
||||
*
|
||||
*/
|
||||
SHA2Result sha2_256_result(SHA2Context *context, SHA2Digest digest) {
|
||||
size_t i;
|
||||
|
||||
if (!context)
|
||||
return shaNull;
|
||||
if (!digest)
|
||||
return shaNull;
|
||||
if (context->corrupted)
|
||||
return context->corrupted;
|
||||
|
||||
if (!context->computed) {
|
||||
sha2_256_finalize(context, 0x80);
|
||||
}
|
||||
|
||||
for (i = 0; i < SHA2_256_HashParts; i++)
|
||||
digest[i] = context->intermediate_hash[i];
|
||||
|
||||
return shaSuccess;
|
||||
}
|
||||
|
||||
SHA2Result sha2_256_oneshot(const uint8_t data[], const size_t len,
|
||||
SHA2Digest digest) {
|
||||
SHA2Context context;
|
||||
SHA2Result res;
|
||||
|
||||
res = sha2_256_reset(&context);
|
||||
err_handler(res);
|
||||
sha2_256_show_internal_state((&context));
|
||||
|
||||
res = sha2_256_input(&context, data, len);
|
||||
err_handler(res);
|
||||
sha2_256_show_internal_state((&context));
|
||||
|
||||
res = sha2_256_result(&context, digest);
|
||||
err_handler(res);
|
||||
sha2_256_show_internal_state((&context));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
55
crates/algorithms/algorithms-c/src/hash/sha2.h
Normal file
55
crates/algorithms/algorithms-c/src/hash/sha2.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* This implementation of SHA2 is somewhat similar to that in RFC6234, thanks
|
||||
* for publishing that!
|
||||
*/
|
||||
|
||||
#ifndef SHA2_H
|
||||
#define SHA2_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define HASH(b0, b1, b2, b3, b4, b5, b6, b7) {b0, b1, b2, b3, b4, b5, b6, b7}
|
||||
#define SHA2_256_HashBits 256
|
||||
#define SHA2_256_HashBytes SHA2_256_HashBits / 8
|
||||
#define SHA2_256_HashParts SHA2_256_HashBytes / 4
|
||||
#define SHA2_256_BlockSize 2 * SHA2_256_HashBytes
|
||||
typedef enum {
|
||||
shaSuccess = 0,
|
||||
shaNull, /* Null pointer parameter */
|
||||
shaInputTooLong, /* input data too long */
|
||||
shaStateError, /* called Input after Result */
|
||||
shaBadArg /* Bad argument was given to a function */
|
||||
} SHA2Result;
|
||||
typedef uint32_t SHA2Digest[SHA2_256_HashParts];
|
||||
|
||||
/*
|
||||
* This structure will hold context information for the SHA-1
|
||||
* hashing operation
|
||||
*/
|
||||
typedef struct SHA2Context {
|
||||
SHA2Digest intermediate_hash; /* Message Digest */
|
||||
|
||||
uint32_t length_low; /* Message length in bits */
|
||||
uint32_t length_high; /* Message length in bits */
|
||||
|
||||
/* Index into message block array */
|
||||
int_least16_t message_block_index;
|
||||
uint8_t message_block[SHA2_256_BlockSize]; /* 512-bit message blocks */
|
||||
|
||||
bool computed; /* Is the digest computed? */
|
||||
bool corrupted; /* Is the message digest corrupted? */
|
||||
} SHA2Context;
|
||||
|
||||
/** data should always be null terminated */
|
||||
extern SHA2Result sha2_256_oneshot(const uint8_t data[], const size_t len,
|
||||
SHA2Digest digest);
|
||||
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
|
12
crates/algorithms/algorithms-c/src/trace.c
Normal file
12
crates/algorithms/algorithms-c/src/trace.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "trace.h"
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void dump_data(const uint8_t *data, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
TRACE("%02x", data[i])
|
||||
}
|
||||
TRACELN("")
|
||||
}
|
||||
|
||||
#endif // TEST
|
27
crates/algorithms/algorithms-c/src/trace.h
Normal file
27
crates/algorithms/algorithms-c/src/trace.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef TRACE_H
|
||||
#define TRACE_H
|
||||
|
||||
#define STR(a) #a
|
||||
|
||||
#ifdef TEST
|
||||
#include "stdio.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TRACE(...) fprintf(stderr, __VA_ARGS__);
|
||||
#define TRACELN(MSG) TRACE(MSG "\n")
|
||||
|
||||
extern void dump_data(const uint8_t *data, size_t len);
|
||||
|
||||
#endif // TEST
|
||||
|
||||
// just do nothing if TEST is not defined
|
||||
#ifndef TEST
|
||||
|
||||
#define TRACE(...)
|
||||
#define TRACELN(MSG)
|
||||
#define dump_data(DATA_PTR, LEN)
|
||||
|
||||
#endif // !TEST
|
||||
//
|
||||
#endif // !TRACE_H
|
3
crates/algorithms/algorithms-c/test/crc/crc_common.c
Normal file
3
crates/algorithms/algorithms-c/test/crc/crc_common.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include "crc_common.h"
|
||||
|
||||
const char CRC_CHECK_DATA[CRC_CHECK_DATA_LEN] = "123456789";
|
7
crates/algorithms/algorithms-c/test/crc/crc_common.h
Normal file
7
crates/algorithms/algorithms-c/test/crc/crc_common.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef CRC_COMMON_H
|
||||
#define CRC_COMMON_H
|
||||
|
||||
#define CRC_CHECK_DATA_LEN 9
|
||||
extern const char CRC_CHECK_DATA[CRC_CHECK_DATA_LEN];
|
||||
|
||||
#endif // !CRC_COMMON_H
|
11
crates/algorithms/algorithms-c/test/crc/test_crc.c
Executable file
11
crates/algorithms/algorithms-c/test/crc/test_crc.c
Executable file
|
@ -0,0 +1,11 @@
|
|||
#include "unity.h"
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
void setUp(void) {}
|
||||
|
||||
void tearDown(void) {}
|
||||
|
||||
void test_crc_NeedToImplement(void) {
|
||||
TEST_IGNORE_MESSAGE("Need to Implement crc");
|
||||
}
|
14
crates/algorithms/algorithms-c/test/crc/test_crc32.c
Executable file
14
crates/algorithms/algorithms-c/test/crc/test_crc32.c
Executable file
|
@ -0,0 +1,14 @@
|
|||
#include "crc_common.h"
|
||||
#include "unity.h"
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
void setUp(void) {}
|
||||
|
||||
void tearDown(void) {}
|
||||
|
||||
void test_crc32_check(void) {
|
||||
TEST_ASSERT_EQUAL_HEX(crc32_checksum(CRC_CHECK_DATA, CRC_CHECK_DATA_LEN),
|
||||
0xCBF43926);
|
||||
TEST_ASSERT_EQUAL_HEX(crc32_checksum("Hello World", 11), 0x4a17b156);
|
||||
}
|
56
crates/algorithms/algorithms-c/test/hash/test_sha2.c
Normal file
56
crates/algorithms/algorithms-c/test/hash/test_sha2.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "hash.h"
|
||||
#include "sha2.h"
|
||||
#include "trace.h"
|
||||
#include "unity.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
void setUp(void) {}
|
||||
|
||||
void tearDown(void) {}
|
||||
|
||||
// BUG: may drop the null at end of strings
|
||||
#define SAMPLE(INPUT, HASH) \
|
||||
{(uint8_t[]){INPUT "\0"}, (uint8_t *)(uint32_t[])HASH}
|
||||
|
||||
#define TEST_VALUES_LEN 2
|
||||
uint8_t *test_values[TEST_VALUES_LEN][2] = {
|
||||
SAMPLE("AAAA", HASH(0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8,
|
||||
0xed584f16, 0x2f46e715, 0x114ee184, 0xf8de9201)),
|
||||
SAMPLE("BAAA", HASH(0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c,
|
||||
0xb63c6ef8, 0xc4e7d486, 0x08995343, 0x7f83a159)),
|
||||
};
|
||||
|
||||
void test_sha2_check(void) {
|
||||
SHA2Digest digest;
|
||||
SHA2Result res;
|
||||
uint8_t *input;
|
||||
size_t len;
|
||||
size_t i;
|
||||
for (i = 0; i < TEST_VALUES_LEN; i++) {
|
||||
TRACE("Hash iteration %d\n", i);
|
||||
input = test_values[i][0];
|
||||
len = strlen((char *)input);
|
||||
TRACELN("Input:");
|
||||
dump_data(input, len);
|
||||
|
||||
TRACELN("Call oneshot");
|
||||
res = sha2_256_oneshot(input, len, digest);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(
|
||||
shaSuccess, res,
|
||||
"sha2_256_oneshot exited with a code that is not shaSuccess");
|
||||
|
||||
// NOTE: If it segfaults here, then the sha2_oneshot function is at fault
|
||||
// anyways!!!!!!!!!!!!
|
||||
TRACELN("Hash should be:");
|
||||
print_digest(test_values[i][1]); // idk how to fix this warning
|
||||
|
||||
TRACELN("Hash is:");
|
||||
print_digest(digest);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(test_values[i][1], digest,
|
||||
SHA2_256_HashParts);
|
||||
}
|
||||
}
|
12
crates/algorithms/algorithms-c/test/test_algorithms.c
Normal file
12
crates/algorithms/algorithms-c/test/test_algorithms.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
#include "unity.h"
|
||||
|
||||
#include "algorithms.h"
|
||||
|
||||
void setUp(void) {}
|
||||
|
||||
void tearDown(void) {}
|
||||
|
||||
void test_algorithms_loaded(void) {
|
||||
TEST_ASSERT(algorithms_c_is_loaded() == 1);
|
||||
}
|
22
crates/algorithms/benches/crc32bench.rs
Executable file
22
crates/algorithms/benches/crc32bench.rs
Executable file
|
@ -0,0 +1,22 @@
|
|||
use algorithms::crc::{self, Crc};
|
||||
use algorithms::hash;
|
||||
use criterion::{Criterion, black_box, criterion_group, criterion_main};
|
||||
|
||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
c.bench_function("crc32", |b| {
|
||||
b.iter(|| crc::Crc32::checksum(black_box(&crc::CHECK_DATA)))
|
||||
});
|
||||
c.bench_function("ffi::crc32", |b| {
|
||||
b.iter(|| crc::ffi::Crc32::checksum(black_box(&crc::CHECK_DATA)))
|
||||
});
|
||||
|
||||
c.bench_function("sha2_256", |b| {
|
||||
b.iter(|| hash::sha2_256_oneshot(black_box(hash::HASH_EXAMPLE_DATA)))
|
||||
});
|
||||
c.bench_function("ffi::sha2_256", |b| {
|
||||
b.iter(|| hash::ffi::sha2_256_oneshot(black_box(hash::HASH_EXAMPLE_DATA)))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, criterion_benchmark);
|
||||
criterion_main!(benches);
|
24
crates/algorithms/benches/crc32bench_iai.rs
Executable file
24
crates/algorithms/benches/crc32bench_iai.rs
Executable file
|
@ -0,0 +1,24 @@
|
|||
use algorithms::crc::{self, Crc};
|
||||
use algorithms::hash;
|
||||
use iai::black_box;
|
||||
|
||||
fn crc_benchmark_native() -> <crc::Crc32 as Crc>::Checksum {
|
||||
crc::Crc32::checksum(black_box(&crc::CHECK_DATA))
|
||||
}
|
||||
fn crc_benchmark_ffi() -> <crc::ffi::Crc32 as Crc>::Checksum {
|
||||
crc::ffi::Crc32::checksum(black_box(&crc::CHECK_DATA))
|
||||
}
|
||||
|
||||
fn hash_benchmark_native() -> hash::Digest256 {
|
||||
hash::sha2_256_oneshot(hash::HASH_EXAMPLE_DATA).unwrap()
|
||||
}
|
||||
fn hash_benchmark_ffi() -> hash::Digest256 {
|
||||
hash::ffi::sha2_256_oneshot(hash::HASH_EXAMPLE_DATA).unwrap()
|
||||
}
|
||||
|
||||
iai::main!(
|
||||
crc_benchmark_native,
|
||||
crc_benchmark_ffi,
|
||||
hash_benchmark_native,
|
||||
hash_benchmark_ffi
|
||||
);
|
67
crates/algorithms/build.rs
Executable file
67
crates/algorithms/build.rs
Executable file
|
@ -0,0 +1,67 @@
|
|||
fn env(s: &str) -> String {
|
||||
std::env::var(s).unwrap()
|
||||
}
|
||||
|
||||
// do yourself a favor if you can, don't use windows
|
||||
fn main() {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
println!(concat!(
|
||||
"NOTE: Windows can't easily find what to execute for 'ceedling' (the build system for algorithms-c).\n",
|
||||
"You may need to set it's path in crates/algorithms/build.rs"
|
||||
));
|
||||
|
||||
std::process::Command::new("ceedling.bat")
|
||||
.arg("clobber")
|
||||
.current_dir("./algorithms-c/")
|
||||
.status()
|
||||
.expect("could not cleanup old algorithms-c files");
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
std::process::Command::new("ceedling")
|
||||
.arg("clobber")
|
||||
.current_dir("./algorithms-c/")
|
||||
.status()
|
||||
.expect("could not cleanup old algorithms-c files");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let mut cmd = std::process::Command::new("ceedling.bat");
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let mut cmd = std::process::Command::new("ceedling");
|
||||
|
||||
let arch = env("CARGO_CFG_TARGET_ARCH");
|
||||
let pw = env("CARGO_CFG_TARGET_POINTER_WIDTH");
|
||||
let os = env("CARGO_CFG_TARGET_OS");
|
||||
|
||||
if arch == "arm" && pw == "32" && os == "none" {
|
||||
cmd.env("CC", "arm-none-eabi-gcc")
|
||||
.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 {
|
||||
panic!("Unsupported build target")
|
||||
}
|
||||
|
||||
println!("Cwd: {}", std::env::current_dir().unwrap().display());
|
||||
let status = cmd
|
||||
.arg("release")
|
||||
.current_dir("./algorithms-c")
|
||||
.status()
|
||||
.expect("could not make c stuff");
|
||||
if !status.success() {
|
||||
panic!("ceedling returned an error")
|
||||
}
|
||||
let cwd = std::env::current_dir().unwrap().display().to_string();
|
||||
let libpath_s = format!("{cwd}/algorithms-c/build/artifacts/release/libalgorithms.a");
|
||||
let libpath = std::path::Path::new(&libpath_s);
|
||||
assert!(libpath.exists());
|
||||
println!("cargo::rustc-link-lib=algorithms");
|
||||
println!("cargo::rerun-if-changed={cwd}/algorithms-c/src/");
|
||||
println!(
|
||||
"cargo::rustc-link-search={}",
|
||||
libpath.parent().unwrap().display()
|
||||
);
|
||||
}
|
18
crates/algorithms/src/bin/crc32sum.rs
Normal file
18
crates/algorithms/src/bin/crc32sum.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use std::io::Read;
|
||||
|
||||
use algorithms::crc::Crc;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let use_ffi = args.contains(&"-c".to_string());
|
||||
let mut input = Vec::new();
|
||||
std::io::stdin()
|
||||
.read_to_end(&mut input)
|
||||
.expect("could not read from stdin");
|
||||
let crc = if use_ffi {
|
||||
algorithms::crc::ffi::Crc32::checksum(&input)
|
||||
} else {
|
||||
algorithms::crc::Crc32::checksum(&input)
|
||||
};
|
||||
println!("{crc:08x}");
|
||||
}
|
18
crates/algorithms/src/bin/sha256sum.rs
Normal file
18
crates/algorithms/src/bin/sha256sum.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use std::io::Read;
|
||||
|
||||
use algorithms::hash::format_digest;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let use_ffi = args.contains(&"-c".to_string());
|
||||
let mut input = Vec::new();
|
||||
std::io::stdin()
|
||||
.read_to_end(&mut input)
|
||||
.expect("could not read from stdin");
|
||||
let hash = if use_ffi {
|
||||
algorithms::hash::ffi::sha2_256_oneshot(&input).expect("could not hash your input data")
|
||||
} else {
|
||||
algorithms::hash::sha2_256_oneshot(&input).expect("could not hash your input data")
|
||||
};
|
||||
println!("{}", format_digest(&hash));
|
||||
}
|
82
crates/algorithms/src/crc/crc_32.rs
Executable file
82
crates/algorithms/src/crc/crc_32.rs
Executable file
|
@ -0,0 +1,82 @@
|
|||
//! See RFC1662 Appendix C.3
|
||||
//!
|
||||
//! [Link](https://datatracker.ietf.org/doc/html/rfc1662#appendix-C.3)
|
||||
|
||||
use super::Crc;
|
||||
|
||||
/// Lookup table from RFC1662 C.3
|
||||
pub const CRC32_TABLE: [u32; 256] = [
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
];
|
||||
/// Initial Value from RFC1662
|
||||
pub const CRC32_INIT: u32 = 0xffffffff;
|
||||
|
||||
/// Implements CRC-32/ISO-HDLC with look up table
|
||||
pub struct Crc32(<Crc32 as Crc>::Checksum);
|
||||
impl Crc for Crc32 {
|
||||
type Input = [u8];
|
||||
type Checksum = u32;
|
||||
|
||||
#[inline]
|
||||
fn new() -> Self {
|
||||
Self(Self::Checksum::default())
|
||||
}
|
||||
#[inline]
|
||||
fn shift_reg(&mut self) -> &mut Self::Checksum {
|
||||
&mut self.0
|
||||
}
|
||||
fn process(&mut self, data: &Self::Input) {
|
||||
let chksum = self.shift_reg();
|
||||
*chksum = CRC32_INIT;
|
||||
for byte in data {
|
||||
*chksum ^= *byte as u32;
|
||||
*chksum = (*chksum >> 8) ^ CRC32_TABLE[(*chksum & 0xff) as usize];
|
||||
}
|
||||
*chksum ^= CRC32_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::crc::CHECK_DATA;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_check() {
|
||||
// see https://reveng.sourceforge.io/crc-catalogue/17plus.htm#crc.cat-bits.32 for the check
|
||||
// value
|
||||
assert_eq!(Crc32::checksum(&CHECK_DATA), 0xCBF43926);
|
||||
}
|
||||
}
|
65
crates/algorithms/src/crc/ffi/crc32.rs
Executable file
65
crates/algorithms/src/crc/ffi/crc32.rs
Executable file
|
@ -0,0 +1,65 @@
|
|||
use crate::{crc::Crc, ffi::ref_to_ptr};
|
||||
|
||||
pub type ChecksumCrc32 = u32; // uint32_t in C
|
||||
|
||||
unsafe extern "C" {
|
||||
fn crc32_new() -> Crc32;
|
||||
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)]
|
||||
pub struct Crc32 {
|
||||
buf: ChecksumCrc32,
|
||||
}
|
||||
|
||||
impl Crc for Crc32 {
|
||||
type Input = [u8];
|
||||
|
||||
type Checksum = ChecksumCrc32;
|
||||
|
||||
#[inline(always)]
|
||||
fn new() -> Self {
|
||||
unsafe { crc32_new() }
|
||||
}
|
||||
|
||||
#[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(always)]
|
||||
fn shift_reg(&mut self) -> &mut Self::Checksum {
|
||||
&mut self.buf
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_check() {
|
||||
// see https://reveng.sourceforge.io/crc-catalogue/17plus.htm#crc.cat-bits.32 for the check
|
||||
// value
|
||||
assert_eq!(Crc32::checksum(&CHECK_DATA), 0xCBF43926);
|
||||
}
|
||||
}
|
3
crates/algorithms/src/crc/ffi/mod.rs
Executable file
3
crates/algorithms/src/crc/ffi/mod.rs
Executable file
|
@ -0,0 +1,3 @@
|
|||
mod crc32;
|
||||
|
||||
pub use crc32::*;
|
22
crates/algorithms/src/crc/mod.rs
Executable file
22
crates/algorithms/src/crc/mod.rs
Executable file
|
@ -0,0 +1,22 @@
|
|||
/// CRCs from this module are implemented in C instead of Rust
|
||||
pub mod ffi;
|
||||
|
||||
mod crc_32;
|
||||
pub use crc_32::*;
|
||||
|
||||
pub const CHECK_DATA: [u8; 9] = *b"123456789";
|
||||
|
||||
pub trait Crc: Sized {
|
||||
type Input: ?Sized;
|
||||
type Checksum: Eq + Default + Copy;
|
||||
|
||||
fn new() -> Self;
|
||||
fn process(&mut self, data: &Self::Input);
|
||||
fn shift_reg(&mut self) -> &mut Self::Checksum;
|
||||
#[inline]
|
||||
fn checksum(data: &Self::Input) -> Self::Checksum {
|
||||
let mut c = Self::new();
|
||||
c.process(data);
|
||||
*c.shift_reg()
|
||||
}
|
||||
}
|
28
crates/algorithms/src/ffi/mod.rs
Executable file
28
crates/algorithms/src/ffi/mod.rs
Executable file
|
@ -0,0 +1,28 @@
|
|||
unsafe extern "C" {
|
||||
fn algorithms_c_is_loaded() -> i32;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ffi_is_loaded() -> bool {
|
||||
unsafe { algorithms_c_is_loaded() == 1 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn ref_to_ptr<T: ?Sized, P>(r: &T) -> *const P {
|
||||
r as *const T as *const P
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn ref_to_ptr_mut<T: ?Sized, P>(r: &mut T) -> *mut P {
|
||||
r as *mut T as *mut P
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::ffi_is_loaded;
|
||||
|
||||
#[test]
|
||||
fn test_ffi_loaded() {
|
||||
assert!(ffi_is_loaded())
|
||||
}
|
||||
}
|
2
crates/algorithms/src/hash/ffi/mod.rs
Normal file
2
crates/algorithms/src/hash/ffi/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
mod sha2;
|
||||
pub use sha2::*;
|
128
crates/algorithms/src/hash/ffi/sha2.rs
Normal file
128
crates/algorithms/src/hash/ffi/sha2.rs
Normal file
|
@ -0,0 +1,128 @@
|
|||
use crate::ffi::{ref_to_ptr, ref_to_ptr_mut};
|
||||
|
||||
use super::super::sha2::{DIGEST256_EMPTY, Digest256, SHA2_256_BLOCK_SIZE};
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(unused)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum SHA2Outcome {
|
||||
shaSuccess = 0,
|
||||
shaNull, /* Null pointer parameter */
|
||||
shaInputTooLong, /* input data too long */
|
||||
shaStateError, /* called Input after Result */
|
||||
shaBadArg, /* Bad argument was given to a function */
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub struct Sha2_256Context {
|
||||
pub intermediate_hash: Digest256,
|
||||
pub length_low: u32,
|
||||
pub length_high: u32,
|
||||
pub message_block_index: i16,
|
||||
pub message_block: [u8; SHA2_256_BLOCK_SIZE],
|
||||
pub computed: bool,
|
||||
pub corrupted: bool,
|
||||
}
|
||||
|
||||
impl Sha2_256Context {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
intermediate_hash: DIGEST256_EMPTY,
|
||||
length_low: 0,
|
||||
length_high: 0,
|
||||
message_block_index: 0,
|
||||
message_block: [0; SHA2_256_BLOCK_SIZE],
|
||||
computed: false,
|
||||
corrupted: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Sha2_256Context {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
mod ffi {
|
||||
use super::*;
|
||||
unsafe extern "C" {
|
||||
pub fn sha2_256_oneshot(data: *const u8, len: usize, digest: *mut Digest256)
|
||||
-> SHA2Outcome;
|
||||
pub fn sha2_256_reset(context: *mut Sha2_256Context) -> SHA2Outcome;
|
||||
pub fn sha2_256_input(
|
||||
context: *mut Sha2_256Context,
|
||||
data: *const u8,
|
||||
len: usize,
|
||||
) -> SHA2Outcome;
|
||||
pub fn sha2_256_result(
|
||||
context: *mut Sha2_256Context,
|
||||
digest: *mut Digest256,
|
||||
) -> SHA2Outcome;
|
||||
|
||||
pub fn sha2_256_oneshot_n_times(n: u32, data: *const u8, len: usize);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Outcome> {
|
||||
let mut digest: Digest256 = DIGEST256_EMPTY;
|
||||
let res =
|
||||
unsafe { ffi::sha2_256_oneshot(ref_to_ptr(data), data.len(), ref_to_ptr_mut(&mut digest)) };
|
||||
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(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)
|
||||
} else {
|
||||
Err(res)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: this SHA2_256 implementation does not suit core::hash::Hasher in Rust, since that expects
|
||||
// a finish method with &self and that the hasher can be used after finish.
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::hash::Digest256;
|
||||
use crate::hash::ffi::sha2_256_oneshot;
|
||||
use crate::hash::test::TEST_VALUES;
|
||||
|
||||
#[test]
|
||||
fn test_sha2_ffi_check() {
|
||||
for (input, expected_output) in TEST_VALUES.iter().copied() {
|
||||
assert_eq!(sha2_256_oneshot(input.as_bytes()), Ok(expected_output))
|
||||
}
|
||||
}
|
||||
}
|
79
crates/algorithms/src/hash/mod.rs
Normal file
79
crates/algorithms/src/hash/mod.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
pub mod ffi;
|
||||
|
||||
mod sha2;
|
||||
pub use sha2::*;
|
||||
|
||||
pub const HASH_EXAMPLE_DATA: &[u8] = b"lalilolela";
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn format_digest(digest: &[u32]) -> String {
|
||||
digest
|
||||
.iter()
|
||||
.map(|b| format!("{b:08x}"))
|
||||
.collect::<String>()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test {
|
||||
use super::*;
|
||||
use assert_hex::*;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_eq_bin {
|
||||
($left:expr, $right:expr $(,)?) => ({
|
||||
match (&$left, &$right) {
|
||||
(left_val, right_val) => {
|
||||
if !(*left_val == *right_val) {
|
||||
panic!(r#"assertion `left == right` failed
|
||||
left: {:b}
|
||||
right: {:b}"#, &*left_val, &*right_val)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
($left:expr, $right:expr, $($arg:tt)+) => ({
|
||||
match (&($left), &($right)) {
|
||||
(left_val, right_val) => {
|
||||
if !(*left_val == *right_val) {
|
||||
panic!(r#"assertion `left == right` failed: {}
|
||||
left: {:b}
|
||||
right: {:b}"#, format_args!($($arg)+), &*left_val, &*right_val)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) const TEST_VALUES: &[(&str, Digest256)] = &[
|
||||
(
|
||||
"AAAA",
|
||||
[
|
||||
0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, 0xed584f16, 0x2f46e715, 0x114ee184,
|
||||
0xf8de9201,
|
||||
],
|
||||
),
|
||||
(
|
||||
"BAAA",
|
||||
[
|
||||
0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c, 0xb63c6ef8, 0xc4e7d486, 0x08995343,
|
||||
0x7f83a159,
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn test_sha2_ffi_same_as_native() {
|
||||
let mut dig_native;
|
||||
let mut dig_ffi;
|
||||
for (input, expected_output) in TEST_VALUES.iter().copied() {
|
||||
dig_native = sha2_256_oneshot(input.as_bytes()).unwrap();
|
||||
dig_ffi = ffi::sha2_256_oneshot(input.as_bytes()).unwrap();
|
||||
assert_eq_hex!(
|
||||
dig_native,
|
||||
dig_ffi,
|
||||
"ffi does not return the same result as native"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
393
crates/algorithms/src/hash/sha2.rs
Normal file
393
crates/algorithms/src/hash/sha2.rs
Normal file
|
@ -0,0 +1,393 @@
|
|||
use crate::hash::ffi::SHA2Outcome;
|
||||
|
||||
pub const SHA2_256_HASH_BITS: usize = 256;
|
||||
pub const SHA2_256_HASH_BYTES: usize = SHA2_256_HASH_BITS / 8;
|
||||
pub const SHA2_256_HASH_PARTS: usize = SHA2_256_HASH_BYTES / 4 /* storing with u32 */;
|
||||
pub const SHA2_256_BLOCK_SIZE: usize = 2 * SHA2_256_HASH_BYTES;
|
||||
|
||||
pub type Digest256 = [u32; SHA2_256_HASH_PARTS];
|
||||
pub(crate) const DIGEST256_EMPTY: Digest256 = [0; SHA2_256_HASH_PARTS];
|
||||
|
||||
macro_rules! show_internals {
|
||||
($block:block) => {
|
||||
#[cfg(feature = "show_internals")]
|
||||
$block
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Hash)]
|
||||
pub struct Sha2_256Context {
|
||||
intermediate_hash: Digest256,
|
||||
block: [u8; SHA2_256_BLOCK_SIZE],
|
||||
block_idx: usize,
|
||||
length_low: usize,
|
||||
length_high: usize,
|
||||
}
|
||||
|
||||
impl Sha2_256Context {
|
||||
const K: [u32; SHA2_256_BLOCK_SIZE] = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
|
||||
0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
|
||||
0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
|
||||
0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
|
||||
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
|
||||
0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
|
||||
0xc67178f2,
|
||||
];
|
||||
const H: [u32; SHA2_256_HASH_PARTS] = [
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
|
||||
0x5be0cd19,
|
||||
];
|
||||
const PAD_BYTE: u8 = 0x80;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
intermediate_hash: Self::H,
|
||||
block: [0; SHA2_256_BLOCK_SIZE],
|
||||
block_idx: Default::default(),
|
||||
length_low: Default::default(),
|
||||
length_high: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
*self = Self::new();
|
||||
}
|
||||
|
||||
pub fn input(&mut self, data: &[u8]) -> Result<(), SHA2Outcome> {
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
for byte in data {
|
||||
self.block[self.block_idx] = *byte;
|
||||
self.block_idx += 1;
|
||||
if self.add_length(8).is_ok() && self.block_idx == SHA2_256_BLOCK_SIZE {
|
||||
self.process_block();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn finish(mut self) -> Result<Digest256, SHA2Outcome> {
|
||||
self.finalize();
|
||||
Ok(self.intermediate_hash)
|
||||
}
|
||||
|
||||
fn process_block(&mut self) {
|
||||
show_internals!({
|
||||
self.show_internal_state("start processing");
|
||||
});
|
||||
|
||||
let mut w = [0; SHA2_256_BLOCK_SIZE];
|
||||
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for t in 0..16 {
|
||||
let t4 = t * 4;
|
||||
w[t] = ((self.block[t4] as u32) << 24)
|
||||
| ((self.block[t4 + 1] as u32) << 16)
|
||||
| ((self.block[t4 + 2] as u32) << 8)
|
||||
| (self.block[t4 + 3] as u32);
|
||||
}
|
||||
|
||||
// NOTE: The sigma functions used for initializing W and for calculating the alphabet
|
||||
// variables differ.
|
||||
for t in 16..SHA2_256_BLOCK_SIZE {
|
||||
w[t] = Self::sha256_sigma1_w(w[t - 2])
|
||||
.wrapping_add(w[t - 7])
|
||||
.wrapping_add(Self::sha256_sigma0_w(w[t - 15]))
|
||||
.wrapping_add(w[t - 16]);
|
||||
}
|
||||
|
||||
show_internals!({
|
||||
for (i, w) in w.iter().enumerate() {
|
||||
println!("w[{i}]:\t{w:032b}")
|
||||
}
|
||||
});
|
||||
|
||||
let mut a = self.intermediate_hash[0];
|
||||
let mut b = self.intermediate_hash[1];
|
||||
let mut c = self.intermediate_hash[2];
|
||||
let mut d = self.intermediate_hash[3];
|
||||
let mut e = self.intermediate_hash[4];
|
||||
let mut f = self.intermediate_hash[5];
|
||||
let mut g = self.intermediate_hash[6];
|
||||
let mut h = self.intermediate_hash[7];
|
||||
|
||||
show_internals!({
|
||||
println!("A:\t{a:032b}");
|
||||
println!("B:\t{b:032b}");
|
||||
println!("C:\t{c:032b}");
|
||||
println!("D:\t{d:032b}");
|
||||
println!("E:\t{e:032b}");
|
||||
println!("F:\t{f:032b}");
|
||||
println!("G:\t{g:032b}");
|
||||
println!("H:\t{h:032b}");
|
||||
});
|
||||
|
||||
let mut temp1;
|
||||
let mut temp2;
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for t in 0..SHA2_256_BLOCK_SIZE {
|
||||
show_internals!({
|
||||
println!("Iter {t}");
|
||||
});
|
||||
|
||||
temp1 = h
|
||||
.wrapping_add(Self::sha256_sigma1(e))
|
||||
.wrapping_add(Self::sha_ch(e, f, g))
|
||||
.wrapping_add(Self::K[t])
|
||||
.wrapping_add(w[t]);
|
||||
temp2 = Self::sha256_sigma0(a).wrapping_add(Self::sha_maj(a, b, c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d.wrapping_add(temp1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = temp1.wrapping_add(temp2);
|
||||
|
||||
show_internals!({
|
||||
println!("temp1:\t{temp1:032b} {temp1:08x}");
|
||||
println!("temp2:\t{temp2:032b} {temp2:08x}");
|
||||
println!("A:\t{a:032b} {a:08x}");
|
||||
println!("B:\t{b:032b} {b:08x}");
|
||||
println!("C:\t{c:032b} {c:08x}");
|
||||
println!("D:\t{d:032b} {d:08x}");
|
||||
println!("E:\t{e:032b} {e:08x}");
|
||||
println!("F:\t{f:032b} {f:08x}");
|
||||
println!("G:\t{g:032b} {g:08x}");
|
||||
println!("H:\t{h:032b} {h:08x}");
|
||||
for (i, h) in self.intermediate_hash.iter().enumerate() {
|
||||
println!("h[{i}]:\t{h:032b} {h:08x}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
show_internals!({
|
||||
self.show_internal_state("assigning intermediate_hash");
|
||||
});
|
||||
|
||||
self.intermediate_hash[0] = self.intermediate_hash[0].wrapping_add(a);
|
||||
self.intermediate_hash[1] = self.intermediate_hash[1].wrapping_add(b);
|
||||
self.intermediate_hash[2] = self.intermediate_hash[2].wrapping_add(c);
|
||||
self.intermediate_hash[3] = self.intermediate_hash[3].wrapping_add(d);
|
||||
self.intermediate_hash[4] = self.intermediate_hash[4].wrapping_add(e);
|
||||
self.intermediate_hash[5] = self.intermediate_hash[5].wrapping_add(f);
|
||||
self.intermediate_hash[6] = self.intermediate_hash[6].wrapping_add(g);
|
||||
self.intermediate_hash[7] = self.intermediate_hash[7].wrapping_add(h);
|
||||
|
||||
self.block_idx = 0;
|
||||
|
||||
show_internals!({
|
||||
self.show_internal_state("processing end");
|
||||
for (i, h) in self.intermediate_hash.iter().enumerate() {
|
||||
println!("h[{i}]:\t{h:032b}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn add_length(&mut self, len: usize) -> Result<(), SHA2Outcome> {
|
||||
let add_temp = self.length_low;
|
||||
|
||||
// Update length_low and check for overflow
|
||||
self.length_low = self.length_low.wrapping_add(len);
|
||||
if self.length_low < add_temp {
|
||||
// Overflow occurred, increment length_high
|
||||
self.length_high = self.length_high.wrapping_add(1);
|
||||
if self.length_high == 0 {
|
||||
return Err(SHA2Outcome::shaInputTooLong);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finalize(&mut self) {
|
||||
self.pad_block();
|
||||
}
|
||||
|
||||
fn pad_block(&mut self) {
|
||||
if self.block_idx >= (SHA2_256_BLOCK_SIZE - 8) {
|
||||
self.block[self.block_idx] = Self::PAD_BYTE;
|
||||
self.block_idx += 1;
|
||||
while self.block_idx < SHA2_256_BLOCK_SIZE {
|
||||
self.block[self.block_idx] = 0;
|
||||
self.block_idx += 1;
|
||||
}
|
||||
self.process_block();
|
||||
} else {
|
||||
self.block[self.block_idx] = Self::PAD_BYTE;
|
||||
self.block_idx += 1;
|
||||
}
|
||||
|
||||
while self.block_idx < (SHA2_256_BLOCK_SIZE - 8) {
|
||||
self.block[self.block_idx] = 0;
|
||||
self.block_idx += 1;
|
||||
}
|
||||
|
||||
self.block[56] = (self.length_high >> 24) as u8;
|
||||
self.block[57] = (self.length_high >> 16) as u8;
|
||||
self.block[58] = (self.length_high >> 8) as u8;
|
||||
self.block[59] = (self.length_high) as u8;
|
||||
self.block[60] = (self.length_low >> 24) as u8;
|
||||
self.block[61] = (self.length_low >> 16) as u8;
|
||||
self.block[62] = (self.length_low >> 8) as u8;
|
||||
self.block[63] = (self.length_low) as u8;
|
||||
|
||||
self.process_block();
|
||||
}
|
||||
|
||||
#[cfg(feature = "show_internals")]
|
||||
fn show_internal_state(&self, msg: impl core::fmt::Display) {
|
||||
println!("{msg}\n{self:#x?}")
|
||||
}
|
||||
}
|
||||
|
||||
/// internal functions for SHA2 process_block
|
||||
impl Sha2_256Context {
|
||||
#[inline]
|
||||
fn sha256_shr(bits: u32, word: u32) -> u32 {
|
||||
word >> bits
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha256_rotr(bits: u32, word: u32) -> u32 {
|
||||
word.rotate_right(bits)
|
||||
}
|
||||
|
||||
/// This is a different function for W
|
||||
#[inline]
|
||||
fn sha256_sigma0_w(word: u32) -> u32 {
|
||||
Self::sha256_rotr(7, word) ^ Self::sha256_rotr(18, word) ^ Self::sha256_shr(3, word)
|
||||
}
|
||||
|
||||
/// This is a different function for W
|
||||
#[inline]
|
||||
fn sha256_sigma1_w(word: u32) -> u32 {
|
||||
Self::sha256_rotr(17, word) ^ Self::sha256_rotr(19, word) ^ Self::sha256_shr(10, word)
|
||||
}
|
||||
|
||||
// NOTE: these do not use shift right for the last internal variable!
|
||||
#[inline]
|
||||
fn sha256_sigma0(word: u32) -> u32 {
|
||||
Self::sha256_rotr(2, word) ^ Self::sha256_rotr(13, word) ^ Self::sha256_rotr(22, word)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha256_sigma1(word: u32) -> u32 {
|
||||
Self::sha256_rotr(6, word) ^ Self::sha256_rotr(11, word) ^ Self::sha256_rotr(25, word)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha_ch(x: u32, y: u32, z: u32) -> u32 {
|
||||
(x & (y ^ z)) ^ z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sha_maj(x: u32, y: u32, z: u32) -> u32 {
|
||||
(x & y) ^ (x & z) ^ (y & z)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Sha2_256Context {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sha2_256_oneshot(data: &[u8]) -> Result<Digest256, SHA2Outcome> {
|
||||
let mut ctx = Sha2_256Context::default();
|
||||
ctx.input(data)?;
|
||||
ctx.finish()
|
||||
}
|
||||
|
||||
#[cfg(feature = "show_internals")]
|
||||
#[allow(unused)]
|
||||
mod debug {
|
||||
use super::*;
|
||||
|
||||
struct InlineArrHex2<'a, T: core::fmt::Debug + core::fmt::LowerHex>(&'a [T]);
|
||||
|
||||
impl<'a, T> core::fmt::Debug for InlineArrHex2<'a, T>
|
||||
where
|
||||
T: core::fmt::Debug + core::fmt::LowerHex,
|
||||
{
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
writeln!(f, "[")?;
|
||||
for (i, t) in self.0.iter().enumerate() {
|
||||
write!(f, "0x{t:02x}")?;
|
||||
if i < self.0.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
if i % 8 == 7 && i < self.0.len() - 1 {
|
||||
writeln!(f)?;
|
||||
}
|
||||
}
|
||||
write!(f, "\n]")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Sha2_256Context {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("Sha2_256Context")
|
||||
.field("intermediate_hash", &InlineArrHex2(&self.intermediate_hash))
|
||||
.field("block", &InlineArrHex2(&self.block))
|
||||
.field("block_idx", &self.block_idx)
|
||||
.field("length_low", &self.length_low)
|
||||
.field("length_high", &self.length_high)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "show_internals")]
|
||||
#[allow(unused)]
|
||||
use debug::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::assert_eq_bin;
|
||||
use crate::hash::test::TEST_VALUES;
|
||||
use assert_hex::*;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
|
||||
#[test]
|
||||
fn test_sha256_check() {
|
||||
let mut dig;
|
||||
for (input, expected_output) in TEST_VALUES.iter().copied() {
|
||||
dig = sha2_256_oneshot(input.as_bytes()).unwrap();
|
||||
println!(
|
||||
"Binary of first seg matches: {}\n{:032b}\n{:032b}",
|
||||
dig[0] == expected_output[0],
|
||||
dig[0],
|
||||
expected_output[0]
|
||||
);
|
||||
assert_eq_hex!(dig, expected_output)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha256_sigma0() {
|
||||
let a = 0b01101010000010011110011001100111;
|
||||
assert_eq_bin!(
|
||||
Sha2_256Context::sha256_sigma0(a),
|
||||
0b11001110001000001011010001111110
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha256_sigma1() {
|
||||
let a = 0b01010001000011100101001001111111;
|
||||
assert_eq_bin!(
|
||||
Sha2_256Context::sha256_sigma1(a),
|
||||
0b00110101100001110010011100101011
|
||||
);
|
||||
}
|
||||
}
|
16
crates/algorithms/src/lib.rs
Executable file
16
crates/algorithms/src/lib.rs
Executable file
|
@ -0,0 +1,16 @@
|
|||
//! # CRC's from scratch, nothing else
|
||||
//!
|
||||
//! This crate implements some CRC algorithms from scratch in a `no_std` environment.
|
||||
//!
|
||||
//! ## Acknowledgements
|
||||
//!
|
||||
//! Many thanks to the [crc-catalogue](https://reveng.sourceforge.io/crc-catalogue/) for providing
|
||||
//! an overview over the various algorithms with test vectors and examples.
|
||||
|
||||
#![cfg_attr(not(any(test, feature = "std")), no_std)]
|
||||
|
||||
pub mod crc;
|
||||
pub mod hash;
|
||||
|
||||
pub(crate) mod ffi;
|
||||
pub use ffi::ffi_is_loaded;
|
|
@ -1,47 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use defmt::{debug, info};
|
||||
use hal::pwr::PWR;
|
||||
use hal::rtc::{Datelike, NaiveDateTime, Rtc, Timelike};
|
||||
use panic_probe as _;
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
const AES_PT: [u8; 16] = [
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
];
|
||||
const AES_KEY: [u32; 4] = [0x1991, 0x1991, 0xAAAAAAAA, 0xBBBBBBBB];
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
// WARN: Make sure your chip has AES
|
||||
panic!("The chip does not have an AES unit >:");
|
||||
let aes = hal::aes::AES::new(dp.AES, &mut rcc);
|
||||
let mut ecb_stream = aes.enable(<dyn hal::aes::Mode>::ecb_encrypt(), AES_KEY);
|
||||
let mut encbuf: [[u8; 16]; 4] = [[0; 16]; 4];
|
||||
|
||||
let mut i = 0;
|
||||
debug!("Entering Loop");
|
||||
#[allow(clippy::never_loop)]
|
||||
loop {
|
||||
debug!("reading from aes stream");
|
||||
encbuf[i % 4] = ecb_stream.process(&AES_PT).unwrap();
|
||||
|
||||
info!("encbuf[{:02}]: {:02x}", i, encbuf);
|
||||
|
||||
if i > 100 {
|
||||
delay.delay_ms(200_u16);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
//
|
||||
use panic_probe as _;
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let gpiob = dp.GPIOB.split(&mut rcc);
|
||||
|
||||
let mut builtin_led = gpioa.pa5.into_push_pull_output();
|
||||
let mut led0 = gpiob.pb5.into_push_pull_output(); // D4
|
||||
let mut led1 = gpiob.pb4.into_push_pull_output(); // D5
|
||||
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
builtin_led.set_high().unwrap();
|
||||
led0.set_high().unwrap();
|
||||
led1.set_high().unwrap();
|
||||
|
||||
loop {
|
||||
builtin_led.set_high().unwrap();
|
||||
led0.set_low().unwrap();
|
||||
led1.set_low().unwrap();
|
||||
delay.delay_ms(100_u16);
|
||||
|
||||
led0.set_high().unwrap();
|
||||
delay.delay_ms(100_u16);
|
||||
|
||||
builtin_led.set_low().unwrap();
|
||||
delay.delay_ms(100_u16);
|
||||
|
||||
led0.set_low().unwrap();
|
||||
led1.set_high().unwrap();
|
||||
delay.delay_ms(100_u16);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let gpioc = dp.GPIOC.split(&mut rcc);
|
||||
|
||||
// Configure PA5 as output.
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
let mut button = gpioc.pc13.into_pull_down_input();
|
||||
|
||||
// Get the delay provider.
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
loop {
|
||||
if button.is_low().expect("button.is_low failed") {
|
||||
led.set_high().unwrap();
|
||||
} else {
|
||||
led.set_low().unwrap();
|
||||
}
|
||||
|
||||
delay.delay_ms(10_u16);
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let gpioc = dp.GPIOC.split(&mut rcc);
|
||||
|
||||
// Configure PA5 as output.
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
let button = gpioc.pc13.into_pull_down_input();
|
||||
|
||||
// Get the delay provider.
|
||||
let mut _delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
let mut is_on: bool;
|
||||
let mut was_on: bool = false;
|
||||
#[allow(unused_variables)] // it is used later??
|
||||
let mut enable_led: bool = false;
|
||||
|
||||
loop {
|
||||
is_on = button.is_low().unwrap();
|
||||
if is_on != was_on {
|
||||
enable_led ^= true;
|
||||
}
|
||||
if is_on {
|
||||
led.set_high().unwrap();
|
||||
} else {
|
||||
led.set_low().unwrap();
|
||||
}
|
||||
|
||||
was_on = is_on;
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
extern crate panic_halt;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
// get access to the peripherals
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// configure the clock
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
// get access to GPIO Port A
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
|
||||
// configure Pin 5 og GPIO Port A as output
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
|
||||
// prepare delays (sleeping)
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
loop {
|
||||
led.set_high().unwrap(); // light on
|
||||
delay.delay_ms(500_u16); // wait
|
||||
|
||||
led.set_low().unwrap(); // light off
|
||||
delay.delay_ms(500_u16); // wait
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use defmt::info;
|
||||
use panic_probe as _;
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
use hd44780_driver::HD44780;
|
||||
|
||||
#[defmt::panic_handler]
|
||||
fn panic() -> ! {
|
||||
cortex_m::asm::udf()
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let gpiob = dp.GPIOB.split(&mut rcc);
|
||||
let gpioc = dp.GPIOC.split(&mut rcc);
|
||||
|
||||
// literal D4-D7 ports etc as written on the nucleo board, mapped to the D4-D7 ports of the LCD
|
||||
// controller
|
||||
let d4 = gpiob.pb5.into_push_pull_output();
|
||||
let d5 = gpiob.pb4.into_push_pull_output();
|
||||
let d6 = gpiob.pb10.into_push_pull_output();
|
||||
let d7 = gpioa.pa8.into_push_pull_output();
|
||||
|
||||
// clock enable on D9
|
||||
let en = gpioc.pc7.into_push_pull_output();
|
||||
// register select on D8, the lib wants that but I'd just put it on ground otherwise
|
||||
let rs = gpioa.pa9.into_push_pull_output();
|
||||
|
||||
// See https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller#Interface
|
||||
// for the pins of the LCD
|
||||
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
let mut lcd = HD44780::new_4bit(rs, en, d4, d5, d6, d7, &mut delay)
|
||||
.expect("could not init HD44780 driver");
|
||||
lcd.set_display_mode(
|
||||
hd44780_driver::DisplayMode {
|
||||
cursor_visibility: hd44780_driver::Cursor::Visible,
|
||||
cursor_blink: hd44780_driver::CursorBlink::On,
|
||||
display: hd44780_driver::Display::On,
|
||||
},
|
||||
&mut delay,
|
||||
)
|
||||
.expect("could not set display properties");
|
||||
lcd.reset(&mut delay).expect("could not reset the lcd");
|
||||
lcd.write_str("Hello world!", &mut delay)
|
||||
.expect("could not write to LCD");
|
||||
|
||||
let mut i = 0;
|
||||
loop {
|
||||
led.set_high().unwrap();
|
||||
info!("Writing to LCD...");
|
||||
lcd.write_str("Hello world!\nGoing on", &mut delay)
|
||||
.expect("could not write to LCD");
|
||||
|
||||
info!("Done!");
|
||||
led.set_low().unwrap();
|
||||
|
||||
delay.delay_ms(500_u16);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use defmt::{debug, error, info, println, trace, warn};
|
||||
use panic_probe as _;
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
|
||||
// the RCC register.
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
|
||||
// Configure PA5 as output.
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
|
||||
// Get the delay provider.
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
#[allow(clippy::never_loop)]
|
||||
loop {
|
||||
println!("Hello World!");
|
||||
trace!("trace log");
|
||||
debug!("debug log");
|
||||
info!("info log");
|
||||
warn!("warn log");
|
||||
error!("error log");
|
||||
|
||||
led.set_high().unwrap();
|
||||
delay.delay_ms(500_u16);
|
||||
|
||||
led.set_low().unwrap();
|
||||
delay.delay_ms(500_u16);
|
||||
|
||||
panic!("This will use the defmt panic handler too");
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use defmt::info;
|
||||
use hal::pwr::PWR;
|
||||
use hal::rtc::{Datelike, NaiveDateTime, Rtc, Timelike};
|
||||
use panic_probe as _;
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
let pwr = PWR::new(dp.PWR, &mut rcc);
|
||||
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
// Setup the Real-Time-Clock of the Controller.
|
||||
// starts at 0 (2001-01-01 00:00:00) and resets
|
||||
// when the Controller is no longer powered.
|
||||
let mut rtc = Rtc::new(dp.RTC, &mut rcc, &pwr, None).unwrap();
|
||||
|
||||
loop {
|
||||
led.set_high().unwrap(); // light on
|
||||
delay.delay_ms(500_u16); // wait
|
||||
|
||||
led.set_low().unwrap(); // light off
|
||||
delay.delay_ms(500_u16); // wait
|
||||
|
||||
// print the current time from the RTC
|
||||
ptime(&mut rtc);
|
||||
}
|
||||
}
|
||||
|
||||
/// prints the time to the "host" computer via RTT
|
||||
fn ptime(rtc: &mut Rtc) {
|
||||
let time: NaiveDateTime = rtc.now();
|
||||
info!(
|
||||
"Time: {:04}-{:02}-{:02} {:02}:{:02}:{:02}",
|
||||
time.year(),
|
||||
time.month(),
|
||||
time.day(),
|
||||
time.hour(),
|
||||
time.minute(),
|
||||
time.second()
|
||||
)
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
#![cfg_attr(not(test), no_main)]
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
#[cfg(not(test))]
|
||||
extern crate panic_halt;
|
||||
|
||||
use hal::adc::{Adc, Ready, VRef, VTemp};
|
||||
use hal::calibration::{VtempCal30, VtempCal130};
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
use defmt::{debug, info};
|
||||
use defmt_rtt as _; // global logger
|
||||
|
||||
#[cfg_attr(not(test), cortex_m_rt::entry)] // this is the entrypoint unless testing
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
let mut adc: Adc<_> = dp.ADC.constrain(&mut rcc);
|
||||
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
// NOTE: TSEN bit must be enabled for reading the temperature
|
||||
VTemp.enable(&mut adc);
|
||||
VRef.enable(&mut adc);
|
||||
|
||||
// reference temperatures from the chips readonly memory
|
||||
// [Source](https://www.st.com/resource/en/datasheet/stm32l053r8.pdf),
|
||||
// Table 6 in Secion 3.13 "Temperature sensor"
|
||||
//
|
||||
// More and better info in the large 1000+ page sheet "Ultra-low-power
|
||||
// STM32L0x3 advanced Arm®-based 32-bit MCUs" (RM0367), 14.9
|
||||
//
|
||||
// This is basically calibration data
|
||||
info!(
|
||||
"reading calibration data... If this is the last thing you hear from me something has gone terribly wrong"
|
||||
);
|
||||
let vref_cal = hal::calibration::VrefintCal::get().read();
|
||||
let tsense_cal1 = (30, VtempCal30::get().read());
|
||||
let tsense_cal2 = (130, VtempCal130::get().read());
|
||||
info!("tsense_cal1: {:?}", (30, tsense_cal1));
|
||||
info!("tsense_cal2: {:?}", (130, tsense_cal2));
|
||||
|
||||
// read a few values into void, maybe this will help get that thing started
|
||||
for _ in 0..20 {
|
||||
let _ = read_temp_mv(&mut adc, 1.0);
|
||||
delay.delay_ms(10_u16);
|
||||
}
|
||||
|
||||
let vref_actual: u16 = adc.read(&mut VRef).unwrap();
|
||||
let vref_factor = vref_cal as f32 / vref_actual as f32;
|
||||
info!(
|
||||
"vref actual={} calibration={} => factor={}",
|
||||
vref_actual, vref_cal, vref_factor
|
||||
);
|
||||
|
||||
delay.delay_ms(10_u16);
|
||||
|
||||
let mut temp_c;
|
||||
let mut temp_mv;
|
||||
loop {
|
||||
temp_mv = read_temp_mv(&mut adc, vref_factor);
|
||||
temp_c = temp_mv_to_c(temp_mv, tsense_cal1, tsense_cal2);
|
||||
info!("Temperature: {:03}mv, {:04}°C", temp_mv, temp_c as i32);
|
||||
delay.delay_ms(500_u16);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_temp_mv(adc: &mut Adc<Ready>, vref_factor: f32) -> f32 {
|
||||
let bare: f32 = adc.read(&mut VTemp).expect("could not read with adc");
|
||||
bare * vref_factor
|
||||
}
|
||||
|
||||
// This unholy abomination is from the datasheet and does not actually look so bad if it's written
|
||||
// in Math instead of Rust.
|
||||
fn temp_mv_to_c(temp: f32, ts_cal_1: (i32, u16), ts_cal_2: (i32, u16)) -> f32 {
|
||||
((ts_cal_2.0 as f32 - ts_cal_1.0 as f32) / (ts_cal_2.1 as f32 - ts_cal_1.1 as f32))
|
||||
* (temp - ts_cal_1.1 as f32)
|
||||
+ ts_cal_1.0 as f32
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// run these tests: cargo test --example=temperature --target=x86_64-unknown-linux-gnu
|
||||
use super::temp_mv_to_c;
|
||||
|
||||
#[test]
|
||||
fn test_mv_to_c() {
|
||||
// values read out from my board as logged
|
||||
// after flashing and running
|
||||
//
|
||||
// First is the temperature for that calibratoin, second is the measured voltage at that
|
||||
// temperature
|
||||
let calibration_data = [(30, 673), (130, 912)];
|
||||
for caldat in calibration_data {
|
||||
let degrees: f32 =
|
||||
temp_mv_to_c(caldat.1 as f32, calibration_data[0], calibration_data[1]);
|
||||
assert_eq!(caldat.0 as f32, degrees);
|
||||
dbg!(caldat);
|
||||
dbg!(degrees);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
//! This example shows how a embedded program can be written that is testable on the host with
|
||||
//! libtest.
|
||||
//!
|
||||
//! The tests can be run with:
|
||||
//! ```bash
|
||||
//! cargo test --example=test-on-host --target=x86_64-unknown-linux-gnu
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(not(test), no_main)]
|
||||
#![no_std]
|
||||
|
||||
#[cfg(not(test))]
|
||||
extern crate panic_halt;
|
||||
|
||||
use hal::{pac, prelude::*, rcc::Config};
|
||||
|
||||
#[cfg_attr(not(test), cortex_m_rt::entry)] // this is the entrypoint unless testing
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
// Acquire the GPIOA peripheral. This also enables the clock for GPIOA in
|
||||
// the RCC register.
|
||||
let gpioa = dp.GPIOA.split(&mut rcc);
|
||||
|
||||
// Configure PA5 as output.
|
||||
let mut led = gpioa.pa5.into_push_pull_output();
|
||||
|
||||
// Get the delay provider.
|
||||
let mut delay = cp.SYST.delay(rcc.clocks);
|
||||
|
||||
loop {
|
||||
led.set_high().unwrap();
|
||||
delay.delay_ms(500_u16);
|
||||
|
||||
let important_number = some_function(19);
|
||||
delay.delay_ms(important_number as u16);
|
||||
|
||||
led.set_low().unwrap();
|
||||
delay.delay_ms(500_u16);
|
||||
}
|
||||
}
|
||||
|
||||
fn some_function(num: i32) -> i32 {
|
||||
num * 2
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::some_function;
|
||||
|
||||
#[test]
|
||||
fn test_it_works() {
|
||||
assert_eq!(some_function(9), 18)
|
||||
}
|
||||
}
|
BIN
measurements/measurement-2025-08-11.tar.gz
Normal file
BIN
measurements/measurement-2025-08-11.tar.gz
Normal file
Binary file not shown.
1
measurements/measurement-2025-08-11.tar.gz.sha256
Normal file
1
measurements/measurement-2025-08-11.tar.gz.sha256
Normal file
|
@ -0,0 +1 @@
|
|||
37206c142fbe243e5eb299fea8fa4a0cc7b26d668dc394d8851c8059c5a8abcf measurement-2025-08-11.tar.gz
|
6
scripts/bench_algorithms.sh
Executable file
6
scripts/bench_algorithms.sh
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
# I'm using a bash script because if i set the target in .cargo/config.toml
|
||||
# i can't build for x86_64 anymore, which means I can't run the unit tests.
|
||||
TARGET="x86_64-unknown-linux-gnu"
|
||||
cd crates/algorithms
|
||||
cargo bench --target $TARGET --no-default-features
|
5
scripts/build.sh
Executable file
5
scripts/build.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
# I'm using a bash script because if i set the target in .cargo/config.toml
|
||||
# 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 $@
|
6
scripts/flash.sh
Executable file
6
scripts/flash.sh
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
# I'm using a bash script because if i set the target in .cargo/config.toml
|
||||
# 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 -r --target $TARGET $@
|
6
scripts/test_algorithms.sh
Executable file
6
scripts/test_algorithms.sh
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
# I'm using a bash script because if i set the target in .cargo/config.toml
|
||||
# i can't build for x86_64 anymore, which means I can't run the unit tests.
|
||||
TARGET="x86_64-unknown-linux-gnu"
|
||||
cd crates/algorithms
|
||||
cargo test --target $TARGET --no-default-features
|
2
scripts/winattach.sh
Executable file
2
scripts/winattach.sh
Executable 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"
|
10
scripts/winflash.sh
Executable file
10
scripts/winflash.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
bash ./scripts/copy_to_svn.sh
|
||||
TARGET="thumbv6m-none-eabi"
|
||||
|
||||
powershell.exe -Command "
|
||||
cd C:\SVN\nt\BA\trunk\Studium\Christoph_Scherr\system\Implementation\crcbench;
|
||||
cargo build -r --target $TARGET;
|
||||
cargo run -r --target $TARGET $@
|
||||
"
|
130
src/bench.rs
Normal file
130
src/bench.rs
Normal file
|
@ -0,0 +1,130 @@
|
|||
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,
|
||||
gpio::{Output, Pin, PushPull},
|
||||
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(pins: &mut MeasurePins, delay: &mut Delay) {
|
||||
bench_crc(pins, delay);
|
||||
bench_sha256(pins, delay);
|
||||
}
|
||||
|
||||
fn time_exec<F>(
|
||||
id: &str,
|
||||
kind: MeasurementKind,
|
||||
pins: &mut MeasurePins,
|
||||
delay: &mut Delay,
|
||||
do_loop: bool,
|
||||
mut f: F,
|
||||
) where
|
||||
F: FnMut(),
|
||||
{
|
||||
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);
|
||||
}
|
||||
info!("Measurement of '{}' finished!", id);
|
||||
delay.delay_ms(100_u32);
|
||||
}
|
||||
|
||||
fn bench_crc(pins: &mut MeasurePins, delay: &mut Delay) {
|
||||
const DATA: &[u8] = b"hello world AAAAAAAAAAAAAAAAAAAAAAA";
|
||||
time_exec("crc32_rs", MeasurementKind::Rust, pins, delay, true, || {
|
||||
Crc32Rust::checksum(DATA);
|
||||
});
|
||||
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);
|
||||
},
|
||||
);
|
||||
}
|
47
src/error_handlers.rs
Normal file
47
src/error_handlers.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
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);
|
||||
impl defmt::Format for Wrapper {
|
||||
fn format(&self, fmt: defmt::Formatter) {
|
||||
defmt::write!(
|
||||
fmt,
|
||||
"ExceptionFrame(\n\tr0: {:08x}\n\tr1: {:08x}\n\tr2: {:08x}\n\tr3: {:08x}\n\tr12: {:08x}\n\tlr: {:08x}\n\tpc: {:08x}\n\txpsr: {:08x}\n)",
|
||||
self.0.r0(),
|
||||
self.0.r1(),
|
||||
self.0.r2(),
|
||||
self.0.r3(),
|
||||
self.0.r12(),
|
||||
self.0.lr(),
|
||||
self.0.pc(),
|
||||
self.0.xpsr()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
error!("HardFault: Exception occured!");
|
||||
error!("Exception occured at: {:08x}", ef.pc());
|
||||
error!("XSPR: {:032b}", ef.xpsr());
|
||||
error!("LR: {:08x}", ef.lr());
|
||||
|
||||
error!("HardFault: {:#?}", Wrapper(*ef))
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
#[cortex_m_rt::exception(trampoline = true)]
|
||||
unsafe fn HardFault(ef: &ExceptionFrame) -> ! {
|
||||
static mut EXCEPTION: Option<ExceptionFrame> = None;
|
||||
unsafe { EXCEPTION = Some(*ef) };
|
||||
|
||||
display_ef(ef);
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
#![no_std]
|
75
src/main.rs
Executable file
75
src/main.rs
Executable file
|
@ -0,0 +1,75 @@
|
|||
// 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]
|
||||
|
||||
#[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, info};
|
||||
use panic_probe as _;
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use hal::{
|
||||
pac::{self},
|
||||
prelude::*,
|
||||
rcc::Config,
|
||||
};
|
||||
|
||||
use crate::bench::MeasurePins;
|
||||
|
||||
mod bench;
|
||||
mod error_handlers; // defines a handler for evil hardfaults
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let mut cp = cortex_m::Peripherals::take().unwrap();
|
||||
|
||||
// Configure the clock.
|
||||
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
cp.SYST.clear_current();
|
||||
cp.SYST.enable_counter();
|
||||
|
||||
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 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);
|
||||
|
||||
loop {
|
||||
delay.delay_ms(5000u32);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue