try to test this

This commit is contained in:
Robin Müller 2024-09-11 18:55:15 +02:00
parent 1b313d21c4
commit 46937f5bf9
Signed by: muellerr
GPG Key ID: A649FB78196E3849
13 changed files with 340 additions and 31 deletions

View File

@ -2,11 +2,16 @@
resolver = "2" resolver = "2"
members = [ members = [
"bootloader", "bootloader",
"examples/simple", "flashloader", "flashloader",
"examples/simple",
"va416xx", "va416xx",
"va416xx-hal", "va416xx-hal",
"vorago-peb1" "vorago-peb1"
] ]
exclude = [
"flashloader/slot-a-blinky",
"flashloader/slot-b-blinky",
]
[profile.dev] [profile.dev]
codegen-units = 1 codegen-units = 1
@ -34,4 +39,4 @@ debug-assertions = false # <-
lto = true lto = true
opt-level = 'z' # <- opt-level = 'z' # <-
overflow-checks = false # <- overflow-checks = false # <-
strip = true # Automatically strip symbols from the binary. # strip = true # Automatically strip symbols from the binary.

View File

@ -1,11 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from dataclasses import dataclass
from spacepackets.ecss.defs import PusService from spacepackets.ecss.defs import PusService
import toml import toml
import struct import struct
import logging import logging
import argparse import argparse
from typing import List
import time import time
from tmtccmd.com.serial_base import SerialCfg from tmtccmd.com.serial_base import SerialCfg
from tmtccmd.com.serial_cobs import SerialCobsComIF from tmtccmd.com.serial_cobs import SerialCobsComIF
@ -102,6 +100,7 @@ def main() -> int:
assert file_path is not None assert file_path is not None
loadable_segments = [] loadable_segments = []
_LOGGER.info("Parsing ELF file for loadable sections") _LOGGER.info("Parsing ELF file for loadable sections")
total_size = 0
with open(file_path, "rb") as app_file: with open(file_path, "rb") as app_file:
elf_file = ELFFile(app_file) elf_file = ELFFile(app_file)
@ -115,17 +114,17 @@ def main() -> int:
and segment.header.p_paddr != BOOTLOADER_START_ADDR and segment.header.p_paddr != BOOTLOADER_START_ADDR
): ):
raise ValueError( raise ValueError(
f"detected possibly invalid start address {segment.header.p_paddr} for " f"detected possibly invalid start address {segment.header.p_paddr:#08x} for "
f"bootloader, expected {BOOTLOADER_START_ADDR}" f"bootloader, expected {BOOTLOADER_START_ADDR}"
) )
if args.flash == "a" and segment.header.p_paddr != APP_A_START_ADDR: if args.flash == "a" and segment.header.p_paddr != APP_A_START_ADDR:
raise ValueError( raise ValueError(
f"detected possibly invalid start address {segment.header.p_paddr} for " f"detected possibly invalid start address {segment.header.p_paddr:#08x} for "
f"App A, expected {APP_A_START_ADDR}" f"App A, expected {APP_A_START_ADDR}"
) )
if args.flash == "b" and segment.header.p_paddr != APP_B_START_ADDR: if args.flash == "b" and segment.header.p_paddr != APP_B_START_ADDR:
raise ValueError( raise ValueError(
f"detected possibly invalid start address {segment.header.p_paddr} for " f"detected possibly invalid start address {segment.header.p_paddr:#08x} for "
f"App B, expected {APP_B_START_ADDR}" f"App B, expected {APP_B_START_ADDR}"
) )
name = None name = None
@ -149,38 +148,75 @@ def main() -> int:
data=segment.data(), data=segment.data(),
) )
) )
total_size += segment.header.p_filesz
context_str = None
if args.flash == "bl":
context_str = "Bootloader"
elif args.flash == "a":
context_str = "App Slot A"
elif args.flash == "b":
context_str = "App Slot B"
_LOGGER.info(
f"Flashing {context_str} with image {file_path} (size {total_size})"
)
for idx, segment in enumerate(loadable_segments): for idx, segment in enumerate(loadable_segments):
_LOGGER.info( _LOGGER.info(
f"Loadable section {idx} {segment.name} with offset {segment.offset} and size {segment.size}" f"Loadable section {idx} {segment.name} with offset {segment.offset:#08x} and size {segment.size}"
) )
for segment in loadable_segments: for segment in loadable_segments:
segment_end = segment.offset + segment.size
current_addr = segment.offset current_addr = segment.offset
while current_addr < segment.offset + segment.size: pos_in_segment = 0
next_chunk_size = segment.offset + segment.size - current_addr while pos_in_segment < segment.size:
if next_chunk_size > CHUNK_SIZE: next_chunk_size = min(segment_end - current_addr, CHUNK_SIZE)
next_chunk_size = CHUNK_SIZE data = segment.data[
next_packet = pack_memory_write_command( pos_in_segment : pos_in_segment + next_chunk_size
current_addr, ]
segment.data[current_addr : current_addr + next_chunk_size], _LOGGER.info(
f"Sending memory write command for address {current_addr:#08x} and data with "
f"length {len(data)}"
) )
current_addr += next_chunk_size next_packet = pack_memory_write_command(current_addr, data)
com_if.send(next_packet.pack()) com_if.send(next_packet.pack())
time.sleep(0.5) current_addr += next_chunk_size
crc_calc = PredefinedCrc("crc-32") pos_in_segment += next_chunk_size
for segment in loadable_segments: time.sleep(0.2)
crc_calc.update(segment)
if args.flash == "bl": if args.flash == "bl":
crc_addr = BOOTLOADER_CRC_ADDR _LOGGER.info("Blanking the bootloader checksum")
elif args.flash == "a": # Blank the checksum. For the bootloader, the bootloader will calculate the
# checksum itself on the initial run.
checksum_write_packet = pack_memory_write_command(
BOOTLOADER_CRC_ADDR, bytes([0x00, 0x00, 0x00, 0x00])
)
com_if.send(checksum_write_packet.pack())
else:
crc_addr = None
size_addr = None
if args.flash == "a":
crc_addr = APP_A_CRC_ADDR crc_addr = APP_A_CRC_ADDR
size_addr = APP_A_SIZE_ADDR
elif args.flash == "b": elif args.flash == "b":
crc_addr = APP_B_CRC_ADDR crc_addr = APP_B_CRC_ADDR
else: size_addr = APP_B_SIZE_ADDR
raise ValueError(f"unknown flash target {args.flash}") assert crc_addr is not None
assert size_addr is not None
_LOGGER.info(
f"Writing app size {total_size } at address {size_addr:#08x}"
)
size_write_packet = pack_memory_write_command(
size_addr, struct.pack("!I", total_size)
)
com_if.send(size_write_packet.pack())
time.sleep(0.2)
crc_calc = PredefinedCrc("crc-32")
for segment in loadable_segments:
crc_calc.update(segment.data)
checksum = crc_calc.digest() checksum = crc_calc.digest()
_LOGGER.info(
f"Writing checksum 0x[{checksum.hex(sep=',')}] at address {crc_addr:#08x}"
)
checksum_write_packet = pack_memory_write_command(crc_addr, checksum) checksum_write_packet = pack_memory_write_command(crc_addr, checksum)
com_if.send(checksum_write_packet.pack()) com_if.send(checksum_write_packet.pack())
time.sleep(0.5)
while True: while True:
data_available = com_if.data_available(0.4) data_available = com_if.data_available(0.4)
if data_available: if data_available:

2
flashloader/slot-a-blinky/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/app.map

View File

@ -0,0 +1,42 @@
[package]
name = "slot-a-blinky"
version = "0.1.0"
edition = "2021"
[workspace]
[dependencies]
cortex-m-rt = "0.7"
va416xx-hal = { path = "../../va416xx-hal" }
panic-rtt-target = { version = "0.1.3" }
rtt-target = { version = "0.5" }
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
embedded-hal = "1"
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
# This is problematic for stepping..
# opt-level = 'z' # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
[profile.small]
inherits = "release"
codegen-units = 1
debug-assertions = false # <-
lto = true
opt-level = 'z' # <-
overflow-checks = false # <-
# strip = true # Automatically strip symbols from the binary.

View File

@ -0,0 +1,24 @@
/* Special linker script for application slot A with an offset at address 0x4000 */
MEMORY
{
FLASH : ORIGIN = 0x00004000, LENGTH = 256K
/* RAM is a mandatory region. This RAM refers to the SRAM_0 */
RAM : ORIGIN = 0x1FFF8000, LENGTH = 32K
SRAM_1 : ORIGIN = 0x20000000, LENGTH = 32K
}
/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
/* SRAM_0 can be used for all busses: Instruction, Data and System */
/* SRAM_1 only supports the system bus */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
/* Define sections for placing symbols into the extra memory regions above. */
/* This makes them accessible from code. */
SECTIONS {
.sram1 (NOLOAD) : ALIGN(8) {
*(.sram1 .sram1.*);
. = ALIGN(4);
} > SRAM_1
};

View File

@ -0,0 +1,23 @@
//! Simple blinky example using the HAL
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use embedded_hal::digital::StatefulOutputPin;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::{gpio::PinsG, pac};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("VA416xx HAL blinky example for App Slot A");
let mut dp = pac::Peripherals::take().unwrap();
let portg = PinsG::new(&mut dp.sysconfig, dp.portg);
let mut led = portg.pg5.into_readable_push_pull_output();
loop {
cortex_m::asm::delay(1_000_000);
led.toggle().ok();
}
}

View File

@ -0,0 +1,42 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "gdb-multiarch -q -x jlink/jlink.gdb"
# runner = "arm-none-eabi-gdb -q -x jlink/jlink-reva.gdb"
# runner = "gdb-multiarch -q -x jlink/jlink-reva.gdb"
# Probe-rs is currently problematic, possibly because of the
# ROM protection?
# runner = "probe-rs run --chip VA416xx"
# runner = ["probe-rs", "run", "--chip", "$CHIP", "--log-format", "{L} {s}"]
rustflags = [
"-C",
"link-arg=-Tlink.x",
# "-C",
# "linker=flip-link",
# "-C",
# "link-arg=-Tdefmt.x",
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
"-C",
"link-arg=--nmagic",
# Can be useful for debugging.
"-Clink-args=-Map=app.map"
]
[build]
# (`thumbv6m-*` is compatible with all ARM Cortex-M chips but using the right
# target improves performance)
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
[alias]
rb = "run --bin"
rrb = "run --release --bin"
ut = "test --target=x86_64-unknown-linux-gnu"
oc = "objcopy"
[env]
DEFMT_LOG = "info"

View File

@ -0,0 +1,42 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "gdb-multiarch -q -x jlink/jlink.gdb"
# runner = "arm-none-eabi-gdb -q -x jlink/jlink-reva.gdb"
# runner = "gdb-multiarch -q -x jlink/jlink-reva.gdb"
# Probe-rs is currently problematic, possibly because of the
# ROM protection?
# runner = "probe-rs run --chip-description-path ./scripts/VA416xx_Series.yaml"
# runner = ["probe-rs", "run", "--chip", "$CHIP", "--log-format", "{L} {s}"]
rustflags = [
"-C",
"link-arg=-Tlink.x",
# "-C",
# "linker=flip-link",
# "-C",
# "link-arg=-Tdefmt.x",
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x
# See https://github.com/rust-embedded/cortex-m-quickstart/pull/95
"-C",
"link-arg=--nmagic",
# Can be useful for debugging.
# "-Clink-args=-Map=app.map"
]
[build]
# (`thumbv6m-*` is compatible with all ARM Cortex-M chips but using the right
# target improves performance)
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
[alias]
rb = "run --bin"
rrb = "run --release --bin"
ut = "test --target=x86_64-unknown-linux-gnu"
genbin = "objcopy --release -- -O binary app.bin"
[env]
DEFMT_LOG = "info"

2
flashloader/slot-b-blinky/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/app.map

View File

@ -0,0 +1,42 @@
[package]
name = "slot-b-blinky"
version = "0.1.0"
edition = "2021"
[workspace]
[dependencies]
cortex-m-rt = "0.7"
va416xx-hal = { path = "../../va416xx-hal" }
panic-rtt-target = { version = "0.1.3" }
rtt-target = { version = "0.5" }
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
embedded-hal = "1"
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
# This is problematic for stepping..
# opt-level = 'z' # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = 3 # <-
overflow-checks = false # <-
[profile.small]
inherits = "release"
codegen-units = 1
debug-assertions = false # <-
lto = true
opt-level = 'z' # <-
overflow-checks = false # <-
# strip = true # Automatically strip symbols from the binary.

View File

@ -0,0 +1,24 @@
/* Special linker script for application slot B with an offset at address 0x22000 */
MEMORY
{
FLASH : ORIGIN = 0x00022000, LENGTH = 256K
/* RAM is a mandatory region. This RAM refers to the SRAM_0 */
RAM : ORIGIN = 0x1FFF8000, LENGTH = 32K
SRAM_1 : ORIGIN = 0x20000000, LENGTH = 32K
}
/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
/* SRAM_0 can be used for all busses: Instruction, Data and System */
/* SRAM_1 only supports the system bus */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
/* Define sections for placing symbols into the extra memory regions above. */
/* This makes them accessible from code. */
SECTIONS {
.sram1 (NOLOAD) : ALIGN(8) {
*(.sram1 .sram1.*);
. = ALIGN(4);
} > SRAM_1
};

View File

@ -0,0 +1,23 @@
//! Simple blinky example using the HAL
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use embedded_hal::digital::StatefulOutputPin;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::{gpio::PinsG, pac};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("VA416xx HAL blinky example for App Slot B");
let mut dp = pac::Peripherals::take().unwrap();
let portg = PinsG::new(&mut dp.sysconfig, dp.portg);
let mut led = portg.pg5.into_readable_push_pull_output();
loop {
cortex_m::asm::delay(8_000_000);
led.toggle().ok();
}
}

View File

@ -260,6 +260,8 @@ impl Nvm {
/// Call [Self::shutdown] on drop. /// Call [Self::shutdown] on drop.
impl Drop for Nvm { impl Drop for Nvm {
fn drop(&mut self) { fn drop(&mut self) {
if self.spi.is_some() {
self.shutdown(unsafe { &mut pac::Sysconfig::steal() }); self.shutdown(unsafe { &mut pac::Sysconfig::steal() });
} }
} }
}