Merge pull request 'start switching to defmt' (#67) from add-defmt-support into main

Reviewed-on: #67
This commit is contained in:
Robin Müller 2025-04-24 14:29:02 +02:00
commit d641f3943f
35 changed files with 317 additions and 240 deletions

View File

@ -2,18 +2,15 @@
# 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_RAM --protocol swd"
rustflags = [
"-C",
"link-arg=-Tlink.x",
# "-C",
# "linker=flip-link",
# "-C",
# "link-arg=-Tdefmt.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",
@ -37,4 +34,4 @@ ut = "test --target=x86_64-unknown-linux-gnu"
genbin = "objcopy --release -- -O binary app.bin"
[env]
DEFMT_LOG = "info"
DEFMT_LOG = "debug"

View File

@ -74,8 +74,8 @@ probe-rs run --chip VA416xx_RAM --protocol jtag target/thumbv7em-none-eabihf/deb
to flash and run the blinky program on the RAM. There is also a `VA416xx` chip target
available for persistent flashing.
Runner configuration avilable in the `.cargo/def-config.toml` file to use `probe-rs` for
convenience.
Runner configuration is available in the `.cargo/def-config.toml` file to use `probe-rs` for
convenience. `probe-rs` is also able to process and display `defmt` strings directly.
### Pre-Requisites
@ -123,16 +123,25 @@ You can build the blinky example application with the following command
cargo build --example blinky
```
Start the GDB server first. The server needs to be started with a certain configuration and with
a JLink script to disable ROM protection.
Start the GDB server first. Depending on whether the application is flashed to RAM or the NVM
flash memory, the server needs to be started with a different configuration
For example, on Debian based system the following command can be used to do this (this command
is also run when running the `jlink-gdb.sh` script)
**RAM Flash**
```sh
JLinkGDBServer -select USB -device Cortex-M4 -endian little -if SWD -speed 2000 \
-LocalhostOnly -vd -jlinkscriptfile ./jlink/JLinkSettings.JLinkScript
```
**NVM Flash**
```sh
JLinkGDBServer -select USB -device VA416xx -endian little -if SWD -speed 2000 \
-LocalhostOnly -vd
```
After this, you can flash and debug the application with the following command
```sh
@ -144,7 +153,7 @@ runner configuration, for example with the following lines in your `.cargo/confi
```toml
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "gdb-multiarch -q -x jlink/jlink.gdb"
runner = "gdb-multiarch -q -x jlink/jlink.gdb -tui"
```
After that, you can simply use `cargo run --example blinky` to flash the blinky
@ -156,6 +165,15 @@ The Segger RTT viewer can be used to display log messages received from the targ
address for the RTT block placement is 0x1fff8000. It is recommended to use a search range of
0x1000 around that base address when using the RTT viewer.
The RTT viewer will not be able to process `defmt` printouts. However, you can view the defmt
logs by [installing defmt-print](https://crates.io/crates/defmt-print) first and then running
```sh
defmt-print -e <pathToElfFile> tcp
```
The path of the ELF file which is being debugged needs to be specified for this to work.
## Learning (Embedded) Rust
If you are unfamiliar with Rust on Embedded Systems or Rust in general, the following resources

View File

@ -7,16 +7,12 @@ edition = "2021"
cortex-m = "0.7"
cortex-m-rt = "0.7"
embedded-hal = "1"
panic-rtt-target = { version = "0.2" }
panic-halt = { version = "1" }
rtt-target = { version = "0.6" }
defmt-rtt = "0.4"
defmt = "1"
panic-probe = { version = "1", features = ["defmt"] }
crc = "3"
static_assertions = "1"
[dependencies.va416xx-hal]
version = "0.5"
features = ["va41630"]
[features]
default = []
rtt-panic = []
features = ["va41630", "defmt"]

View File

@ -7,11 +7,8 @@
use cortex_m_rt::entry;
use crc::{Crc, CRC_32_ISO_HDLC};
#[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 defmt_rtt as _;
use panic_probe as _;
use va416xx_hal::{
clock::{pll_setup_delay, ClkDivSel, ClkselSys},
edac,
@ -35,7 +32,7 @@ const DEBUG_PRINTOUTS: bool = true;
const FLASH_SELF: bool = false;
// 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_PRINTOUTS: bool = true;
// Important bootloader addresses and offsets, vector table information.
@ -76,7 +73,7 @@ pub const RESET_VECTOR_OFFSET: u32 = 0x4;
const CRC_ALGO: Crc<u32> = Crc::<u32>::new(&CRC_32_ISO_HDLC);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, defmt::Format)]
enum AppSel {
A,
B,
@ -98,9 +95,8 @@ impl WdtInterface for OptWdt {
#[entry]
fn main() -> ! {
if RTT_PRINTOUT {
rtt_init_print!();
rprintln!("-- VA416xx bootloader --");
if DEFMT_PRINTOUTS {
defmt::println!("-- VA416xx bootloader --");
}
let mut dp = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap();
@ -145,20 +141,20 @@ fn main() -> ! {
nvm.write_data(0x0, &first_four_bytes);
nvm.write_data(0x4, bootloader_data);
if let Err(e) = nvm.verify_data(0x0, &first_four_bytes) {
if RTT_PRINTOUT {
rprintln!("verification of self-flash to NVM failed: {:?}", e);
if DEFMT_PRINTOUTS {
defmt::error!("verification of self-flash to NVM failed: {:?}", e);
}
}
if let Err(e) = nvm.verify_data(0x4, bootloader_data) {
if RTT_PRINTOUT {
rprintln!("verification of self-flash to NVM failed: {:?}", e);
if DEFMT_PRINTOUTS {
defmt::error!("verification of self-flash to NVM failed: {:?}", e);
}
}
nvm.write_data(BOOTLOADER_CRC_ADDR, &bootloader_crc.to_be_bytes());
if let Err(e) = nvm.verify_data(BOOTLOADER_CRC_ADDR, &bootloader_crc.to_be_bytes()) {
if RTT_PRINTOUT {
rprintln!(
if DEFMT_PRINTOUTS {
defmt::error!(
"error: CRC verification for bootloader self-flash failed: {:?}",
e
);
@ -174,8 +170,8 @@ fn main() -> ! {
} else if check_app_crc(AppSel::B, &opt_wdt) {
boot_app(AppSel::B, &cp)
} else {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("both images corrupt! booting image A");
if DEBUG_PRINTOUTS && DEFMT_PRINTOUTS {
defmt::println!("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.
@ -202,8 +198,8 @@ fn check_own_crc(wdt: &OptWdt, nvm: &Nvm, cp: &cortex_m::Peripherals) {
let crc_calc = digest.finalize();
wdt.feed();
if crc_exp == 0x0000 || crc_exp == 0xffff {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("BL CRC blank - prog new CRC");
if DEBUG_PRINTOUTS && DEFMT_PRINTOUTS {
defmt::info!("BL CRC blank - prog new CRC");
}
// Blank CRC, write it to NVM.
nvm.write_data(BOOTLOADER_CRC_ADDR, &crc_calc.to_be_bytes());
@ -212,8 +208,8 @@ fn check_own_crc(wdt: &OptWdt, nvm: &Nvm, cp: &cortex_m::Peripherals) {
// 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_PRINTOUTS {
defmt::info!(
"bootloader CRC corrupt, read {} and expected {}. booting image A immediately",
crc_calc,
crc_exp
@ -235,8 +231,8 @@ fn read_four_bytes_at_addr_zero(buf: &mut [u8; 4]) {
}
}
fn check_app_crc(app_sel: AppSel, wdt: &OptWdt) -> bool {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("Checking image {:?}", app_sel);
if DEBUG_PRINTOUTS && DEFMT_PRINTOUTS {
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, wdt)
@ -255,8 +251,8 @@ fn check_app_given_addr(
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_PRINTOUTS {
defmt::info!("detected invalid app size {}", image_size);
}
return false;
}
@ -272,8 +268,8 @@ fn check_app_given_addr(
}
fn boot_app(app_sel: AppSel, cp: &cortex_m::Peripherals) -> ! {
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
rprintln!("booting app {:?}", app_sel);
if DEBUG_PRINTOUTS && DEFMT_PRINTOUTS {
defmt::info!("booting app {:?}", app_sel);
}
let clkgen = unsafe { pac::Clkgen::steal() };
clkgen

View File

@ -12,9 +12,10 @@ embedded-io = "0.6"
embedded-hal-async = "1"
embedded-io-async = "0.6"
rtt-target = { version = "0.6" }
heapless = "0.8"
panic-rtt-target = { version = "0.2" }
defmt-rtt = "0.4"
defmt = "1"
panic-probe = { version = "1", features = ["defmt"] }
static_cell = "2"
critical-section = "1"
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
@ -28,7 +29,7 @@ embassy-executor = { version = "0.7", features = [
"executor-interrupt"
]}
va416xx-hal = { version = "0.5" }
va416xx-hal = { version = "0.5", features = ["defmt"] }
va416xx-embassy = { version = "0.1", default-features = false }
[features]

View File

@ -5,6 +5,10 @@
//! [CHECK_XXX_TO_XXX] constants to true.
#![no_std]
#![no_main]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use embassy_example::EXTCLK_FREQ;
use embassy_executor::Spawner;
@ -12,8 +16,6 @@ use embassy_sync::channel::{Receiver, Sender};
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, channel::Channel};
use embassy_time::{Duration, Instant, Timer};
use embedded_hal_async::digital::Wait;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::clock::ClkgenExt;
use va416xx_hal::gpio::{
on_interrupt_for_async_gpio_for_port, InputDynPinAsync, InputPinAsync, PinsB, PinsC, PinsD,
@ -66,8 +68,7 @@ static CHANNEL_PF0_TO_PF1: Channel<ThreadModeRawMutex, GpioCmd, 3> = Channel::ne
#[embassy_executor::main]
async fn main(spawner: Spawner) {
rtt_init_print!();
rprintln!("-- VA416xx Async GPIO Demo --");
defmt::println!("-- VA416xx Async GPIO Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -114,7 +115,7 @@ async fn main(spawner: Spawner) {
))
.unwrap();
check_pin_to_pin_async_ops("PA0 to PA1", CHANNEL_PA0_TO_PA1.sender(), in_pin).await;
rprintln!("Example PA0 to PA1 done");
defmt::info!("Example PA0 to PA1 done");
}
if CHECK_PB0_TO_PB1 {
@ -131,7 +132,7 @@ async fn main(spawner: Spawner) {
))
.unwrap();
check_pin_to_pin_async_ops("PB0 to PB1", CHANNEL_PB0_TO_PB1.sender(), in_pin).await;
rprintln!("Example PB0 to PB1 done");
defmt::info!("Example PB0 to PB1 done");
}
if CHECK_PC14_TO_PC15 {
@ -147,7 +148,7 @@ async fn main(spawner: Spawner) {
))
.unwrap();
check_pin_to_pin_async_ops("PC14 to PC15", CHANNEL_PC14_TO_PC15.sender(), in_pin).await;
rprintln!("Example PC14 to PC15 done");
defmt::info!("Example PC14 to PC15 done");
}
if CHECK_PD2_TO_PD3 {
@ -163,7 +164,7 @@ async fn main(spawner: Spawner) {
))
.unwrap();
check_pin_to_pin_async_ops("PD2 to PD3", CHANNEL_PD2_TO_PD3.sender(), in_pin).await;
rprintln!("Example PD2 to PD3 done");
defmt::info!("Example PD2 to PD3 done");
}
if CHECK_PE0_TO_PE1 {
@ -179,7 +180,7 @@ async fn main(spawner: Spawner) {
))
.unwrap();
check_pin_to_pin_async_ops("PE0 to PE1", CHANNEL_PE0_TO_PE1.sender(), in_pin).await;
rprintln!("Example PE0 to PE1 done");
defmt::info!("Example PE0 to PE1 done");
}
if CHECK_PF0_TO_PF1 {
@ -195,10 +196,10 @@ async fn main(spawner: Spawner) {
))
.unwrap();
check_pin_to_pin_async_ops("PF0 to PF1", CHANNEL_PF0_TO_PF1.sender(), in_pin).await;
rprintln!("Example PF0 to PF1 done");
defmt::info!("Example PF0 to PF1 done");
}
rprintln!("Example done, toggling LED0");
defmt::info!("Example done, toggling LED0");
loop {
led.toggle();
Timer::after(Duration::from_millis(500)).await;
@ -210,46 +211,46 @@ async fn check_pin_to_pin_async_ops(
sender: Sender<'static, ThreadModeRawMutex, GpioCmd, 3>,
mut async_input: impl Wait,
) {
rprintln!(
defmt::info!(
"{}: sending SetHigh command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::SetHigh, 20)).await;
async_input.wait_for_high().await.unwrap();
rprintln!(
defmt::info!(
"{}: Input pin is high now ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
defmt::info!(
"{}: sending SetLow command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::SetLow, 20)).await;
async_input.wait_for_low().await.unwrap();
rprintln!(
defmt::info!(
"{}: Input pin is low now ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
defmt::info!(
"{}: sending RisingEdge command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::RisingEdge, 20)).await;
async_input.wait_for_rising_edge().await.unwrap();
rprintln!(
defmt::info!(
"{}: input pin had rising edge ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
defmt::info!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
@ -258,13 +259,13 @@ async fn check_pin_to_pin_async_ops(
.send(GpioCmd::new(GpioCmdType::FallingEdge, 20))
.await;
async_input.wait_for_falling_edge().await.unwrap();
rprintln!(
defmt::info!(
"{}: input pin had a falling edge ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
defmt::info!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
@ -273,20 +274,20 @@ async fn check_pin_to_pin_async_ops(
.send(GpioCmd::new(GpioCmdType::FallingEdge, 20))
.await;
async_input.wait_for_any_edge().await.unwrap();
rprintln!(
defmt::info!(
"{}: input pin had a falling (any) edge ({} ms)",
ctx,
Instant::now().as_millis()
);
rprintln!(
defmt::info!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::RisingEdge, 20)).await;
async_input.wait_for_any_edge().await.unwrap();
rprintln!(
defmt::info!(
"{}: input pin had a rising (any) edge ({} ms)",
ctx,
Instant::now().as_millis()
@ -305,29 +306,29 @@ async fn output_task(
Timer::after(Duration::from_millis(next_cmd.after_delay.into())).await;
match next_cmd.cmd_type {
GpioCmdType::SetHigh => {
rprintln!("{}: Set output high", ctx);
defmt::info!("{}: Set output high", ctx);
out.set_high().unwrap();
}
GpioCmdType::SetLow => {
rprintln!("{}: Set output low", ctx);
defmt::info!("{}: Set output low", ctx);
out.set_low().unwrap();
}
GpioCmdType::RisingEdge => {
rprintln!("{}: Rising edge", ctx);
defmt::info!("{}: Rising edge", ctx);
if !out.is_low().unwrap() {
out.set_low().unwrap();
}
out.set_high().unwrap();
}
GpioCmdType::FallingEdge => {
rprintln!("{}: Falling edge", ctx);
defmt::info!("{}: Falling edge", ctx);
if !out.is_high().unwrap() {
out.set_high().unwrap();
}
out.set_low().unwrap();
}
GpioCmdType::CloseTask => {
rprintln!("{}: Closing task", ctx);
defmt::info!("{}: Closing task", ctx);
break;
}
}

View File

@ -12,7 +12,12 @@
//! RTT logs to see received data.
#![no_std]
#![no_main]
// Import panic provider.
use panic_probe as _;
// Import logger.
use core::cell::RefCell;
use defmt_rtt as _;
use defmt_rtt as _;
use critical_section::Mutex;
use embassy_example::EXTCLK_FREQ;
@ -21,8 +26,6 @@ use embassy_time::Instant;
use embedded_io::Write;
use embedded_io_async::Read;
use heapless::spsc::{Producer, Queue};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::{
gpio::PinsG,
pac::{self, interrupt},
@ -41,8 +44,7 @@ static PRODUCER_UART_A: Mutex<RefCell<Option<Producer<u8, 256>>>> = Mutex::new(R
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
rtt_init_print!();
rprintln!("-- VA108xx Async UART RX Demo --");
defmt::println!("-- VA108xx Async UART RX Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -84,11 +86,11 @@ async fn main(_spawner: Spawner) {
let mut async_uart_rx = RxAsync::new(rx_uart_a, cons_uart_a);
let mut buf = [0u8; 256];
loop {
rprintln!("Current time UART A: {}", Instant::now().as_secs());
defmt::info!("Current time UART A: {}", Instant::now().as_secs());
led.toggle();
let read_bytes = async_uart_rx.read(&mut buf).await.unwrap();
let read_str = core::str::from_utf8(&buf[..read_bytes]).unwrap();
rprintln!(
defmt::info!(
"Read {} bytes asynchronously on UART A: {:?}",
read_bytes,
read_str
@ -106,6 +108,6 @@ fn UART0_RX() {
critical_section::with(|cs| *PRODUCER_UART_A.borrow(cs).borrow_mut() = Some(prod));
// In a production app, we could use a channel to send the errors to the main task.
if let Err(errors) = errors {
rprintln!("UART A errors: {:?}", errors);
defmt::info!("UART A errors: {:?}", errors);
}
}

View File

@ -11,12 +11,15 @@
//! RTT logs to see received data.
#![no_std]
#![no_main]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use embassy_example::EXTCLK_FREQ;
use embassy_executor::Spawner;
use embassy_time::{Duration, Instant, Ticker};
use embedded_io_async::Write;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::{
gpio::PinsG,
pac::{self, interrupt},
@ -39,8 +42,7 @@ const STR_LIST: &[&str] = &[
// main is itself an async function.
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
rtt_init_print!();
rprintln!("-- VA108xx Async UART TX Demo --");
defmt::println!("-- VA108xx Async UART TX Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -75,7 +77,7 @@ async fn main(_spawner: Spawner) {
let mut ticker = Ticker::every(Duration::from_secs(1));
let mut idx = 0;
loop {
rprintln!("Current time: {}", Instant::now().as_secs());
defmt::println!("Current time: {}", Instant::now().as_secs());
led.toggle();
let _written = async_tx
.write(STR_LIST[idx].as_bytes())

View File

@ -9,6 +9,11 @@
//! on the UART without requiring polling.
#![no_std]
#![no_main]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use core::cell::RefCell;
use embassy_example::EXTCLK_FREQ;
@ -17,12 +22,10 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_time::{Duration, Ticker};
use embedded_io::Write;
use panic_rtt_target as _;
use ringbuf::{
traits::{Consumer, Observer, Producer},
StaticRb,
};
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::{
gpio::{OutputReadablePushPull, Pin, PinsG, PG5},
pac::{self, interrupt},
@ -49,8 +52,7 @@ static RINGBUF: SharedRingBuf = Mutex::new(RefCell::new(None));
// a peripheral with embassy.
#[embassy_executor::main]
async fn main(spawner: Spawner) {
rtt_init_print!();
rprintln!("VA416xx UART-Embassy Example");
defmt::println!("VA416xx UART-Embassy Example");
let mut dp = pac::Peripherals::take().unwrap();
@ -153,9 +155,9 @@ fn UART0_RX() {
}
if errors.is_some() {
rprintln!("UART error: {:?}", errors);
defmt::info!("UART error: {:?}", errors);
}
if ringbuf_full {
rprintln!("ringbuffer is full, deleted oldest data");
defmt::info!("ringbuffer is full, deleted oldest data");
}
}

View File

@ -1,10 +1,13 @@
#![no_std]
#![no_main]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use embassy_example::EXTCLK_FREQ;
use embassy_executor::Spawner;
use embassy_time::{Duration, Instant, Ticker};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::{gpio::PinsG, pac, prelude::*, time::Hertz};
cfg_if::cfg_if! {
@ -17,8 +20,7 @@ cfg_if::cfg_if! {
// main is itself an async function.
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
rtt_init_print!();
rprintln!("VA416xx Embassy Demo");
defmt::println!("VA416xx Embassy Demo");
let mut dp = pac::Peripherals::take().unwrap();
@ -57,7 +59,7 @@ async fn main(_spawner: Spawner) {
let mut ticker = Ticker::every(Duration::from_secs(1));
loop {
ticker.next().await;
rprintln!("Current time: {}", Instant::now().as_secs());
defmt::info!("Current time: {}", Instant::now().as_secs());
led.toggle();
}
}

View File

@ -7,9 +7,10 @@ edition = "2021"
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
embedded-hal = "1"
rtt-target = { version = "0.6" }
defmt-rtt = "0.4"
defmt = "1"
panic-probe = { version = "1", features = ["defmt"] }
rtic-sync = { version = "1.3", features = ["defmt-03"] }
panic-rtt-target = { version = "0.2" }
va416xx-hal = { version = "0.5", features = ["va41630"] }

View File

@ -4,8 +4,10 @@
#[rtic::app(device = pac)]
mod app {
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_default};
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use va416xx_hal::pac;
#[local]
@ -16,8 +18,7 @@ mod app {
#[init]
fn init(_ctx: init::Context) -> (Shared, Local) {
rtt_init_default!();
rprintln!("-- Vorago RTIC template --");
defmt::println!("-- Vorago RTIC template --");
(Shared {}, Local {})
}

View File

@ -9,11 +9,13 @@ const EXTCLK_FREQ: Hertz = Hertz::from_raw(40_000_000);
#[rtic::app(device = pac, dispatchers = [U1, U2, U3])]
mod app {
use super::*;
// Import panic provider.
use panic_probe as _;
// Import logger.
use cortex_m::asm;
use panic_rtt_target as _;
use defmt_rtt as _;
use rtic_monotonics::systick::prelude::*;
use rtic_monotonics::Monotonic;
use rtt_target::{rprintln, rtt_init_default};
use va416xx_hal::{
gpio::{OutputReadablePushPull, Pin, PinsG, PG5},
pac,
@ -32,8 +34,7 @@ mod app {
#[init]
fn init(mut cx: init::Context) -> (Shared, Local) {
rtt_init_default!();
rprintln!("-- Vorago RTIC example application --");
defmt::println!("-- Vorago RTIC example application --");
// Use the external clock connected to XTAL_N.
let clocks = cx
.device

View File

@ -7,8 +7,9 @@ edition = "2021"
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
critical-section = "1"
panic-rtt-target = { version = "0.2" }
rtt-target = { version = "0.6" }
defmt-rtt = "0.4"
defmt = "1"
panic-probe = { version = "1", features = ["defmt"] }
embedded-hal = "1"
embedded-hal-nb = "1"
nb = "1"
@ -16,7 +17,7 @@ embedded-io = "0.6"
panic-halt = "1"
accelerometer = "0.12"
va416xx-hal = { version = "0.5", features = ["va41630"] }
va416xx-hal = { version = "0.5", features = ["va41630", "defmt"] }
[dependencies.vorago-peb1]
path = "../../vorago-peb1"

View File

@ -2,10 +2,13 @@
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::{
adc::{Adc, ChannelSelect, ChannelValue, MultiChannelSelect},
@ -19,8 +22,7 @@ const ENABLE_BUF_PRINTOUT: bool = false;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("VA416xx ADC example");
defmt::println!("VA416xx ADC example");
let mut dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
@ -38,7 +40,7 @@ fn main() -> ! {
let single_value = adc
.trigger_and_read_single_channel(va416xx_hal::adc::ChannelSelect::TempSensor)
.expect("reading single channel value failed");
rprintln!(
defmt::info!(
"Read single ADC value on temperature sensor channel: {:?}",
single_value
);
@ -46,8 +48,8 @@ fn main() -> ! {
.sweep_and_read_range(0, 7, &mut read_buf)
.expect("ADC range read failed");
if ENABLE_BUF_PRINTOUT {
rprintln!("ADC Range Read (0-8) read {} values", read_num);
rprintln!("ADC Range Read (0-8): {:?}", read_buf);
defmt::info!("ADC Range Read (0-8) read {} values", read_num);
defmt::info!("ADC Range Read (0-8): {:?}", read_buf);
}
assert_eq!(read_num, 8);
for (idx, ch_val) in read_buf.iter().enumerate() {
@ -63,7 +65,7 @@ fn main() -> ! {
)
.expect("ADC multiselect read failed");
if ENABLE_BUF_PRINTOUT {
rprintln!("ADC Multiselect Read(0, 2 and 10): {:?}", &read_buf[0..3]);
defmt::info!("ADC Multiselect Read(0, 2 and 10): {:?}", &read_buf[0..3]);
}
assert_eq!(read_buf[0].channel(), ChannelSelect::AnIn0);
assert_eq!(read_buf[1].channel(), ChannelSelect::AnIn2);

View File

@ -2,15 +2,17 @@
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
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");
defmt::println!("VA416xx HAL blinky example");
let mut dp = pac::Peripherals::take().unwrap();
let portg = PinsG::new(&mut dp.sysconfig, dp.portg);

View File

@ -2,10 +2,13 @@
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::{adc::Adc, dac::Dac, pac, prelude::*, timer::CountdownTimer};
@ -25,8 +28,7 @@ const APP_MODE: AppMode = AppMode::DacAndAdc;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("VA416xx DAC/ADC example");
defmt::println!("VA416xx DAC/ADC example");
let mut dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
@ -53,7 +55,7 @@ fn main() -> ! {
let mut current_val = 0;
loop {
if let Some(dac) = &dac {
rprintln!("loading DAC with value {}", current_val);
defmt::info!("loading DAC with value {}", current_val);
dac.load_and_trigger_manually(current_val)
.expect("loading DAC value failed");
if current_val + DAC_INCREMENT >= 4096 {
@ -70,7 +72,7 @@ fn main() -> ! {
let ch_value = adc
.trigger_and_read_single_channel(va416xx_hal::adc::ChannelSelect::AnIn0)
.expect("reading ADC channel 0 failed");
rprintln!("Received channel value {:?}", ch_value);
defmt::info!("Received channel value {:?}", ch_value);
}
delay_provider.delay_ms(500);

View File

@ -2,13 +2,16 @@
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use core::cell::Cell;
use cortex_m_rt::entry;
use critical_section::Mutex;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::dma::{Dma, DmaCfg, DmaChannel, DmaCtrlBlock};
use va416xx_hal::irq_router::enable_and_init_irq_router;
@ -35,8 +38,7 @@ static mut DMA_DEST_BUF: [u16; 36] = [0; 36];
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("VA416xx DMA example");
defmt::println!("VA416xx DMA example");
let mut dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
@ -119,7 +121,7 @@ fn transfer_example_8_bit(
let mut dma_done = false;
critical_section::with(|cs| {
if DMA_ACTIVE_FLAG.borrow(cs).get() {
rprintln!("DMA0 is active with 8 bit transfer");
defmt::info!("DMA0 is active with 8 bit transfer");
DMA_ACTIVE_FLAG.borrow(cs).set(false);
}
if DMA_DONE_FLAG.borrow(cs).get() {
@ -127,7 +129,7 @@ fn transfer_example_8_bit(
}
});
if dma_done {
rprintln!("8-bit transfer done");
defmt::info!("8-bit transfer done");
break;
}
delay_ms.delay_ms(1);
@ -177,7 +179,7 @@ fn transfer_example_16_bit(dma0: &mut DmaChannel, delay_ms: &mut CountdownTimer<
let mut dma_done = false;
critical_section::with(|cs| {
if DMA_ACTIVE_FLAG.borrow(cs).get() {
rprintln!("DMA0 is active with 16-bit transfer");
defmt::info!("DMA0 is active with 16-bit transfer");
DMA_ACTIVE_FLAG.borrow(cs).set(false);
}
if DMA_DONE_FLAG.borrow(cs).get() {
@ -185,7 +187,7 @@ fn transfer_example_16_bit(dma0: &mut DmaChannel, delay_ms: &mut CountdownTimer<
}
});
if dma_done {
rprintln!("16-bit transfer done");
defmt::info!("16-bit transfer done");
break;
}
delay_ms.delay_ms(1);
@ -237,7 +239,7 @@ fn transfer_example_32_bit(
let mut dma_done = false;
critical_section::with(|cs| {
if DMA_ACTIVE_FLAG.borrow(cs).get() {
rprintln!("DMA0 is active with 32-bit transfer");
defmt::info!("DMA0 is active with 32-bit transfer");
DMA_ACTIVE_FLAG.borrow(cs).set(false);
}
if DMA_DONE_FLAG.borrow(cs).get() {
@ -245,7 +247,7 @@ fn transfer_example_32_bit(
}
});
if dma_done {
rprintln!("32-bit transfer done");
defmt::info!("32-bit transfer done");
break;
}
delay_ms.delay_ms(1);

View File

@ -2,11 +2,14 @@
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use accelerometer::{Accelerometer, RawAccelerometer};
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::{
i2c,
@ -25,9 +28,8 @@ const DISPLAY_MODE: DisplayMode = DisplayMode::Normalized;
#[entry]
fn main() -> ! {
rtt_init_print!();
let mut dp = pac::Peripherals::take().unwrap();
rprintln!("-- Vorago PEB1 accelerometer example --");
defmt::println!("-- Vorago PEB1 accelerometer example --");
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen

View File

@ -4,8 +4,10 @@
use cortex_m_rt::entry;
use embedded_hal::{delay::DelayNs, pwm::SetDutyCycle};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use simple_examples::peb1;
use va416xx_hal::{
gpio::PinsA,
@ -17,8 +19,7 @@ use va416xx_hal::{
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx PWM example application--");
defmt::println!("-- VA108xx PWM example application--");
let mut dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
@ -52,7 +53,7 @@ fn main() -> ! {
current_duty_cycle += 0.02;
counter += 1;
if counter % 10 == 0 {
rprintln!("current duty cycle: {}", current_duty_cycle);
defmt::info!("current duty cycle: {}", current_duty_cycle);
}
reduced_pin
@ -74,8 +75,8 @@ fn main() -> ! {
upper_limit -= 0.01;
pwmb.set_pwmb_lower_limit(get_duty_from_percent(lower_limit));
pwmb.set_pwmb_upper_limit(get_duty_from_percent(upper_limit));
rprintln!("Lower limit: {}", pwmb.pwmb_lower_limit());
rprintln!("Upper limit: {}", pwmb.pwmb_upper_limit());
defmt::info!("Lower limit: {}", pwmb.pwmb_lower_limit());
defmt::info!("Upper limit: {}", pwmb.pwmb_upper_limit());
}
reduced_pin = ReducedPwmPin::<PwmA>::from(pwmb);
}

View File

@ -2,9 +2,12 @@
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va416xx_hal::pac;
// Mask for the LED
@ -12,6 +15,7 @@ const LED_PG5: u32 = 1 << 5;
#[entry]
fn main() -> ! {
defmt::println!("VA416xx RTT Demo");
let dp = pac::Peripherals::take().unwrap();
// Enable all peripheral clocks
dp.sysconfig
@ -22,11 +26,9 @@ fn main() -> ! {
.datamask()
.modify(|_, w| unsafe { w.bits(LED_PG5) });
rtt_init_print!();
rprintln!("VA416xx RTT Demo");
let mut counter = 0;
loop {
rprintln!("{}: Hello, world!", counter);
defmt::info!("{}: Hello, world!", counter);
// Still toggle LED. If there are issues with the RTT log, the LED
// blinking ensures that the application is actually running.
dp.portg.togout().write(|w| unsafe { w.bits(LED_PG5) });

View File

@ -3,10 +3,13 @@
//! If you do not use the loopback mode, MOSI and MISO need to be tied together on the board.
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
use embedded_hal::spi::{Mode, SpiBus, MODE_0};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::spi::{Spi, SpiClkConfig};
use va416xx_hal::{
@ -33,8 +36,7 @@ const FILL_WORD: u8 = 0x0f;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx SPI example application--");
defmt::println!("-- VA108xx SPI example application--");
let cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.

View File

@ -1,13 +1,15 @@
//! MS and Second counter implemented using the TIM0 and TIM1 peripheral
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use core::cell::Cell;
use cortex_m::asm;
use cortex_m_rt::entry;
use critical_section::Mutex;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::{
irq_router::enable_and_init_irq_router,
@ -26,10 +28,9 @@ static SEC_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
#[entry]
fn main() -> ! {
rtt_init_print!();
let mut dp = pac::Peripherals::take().unwrap();
let mut last_ms = 0;
rprintln!("-- Vorago system ticks using timers --");
defmt::println!("-- Vorago system ticks using timers --");
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
@ -47,9 +48,9 @@ fn main() -> ! {
if current_ms >= last_ms + 1000 {
// To prevent drift.
last_ms += 1000;
rprintln!("MS counter: {}", current_ms);
defmt::info!("MS counter: {}", current_ms);
let second = critical_section::with(|cs| SEC_COUNTER.borrow(cs).get());
rprintln!("Second counter: {}", second);
defmt::info!("Second counter: {}", second);
}
asm::delay(1000);
}

View File

@ -2,12 +2,14 @@
// echo mode
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
use embedded_hal_nb::serial::Read;
use embedded_io::Write;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::clock::ClkgenExt;
use va416xx_hal::time::Hertz;
@ -15,8 +17,7 @@ use va416xx_hal::{gpio::PinsG, pac, uart};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA416xx UART example application--");
defmt::println!("-- VA416xx UART example application--");
let mut dp = pac::Peripherals::take().unwrap();
@ -45,12 +46,11 @@ fn main() -> ! {
// Echo what is received on the serial link.
match nb::block!(rx.read()) {
Ok(recvd) => {
if let Err(e) = embedded_hal_nb::serial::Write::write(&mut tx, recvd) {
rprintln!("UART TX error: {:?}", e);
}
// Infallible operation.
embedded_hal_nb::serial::Write::write(&mut tx, recvd).unwrap();
}
Err(e) => {
rprintln!("UART RX error {:?}", e);
defmt::info!("UART RX error {:?}", e);
}
}
}

View File

@ -1,12 +1,14 @@
// Code to test the watchdog timer.
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use core::cell::Cell;
use cortex_m_rt::entry;
use critical_section::Mutex;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use simple_examples::peb1;
use va416xx_hal::irq_router::enable_and_init_irq_router;
use va416xx_hal::pac::{self, interrupt};
@ -29,8 +31,7 @@ const WDT_ROLLOVER_MS: u32 = 100;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA416xx WDT example application--");
defmt::println!("-- VA416xx WDT example application--");
let cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
@ -53,7 +54,7 @@ fn main() -> ! {
}
let interrupt_counter = critical_section::with(|cs| WDT_INTRPT_COUNT.borrow(cs).get());
if interrupt_counter > last_interrupt_counter {
rprintln!("interrupt counter has increased to {}", interrupt_counter);
defmt::info!("interrupt counter has increased to {}", interrupt_counter);
last_interrupt_counter = interrupt_counter;
}
match TEST_MODE {

View File

@ -3,7 +3,7 @@
#![no_std]
use cortex_m_rt::entry;
use panic_rtt_target as _;
use panic_halt as _;
#[entry]
fn main() -> ! {

View File

@ -9,9 +9,9 @@ cortex-m-rt = "0.7"
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"
panic-rtt-target = { version = "0.2" }
rtt-target = { version = "0.6" }
rtt-log = "0.5"
defmt-rtt = "0.4"
defmt = "1"
panic-probe = { version = "1", features = ["defmt"] }
log = "0.4"
crc = "3"
rtic-sync = "1"
@ -19,10 +19,10 @@ static_cell = "2"
satrs = { version = "0.3.0-alpha.0", default-features = false }
ringbuf = { version = "0.4", default-features = false }
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
spacepackets = { version = "0.13", default-features = false }
spacepackets = { version = "0.13", default-features = false, features = ["defmt"] }
cobs = { version = "0.3", default-features = false }
va416xx-hal = { version = "0.5", features = ["va41630"] }
va416xx-hal = { version = "0.5", features = ["va41630", "defmt"] }
rtic = { version = "2", features = ["thumbv7-backend"] }
rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }

View File

@ -2,16 +2,15 @@
from typing import List, Tuple
from spacepackets.ecss.defs import PusService
from spacepackets.ecss.tm import PusTm
from tmtccmd.com import ComInterface
from com_interface import ComInterface
import toml
import struct
import logging
import argparse
import time
import enum
from tmtccmd.com.serial_base import SerialCfg
from tmtccmd.com.serial_cobs import SerialCobsComIF
from tmtccmd.com.ser_utils import prompt_com_port
from com_interface.serial_base import SerialCfg
from com_interface.serial_cobs import SerialCobsComIF
from crcmod.predefined import PredefinedCrc
from spacepackets.ecss.tc import PusTc
from spacepackets.ecss.pus_verificator import PusVerificator, StatusField
@ -58,6 +57,7 @@ PING_PAYLOAD_SIZE = 0
class ActionId(enum.IntEnum):
CORRUPT_APP_A = 128
CORRUPT_APP_B = 129
SET_BOOT_SLOT = 130
_LOGGER = logging.getLogger(__name__)
@ -78,11 +78,29 @@ class Target(enum.Enum):
APP_B = 2
class AppSel(enum.IntEnum):
APP_A = 0
APP_B = 1
class ImageLoader:
def __init__(self, com_if: ComInterface, verificator: PusVerificator) -> None:
self.com_if = com_if
self.verificator = verificator
def handle_boot_sel_cmd(self, target: AppSel):
_LOGGER.info("Sending ping command")
action_tc = PusTc(
apid=0x00,
service=PusService.S8_FUNC_CMD,
subservice=ActionId.SET_BOOT_SLOT,
seq_count=SEQ_PROVIDER.get_and_increment(),
app_data=bytes([target]),
)
self.verificator.add_tc(action_tc)
self.com_if.send(bytes(action_tc.pack()))
self.await_for_command_copletion("boot image selection command")
def handle_ping_cmd(self):
_LOGGER.info("Sending ping command")
ping_tc = PusTc(
@ -94,19 +112,9 @@ class ImageLoader:
)
self.verificator.add_tc(ping_tc)
self.com_if.send(bytes(ping_tc.pack()))
data_available = self.com_if.data_available(0.4)
if not data_available:
_LOGGER.warning("no ping reply received")
for reply in self.com_if.receive():
result = self.verificator.add_tm(
Service1Tm.from_tm(PusTm.unpack(reply, 0), UnpackParams(0))
)
if result is not None and result.completed:
_LOGGER.info("received ping completion reply")
self.await_for_command_copletion("ping command")
def handle_corruption_cmd(self, target: Target):
if target == Target.BOOTLOADER:
_LOGGER.error("can not corrupt bootloader")
if target == Target.APP_A:
@ -126,6 +134,25 @@ class ImageLoader:
),
)
def await_for_command_copletion(self, context: str):
done = False
now = time.time()
while time.time() - now < 2.0:
if not self.com_if.data_available():
time.sleep(0.2)
continue
for reply in self.com_if.receive():
result = self.verificator.add_tm(
Service1Tm.from_tm(PusTm.unpack(reply, 0), UnpackParams(0))
)
if result is not None and result.completed:
_LOGGER.info(f"received {context} reply")
done = True
if done:
break
if not done:
_LOGGER.warning(f"no {context} reply received")
def handle_flash_cmd(self, target: Target, file_path: Path) -> int:
loadable_segments = []
_LOGGER.info("Parsing ELF file for loadable sections")
@ -269,12 +296,12 @@ def main() -> int:
if "serial_port" in parsed_toml:
serial_port = parsed_toml["serial_port"]
if serial_port is None:
serial_port = prompt_com_port()
serial_port = input("Please specify the serial port manually: ")
serial_cfg = SerialCfg(
com_if_id="ser_cobs",
serial_port=serial_port,
baud_rate=BAUD_RATE,
serial_timeout=0.1,
polling_frequency=0.1,
)
verificator = PusVerificator()
com_if = SerialCobsComIF(serial_cfg)

View File

@ -1,5 +1,5 @@
spacepackets == 0.24
tmtccmd == 8.0.2
spacepackets == 0.28
com-interface == 0.1.0
toml == 0.10
pyelftools == 0.31
crcmod == 1.7

View File

@ -1,9 +0,0 @@
#![no_std]
#[cfg(test)]
mod tests {
#[test]
fn simple() {
assert_eq!(1 + 1, 2);
}
}

View File

@ -19,7 +19,6 @@
#![no_std]
use once_cell::sync::OnceCell;
use panic_rtt_target as _;
use va416xx_hal::{clock::Clocks, edac, pac, time::Hertz, wdt::Wdt};
const EXTCLK_FREQ: u32 = 40_000_000;
@ -95,10 +94,12 @@ mod app {
use super::*;
use cortex_m::asm;
use embedded_io::Write;
use panic_rtt_target as _;
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use rtic::Mutex;
use rtic_monotonics::systick::prelude::*;
use rtt_target::rprintln;
use satrs::pus::verification::VerificationReportCreator;
use spacepackets::ecss::PusServiceId;
use spacepackets::ecss::{
@ -150,9 +151,7 @@ mod app {
#[init]
fn init(mut cx: init::Context) -> (Shared, Local) {
//rtt_init_default!();
rtt_log::init();
rprintln!("-- Vorago flashloader --");
defmt::println!("-- Vorago flashloader --");
// Initialize the systick interrupt & obtain the token to prove that we did
// Use the external clock connected to XTAL_N.
let clocks = cx
@ -272,7 +271,7 @@ mod app {
let decoded_size =
cobs::decode_in_place(&mut cx.local.rx_buf[1..result.bytes_read]);
if decoded_size.is_err() {
log::warn!("COBS decoding failed");
defmt::warn!("COBS decoding failed");
} else {
let decoded_size = decoded_size.unwrap();
if cx.local.tc_prod.sizes_prod.vacant_len() >= 1
@ -285,11 +284,13 @@ mod app {
.buf_prod
.push_slice(&cx.local.rx_buf[1..1 + decoded_size]);
} else {
log::warn!("COBS TC queue full");
defmt::warn!("COBS TC queue full");
}
}
} else {
log::warn!("COBS frame with invalid format, start and end bytes are not 0");
defmt::warn!(
"COBS frame with invalid format, start and end bytes are not 0"
);
}
// Initiate next transfer.
@ -299,11 +300,11 @@ mod app {
.expect("read operation failed");
}
if result.has_errors() {
log::warn!("UART error: {:?}", result.errors.unwrap());
defmt::warn!("UART error: {:?}", result.errors.unwrap());
}
}
Err(e) => {
log::warn!("UART error: {:?}", e);
defmt::warn!("UART error: {:?}", e);
}
}
}
@ -346,7 +347,7 @@ mod app {
fn handle_valid_pus_tc(cx: &mut pus_tc_handler::Context) {
let pus_tc = PusTcReader::new(cx.local.tc_buf);
if pus_tc.is_err() {
log::warn!("PUS TC error: {}", pus_tc.unwrap_err());
defmt::warn!("PUS TC error: {}", pus_tc.unwrap_err());
return;
}
let (pus_tc, _) = pus_tc.unwrap();
@ -396,11 +397,11 @@ mod app {
write_and_send(&tm);
};
if pus_tc.subservice() == ActionId::CorruptImageA as u8 {
rprintln!("corrupting App Image A");
defmt::info!("corrupting App Image A");
corrupt_image(APP_A_START_ADDR);
}
if pus_tc.subservice() == ActionId::CorruptImageB as u8 {
rprintln!("corrupting App Image B");
defmt::info!("corrupting App Image B");
corrupt_image(APP_B_START_ADDR);
}
}
@ -430,23 +431,21 @@ mod app {
if pus_tc.subservice() == 2 {
let app_data = pus_tc.app_data();
if app_data.len() < 10 {
log::warn!(
target: "TC Handler",
defmt::warn!(
"app data for raw memory write is too short: {}",
app_data.len()
);
}
let memory_id = app_data[0];
if memory_id != BOOT_NVM_MEMORY_ID {
log::warn!(target: "TC Handler", "memory ID {} not supported", memory_id);
defmt::warn!("memory ID {} not supported", memory_id);
// TODO: Error reporting
return;
}
let offset = u32::from_be_bytes(app_data[2..6].try_into().unwrap());
let data_len = u32::from_be_bytes(app_data[6..10].try_into().unwrap());
if 10 + data_len as usize > app_data.len() {
log::warn!(
target: "TC Handler",
defmt::warn!(
"invalid data length {} for raw mem write detected",
data_len
);

5
jlink-gdb-ram.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
# Start the JLinkGDBServer while also specifying the JLinkScript file. The JLinkScript is necessary
# to disable ROM protection to allow flashing
JLinkGDBServer -select USB -device Cortex-M4 -endian little -if SWD -speed 2000 \
-LocalhostOnly -vd -jlinkscriptfile ./jlink/JLinkSettings.JLinkScript

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Start the JLinkGDBServer while also specifying the JLinkScript file. The JLinkScript is necessary
# to disable ROM protection to allow flashing
JLinkGDBServer -select USB -device Cortex-M4 -endian little -if SWD -speed 2000 \
-LocalhostOnly -vd -jlinkscriptfile ./jlink/JLinkSettings.JLinkScript
JLinkGDBServer -select USB -device VA416xx -endian little -if SWD -speed 2000 \
-LocalhostOnly -vd

View File

@ -18,6 +18,5 @@ _stack_start = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS {
.sram1 (NOLOAD) : ALIGN(8) {
*(.sram1 .sram1.*);
. = ALIGN(4);
} > SRAM_1
} > SRAM_1
};

18
scripts/defmt-telnet.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
# Check if binary path was provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <path-to-binary>"
exit 1
fi
BINARY="$1"
# Check if file exists
if [ ! -f "$BINARY" ]; then
echo "Error: File '$BINARY' not found."
exit 1
fi
# Run the command
defmt-print -e "$BINARY" tcp