Skip to content

Commit ad78adb

Browse files
authored
build on nightly, enable linker relaxation and WCH compressed opcodes (#35)
* build everything on nightly * enable linker relaxation, and WCH compressed opcodes on QingKe V2
1 parent 7e5f8ec commit ad78adb

11 files changed

Lines changed: 49 additions & 38 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ jobs:
1717
working-directory: lib
1818
steps:
1919
- uses: actions/checkout@v6
20-
- run: rustup toolchain install stable --profile minimal --component rustfmt,clippy
21-
- run: cargo fmt --all -- --check
22-
- run: cargo clippy --all-targets -- -D warnings
23-
- run: cargo build
24-
- run: cargo test
25-
- run: cargo doc --no-deps
26-
- run: cargo build --release
20+
- run: rustup toolchain install nightly --profile minimal --component rustfmt,clippy
21+
- run: cargo +nightly fmt --all -- --check
22+
- run: cargo +nightly clippy --all-targets -- -D warnings
23+
- run: cargo +nightly build
24+
- run: cargo +nightly test
25+
- run: cargo +nightly doc --no-deps
26+
- run: cargo +nightly build --release
2727

2828
cli:
2929
name: CLI
@@ -34,11 +34,11 @@ jobs:
3434
steps:
3535
- uses: actions/checkout@v6
3636
- run: sudo apt-get update && sudo apt-get install -y libudev-dev
37-
- run: rustup toolchain install stable --profile minimal --component rustfmt,clippy
38-
- run: cargo fmt --all -- --check
39-
- run: cargo clippy -- -D warnings
40-
- run: cargo build
41-
- run: cargo build --release
37+
- run: rustup toolchain install nightly --profile minimal --component rustfmt,clippy
38+
- run: cargo +nightly fmt --all -- --check
39+
- run: cargo +nightly clippy -- -D warnings
40+
- run: cargo +nightly build
41+
- run: cargo +nightly build --release
4242

4343
ch32-v003:
4444
name: CH32V003 (${{ matrix.chip }})
@@ -135,29 +135,28 @@ jobs:
135135
- uses: actions/checkout@v6
136136
- name: Install toolchain
137137
run: |
138-
rustup toolchain install stable --profile minimal --component rustfmt,clippy
139-
rustup target add riscv32imc-unknown-none-elf
138+
rustup toolchain install nightly --profile minimal --component rustfmt,clippy --target riscv32imc-unknown-none-elf
140139
- name: Clippy libraries
141-
run: cd ch32 && cargo clippy --no-default-features --features ${{ matrix.chip }} --target riscv32imc-unknown-none-elf -- -D warnings
140+
run: cd ch32 && cargo +nightly clippy --no-default-features --features ${{ matrix.chip }} --target riscv32imc-unknown-none-elf -- -D warnings
142141
- name: Build libraries
143-
run: cd ch32 && cargo build --no-default-features --features ${{ matrix.chip }} --target riscv32imc-unknown-none-elf --release
142+
run: cd ch32 && cargo +nightly build --no-default-features --features ${{ matrix.chip }} --target riscv32imc-unknown-none-elf --release
144143
- name: Clippy libraries (half-duplex)
145-
run: cd ch32 && cargo clippy --no-default-features --features ${{ matrix.chip }},half-duplex --target riscv32imc-unknown-none-elf -- -D warnings
144+
run: cd ch32 && cargo +nightly clippy --no-default-features --features ${{ matrix.chip }},half-duplex --target riscv32imc-unknown-none-elf -- -D warnings
146145
- name: Fmt examples
147-
run: cd examples/ch32/v103 && cargo fmt --all -- --check
146+
run: cd examples/ch32/v103 && cargo +nightly fmt --all -- --check
148147
- name: Clippy boot (system-flash)
149-
run: cd examples/ch32/v103 && cargo clippy -p boot --no-default-features --features "${{ matrix.chip }},system-flash" -- -D warnings
148+
run: cd examples/ch32/v103 && cargo +nightly clippy -p boot --no-default-features --features "${{ matrix.chip }},system-flash" -- -D warnings
150149
- name: Build boot (system-flash)
151-
run: cd examples/ch32/v103 && cargo build -p boot --no-default-features --features "${{ matrix.chip }},system-flash" --release
150+
run: cd examples/ch32/v103 && cargo +nightly build -p boot --no-default-features --features "${{ matrix.chip }},system-flash" --release
152151
- name: Clippy boot (user-flash)
153-
run: cd examples/ch32/v103 && cargo clippy -p boot --no-default-features --features "${{ matrix.chip }},user-flash" -- -D warnings
152+
run: cd examples/ch32/v103 && cargo +nightly clippy -p boot --no-default-features --features "${{ matrix.chip }},user-flash" -- -D warnings
154153
- name: Build boot (user-flash)
155-
run: cd examples/ch32/v103 && cargo build -p boot --no-default-features --features "${{ matrix.chip }},user-flash" --release
154+
run: cd examples/ch32/v103 && cargo +nightly build -p boot --no-default-features --features "${{ matrix.chip }},user-flash" --release
156155
- name: Clippy app (system-flash)
157-
run: cd examples/ch32/v103 && cargo clippy -p app --no-default-features --features "${{ matrix.chip }},system-flash" -- -D warnings
156+
run: cd examples/ch32/v103 && cargo +nightly clippy -p app --no-default-features --features "${{ matrix.chip }},system-flash" -- -D warnings
158157
- name: Build app (system-flash)
159-
run: cd examples/ch32/v103 && cargo build -p app --no-default-features --features "${{ matrix.chip }},system-flash" --release
158+
run: cd examples/ch32/v103 && cargo +nightly build -p app --no-default-features --features "${{ matrix.chip }},system-flash" --release
160159
- name: Clippy app (user-flash)
161-
run: cd examples/ch32/v103 && cargo clippy -p app --no-default-features --features "${{ matrix.chip }},user-flash" -- -D warnings
160+
run: cd examples/ch32/v103 && cargo +nightly clippy -p app --no-default-features --features "${{ matrix.chip }},user-flash" -- -D warnings
162161
- name: Build app (user-flash)
163-
run: cd examples/ch32/v103 && cargo build -p app --no-default-features --features "${{ matrix.chip }},user-flash" --release
162+
run: cd examples/ch32/v103 && cargo +nightly build -p app --no-default-features --features "${{ matrix.chip }},user-flash" --release

‎docs/contributing.md‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,9 @@ Each directory is its own Cargo workspace with an independent `Cargo.lock`. A "c
3737

3838
## Rust toolchain
3939

40-
- **Library crates (`lib/`, `cli/`)** — stable Rust 1.85+, edition 2024.
41-
- **CH32 example binaries** — nightly, for `-Zbuild-std` on `riscv32ec-unknown-none-elf` (V003 / V00x) or the stable `riscv32imc-unknown-none-elf` target (V103).
40+
Everything builds and is tested on nightly, edition 2024: the library crates (`lib/`, `cli/`, `ch32/`) and the CH32 examples. The V003 / V00x examples need it for `-Zbuild-std` on `riscv32ec-unknown-none-elf`; the V103 examples use the built-in `riscv32imc-unknown-none-elf` target with linker relaxation (`+relax`), which stable rustc warns about as an unstable target feature.
4241

43-
Each example workspace pins its toolchain via `rust-toolchain.toml`.
42+
The repository root and each example workspace pin nightly via `rust-toolchain.toml`.
4443

4544
## Running tests
4645

‎docs/design.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ To build your bootloader, you create a small crate with a `main.rs` that wires u
2323

2424
Beyond the usual Cargo profile tricks (`opt-level = "z"`, LTO, `codegen-units = 1`, `panic = "abort"`), fitting a real bootloader in 1920 bytes required more deliberate choices:
2525

26+
- **Linker relaxation and WCH compressed opcodes** - the examples enable `+relax`, so the linker shrinks every `auipc`+`jalr` call pair to `jal` or `c.jal`, and on QingKe V2 cores (V003, V00x) `+xwchc`, WCH's 16-bit byte and halfword loads and stores. Together they take the V003 bootloader from 1898 to 1710 bytes. QingKe V3A (V103) has no XW extension, so its example enables only `+relax`.
2627
- **No HAL crates** — bare metal register access via PAC crates only; HAL abstractions are too expensive for this budget.
2728
- **Custom runtime** — `tinyboot-ch32-rt` replaces `qingke-rt` in the bootloader; its startup is just GP/SP init and a jump to main (20 bytes of assembly instead of ~1.4KB of full runtime).
2829
- **Symmetric frame format** — the same `Frame` struct is used for both requests and responses with one shared parse and format path, eliminating code duplication.

‎docs/getting-started.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ cargo install wlink
2424
cargo install tinyboot
2525
```
2626

27-
The CH32V003 examples use `riscv32ec-unknown-none-elf`, which is a Tier 3 target that `-Zbuild-std` builds on the fly — nightly is required. CH32V103 examples use the stable `riscv32imc-unknown-none-elf` target.
27+
The CH32V003 examples use `riscv32ec-unknown-none-elf`, which is a Tier 3 target that `-Zbuild-std` builds on the fly — nightly is required. CH32V103 examples use the built-in `riscv32imc-unknown-none-elf` target, also on nightly like every tinyboot build.
2828

2929
## 2. Clone the repo
3030

‎docs/porting-series.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ Then flash to hardware using `wlink` and walk through the [standard test sequenc
188188

189189
Add the new series to `.github/workflows/ci.yml`. Each series has its own job with a matrix of variants. The CI runs `cargo fmt`, `cargo clippy`, and `cargo build --release` for both `system-flash` and `user-flash` modes on every variant. This ensures formatting, lint, compilation, and that the bootloader fits within the system flash region.
190190

191-
Add a new job following the pattern of the existing series jobs. Use the V003 job as a template for custom-target chips (nightly + `-Zbuild-std`) or the V103 job for standard-target chips (stable + `rustup target add`).
191+
Add a new job following the pattern of the existing series jobs. Use the V003 job as a template for custom-target chips (nightly + `-Zbuild-std`) or the V103 job for standard-target chips (nightly with the target added).
192192

193193
```yaml
194194
strategy:

‎examples/ch32/v003/riscv32ec-unknown-none-elf.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"data-layout": "e-m:e-p:32:32-i64:64-n32-S32",
77
"eh-frame-header": false,
88
"emit-debug-gdb-scripts": false,
9-
"features": "+e,+c,+forced-atomics",
9+
"features": "+e,+c,+forced-atomics,+xwchc,+relax",
1010
"linker": "rust-lld",
1111
"linker-flavor": "gnu-lld",
1212
"llvm-target": "riscv32",

‎examples/ch32/v00x/riscv32ec-unknown-none-elf.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"data-layout": "e-m:e-p:32:32-i64:64-n32-S32",
77
"eh-frame-header": false,
88
"emit-debug-gdb-scripts": false,
9-
"features": "+e,+c,+forced-atomics",
9+
"features": "+e,+c,+forced-atomics,+xwchc,+relax",
1010
"linker": "rust-lld",
1111
"linker-flavor": "gnu-lld",
1212
"llvm-target": "riscv32",

‎examples/ch32/v103/.cargo/config.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ target = "riscv32imc-unknown-none-elf"
55
rustflags = [
66
"-C", "link-arg=-Tlink.x",
77
"-C", "link-arg=--nmagic",
8+
# Linker relaxation: calls shrink from auipc+jalr to jal/c.jal.
9+
"-C", "target-feature=+relax",
810
]
911
runner = "probe-rs run --chip CH32V103"
1012

‎examples/ch32/v103/app/src/main.rs‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ fn main() -> ! {
7373
// system-flash: pass BOOT0 pin, the level that selects system flash,
7474
// and the reset delay in cycles (RC ~1ms @ 8MHz = 8000; flip-flop: 0).
7575
let mut app = tinyboot_ch32::app::new_app(core::cfg_select! {
76-
feature = "system-flash" => tinyboot_ch32::app::BootCtl::new(
77-
tinyboot_ch32::app::Pin::PB1,
78-
tinyboot_ch32::app::Level::High,
79-
8000,
80-
),
76+
feature = "system-flash" => {
77+
tinyboot_ch32::app::BootCtl::new(
78+
tinyboot_ch32::app::Pin::PB1,
79+
tinyboot_ch32::app::Level::High,
80+
8000,
81+
)
82+
}
8183
_ => tinyboot_ch32::app::BootCtl::new(),
8284
});
8385

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[toolchain]
2+
channel = "nightly"
3+
components = ["rustfmt", "clippy", "rust-analyzer"]
4+
targets = ["riscv32imc-unknown-none-elf"]

0 commit comments

Comments
 (0)