diff --git a/Cargo.toml b/Cargo.toml index 999ed3f..d50955e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,4 @@ debug-assertions = false # <- lto = true opt-level = 'z' # <- overflow-checks = false # <- +strip = true # Automatically strip symbols from the binary. diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index d81898a..86c4e98 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -18,7 +18,7 @@ #![no_std] use cortex_m_rt::entry; -use crc::{Crc, CRC_16_IBM_3740}; +use crc::{Crc, CRC_32_ISO_HDLC}; use panic_rtt_target as _; use rtt_target::{rprintln, rtt_init_print}; use va416xx_hal::{ @@ -47,7 +47,7 @@ const FLASH_SELF: bool = false; const BOOTLOADER_START_ADDR: u32 = 0x0; const BOOTLOADER_END_ADDR: u32 = 0x4000; -const BOOTLOADER_CRC_ADDR: u32 = 0x3FFE; +const BOOTLOADER_CRC_ADDR: u32 = 0x3FFC; const APP_A_START_ADDR: u32 = 0x4000; pub const APP_A_END_ADDR: u32 = 0x22000; // The actual size of the image which is relevant for CRC calculation. @@ -64,7 +64,7 @@ pub const VECTOR_TABLE_OFFSET: u32 = 0x0; pub const VECTOR_TABLE_LEN: u32 = 0x350; pub const RESET_VECTOR_OFFSET: u32 = 0x4; -const CRC_ALGO: Crc = Crc::::new(&CRC_16_IBM_3740); +const CRC_ALGO: Crc = Crc::::new(&CRC_32_ISO_HDLC); #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum AppSel { @@ -111,6 +111,7 @@ fn main() -> ! { WDT_FREQ_MS, )); } + let nvm = Nvm::new(&mut dp.sysconfig, dp.spi3, &clocks); if FLASH_SELF { @@ -172,7 +173,7 @@ fn main() -> ! { } fn check_own_crc(wdt: &OptWdt, nvm: &Nvm, cp: &cortex_m::Peripherals) { - let crc_exp = unsafe { *(BOOTLOADER_CRC_ADDR as *const u16) }; + let crc_exp = unsafe { *(BOOTLOADER_CRC_ADDR as *const u32) }; wdt.feed(); // 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 @@ -219,7 +220,7 @@ fn check_app_given_addr( image_size_addr: u32, wdt: &OptWdt, ) -> bool { - let crc_exp = unsafe { *(crc_addr as *const u16) }; + let crc_exp = unsafe { *(crc_addr as *const u32) }; let image_size = unsafe { *(image_size_addr as *const u32) }; wdt.feed(); let crc_calc = CRC_ALGO.checksum(unsafe { diff --git a/flashloader/image-loader.py b/flashloader/image-loader.py index 29c6a59..3bbfcf0 100755 --- a/flashloader/image-loader.py +++ b/flashloader/image-loader.py @@ -10,6 +10,7 @@ import time from tmtccmd.com.serial_base import SerialCfg from tmtccmd.com.serial_cobs import SerialCobsComIF from tmtccmd.com.ser_utils import prompt_com_port +from crcmod.predefined import PredefinedCrc from spacepackets.ecss.tc import PusTc from pathlib import Path import dataclasses @@ -19,7 +20,7 @@ from elftools.elf.elffile import ELFFile BAUD_RATE = 115200 BOOTLOADER_START_ADDR = 0x0 BOOTLOADER_END_ADDR = 0x4000 -BOOTLOADER_CRC_ADDR = 0x3FFE +BOOTLOADER_CRC_ADDR = 0x3FFC APP_A_START_ADDR = 0x4000 APP_A_END_ADDR = 0x22000 # The actual size of the image which is relevant for CRC calculation. @@ -104,9 +105,29 @@ def main() -> int: with open(file_path, "rb") as app_file: elf_file = ELFFile(app_file) - for segment in elf_file.iter_segments("PT_LOAD"): + for (idx, segment) in enumerate(elf_file.iter_segments("PT_LOAD")): if segment.header.p_filesz == 0: continue + # Basic validity checks of the base addresses. + if idx == 0: + if ( + args.flash == "bl" + and segment.header.p_paddr != BOOTLOADER_START_ADDR + ): + raise ValueError( + f"detected possibly invalid start address {segment.header.p_paddr} for " + f"bootloader, expected {BOOTLOADER_START_ADDR}" + ) + if args.flash == "a" and segment.header.p_paddr != APP_A_START_ADDR: + raise ValueError( + f"detected possibly invalid start address {segment.header.p_paddr} for " + f"App A, expected {APP_A_START_ADDR}" + ) + if args.flash == "b" and segment.header.p_paddr != APP_B_START_ADDR: + raise ValueError( + f"detected possibly invalid start address {segment.header.p_paddr} for " + f"App B, expected {APP_B_START_ADDR}" + ) name = None for section in elf_file.iter_sections(): if ( @@ -138,24 +159,28 @@ def main() -> int: next_chunk_size = segment.offset + segment.size - current_addr if next_chunk_size > CHUNK_SIZE: next_chunk_size = CHUNK_SIZE - app_data = bytearray() - app_data.append(BOOT_NVM_MEMORY_ID) - # N parameter is always 1 here. - app_data.append(1) - app_data.extend(struct.pack("!I", current_addr)) - app_data.extend(struct.pack("!I", next_chunk_size)) - app_data.extend( - segment.data[current_addr : current_addr + next_chunk_size] + next_packet = pack_memory_write_command( + current_addr, + segment.data[current_addr : current_addr + next_chunk_size], ) current_addr += next_chunk_size - next_packet = PusTc( - apid=0, - service=MEMORY_SERVICE, - subservice=RAW_MEMORY_WRITE_SUBSERVICE, - app_data=app_data, - ) com_if.send(next_packet.pack()) time.sleep(0.5) + crc_calc = PredefinedCrc("crc-32") + for segment in loadable_segments: + crc_calc.update(segment) + if args.flash == "bl": + crc_addr = BOOTLOADER_CRC_ADDR + elif args.flash == "a": + crc_addr = APP_A_CRC_ADDR + elif args.flash == "b": + crc_addr = APP_B_CRC_ADDR + else: + raise ValueError(f"unknown flash target {args.flash}") + checksum = crc_calc.digest() + checksum_write_packet = pack_memory_write_command(crc_addr, checksum) + com_if.send(checksum_write_packet.pack()) + time.sleep(0.5) while True: data_available = com_if.data_available(0.4) if data_available: @@ -167,5 +192,21 @@ def main() -> int: return 0 +def pack_memory_write_command(addr: int, data: bytes) -> PusTc: + app_data = bytearray() + app_data.append(BOOT_NVM_MEMORY_ID) + # N parameter is always 1 here. + app_data.append(1) + app_data.extend(struct.pack("!I", addr)) + app_data.extend(struct.pack("!I", len(data))) + app_data.extend(data) + return PusTc( + apid=0, + service=MEMORY_SERVICE, + subservice=RAW_MEMORY_WRITE_SUBSERVICE, + app_data=app_data, + ) + + if __name__ == "__main__": main() diff --git a/flashloader/requirements.txt b/flashloader/requirements.txt index fe0cdf5..5a2f67b 100644 --- a/flashloader/requirements.txt +++ b/flashloader/requirements.txt @@ -1,4 +1,5 @@ spacepackets == 0.24 -tmtccmd == 8.0.1 +tmtccmd == 8.0.2 toml == 0.10 pyelftools == 0.31 +crcmod == 1.7 diff --git a/flashloader/src/main.rs b/flashloader/src/main.rs index 4ac4abc..27e878f 100644 --- a/flashloader/src/main.rs +++ b/flashloader/src/main.rs @@ -52,6 +52,7 @@ static CLOCKS: OnceCell = OnceCell::new(); #[rtic::app(device = pac, dispatchers = [U1, U2, U3])] mod app { use super::*; + use cortex_m::asm; use embedded_hal_nb::nb; use panic_rtt_target as _; use rtic::Mutex; @@ -157,8 +158,9 @@ mod app { // `shared` cannot be accessed from this context #[idle] fn idle(_cx: idle::Context) -> ! { - #[allow(clippy::empty_loop)] - loop {} + loop { + asm::nop(); + } } #[task(