delay works
Some checks failed
Rust/va108xx-rs/pipeline/pr-main There was a failure building this commit

This commit is contained in:
Robin Müller 2024-09-30 11:21:21 +02:00
parent 7603185156
commit e30d6d3f22
Signed by: muellerr
GPG Key ID: A649FB78196E3849
2 changed files with 27 additions and 10 deletions

View File

@ -22,7 +22,9 @@ The bootloader uses the following memory map:
## Additional Information ## Additional Information
This bootloader was specifically written for the REB1 board, so it assumes a M95M01 ST EEPROM This bootloader was specifically written for the REB1 board, so it assumes a M95M01 ST EEPROM
is used to load the application code. is used to load the application code. The bootloader will also delay for a configurable amount
of time before booting. This allows to catch the RTT printout, but should probably be disabled
for production firmware.
This bootloader does not provide tools to flash the NVM memory by itself. Instead, you can use This bootloader does not provide tools to flash the NVM memory by itself. Instead, you can use
the [flashloader](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/flashloader) the [flashloader](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/flashloader)

View File

@ -4,18 +4,21 @@
use bootloader::NvmInterface; use bootloader::NvmInterface;
use cortex_m_rt::entry; use cortex_m_rt::entry;
use crc::{Crc, CRC_16_IBM_3740}; use crc::{Crc, CRC_16_IBM_3740};
use embedded_hal::delay::DelayNs;
#[cfg(not(feature = "rtt-panic"))] #[cfg(not(feature = "rtt-panic"))]
use panic_halt as _; use panic_halt as _;
#[cfg(feature = "rtt-panic")] #[cfg(feature = "rtt-panic")]
use panic_rtt_target as _; use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print}; use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{pac, time::Hertz}; 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 RTT_PRINTOUT: bool = true;
const DEBUG_PRINTOUTS: bool = true; const DEBUG_PRINTOUTS: bool = true;
// Small delay, allows RTT printout to catch up.
const BOOT_DELAY_MS: u32 = 2000;
// Dangerous option! An image with this option set to true will flash itself from RAM directly // Dangerous option! An image with this option set to true will flash itself from RAM directly
// into the NVM. This can be used as a recovery option from a direct RAM flash to fix the NVM // into the NVM. This can be used as a recovery option from a direct RAM flash to fix the NVM
@ -99,6 +102,7 @@ fn main() -> ! {
} }
let mut dp = pac::Peripherals::take().unwrap(); let mut dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap(); let cp = cortex_m::Peripherals::take().unwrap();
let mut timer = CountdownTimer::new(&mut dp.sysconfig, CLOCK_FREQ, dp.tim0);
let mut nvm = M95M01::new(&mut dp.sysconfig, CLOCK_FREQ, dp.spic); let mut nvm = M95M01::new(&mut dp.sysconfig, CLOCK_FREQ, dp.spic);
@ -148,23 +152,28 @@ fn main() -> ! {
let mut nvm = NvmWrapper(nvm); let mut nvm = NvmWrapper(nvm);
// Check bootloader's CRC (and write it if blank) // Check bootloader's CRC (and write it if blank)
check_own_crc(&dp.sysconfig, &cp, &mut nvm); check_own_crc(&dp.sysconfig, &cp, &mut nvm, &mut timer);
if check_app_crc(AppSel::A) { if check_app_crc(AppSel::A) {
boot_app(&dp.sysconfig, &cp, AppSel::A) boot_app(&dp.sysconfig, &cp, AppSel::A, &mut timer)
} else if check_app_crc(AppSel::B) { } else if check_app_crc(AppSel::B) {
boot_app(&dp.sysconfig, &cp, AppSel::B) boot_app(&dp.sysconfig, &cp, AppSel::B, &mut timer)
} else { } else {
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("both images corrupt! booting image A"); rprintln!("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.
boot_app(&dp.sysconfig, &cp, AppSel::A) boot_app(&dp.sysconfig, &cp, AppSel::A, &mut timer)
} }
} }
fn check_own_crc(sysconfig: &pac::Sysconfig, cp: &cortex_m::Peripherals, nvm: &mut NvmWrapper) { fn check_own_crc(
sysconfig: &pac::Sysconfig,
cp: &cortex_m::Peripherals,
nvm: &mut NvmWrapper,
timer: &mut CountdownTimer<pac::Tim0>,
) {
let crc_exp = unsafe { (BOOTLOADER_CRC_ADDR as *const u16).read_unaligned().to_be() }; let crc_exp = unsafe { (BOOTLOADER_CRC_ADDR as *const u16).read_unaligned().to_be() };
// I'd prefer to use [core::slice::from_raw_parts], but that is problematic // I'd prefer to use [core::slice::from_raw_parts], but that is problematic
// because the address of the bootloader is 0x0, so the NULL check fails and the functions // because the address of the bootloader is 0x0, so the NULL check fails and the functions
@ -200,7 +209,7 @@ fn check_own_crc(sysconfig: &pac::Sysconfig, cp: &cortex_m::Peripherals, nvm: &m
); );
} }
// TODO: Shift out minimal CCSDS frame to notify about bootloader corruption. // TODO: Shift out minimal CCSDS frame to notify about bootloader corruption.
boot_app(sysconfig, cp, AppSel::A); boot_app(sysconfig, cp, AppSel::A, timer);
} }
} }
@ -249,10 +258,17 @@ fn check_app_given_addr(crc_addr: u32, start_addr: u32, image_size_addr: u32) ->
// The boot works by copying the interrupt vector table (IVT) of the respective app to the // The boot works by copying the interrupt vector table (IVT) of the respective app to the
// base address in code RAM (0x0) and then performing a soft reset. // base address in code RAM (0x0) and then performing a soft reset.
fn boot_app(syscfg: &pac::Sysconfig, cp: &cortex_m::Peripherals, app_sel: AppSel) -> ! { fn boot_app(
syscfg: &pac::Sysconfig,
cp: &cortex_m::Peripherals,
app_sel: AppSel,
timer: &mut CountdownTimer<pac::Tim0>,
) -> ! {
if DEBUG_PRINTOUTS && RTT_PRINTOUT { if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("booting app {:?}", app_sel); rprintln!("booting app {:?}", app_sel);
} }
timer.delay_ms(BOOT_DELAY_MS);
// Clear all interrupts set. // Clear all interrupts set.
unsafe { unsafe {
cp.NVIC.icer[0].write(0xFFFFFFFF); cp.NVIC.icer[0].write(0xFFFFFFFF);
@ -302,7 +318,6 @@ fn soft_reset(cp: &cortex_m::Peripherals) -> ! {
} }
// Ensure completion of memory access. // Ensure completion of memory access.
cortex_m::asm::dsb(); cortex_m::asm::dsb();
rprintln!("soft reset done");
// Loop until the reset occurs. // Loop until the reset occurs.
loop { loop {