Skip to content

Commit ff4cf85

Browse files
committed
Add easy to iterate utilities for development of flash algorithms
1 parent 1238a99 commit ff4cf85

File tree

12 files changed

+381
-182
lines changed

12 files changed

+381
-182
lines changed

.cargo/config.toml

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[alias]
22
xtask = "run --package xtask --"
33
export = "xtask export"
4+
iterate = "xtask iterate"
45

56
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
67
rustflags = [

.github/workflows/ci.yml

+9-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,15 @@ jobs:
3434
# run: |
3535
# curl -LsSf https://github.com/rust-embedded/cargo-binutils/releases/download/v0.3.6/x86_64-unknown-linux-gnu.tar.gz | tar xzf - -C ${CARGO_HOME:-~/.cargo}/bin
3636
- name: Template a project
37-
run: cargo generate --path ../ --name=test -d target-arch=thumbv7em-none-eabi -d ram-start-address=0x0
37+
run: |
38+
cargo generate --path ../ --name=test \
39+
-d target-arch=thumbv7em-none-eabi \
40+
-d ram-start-address=0x20000000 \
41+
-d ram-size=0x4000 \
42+
-d flash-start-address=0x0 \
43+
-d flash-page-size=0x400 \
44+
-d flash-size=0x40000 \
45+
-d empty-byte-value=0xFF
3846
- name: Check
3947
run: cd test && cargo check --target thumbv7em-none-eabi
4048
- name: Clippy

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ forced-target = "{{target-arch}}"
1111

1212
[dependencies]
1313
cortex-m = "0.7.0"
14-
flash-algorithm = { version = "0.1" }
14+
flash-algorithm = { version = "0.3.0" }
1515

1616
# this lets you use `cargo fix`!
1717
[[bin]]

README.md

+14-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ It can be used to generate new flash algoritms for usage with `probe-rs`.
1010
Run the following requirements:
1111

1212
```bash
13-
cargo install cargo-generate && cargo-binutils && rustup component add llvm-tools-preview
13+
cargo install cargo-generate cargo-binutils target-gen
14+
rustup component add llvm-tools-preview
1415
```
1516

1617
## Instantiating the template
@@ -21,23 +22,24 @@ Run
2122
cargo generate gh:probe-rs/flash-algorithm-template
2223
```
2324

25+
or
26+
27+
```bash
28+
cargo generate gh:probe-rs/flash-algorithm-template --name=algorithm \
29+
-d target-arch=thumbv7em-none-eabi \
30+
-d ram-start-address=0x20000000 \
31+
-d ram-size=0x4000 \
32+
-d flash-start-address=0x0 \
33+
-d flash-size=0x40000
34+
```
35+
2436
to generate a new project from the template.
2537

2638
## Building the algorithm
2739

2840
Building requires nightly Rust.
2941

30-
Just run `cargo export`. It spits out the flash algo in the probe-rs YAML format:
31-
32-
flash-algorithm$ cargo export
33-
flash-algorithm:
34-
name: {{project-name}}
35-
instructions: sLUUIACIGUoBRguI...wRwAgcEc=
36-
pc_init: 0x00000000
37-
pc_uninit: 0x0000007c
38-
pc_program_page: 0x00000088
39-
pc_erase_sector: 0x00000084
40-
pc_erase_all: 0x00000080
42+
Just run `cargo export`. It spits out the flash algo in the probe-rs YAML format.
4143

4244
# License
4345

calculate-memory.rhai

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
variable::set(
2+
"ram-end-address",
3+
"0x" + (
4+
parse_int(variable::get("ram-start-address").sub_string(2), 16)
5+
+ parse_int(variable::get("ram-size").sub_string(2), 16)
6+
).to_hex()
7+
);
8+
variable::set(
9+
"flash-end-address",
10+
"0x" + (
11+
parse_int(variable::get("flash-start-address").sub_string(2), 16)
12+
+ parse_int(variable::get("flash-size").sub_string(2), 16)
13+
).to_hex()
14+
);
15+
16+
let target = variable::get("target");
17+
18+
variable::set("architecture", switch target {
19+
"thumbv6m-none-eabi" => "armv6m",
20+
"thumbv7m-none-eabi" => "armv7m",
21+
"thumbv7em-none-eabi" => "armv7em",
22+
"thumbv7em-none-eabihf" => "armv7em",
23+
"thumbv8m.base-none-eabi" => "armv8",
24+
"thumbv8m.main-none-eabi" => "armv8",
25+
"thumbv8m.main-none-eabihf" => "armv8",
26+
_ => "armv6m",
27+
})

cargo-generate.toml

+28
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,33 @@ type = "string"
1717
prompt = "What is the target RAM start address where the flash algorithm should be placed?"
1818
default = "0x0"
1919

20+
[placeholders.ram-size]
21+
type = "string"
22+
prompt = "What is the target RAM size in bytes?"
23+
default = "0x0"
24+
25+
[placeholders.flash-start-address]
26+
type = "string"
27+
prompt = "What is the target Flash start address of the device the flash algorithm is for?"
28+
default = "0x20000000"
29+
30+
[placeholders.flash-size]
31+
type = "string"
32+
prompt = "What is the target Flash size in bytes?"
33+
default = "0x0"
34+
35+
[placeholders.flash-page-size]
36+
type = "string"
37+
prompt = "What is the target Flash page size in bytes?"
38+
default = "0x400"
39+
40+
[placeholders.empty-byte-value]
41+
type = "string"
42+
prompt = "What is the erased state of a byte in Flash?"
43+
default = "0xFF"
44+
2045
[template]
2146
exclude = ["README.md", "/target", "/test"]
47+
48+
[hooks]
49+
pre = ["calculate-memory.rhai"]

src/main.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,16 @@ use flash_algorithm::*;
77

88
struct Algorithm;
99

10-
algorithm!(Algorithm);
10+
algorithm!(Algorithm, {
11+
flash_address: {{flash-start-address}},
12+
flash_size: {{flash-size}},
13+
page_size: {{flash-page-size}},
14+
empty_value: 0xFF,
15+
sectors: [{
16+
size: {{flash-size}},
17+
address: {{flash-start-address}},
18+
}]
19+
});
1120

1221
impl FlashAlgorithm for Algorithm {
1322
fn new(_address: u32, _clock: u32, _function: Function) -> Result<Self, ErrorCode> {

template.yaml

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: algorithm-test
2+
variants:
3+
- name: algorithm-test
4+
cores:
5+
- name: main
6+
type: {{architecture}}
7+
core_access_options: !Arm
8+
ap: 0x0
9+
psel: 0x0
10+
memory_map:
11+
- !Ram
12+
range:
13+
start: {{ram-start-address}}
14+
end: {{ram-end-address}}
15+
is_boot_memory: false
16+
cores:
17+
- main
18+
- !Nvm
19+
range:
20+
start: {{flash-start-address}}
21+
end: {{flash-end-address}}
22+
is_boot_memory: true
23+
cores:
24+
- main
25+
flash_algorithms:
26+
- algorithm-test
27+
flash_algorithms:
28+
- name: algorithm-test
29+
description: A flash algorithm under test
30+
cores:
31+
- main
32+
default: true
33+
instructions: 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
34+
pc_init: 0x0
35+
pc_uninit: 0x0
36+
pc_program_page: 0x0
37+
pc_erase_sector: 0x0
38+
pc_erase_all: 0x0
39+
data_section_offset: 0x0
40+
# load_address: {{ram-end-address}}
41+
flash_properties:
42+
address_range:
43+
start: 0x0
44+
end: 0x0
45+
page_size: 0x0
46+
erased_byte_value: 0x0
47+
program_page_timeout: 0x0
48+
erase_sector_timeout: 0x0
49+
sectors:
50+
- size: 0x0
51+
address: 0x0

xtask/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ xshell = { version = "0.2", default-features = false }
88
clap = { version = "4", default-features = false, features = ["std", "derive"] }
99
base64 = { version = "0.21", default-features = false, features = ["std"] }
1010
cargo_metadata = { version = "0.15", default-features = false }
11-
anyhow = { version = "1", default-features = false, features = ["std"] }
11+
color-eyre = { version = "0.6", default-features = false }
12+
probe-rs = { version = "0.14", git = "https://github.com/probe-rs/probe-rs" }
13+
probe-rs-cli-util = { version = "0.14", git = "https://github.com/probe-rs/probe-rs" }
14+
indicatif = "0.17"
15+
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

xtask/src/export.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use cargo_metadata::Message;
2+
use color_eyre::eyre::Result;
3+
use xshell::{cmd, Shell};
4+
5+
const DEFINITION_PATH: &str = "target/definition.yaml";
6+
7+
pub fn export() -> Result<&'static str> {
8+
let sh = Shell::new()?;
9+
10+
// We build the actual flash algorithm.
11+
// We relay all the output of the build process to the open shell.
12+
let mut cmd = cmd!(
13+
sh,
14+
"cargo build --release --message-format=json-diagnostic-rendered-ansi"
15+
);
16+
cmd.set_ignore_status(true);
17+
let output = cmd.output()?;
18+
print!("{}", String::from_utf8_lossy(&output.stderr));
19+
20+
// Parse build information to extract the artifcat.
21+
let messages = Message::parse_stream(output.stdout.as_ref());
22+
23+
// Find artifacts.
24+
let mut target_artifact = None;
25+
for message in messages {
26+
match message? {
27+
Message::CompilerArtifact(artifact) => {
28+
if let Some(executable) = artifact.executable {
29+
if target_artifact.is_some() {
30+
// We found multiple binary artifacts,
31+
// so we don't know which one to use.
32+
// This should never happen!
33+
unreachable!()
34+
} else {
35+
target_artifact = Some(executable);
36+
}
37+
}
38+
}
39+
Message::CompilerMessage(message) => {
40+
if let Some(rendered) = message.message.rendered {
41+
print!("{}", rendered);
42+
}
43+
}
44+
// Ignore other messages.
45+
_ => (),
46+
}
47+
}
48+
let target_artifact = target_artifact.expect("a flash algorithm artifact");
49+
let target_artifact = target_artifact.as_str();
50+
51+
cmd!(sh, "cp template.yaml {DEFINITION_PATH}").run()?;
52+
cmd!(
53+
sh,
54+
"target-gen elf -n algorithm-test -u {target_artifact} {DEFINITION_PATH}"
55+
)
56+
.run()?;
57+
58+
generate_debug_info(&sh, target_artifact)?;
59+
60+
Ok(DEFINITION_PATH)
61+
}
62+
63+
/// Generates information about the ELF binary.
64+
fn generate_debug_info(sh: &Shell, target_artifact: &str) -> Result<()> {
65+
std::fs::write(
66+
"target/disassembly.s",
67+
cmd!(sh, "rust-objdump --disassemble {target_artifact}")
68+
.output()?
69+
.stdout,
70+
)?;
71+
std::fs::write(
72+
"target/dump.txt",
73+
cmd!(sh, "rust-objdump -x {target_artifact}")
74+
.output()?
75+
.stdout,
76+
)?;
77+
std::fs::write(
78+
"target/nm.txt",
79+
cmd!(sh, "rust-nm {target_artifact} -n").output()?.stdout,
80+
)?;
81+
82+
Ok(())
83+
}

0 commit comments

Comments
 (0)