Skip to content

Commit e30d6d3

Browse files
committed
delay works
1 parent 7603185 commit e30d6d3

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

bootloader/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ The bootloader uses the following memory map:
2222
## Additional Information
2323

2424
This bootloader was specifically written for the REB1 board, so it assumes a M95M01 ST EEPROM
25-
is used to load the application code.
25+
is used to load the application code. The bootloader will also delay for a configurable amount
26+
of time before booting. This allows to catch the RTT printout, but should probably be disabled
27+
for production firmware.
2628

2729
This bootloader does not provide tools to flash the NVM memory by itself. Instead, you can use
2830
the [flashloader](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/flashloader)

bootloader/src/main.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44
use bootloader::NvmInterface;
55
use cortex_m_rt::entry;
66
use crc::{Crc, CRC_16_IBM_3740};
7+
use embedded_hal::delay::DelayNs;
78
#[cfg(not(feature = "rtt-panic"))]
89
use panic_halt as _;
910
#[cfg(feature = "rtt-panic")]
1011
use panic_rtt_target as _;
1112
use rtt_target::{rprintln, rtt_init_print};
12-
use va108xx_hal::{pac, time::Hertz};
13+
use va108xx_hal::{pac, time::Hertz, timer::CountdownTimer};
1314
use vorago_reb1::m95m01::M95M01;
1415

1516
// Useful for debugging and see what the bootloader is doing. Enabled currently, because
1617
// the binary stays small enough.
1718
const RTT_PRINTOUT: bool = true;
1819
const DEBUG_PRINTOUTS: bool = true;
20+
// Small delay, allows RTT printout to catch up.
21+
const BOOT_DELAY_MS: u32 = 2000;
1922

2023
// Dangerous option! An image with this option set to true will flash itself from RAM directly
2124
// 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() -> ! {
99102
}
100103
let mut dp = pac::Peripherals::take().unwrap();
101104
let cp = cortex_m::Peripherals::take().unwrap();
105+
let mut timer = CountdownTimer::new(&mut dp.sysconfig, CLOCK_FREQ, dp.tim0);
102106

103107
let mut nvm = M95M01::new(&mut dp.sysconfig, CLOCK_FREQ, dp.spic);
104108

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

150154
// Check bootloader's CRC (and write it if blank)
151-
check_own_crc(&dp.sysconfig, &cp, &mut nvm);
155+
check_own_crc(&dp.sysconfig, &cp, &mut nvm, &mut timer);
152156

153157
if check_app_crc(AppSel::A) {
154-
boot_app(&dp.sysconfig, &cp, AppSel::A)
158+
boot_app(&dp.sysconfig, &cp, AppSel::A, &mut timer)
155159
} else if check_app_crc(AppSel::B) {
156-
boot_app(&dp.sysconfig, &cp, AppSel::B)
160+
boot_app(&dp.sysconfig, &cp, AppSel::B, &mut timer)
157161
} else {
158162
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
159163
rprintln!("both images corrupt! booting image A");
160164
}
161165
// TODO: Shift a CCSDS packet out to inform host/OBC about image corruption.
162166
// Both images seem to be corrupt. Boot default image A.
163-
boot_app(&dp.sysconfig, &cp, AppSel::A)
167+
boot_app(&dp.sysconfig, &cp, AppSel::A, &mut timer)
164168
}
165169
}
166170

167-
fn check_own_crc(sysconfig: &pac::Sysconfig, cp: &cortex_m::Peripherals, nvm: &mut NvmWrapper) {
171+
fn check_own_crc(
172+
sysconfig: &pac::Sysconfig,
173+
cp: &cortex_m::Peripherals,
174+
nvm: &mut NvmWrapper,
175+
timer: &mut CountdownTimer<pac::Tim0>,
176+
) {
168177
let crc_exp = unsafe { (BOOTLOADER_CRC_ADDR as *const u16).read_unaligned().to_be() };
169178
// I'd prefer to use [core::slice::from_raw_parts], but that is problematic
170179
// 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
200209
);
201210
}
202211
// TODO: Shift out minimal CCSDS frame to notify about bootloader corruption.
203-
boot_app(sysconfig, cp, AppSel::A);
212+
boot_app(sysconfig, cp, AppSel::A, timer);
204213
}
205214
}
206215

@@ -249,10 +258,17 @@ fn check_app_given_addr(crc_addr: u32, start_addr: u32, image_size_addr: u32) ->
249258

250259
// The boot works by copying the interrupt vector table (IVT) of the respective app to the
251260
// base address in code RAM (0x0) and then performing a soft reset.
252-
fn boot_app(syscfg: &pac::Sysconfig, cp: &cortex_m::Peripherals, app_sel: AppSel) -> ! {
261+
fn boot_app(
262+
syscfg: &pac::Sysconfig,
263+
cp: &cortex_m::Peripherals,
264+
app_sel: AppSel,
265+
timer: &mut CountdownTimer<pac::Tim0>,
266+
) -> ! {
253267
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
254268
rprintln!("booting app {:?}", app_sel);
255269
}
270+
timer.delay_ms(BOOT_DELAY_MS);
271+
256272
// Clear all interrupts set.
257273
unsafe {
258274
cp.NVIC.icer[0].write(0xFFFFFFFF);
@@ -302,7 +318,6 @@ fn soft_reset(cp: &cortex_m::Peripherals) -> ! {
302318
}
303319
// Ensure completion of memory access.
304320
cortex_m::asm::dsb();
305-
rprintln!("soft reset done");
306321

307322
// Loop until the reset occurs.
308323
loop {

0 commit comments

Comments
 (0)