Rework library structure

Changed:

- Move most library components to new [`vorago-shared-periphs`](https://egit.irs.uni-stuttgart.de/rust/vorago-shared-periphs)
  which is mostly re-exported in this crate.
- All HAL API constructors now have a more consistent argument order: PAC structures and resource
  management structures first, then clock configuration, then any other configuration.
- Overhaul and simplification of several HAL APIs. The system configuration and IRQ router
  peripheral instance generally does not need to be passed to HAL API anymore.
- All HAL drivers are now type erased. The constructors will still expect and consume the PAC
  singleton component for resource management purposes, but are not cached anymore.
- Refactoring of GPIO library to be more inline with embassy GPIO API.

Added:

- I2C clock timeout feature support.
This commit is contained in:
2025-04-12 17:01:53 +02:00
parent 5b2ded51f9
commit 0f209c152d
67 changed files with 775 additions and 9242 deletions

View File

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

View File

@ -6,17 +6,16 @@ use cortex_m_rt::entry;
use crc::{Crc, CRC_16_IBM_3740};
use embedded_hal::delay::DelayNs;
use num_enum::TryFromPrimitive;
#[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, timer::CountdownTimer};
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use va108xx_hal::{pac, spi::SpiClkConfig, 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 DEFMT_PRINTOUT: bool = true;
const DEBUG_PRINTOUTS: bool = true;
// Small delay, allows RTT printout to catch up.
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);
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, defmt::Format)]
#[repr(u8)]
enum AppSel {
A = 0,
@ -100,15 +99,15 @@ impl NvmInterface for NvmWrapper {
#[entry]
fn main() -> ! {
if RTT_PRINTOUT {
rtt_init_print!();
rprintln!("-- VA108xx bootloader --");
if DEFMT_PRINTOUT {
defmt::println!("-- VA108xx bootloader --");
}
let mut dp = pac::Peripherals::take().unwrap();
let 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 timer = CountdownTimer::new(dp.tim0, CLOCK_FREQ);
let mut nvm = M95M01::new(&mut dp.sysconfig, CLOCK_FREQ, dp.spic);
let clk_config = SpiClkConfig::new(2, 4);
let mut nvm = M95M01::new(dp.spic, clk_config);
if FLASH_SELF {
let mut first_four_bytes: [u8; 4] = [0; 4];
@ -131,21 +130,21 @@ fn main() -> ! {
nvm.write(0x4, bootloader_data)
.expect("writing to NVM failed");
if let Err(e) = nvm.verify(0x0, &first_four_bytes) {
if RTT_PRINTOUT {
rprintln!("verification of self-flash to NVM failed: {:?}", e);
if DEFMT_PRINTOUT {
defmt::error!("verification of self-flash to NVM failed: {:?}", e);
}
}
if let Err(e) = nvm.verify(0x4, bootloader_data) {
if RTT_PRINTOUT {
rprintln!("verification of self-flash to NVM failed: {:?}", e);
if DEFMT_PRINTOUT {
defmt::error!("verification of self-flash to NVM failed: {:?}", e);
}
}
nvm.write(BOOTLOADER_CRC_ADDR as usize, &bootloader_crc.to_be_bytes())
.expect("writing CRC failed");
if let Err(e) = nvm.verify(BOOTLOADER_CRC_ADDR as usize, &bootloader_crc.to_be_bytes()) {
if RTT_PRINTOUT {
rprintln!(
if DEFMT_PRINTOUT {
defmt::error!(
"error: CRC verification for bootloader self-flash failed: {:?}",
e
);
@ -173,8 +172,8 @@ fn main() -> ! {
} else if check_app_crc(other_app) {
boot_app(&dp.sysconfig, &cp, other_app, &mut timer)
} else {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("both images corrupt! booting image A");
if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
defmt::error!("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.
@ -186,7 +185,7 @@ fn check_own_crc(
sysconfig: &pac::Sysconfig,
cp: &cortex_m::Peripherals,
nvm: &mut NvmWrapper,
timer: &mut CountdownTimer<pac::Tim0>,
timer: &mut CountdownTimer,
) {
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
@ -204,8 +203,8 @@ fn check_own_crc(
});
let crc_calc = digest.finalize();
if crc_exp == 0x0000 || crc_exp == 0xffff {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("BL CRC blank - prog new CRC");
if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
defmt::info!("BL CRC blank - prog new CRC");
}
// Blank CRC, write it to NVM.
nvm.write(BOOTLOADER_CRC_ADDR as usize, &crc_calc.to_be_bytes())
@ -215,8 +214,8 @@ fn check_own_crc(
// cortex_m::peripheral::SCB::sys_reset();
} else if crc_exp != crc_calc {
// Bootloader is corrupted. Try to run App A.
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!(
if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
defmt::warn!(
"bootloader CRC corrupt, read {} and expected {}. booting image A immediately",
crc_calc,
crc_exp
@ -241,8 +240,8 @@ fn read_four_bytes_at_addr_zero(buf: &mut [u8; 4]) {
}
}
fn check_app_crc(app_sel: AppSel) -> bool {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("Checking image {:?}", app_sel);
if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
defmt::info!("Checking image {:?}", app_sel);
}
if app_sel == AppSel::A {
check_app_given_addr(APP_A_CRC_ADDR, APP_A_START_ADDR, APP_A_SIZE_ADDR)
@ -256,8 +255,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() };
// Sanity check.
if image_size > APP_A_END_ADDR - APP_A_START_ADDR - 8 {
if RTT_PRINTOUT {
rprintln!("detected invalid app size {}", image_size);
if DEFMT_PRINTOUT {
defmt::error!("detected invalid app size {}", image_size);
}
return false;
}
@ -276,10 +275,10 @@ fn boot_app(
syscfg: &pac::Sysconfig,
cp: &cortex_m::Peripherals,
app_sel: AppSel,
timer: &mut CountdownTimer<pac::Tim0>,
timer: &mut CountdownTimer,
) -> ! {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("booting app {:?}", app_sel);
if DEBUG_PRINTOUTS && DEFMT_PRINTOUT {
defmt::info!("booting app {:?}", app_sel);
}
timer.delay_ms(BOOT_DELAY_MS);