delay works
Some checks failed
Rust/va108xx-rs/pipeline/pr-main There was a failure building this commit
Some checks failed
Rust/va108xx-rs/pipeline/pr-main There was a failure building this commit
This commit is contained in:
parent
7603185156
commit
e30d6d3f22
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user