-
Notifications
You must be signed in to change notification settings - Fork 48
Description
Thank you for developing this HAL!
Rust and CH32V003 noob so -- feel free -- to tell me to go away.
I've a CH32V003F4P6-R0-1v1 and a WCH-LinkE-RO-1v3.
I'm exploring the examples.
blinky
works and embassy_blinky
works but only briefly (and I'm unsure how to debug).
// PC4 is connected to LED2
spawner.spawn(blink(p.PC4.degrade(), 250)).unwrap();
// PD6 is connected to LED1
spawner.spawn(blink(p.PD6.degrade(), 333)).unwrap();
I've tried with Rust 2021 and 2024.
I do need to uncomment/enable Tlink.x
for successful compilation:
.cargo/config.,toml
:
[target."riscv32ec-unknown-none-elf"]
rustflags = [
"-C", "link-arg=-Tlink.x",
]
cargo run --bin=embassy --release
Finished `release` profile [optimized] target(s) in 0.13s
Running `wlink -v flash --enable-sdi-print --watch-serial target/riscv32ec-unknown-none-elf/release/embassy`
21:38:42 [DEBUG] (1) wlink::usb_device::libusb: Serial number: "0D548F069286"
21:38:42 [INFO] Connected to WCH-Link v2.18(v38) (WCH-LinkE-CH32V305)
21:38:42 [INFO] Attached chip: CH32V003 [CH32V003F4P6] (ChipID: 0x00300510)
21:38:42 [INFO] Chip ESIG: FlashSize(16KB) UID(cd-ab-70-95-2e-bd-6b-fe)
21:38:42 [INFO] Flash protected: false
21:38:42 [INFO] Read target/riscv32ec-unknown-none-elf/release/embassy as ELF format
21:38:42 [DEBUG] (1) wlink::firmware: Found loadable segment, physical address: 0x00000000, virtual address: 0x00000000, flags: 0x5
21:38:42 [DEBUG] (1) wlink::firmware: Matching section: ".vector_table" offset: 0x1000 size: 0x320
21:38:42 [DEBUG] (1) wlink::firmware: Matching section: ".text" offset: 0x1320 size: 0x277a
21:38:42 [DEBUG] (1) wlink::firmware: Section names: [".vector_table", ".text"]
21:38:42 [DEBUG] (1) wlink::firmware: Found loadable segment, physical address: 0x00002a9c, virtual address: 0x00002a9c, flags: 0x4
21:38:42 [DEBUG] (1) wlink::firmware: Matching section: ".rodata" offset: 0x3a9c size: 0xf00
21:38:42 [DEBUG] (1) wlink::firmware: Section names: [".rodata"]
21:38:42 [DEBUG] (1) wlink::firmware: Found loadable segment, physical address: 0x000039a0, virtual address: 0x20000000, flags: 0x6
21:38:42 [DEBUG] (1) wlink::firmware: Matching section: ".data" offset: 0x5000 size: 0x30
21:38:42 [DEBUG] (1) wlink::firmware: Section names: [".data"]
21:38:42 [DEBUG] (1) wlink::firmware: found 3 sections
21:38:42 [DEBUG] (1) wlink::firmware: Merge firmware sections with gap: 2
21:38:42 [DEBUG] (1) wlink::firmware: Merge firmware sections with gap: 4
21:38:42 [INFO] Flashing 14800 bytes to 0x08000000
21:38:42 [DEBUG] (1) wlink::operations: Reattach chip
21:38:42 [DEBUG] (1) wlink::operations: Reattach chip
21:38:42 [INFO] Read protected: false
21:38:42 [DEBUG] (1) wlink::operations: Using write pack size 1024 data pack size 64
21:38:42 [DEBUG] (1) wlink::operations: Flash OP written
14800/14800
21:38:44 [DEBUG] (1) wlink::operations: Fastprogram done
21:38:44 [INFO] Flash done
21:38:45 [INFO] Now reset...
21:38:45 [INFO] Now connect to the WCH-Link serial port to read SDI print
21:38:45 [DEBUG] (1) wlink::probe: Opening serial port: "/dev/ttyACM0"
NOTE I don't have
riscv64-unknown-elf-size
butFlashing 14800 bytes to 0x08000000
seems okay but perhaps it is exceeding flash?
2025-10-03 14:38:45.464: ) }
2025-10-03 14:38:45.464: H
2025-10-03 14:38:45.464: H
2025-10-03 14:38:45.679: L
2025-10-03 14:38:45.760: L
2025-10-03 14:38:45.925: H
2025-10-03 14:38:46.089: H
2025-10-03 14:38:46.172: L
2025-10-03 14:38:46.418: L
2025-10-03 14:38:46.419: H
2025-10-03 14:38:46.666: L
2025-10-03 14:38:46.747: H
NOTE The number of successes varies; reducing to a single LED and task is less (!) reliable iterating fewer times.
The first couple of lines of output are swallowed by wlink
but using e.g. minicom, these are correctly output (pretty-printed):
CHIP signature => CH32V003F4P6
Clocks Clocks {
sysclk: Hertz(48000000),
hclk: Hertz(48000000),
pclk1: Hertz(48000000),
pclk2: Hertz(48000000),
pclk1_tim: Hertz(48000000),
pclk2_tim: Hertz(48000000)
}
Files:
.cargo/config.toml
:
[build]
target = "riscv32ec-unknown-none-elf.json"
[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
runner = "wlink -v flash --enable-sdi-print --watch-serial"
[target."riscv32ec-unknown-none-elf"]
rustflags = [
"-C", "link-arg=-Tlink.x",
]
[unstable]
build-std = ["core"]
Cargo.toml
:
[package]
name = "ch32v003-blinky"
version = "0.0.1"
edition = "2024"
[[bin]]
name = "blinky"
path = "src/bin/blinky.rs"
test = false
bench = false
[[bin]]
name = "embassy"
path = "src/bin/embassy.rs"
test = false
bench = false
[dependencies]
ch32-hal = { git = "https://github.com/ch32-rs/ch32-hal", features = [
"ch32v003f4u6",
"embassy",
"memory-x",
"rt",
"time-driver-tim2",
] }
embassy-executor = { version = "0.7.0", features = [
"arch-spin",
"executor-thread",
"task-arena-size-256", # or better use nightly, but fails on recent Rust versions
] }
embassy-time = "0.4.0"
embedded-hal = "1.0.0"
panic-halt = "1.0.0"
qingke = "*"
qingke-rt = "0.5.0"
[profile.dev]
strip = false
lto = false
opt-level = "s"
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
strip = false
overflow-checks = false
panic = "abort"
embassy.rs
:
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]
use ch32_hal as hal;
use embassy_executor::Spawner;
use embassy_time::Timer;
use hal::gpio::{AnyPin, Level, Output, Pin};
use hal::println;
#[embassy_executor::task(pool_size = 2)]
async fn blink(pin: AnyPin, interval_ms: u64) {
let mut led = Output::new(pin, Level::Low, Default::default());
loop {
led.set_high();
println!("H");
Timer::after_millis(interval_ms).await;
led.set_low();
println!("L");
Timer::after_millis(interval_ms).await;
}
}
#[embassy_executor::main(entry = "qingke_rt::entry")]
async fn main(spawner: Spawner) -> ! {
hal::debug::SDIPrint::enable();
let mut config = hal::Config::default();
config.rcc = hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSI;
let p = hal::init(config);
println!("CHIP signature => {}", hal::signature::chip_id().name());
println!("Clocks {:?}", hal::rcc::clocks());
// PC4 is connected to LED2
spawner.spawn(blink(p.PC4.degrade(), 250)).unwrap();
// PD6 is connected to LED1
spawner.spawn(blink(p.PD6.degrade(), 333)).unwrap();
loop {
Timer::after_millis(1000).await;
// println!("tick");
}
}
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
let _ = println!("\n\n\n{}", info);
loop {}
}