Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions ch32v203/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
target = "riscv32imc-unknown-none-elf"

[target."riscv32imc-unknown-none-elf"]
# runner = "wlink -v flash --enable-sdi-print --watch-serial --erase"
runner = "wchisp flash"
# runner = "wlink flash"
# runner = "wchisp flash"
runner = "./uf2_flash.sh"

# runner = "probe-rs run --chip ch32v203"
# runner = "arm-none-eabi-size"
Expand Down
2 changes: 2 additions & 0 deletions ch32v203/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ ch32v203k6t6 = ["ch32-hal/ch32v203k6t6"]
ch32v203k8t6 = ["ch32-hal/ch32v203k8t6"]
ch32v203rbt6 = ["ch32-hal/ch32v203rbt6"]

bootloader = []

default = ["ch32v203g6u6"]

[dependencies]
Expand Down
Binary file added ch32v203/bootloader.elf
Binary file not shown.
60 changes: 54 additions & 6 deletions ch32v203/build.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.

#[cfg(feature = "bootloader")]
fn linker_data() -> &'static [u8] {
#[cfg(any(
feature = "ch32v203c6t6",
feature = "ch32v203f6p6",
feature = "ch32v203g6u6",
feature = "ch32v203k6t6"
))]
return include_bytes!("memory-with-bootloader-32k.x");
#[cfg(any(
feature = "ch32v203c8t6",
feature = "ch32v203c8u6",
feature = "ch32v203f8p6",
feature = "ch32v203f8u6",
feature = "ch32v203g8r6",
feature = "ch32v203k8t6"
))]
return include_bytes!("memory-with-bootloader-64k.x");
#[cfg(feature = "ch32v203rbt6")]
return include_bytes!("memory-with-bootloader-128k.x");
}

fn main() {
#[cfg(feature = "bootloader")]
{
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
// If we use a bootloader, then we want to alter flash origin to 0x1000
// We do this by giving the linker a different memory.x file
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(linker_data())
.unwrap();
println!("cargo::rustc-link-search={}", out.display());

// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo::rerun-if-changed=memory.x");
}

// println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
// println!("cargo:rustc-link-arg-bins=-Tdefmt.x");

// let out_dir = std::env::var("OUT_DIR").unwrap();
// let out_dir = std::path::PathBuf::from(out_dir);
// std::fs::write(out_dir.join("memory.x"), include_bytes!("memory.x")).unwrap();
// println!("cargo:rustc-link-search={}", out_dir.display());
// println!("cargo:rerun-if-changed=memory.x");
}
11 changes: 11 additions & 0 deletions ch32v203/memory-with-bootloader-128k.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MEMORY
{
FLASH : ORIGIN = 0x00001000, LENGTH = 124K
RAM : ORIGIN = 0x20000000, LENGTH = 64K
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);
11 changes: 11 additions & 0 deletions ch32v203/memory-with-bootloader-32k.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MEMORY
{
FLASH : ORIGIN = 0x00001000, LENGTH = 28K
RAM : ORIGIN = 0x20000000, LENGTH = 10K
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);
11 changes: 11 additions & 0 deletions ch32v203/memory-with-bootloader-64k.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MEMORY
{
FLASH : ORIGIN = 0x00001000, LENGTH = 60K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);
8 changes: 8 additions & 0 deletions ch32v203/src/bin/usb_dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {

#[embassy_executor::main(entry = "qingke_rt::entry")]
async fn main(spawner: Spawner) {
#[cfg(feature = "bootloader")]
unsafe {
qingke::register::mtvec::write(
0x00001000,
qingke::register::mtvec::TrapMode::VectoredAddress,
);
}

let p = hal::init(hal::Config {
rcc: hal::rcc::Config::SYSCLK_FREQ_144MHZ_HSI,
..Default::default()
Expand Down
8 changes: 8 additions & 0 deletions ch32v203/src/bin/usb_dap_ppk2_uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {

#[embassy_executor::main(entry = "qingke_rt::entry")]
async fn main(spawner: Spawner) {
#[cfg(feature = "bootloader")]
unsafe {
qingke::register::mtvec::write(
0x00001000,
qingke::register::mtvec::TrapMode::VectoredAddress,
);
}

let mut config = hal::Config::default();
config.rcc = hal::rcc::Config::SYSCLK_FREQ_144MHZ_HSI;
config.rcc.apb2_pre = ch32_hal::rcc::APBPrescaler::DIV2;
Expand Down
9 changes: 8 additions & 1 deletion ch32v203/src/bin/usb_ppk2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,14 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {

#[embassy_executor::main(entry = "qingke_rt::entry")]
async fn main(spawner: Spawner) {
hal::debug::SDIPrint::enable();
#[cfg(feature = "bootloader")]
unsafe {
qingke::register::mtvec::write(
0x00001000,
qingke::register::mtvec::TrapMode::VectoredAddress,
);
}

let mut config = hal::Config::default();
config.rcc = hal::rcc::Config::SYSCLK_FREQ_144MHZ_HSI;
config.rcc.apb2_pre = ch32_hal::rcc::APBPrescaler::DIV2;
Expand Down
8 changes: 8 additions & 0 deletions ch32v203/src/bin/usb_uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
// println will not work without probe.
#[embassy_executor::main(entry = "qingke_rt::entry")]
async fn main(spawner: Spawner) {
#[cfg(feature = "bootloader")]
unsafe {
qingke::register::mtvec::write(
0x00001000,
qingke::register::mtvec::TrapMode::VectoredAddress,
);
}

let p = hal::init(hal::Config {
rcc: hal::rcc::Config::SYSCLK_FREQ_144MHZ_HSI,
..Default::default()
Expand Down
25 changes: 25 additions & 0 deletions ch32v203/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ macro_rules! my_println {
};
}

#[cfg(feature = "bootloader")]
pub unsafe fn enable_backup_registers() {
ch32_hal::pac::RCC.apb1pcenr().modify(|w| {
w.set_pwren(true);
w.set_bkpen(true);
});
const R32_PWR_CTLR: usize = 0x40007000;
unsafe {
// BDP: Backup domain write enable
*(R32_PWR_CTLR as *mut u32) |= 1 << 8;
}
}

#[cfg(feature = "bootloader")]
pub unsafe fn enter_bootloader() {
const R16_BKP_DATAR10: usize = 0x40006C28;
unsafe {
// Set R16_BKP_DATAR10 to 0x624c ('bL') to enter bootloader on next boot
*(R16_BKP_DATAR10 as *mut u16) = 0x624c;
}

// Reset chip to enter bootloader
ch32_hal::pac::PFIC.sctlr().write(|w| w.set_sysreset(true));
}

pub fn bytes_to_hex<'a>(bytes: &[u8], out: &'a mut [u8]) -> Result<&'a str, ()> {
// Need exactly 2 chars per byte
if out.len() < bytes.len() * 2 {
Expand Down
8 changes: 8 additions & 0 deletions ch32v203/src/usb_uart_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ pub async fn usb_tx_uart_rx_task(
mut uart_config: UartConfig,
) -> ! {
let mut buf = [0; 64];
#[cfg(feature = "bootloader")]
unsafe {
crate::enable_backup_registers();
}

loop {
usb_tx.wait_connection().await;
Expand All @@ -34,6 +38,10 @@ pub async fn usb_tx_uart_rx_task(
{
Either::First(_) => {
let baud = usb_tx.line_coding().data_rate();
#[cfg(feature = "bootloader")]
if baud == 1337 {
unsafe { crate::enter_bootloader() }
}
println!("Setting baud to: {}", baud);
uart_config.baudrate = baud;
if let Err(err) = uart_rx.set_config(&uart_config) {
Expand Down
7 changes: 7 additions & 0 deletions ch32v203/uf2_flash.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# Convert ELF to binary
riscv64-unknown-elf-objcopy -O binary $1 target/output.bin
# Convert binary to UF2 using the WCH Family ID
uf2conv -f 0x699b62ec -b 0x08001000 -o target/flash.uf2 target/output.bin
# Copy to the board (assuming it's mounted)
cp target/flash.uf2 /media/$USER/CH32V\ UF2/