Skip to content

Commit

Permalink
delay works
Browse files Browse the repository at this point in the history
  • Loading branch information
robamu committed Sep 30, 2024
1 parent 7603185 commit e30d6d3
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
4 changes: 3 additions & 1 deletion bootloader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ The bootloader uses the following memory map:
## Additional Information

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
the [flashloader](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/flashloader)
Expand Down
33 changes: 24 additions & 9 deletions bootloader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@
use bootloader::NvmInterface;
use cortex_m_rt::entry;
use crc::{Crc, CRC_16_IBM_3740};
use embedded_hal::delay::DelayNs;
#[cfg(not(feature = "rtt-panic"))]
use panic_halt as _;
#[cfg(feature = "rtt-panic")]
use panic_rtt_target as _;
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;

// Useful for debugging and see what the bootloader is doing. Enabled currently, because
// the binary stays small enough.
const RTT_PRINTOUT: 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
// into the NVM. This can be used as a recovery option from a direct RAM flash to fix the NVM
Expand Down Expand Up @@ -99,6 +102,7 @@ fn main() -> ! {
}
let mut dp = pac::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);

Expand Down Expand Up @@ -148,23 +152,28 @@ fn main() -> ! {
let mut nvm = NvmWrapper(nvm);

// 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) {
boot_app(&dp.sysconfig, &cp, AppSel::A)
boot_app(&dp.sysconfig, &cp, AppSel::A, &mut timer)
} else if check_app_crc(AppSel::B) {
boot_app(&dp.sysconfig, &cp, AppSel::B)
boot_app(&dp.sysconfig, &cp, AppSel::B, &mut timer)
} else {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("both images corrupt! booting image A");
}
// TODO: Shift a CCSDS packet out to inform host/OBC about image corruption.
// 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() };
// 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
Expand Down Expand Up @@ -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.
boot_app(sysconfig, cp, AppSel::A);
boot_app(sysconfig, cp, AppSel::A, timer);
}
}

Expand Down Expand Up @@ -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
// 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 {
rprintln!("booting app {:?}", app_sel);
}
timer.delay_ms(BOOT_DELAY_MS);

// Clear all interrupts set.
unsafe {
cp.NVIC.icer[0].write(0xFFFFFFFF);
Expand Down Expand Up @@ -302,7 +318,6 @@ fn soft_reset(cp: &cortex_m::Peripherals) -> ! {
}
// Ensure completion of memory access.
cortex_m::asm::dsb();
rprintln!("soft reset done");

// Loop until the reset occurs.
loop {
Expand Down

0 comments on commit e30d6d3

Please sign in to comment.