implement CRC write
Some checks failed
Rust/va416xx-rs/pipeline/pr-main There was a failure building this commit

This commit is contained in:
2024-09-11 17:26:31 +02:00
parent 1cc8645781
commit 1b313d21c4
5 changed files with 70 additions and 24 deletions

View File

@ -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()

View File

@ -1,4 +1,5 @@
spacepackets == 0.24
tmtccmd == 8.0.1
tmtccmd == 8.0.2
toml == 0.10
pyelftools == 0.31
crcmod == 1.7

View File

@ -52,6 +52,7 @@ static CLOCKS: OnceCell<Clocks> = 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(