move bootloader to defmt

This commit is contained in:
Robin Müller 2025-04-22 18:19:39 +02:00
parent d6b2fadab3
commit 75a339222b
Signed by: muellerr
GPG Key ID: A649FB78196E3849
3 changed files with 33 additions and 35 deletions

View File

@ -76,7 +76,7 @@ probe-rs run --chip VA108xx_RAM --protocol jtag target/thumbv6m-none-eabi/debug/
to flash and run the blinky program on the RAM. There is also a `VA108xx` chip target to flash and run the blinky program on the RAM. There is also a `VA108xx` chip target
available for persistent flashing. available for persistent flashing.
Runner configuration avilable in the `.cargo/def-config.toml` file to use `probe-rs` for Runner configuration is available in the `.cargo/def-config.toml` file to use `probe-rs` for
convenience. `probe-rs` is also able to process and display `defmt` strings directly. convenience. `probe-rs` is also able to process and display `defmt` strings directly.
### Using VS Code ### Using VS Code
@ -150,11 +150,10 @@ address for the RTT block placement is 0x10000000. It is recommended to use a se
0x1000 around that base address when using the RTT viewer. 0x1000 around that base address when using the RTT viewer.
The RTT viewer will not be able to process `defmt` printouts. However, you can view the defmt The RTT viewer will not be able to process `defmt` printouts. However, you can view the defmt
logs by [installing defmt-print](https://crates.io/crates/defmt-print) first and then piping logs by [installing defmt-print](https://crates.io/crates/defmt-print) first and then running
the output on telnet port 19021 into `defmt-print`, for example by running
```sh ```sh
telnet localhost 19021 | defmt-print -e <pathToElfFile> defmt-print -e <pathToElfFile> tcp
``` ```
The path of the ELF file which is being debugged needs to be specified for this to work. The path of the ELF file which is being debugged needs to be specified for this to work.

View File

@ -7,9 +7,9 @@ edition = "2021"
cortex-m = "0.7" cortex-m = "0.7"
cortex-m-rt = "0.7" cortex-m-rt = "0.7"
embedded-hal = "1" embedded-hal = "1"
panic-rtt-target = "0.2" defmt-rtt = "0.4"
panic-halt = "1" defmt = "1"
rtt-target = "0.6" panic-probe = { version = "1", features = ["defmt"] }
crc = "3" crc = "3"
num_enum = { version = "0.7", default-features = false } num_enum = { version = "0.7", default-features = false }
static_assertions = "1" static_assertions = "1"
@ -17,6 +17,7 @@ static_assertions = "1"
[dependencies.va108xx-hal] [dependencies.va108xx-hal]
version = "0.11" version = "0.11"
path = "../va108xx-hal" path = "../va108xx-hal"
features = ["defmt"]
[dependencies.vorago-reb1] [dependencies.vorago-reb1]
version = "0.8" version = "0.8"

View File

@ -6,17 +6,16 @@ use cortex_m_rt::entry;
use crc::{Crc, CRC_16_IBM_3740}; use crc::{Crc, CRC_16_IBM_3740};
use embedded_hal::delay::DelayNs; use embedded_hal::delay::DelayNs;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
#[cfg(not(feature = "rtt-panic"))] // Import panic provider.
use panic_halt as _; use panic_probe as _;
#[cfg(feature = "rtt-panic")] // Import logger.
use panic_rtt_target as _; use defmt_rtt as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{pac, time::Hertz, timer::CountdownTimer}; use va108xx_hal::{pac, time::Hertz, timer::CountdownTimer};
use vorago_reb1::m95m01::M95M01; use vorago_reb1::m95m01::M95M01;
// Useful for debugging and see what the bootloader is doing. Enabled currently, because // Useful for debugging and see what the bootloader is doing. Enabled currently, because
// the binary stays small enough. // the binary stays small enough.
const RTT_PRINTOUT: bool = true; const DEFMT_PRINTOUT: bool = true;
const DEBUG_PRINTOUTS: bool = true; const DEBUG_PRINTOUTS: bool = true;
// Small delay, allows RTT printout to catch up. // Small delay, allows RTT printout to catch up.
const BOOT_DELAY_MS: u32 = 2000; const BOOT_DELAY_MS: u32 = 2000;
@ -74,7 +73,7 @@ pub const PREFERRED_SLOT_OFFSET: u32 = 0x20000 - 1;
const CRC_ALGO: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740); const CRC_ALGO: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive)] #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, defmt::Format)]
#[repr(u8)] #[repr(u8)]
enum AppSel { enum AppSel {
A = 0, A = 0,
@ -100,9 +99,8 @@ impl NvmInterface for NvmWrapper {
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
if RTT_PRINTOUT { if DEFMT_PRINTOUT {
rtt_init_print!(); defmt::println!("-- VA108xx bootloader --");
rprintln!("-- VA108xx bootloader --");
} }
let dp = pac::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap(); let cp = cortex_m::Peripherals::take().unwrap();
@ -131,21 +129,21 @@ fn main() -> ! {
nvm.write(0x4, bootloader_data) nvm.write(0x4, bootloader_data)
.expect("writing to NVM failed"); .expect("writing to NVM failed");
if let Err(e) = nvm.verify(0x0, &first_four_bytes) { if let Err(e) = nvm.verify(0x0, &first_four_bytes) {
if RTT_PRINTOUT { if DEFMT_PRINTOUT {
rprintln!("verification of self-flash to NVM failed: {:?}", e); defmt::error!("verification of self-flash to NVM failed: {:?}", e);
} }
} }
if let Err(e) = nvm.verify(0x4, bootloader_data) { if let Err(e) = nvm.verify(0x4, bootloader_data) {
if RTT_PRINTOUT { if DEFMT_PRINTOUT {
rprintln!("verification of self-flash to NVM failed: {:?}", e); defmt::error!("verification of self-flash to NVM failed: {:?}", e);
} }
} }
nvm.write(BOOTLOADER_CRC_ADDR as usize, &bootloader_crc.to_be_bytes()) nvm.write(BOOTLOADER_CRC_ADDR as usize, &bootloader_crc.to_be_bytes())
.expect("writing CRC failed"); .expect("writing CRC failed");
if let Err(e) = nvm.verify(BOOTLOADER_CRC_ADDR as usize, &bootloader_crc.to_be_bytes()) { if let Err(e) = nvm.verify(BOOTLOADER_CRC_ADDR as usize, &bootloader_crc.to_be_bytes()) {
if RTT_PRINTOUT { if DEFMT_PRINTOUT {
rprintln!( defmt::error!(
"error: CRC verification for bootloader self-flash failed: {:?}", "error: CRC verification for bootloader self-flash failed: {:?}",
e e
); );
@ -173,8 +171,8 @@ fn main() -> ! {
} else if check_app_crc(other_app) { } else if check_app_crc(other_app) {
boot_app(&dp.sysconfig, &cp, other_app, &mut timer) boot_app(&dp.sysconfig, &cp, other_app, &mut timer)
} else { } else {
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
rprintln!("both images corrupt! booting image A"); defmt::error!("both images corrupt! booting image A");
} }
// TODO: Shift a CCSDS packet out to inform host/OBC about image corruption. // TODO: Shift a CCSDS packet out to inform host/OBC about image corruption.
// Both images seem to be corrupt. Boot default image A. // Both images seem to be corrupt. Boot default image A.
@ -204,8 +202,8 @@ fn check_own_crc(
}); });
let crc_calc = digest.finalize(); let crc_calc = digest.finalize();
if crc_exp == 0x0000 || crc_exp == 0xffff { if crc_exp == 0x0000 || crc_exp == 0xffff {
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
rprintln!("BL CRC blank - prog new CRC"); defmt::info!("BL CRC blank - prog new CRC");
} }
// Blank CRC, write it to NVM. // Blank CRC, write it to NVM.
nvm.write(BOOTLOADER_CRC_ADDR as usize, &crc_calc.to_be_bytes()) nvm.write(BOOTLOADER_CRC_ADDR as usize, &crc_calc.to_be_bytes())
@ -215,8 +213,8 @@ fn check_own_crc(
// cortex_m::peripheral::SCB::sys_reset(); // cortex_m::peripheral::SCB::sys_reset();
} else if crc_exp != crc_calc { } else if crc_exp != crc_calc {
// Bootloader is corrupted. Try to run App A. // Bootloader is corrupted. Try to run App A.
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
rprintln!( defmt::warn!(
"bootloader CRC corrupt, read {} and expected {}. booting image A immediately", "bootloader CRC corrupt, read {} and expected {}. booting image A immediately",
crc_calc, crc_calc,
crc_exp crc_exp
@ -241,8 +239,8 @@ fn read_four_bytes_at_addr_zero(buf: &mut [u8; 4]) {
} }
} }
fn check_app_crc(app_sel: AppSel) -> bool { fn check_app_crc(app_sel: AppSel) -> bool {
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
rprintln!("Checking image {:?}", app_sel); defmt::info!("Checking image {:?}", app_sel);
} }
if app_sel == AppSel::A { if app_sel == AppSel::A {
check_app_given_addr(APP_A_CRC_ADDR, APP_A_START_ADDR, APP_A_SIZE_ADDR) check_app_given_addr(APP_A_CRC_ADDR, APP_A_START_ADDR, APP_A_SIZE_ADDR)
@ -256,8 +254,8 @@ fn check_app_given_addr(crc_addr: u32, start_addr: u32, image_size_addr: u32) ->
let image_size = unsafe { (image_size_addr as *const u32).read_unaligned().to_be() }; let image_size = unsafe { (image_size_addr as *const u32).read_unaligned().to_be() };
// Sanity check. // Sanity check.
if image_size > APP_A_END_ADDR - APP_A_START_ADDR - 8 { if image_size > APP_A_END_ADDR - APP_A_START_ADDR - 8 {
if RTT_PRINTOUT { if DEFMT_PRINTOUT {
rprintln!("detected invalid app size {}", image_size); defmt::error!("detected invalid app size {}", image_size);
} }
return false; return false;
} }
@ -278,8 +276,8 @@ fn boot_app(
app_sel: AppSel, app_sel: AppSel,
timer: &mut CountdownTimer, timer: &mut CountdownTimer,
) -> ! { ) -> ! {
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
rprintln!("booting app {:?}", app_sel); defmt::info!("booting app {:?}", app_sel);
} }
timer.delay_ms(BOOT_DELAY_MS); timer.delay_ms(BOOT_DELAY_MS);