Compare commits

..

No commits in common. "main" and "va108xx-hal-v0.11.0" have entirely different histories.

37 changed files with 28138 additions and 198 deletions

View File

@ -18,9 +18,9 @@ rustflags = [
"-C", "link-arg=-Tlink.x",
# knurling-rs tooling. If you want to use flip-link, ensure it is installed first.
"-C", "linker=flip-link",
# "-C", "linker=flip-link",
# Unfortunately, defmt is clunky to use without probe-rs..
"-C", "link-arg=-Tdefmt.x",
# "-C", "link-arg=-Tdefmt.x",
# Can be useful for debugging.
# "-Clink-args=-Map=app.map"

View File

@ -13,6 +13,7 @@ members = [
"flashloader",
]
exclude = [
"defmt-testapp",
"flashloader/slot-a-blinky",
"flashloader/slot-b-blinky",
]

View File

@ -77,7 +77,7 @@ to flash and run the blinky program on the RAM. There is also a `VA108xx` chip t
available for persistent flashing.
Runner configuration avilable 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.
convenience.
### Using VS Code
@ -123,13 +123,13 @@ is also run when running the `jlink-gdb.sh` script)
```sh
JLinkGDBServer -select USB -device Cortex-M0 -endian little -if JTAG-speed auto \
-LocalhostOnly -jtagconf -1,-1
-LocalhostOnly
```
After this, you can flash and debug the application with the following command
```sh
gdb-mutliarch -q -x jlink/jlink.gdb target/thumbv6m-none-eabihf/debug/examples/blinky -tui
gdb-mutliarch -q -x jlink/jlink.gdb target/thumbv6m-none-eabihf/debug/examples/blinky
```
Please note that you can automate all steps except starting the GDB server by using a cargo
@ -148,23 +148,3 @@ example.
The Segger RTT viewer can be used to display log messages received from the target. The base
address for the RTT block placement is 0x10000000. 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 piping
the output on telnet port 19021 into `defmt-print`, for example by running
```sh
telnet localhost 19021 | defmt-print -e <pathToElfFile>
```
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
are recommended:
- [Rust Book](https://doc.rust-lang.org/book/)
- [Embedded Rust Book](https://docs.rust-embedded.org/book/)
- [Embedded Rust Discovery](https://docs.rust-embedded.org/discovery/microbit/)
- [Awesome Embedded Rust](https://github.com/rust-embedded/awesome-embedded-rust)

View File

@ -14,6 +14,6 @@ embedded-hal-nb = "1"
embedded-io = "0.6"
[dependencies.va108xx-hal]
version = "0.11"
version = "0.10.0"
features = ["rt"]

View File

@ -15,7 +15,7 @@ num_enum = { version = "0.7", default-features = false }
static_assertions = "1"
[dependencies.va108xx-hal]
version = "0.11"
version = "0.10"
[dependencies.vorago-reb1]
version = "0.8"

View File

@ -0,0 +1,48 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# uncomment ONE of these three option to make `cargo run` start a GDB session
# which option to pick depends on your system
# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
# runner = "gdb-multiarch -q -x openocd.gdb"
# runner = "gdb -q -x openocd.gdb"
runner = "gdb-multiarch -q -x jlink.gdb"
# Probe-rs is currently problematic: https://github.com/probe-rs/probe-rs/issues/2567
# runner = "probe-rs run --chip VA108xx --chip-description-path ./scripts/VA108xx_Series.yaml"
# runner = ["probe-rs", "run", "--chip", "$CHIP", "--log-format", "{L} {s}"]
rustflags = [
# 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",
# LLD (shipped with the Rust toolchain) is used as the default linker
"-C", "link-arg=-Tlink.x",
# knurling-rs tooling. If you want to use flip-link, ensure it is installed first.
"-C", "linker=flip-link",
# Unfortunately, defmt is clunky to use without probe-rs..
"-C", "link-arg=-Tdefmt.x",
# Can be useful for debugging.
"-Clink-args=-Map=app.map"
]
[build]
# Pick ONE of these compilation targets
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)
# target = "thumbv8m.base-none-eabi" # Cortex-M23
# target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU)
# target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU)
[alias]
re = "run --example"
rb = "run --bin"
rrb = "run --release --bin"
ut = "test --target x86_64-unknown-linux-gnu"
[env]
DEFMT_LOG = "info"

1
defmt-testapp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

34
defmt-testapp/Cargo.toml Normal file
View File

@ -0,0 +1,34 @@
[package]
name = "defmt-testapp"
version = "0.1.0"
edition = "2021"
[dependencies]
cortex-m = {version = "0.7", features = ["critical-section-single-core"]}
panic-rtt-target = "0.1"
cortex-m-rt = "0.7"
rtt-target = "0.5"
rtic-sync = { version = "1.3", features = ["defmt-03"] }
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"
cortex-m-semihosting = "0.5.0"
# Tricky without probe-rs.
defmt = "0.3"
defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
[dependencies.rtic]
version = "2"
features = ["thumbv6-backend"]
[dependencies.rtic-monotonics]
version = "1"
features = ["cortex-m-systick"]
[dependencies.va108xx-hal]
version = "0.10"
features = ["rt", "defmt"]
[dependencies.va108xx]
version = "0.5"

9
defmt-testapp/README.md Normal file
View File

@ -0,0 +1,9 @@
defmt Testapp
======
`defmt` is clunky to use without probe-rs and requires special configuration inside the
`.cargo/config.toml` file.
`probe-rs` is currently problematic for usage with the VA108xx , so it is not the default tool
recommended and used for the whole workspace. This project contains an isolated, `defmt` compatible
configuration for testing with `defmt` (and `probe-rs`).

53
defmt-testapp/src/lib.rs Normal file
View File

@ -0,0 +1,53 @@
#![no_main]
#![no_std]
use cortex_m_semihosting::debug;
use defmt_brtt as _; // global logger
use va108xx_hal as _; // memory layout
use panic_probe as _;
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
// #[defmt::panic_handler]
/*
fn panic() -> ! {
cortex_m::asm::udf()
}
*/
/// Terminates the application and makes a semihosting-capable debug tool exit
/// with status code 0.
pub fn exit() -> ! {
loop {
debug::exit(debug::EXIT_SUCCESS);
}
}
/// Hardfault handler.
///
/// Terminates the application and makes a semihosting-capable debug tool exit
/// with an error. This seems better than the default, which is to spin in a
/// loop.
#[cortex_m_rt::exception]
unsafe fn HardFault(_frame: &cortex_m_rt::ExceptionFrame) -> ! {
loop {
debug::exit(debug::EXIT_FAILURE);
}
}
// defmt-test 0.3.0 has the limitation that this `#[tests]` attribute can only be used
// once within a crate. the module can be in any file but there can only be at most
// one `#[tests]` module in this library crate
#[cfg(test)]
#[defmt_test::tests]
mod unit_tests {
use defmt::assert;
#[test]
fn it_works() {
assert!(true)
}
}

29
defmt-testapp/src/main.rs Normal file
View File

@ -0,0 +1,29 @@
//! Empty RTIC project template
#![no_main]
#![no_std]
use defmt_testapp as _;
#[rtic::app(device = pac)]
mod app {
use va108xx_hal::pac;
#[local]
struct Local {}
#[shared]
struct Shared {}
#[init]
fn init(_ctx: init::Context) -> (Shared, Local) {
defmt::println!("-- Vorago RTIC template --");
(Shared {}, Local {})
}
// `shared` cannot be accessed from this context
#[idle]
fn idle(_cx: idle::Context) -> ! {
#[allow(clippy::empty_loop)]
loop {}
}
}

View File

@ -14,10 +14,8 @@ embedded-io-async = "0.6"
heapless = "0.8"
static_cell = "2"
defmt = "1"
defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = ["print-defmt"] }
rtt-target = "0.6"
panic-rtt-target = "0.2"
critical-section = "1"
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
@ -29,8 +27,8 @@ embassy-executor = { version = "0.7", features = [
"executor-interrupt"
]}
va108xx-hal = { version = "0.11", features = ["defmt"] }
va108xx-embassy = { version = "0.2" }
va108xx-hal = { version = "0.11", path = "../../va108xx-hal" }
va108xx-embassy = { version = "0.2", path = "../../va108xx-embassy" }
[features]
default = ["ticks-hz-1_000", "va108xx-embassy/irq-oc30-oc31"]

View File

@ -4,14 +4,14 @@
//! and then set the `CHECK_PB22_TO_PB23` to true to also test async operations on Port B.
#![no_std]
#![no_main]
// This imports the logger and the panic handler.
use embassy_example as _;
use embassy_executor::Spawner;
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 va108xx_hal::gpio::{
on_interrupt_for_async_gpio_for_port, InputDynPinAsync, InputPinAsync, PinsB, Port,
};
@ -58,7 +58,8 @@ static CHANNEL_PB22_TO_PB23: Channel<ThreadModeRawMutex, GpioCmd, 3> = Channel::
#[embassy_executor::main]
async fn main(spawner: Spawner) {
defmt::println!("-- VA108xx Async GPIO Demo --");
rtt_init_print!();
rprintln!("-- VA108xx Async GPIO Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -101,15 +102,15 @@ async fn main(spawner: Spawner) {
if CHECK_PA0_TO_PA1 {
check_pin_to_pin_async_ops("PA0 to PA1", CHANNEL_PA0_PA1.sender(), in_pa1_async).await;
defmt::info!("Example PA0 to PA1 done");
rprintln!("Example PA0 to PA1 done");
}
if CHECK_PB22_TO_PB23 {
check_pin_to_pin_async_ops("PB22 to PB23", CHANNEL_PB22_TO_PB23.sender(), in_pb23_async)
.await;
defmt::info!("Example PB22 to PB23 done");
rprintln!("Example PB22 to PB23 done");
}
defmt::info!("Example done, toggling LED0");
rprintln!("Example done, toggling LED0");
loop {
led0.toggle();
Timer::after(Duration::from_millis(500)).await;
@ -121,46 +122,46 @@ async fn check_pin_to_pin_async_ops(
sender: Sender<'static, ThreadModeRawMutex, GpioCmd, 3>,
mut async_input: impl Wait,
) {
defmt::info!(
rprintln!(
"{}: sending SetHigh command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::SetHigh, 20)).await;
async_input.wait_for_high().await.unwrap();
defmt::info!(
rprintln!(
"{}: Input pin is high now ({} ms)",
ctx,
Instant::now().as_millis()
);
defmt::info!(
rprintln!(
"{}: sending SetLow command ({} ms)",
ctx,
Instant::now().as_millis()
);
sender.send(GpioCmd::new(GpioCmdType::SetLow, 20)).await;
async_input.wait_for_low().await.unwrap();
defmt::info!(
rprintln!(
"{}: Input pin is low now ({} ms)",
ctx,
Instant::now().as_millis()
);
defmt::info!(
rprintln!(
"{}: 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();
defmt::info!(
rprintln!(
"{}: input pin had rising edge ({} ms)",
ctx,
Instant::now().as_millis()
);
defmt::info!(
rprintln!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
@ -169,13 +170,13 @@ async fn check_pin_to_pin_async_ops(
.send(GpioCmd::new(GpioCmdType::FallingEdge, 20))
.await;
async_input.wait_for_falling_edge().await.unwrap();
defmt::info!(
rprintln!(
"{}: input pin had a falling edge ({} ms)",
ctx,
Instant::now().as_millis()
);
defmt::info!(
rprintln!(
"{}: sending Falling command ({} ms)",
ctx,
Instant::now().as_millis()
@ -184,20 +185,20 @@ async fn check_pin_to_pin_async_ops(
.send(GpioCmd::new(GpioCmdType::FallingEdge, 20))
.await;
async_input.wait_for_any_edge().await.unwrap();
defmt::info!(
rprintln!(
"{}: input pin had a falling (any) edge ({} ms)",
ctx,
Instant::now().as_millis()
);
defmt::info!(
rprintln!(
"{}: 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();
defmt::info!(
rprintln!(
"{}: input pin had a rising (any) edge ({} ms)",
ctx,
Instant::now().as_millis()
@ -215,22 +216,22 @@ async fn output_task(
Timer::after(Duration::from_millis(next_cmd.after_delay.into())).await;
match next_cmd.cmd_type {
GpioCmdType::SetHigh => {
defmt::info!("{}: Set output high", ctx);
rprintln!("{}: Set output high", ctx);
out.set_high().unwrap();
}
GpioCmdType::SetLow => {
defmt::info!("{}: Set output low", ctx);
rprintln!("{}: Set output low", ctx);
out.set_low().unwrap();
}
GpioCmdType::RisingEdge => {
defmt::info!("{}: Rising edge", ctx);
rprintln!("{}: Rising edge", ctx);
if !out.is_low().unwrap() {
out.set_low().unwrap();
}
out.set_high().unwrap();
}
GpioCmdType::FallingEdge => {
defmt::info!("{}: Falling edge", ctx);
rprintln!("{}: Falling edge", ctx);
if !out.is_high().unwrap() {
out.set_high().unwrap();
}

View File

@ -13,16 +13,16 @@
//! RTT logs to see received data.
#![no_std]
#![no_main]
// This imports the logger and the panic handler.
use embassy_example as _;
use core::cell::RefCell;
use critical_section::Mutex;
use embassy_executor::Spawner;
use embassy_time::Instant;
use embedded_io::Write;
use embedded_io_async::Read;
use heapless::spsc::{Consumer, Producer, Queue};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{
gpio::PinsA,
pac::{self, interrupt},
@ -49,7 +49,8 @@ static CONSUMER_UART_B: Mutex<RefCell<Option<Consumer<u8, 256>>>> = Mutex::new(R
// main is itself an async function.
#[embassy_executor::main]
async fn main(spawner: Spawner) {
defmt::println!("-- VA108xx Async UART RX Demo --");
rtt_init_print!();
rprintln!("-- VA108xx Async UART RX Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -107,13 +108,13 @@ async fn main(spawner: Spawner) {
.unwrap();
let mut buf = [0u8; 256];
loop {
defmt::info!("Current time UART A: {}", Instant::now().as_secs());
rprintln!("Current time UART A: {}", Instant::now().as_secs());
led0.toggle();
led1.toggle();
led2.toggle();
let read_bytes = async_rx_uart_a.read(&mut buf).await.unwrap();
let read_str = core::str::from_utf8(&buf[..read_bytes]).unwrap();
defmt::info!(
rprintln!(
"Read {} bytes asynchronously on UART A: {:?}",
read_bytes,
read_str
@ -126,11 +127,11 @@ async fn main(spawner: Spawner) {
async fn uart_b_task(mut async_rx: RxAsyncOverwriting<pac::Uartb, 256>, mut tx: Tx<pac::Uartb>) {
let mut buf = [0u8; 256];
loop {
defmt::info!("Current time UART B: {}", Instant::now().as_secs());
rprintln!("Current time UART B: {}", Instant::now().as_secs());
// Infallible asynchronous operation.
let read_bytes = async_rx.read(&mut buf).await.unwrap();
let read_str = core::str::from_utf8(&buf[..read_bytes]).unwrap();
defmt::info!(
rprintln!(
"Read {} bytes asynchronously on UART B: {:?}",
read_bytes,
read_str
@ -148,7 +149,7 @@ fn OC2() {
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 {
defmt::info!("UART A errors: {:?}", errors);
rprintln!("UART A errors: {:?}", errors);
}
}
@ -161,6 +162,6 @@ fn OC3() {
critical_section::with(|cs| *PRODUCER_UART_B.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 {
defmt::info!("UART B errors: {:?}", errors);
rprintln!("UART B errors: {:?}", errors);
}
}

View File

@ -10,12 +10,11 @@
//! can verify the correctness of the sent strings.
#![no_std]
#![no_main]
// This imports the logger and the panic handler.
use embassy_example as _;
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 va108xx_hal::{
gpio::PinsA,
pac::{self, interrupt},
@ -36,7 +35,8 @@ const STR_LIST: &[&str] = &[
// main is itself an async function.
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
defmt::println!("-- VA108xx Async UART TX Demo --");
rtt_init_print!();
rprintln!("-- VA108xx Async UART TX Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) {
let mut ticker = Ticker::every(Duration::from_secs(1));
let mut idx = 0;
loop {
defmt::info!("Current time: {}", Instant::now().as_secs());
rprintln!("Current time: {}", Instant::now().as_secs());
led0.toggle();
led1.toggle();
led2.toggle();

View File

@ -1,3 +0,0 @@
#![no_std]
use defmt_rtt as _;
use panic_probe as _;

View File

@ -1,8 +1,9 @@
#![no_std]
#![no_main]
use embassy_example as _;
use embassy_executor::Spawner;
use embassy_time::{Duration, Instant, Ticker};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
cfg_if::cfg_if! {
if #[cfg(feature = "custom-irqs")] {
@ -19,7 +20,8 @@ const SYSCLK_FREQ: Hertz = Hertz::from_raw(50_000_000);
// main is itself an async function.
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
defmt::println!("-- VA108xx Embassy Demo --");
rtt_init_print!();
rprintln!("-- VA108xx Embassy Demo --");
let mut dp = pac::Peripherals::take().unwrap();
@ -53,7 +55,7 @@ async fn main(_spawner: Spawner) {
let mut ticker = Ticker::every(Duration::from_secs(1));
loop {
ticker.next().await;
defmt::info!("Current time: {}", Instant::now().as_secs());
rprintln!("Current time: {}", Instant::now().as_secs());
led0.toggle();
led1.toggle();
led2.toggle();

View File

@ -22,5 +22,5 @@ rtic-sync = { version = "1.3", features = ["defmt-03"] }
once_cell = {version = "1", default-features = false, features = ["critical-section"]}
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
va108xx-hal = { version = "0.11" }
vorago-reb1 = { version = "0.8" }
va108xx-hal = { version = "0.11", path = "../../va108xx-hal" }
vorago-reb1 = { version = "0.8", path = "../../vorago-reb1" }

View File

@ -17,7 +17,9 @@ cortex-m-semihosting = "0.5.0"
[dependencies.va108xx-hal]
version = "0.11"
features = ["defmt"]
path = "../../va108xx-hal"
features = ["rt", "defmt"]
[dependencies.vorago-reb1]
version = "0.8"
path = "../../vorago-reb1"

View File

@ -45,6 +45,9 @@ fn main() -> ! {
.expect("TX send error");
}
Err(nb::Error::WouldBlock) => (),
Err(nb::Error::Other(uart_error)) => {
rprintln!("UART receive error {:?}", uart_error);
}
}
}
}

View File

@ -4,7 +4,6 @@
use cortex_m_rt::entry;
use panic_rtt_target as _;
use va108xx_hal as _;
#[entry]
fn main() -> ! {

View File

@ -9,16 +9,17 @@ cortex-m-rt = "0.7"
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"
defmt = "1"
defmt-rtt = { version = "0.4" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
panic-rtt-target = "0.2"
rtt-target = "0.6"
num_enum = { version = "0.7", default-features = false }
log = "0.4"
crc = "3"
cobs = { version = "0.3", default-features = false }
satrs = { version = "0.2", default-features = false }
rtt-log = "0.5"
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
spacepackets = { version = "0.11", default-features = false, features = ["defmt"] }
spacepackets = { version = "0.11", default-features = false }
# Even though we do not use this directly, we need to activate this feature explicitely
# so that RTIC compiles because thumv6 does not have CAS operations natively.
portable-atomic = {version = "1", features = ["unsafe-assume-single-core"]}
@ -28,8 +29,7 @@ rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }
rtic-sync = {version = "1", features = ["defmt-03"]}
[dependencies.va108xx-hal]
version = "0.11"
features = ["defmt"]
version = "0.10"
[dependencies.vorago-reb1]
version = "0.8"

9
flashloader/src/lib.rs Normal file
View File

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

View File

@ -3,9 +3,8 @@
#![no_main]
#![no_std]
use defmt_rtt as _; // global logger
use num_enum::TryFromPrimitive;
use panic_probe as _;
use panic_rtt_target as _;
use ringbuf::{
traits::{Consumer, Observer, Producer},
StaticRb,
@ -30,7 +29,7 @@ pub enum ActionId {
SetBootSlot = 130,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, defmt::Format)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
enum AppSel {
A = 0,
@ -61,8 +60,10 @@ mod app {
use super::*;
use cortex_m::asm;
use embedded_io::Write;
use panic_rtt_target as _;
use rtic::Mutex;
use rtic_monotonics::systick::prelude::*;
use rtt_target::rprintln;
use satrs::pus::verification::{FailParams, VerificationReportCreator};
use spacepackets::ecss::PusServiceId;
use spacepackets::ecss::{
@ -101,7 +102,8 @@ mod app {
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
defmt::println!("-- Vorago flashloader --");
rtt_log::init();
rprintln!("-- Vorago flashloader --");
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
@ -179,8 +181,8 @@ mod app {
{
Ok(result) => {
if RX_DEBUGGING {
defmt::debug!("RX Info: {:?}", cx.local.rx_context);
defmt::debug!("RX Result: {:?}", result);
log::debug!("RX Info: {:?}", cx.local.rx_context);
log::debug!("RX Result: {:?}", result);
}
if result.complete() {
// Check frame validity (must have COBS format) and decode the frame.
@ -191,7 +193,7 @@ mod app {
let decoded_size =
cobs::decode_in_place(&mut cx.local.rx_buf[1..result.bytes_read]);
if decoded_size.is_err() {
defmt::warn!("COBS decoding failed");
log::warn!("COBS decoding failed");
} else {
let decoded_size = decoded_size.unwrap();
let mut tc_rb_full = false;
@ -205,13 +207,11 @@ mod app {
}
});
if tc_rb_full {
defmt::warn!("COBS TC queue full");
log::warn!("COBS TC queue full");
}
}
} else {
defmt::warn!(
"COBS frame with invalid format, start and end bytes are not 0"
);
log::warn!("COBS frame with invalid format, start and end bytes are not 0");
}
// Initiate next transfer.
@ -221,11 +221,11 @@ mod app {
.expect("read operation failed");
}
if result.has_errors() {
defmt::warn!("UART error: {:?}", result.errors.unwrap());
log::warn!("UART error: {:?}", result.errors.unwrap());
}
}
Err(e) => {
defmt::warn!("UART error: {:?}", e);
log::warn!("UART error: {:?}", e);
}
}
}
@ -252,7 +252,7 @@ mod app {
continue;
}
let packet_len = packet_len.unwrap();
defmt::info!("received packet with length {}", packet_len);
log::info!(target: "TC Handler", "received packet with length {}", packet_len);
let popped_packet_len = cx
.shared
.tc_rb
@ -266,7 +266,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() {
defmt::warn!("PUS TC error: {}", pus_tc.unwrap_err());
log::warn!(target: "TC Handler", "PUS TC error: {}", pus_tc.unwrap_err());
return;
}
let (pus_tc, _) = pus_tc.unwrap();
@ -312,25 +312,22 @@ mod app {
write_and_send(&tm);
};
if pus_tc.subservice() == ActionId::CorruptImageA as u8 {
defmt::info!("corrupting App Image A");
rprintln!("corrupting App Image A");
corrupt_image(APP_A_START_ADDR);
}
if pus_tc.subservice() == ActionId::CorruptImageB as u8 {
defmt::info!("corrupting App Image B");
rprintln!("corrupting App Image B");
corrupt_image(APP_B_START_ADDR);
}
if pus_tc.subservice() == ActionId::SetBootSlot as u8 {
if pus_tc.app_data().is_empty() {
defmt::warn!("App data for preferred image command too short");
log::warn!(target: "TC Handler", "App data for preferred image command too short");
}
let app_sel_result = AppSel::try_from(pus_tc.app_data()[0]);
if app_sel_result.is_err() {
defmt::warn!("Invalid app selection value: {}", pus_tc.app_data()[0]);
log::warn!("Invalid app selection value: {}", pus_tc.app_data()[0]);
}
defmt::info!(
"received boot selection command with app select: {:?}",
app_sel_result.unwrap()
);
log::info!(target: "TC Handler", "received boot selection command with app select: {:?}", app_sel_result.unwrap());
cx.local
.nvm
.write(PREFERRED_SLOT_OFFSET as usize, &[pus_tc.app_data()[0]])
@ -344,7 +341,7 @@ mod app {
}
}
if pus_tc.service() == PusServiceId::Test as u8 && pus_tc.subservice() == 1 {
defmt::info!("received ping TC");
log::info!(target: "TC Handler", "received ping TC");
let tm = cx
.local
.verif_reporter
@ -369,21 +366,23 @@ mod app {
if pus_tc.subservice() == 2 {
let app_data = pus_tc.app_data();
if app_data.len() < 10 {
defmt::warn!(
log::warn!(
target: "TC Handler",
"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 {
defmt::warn!("memory ID {} not supported", memory_id);
log::warn!(target: "TC Handler", "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() {
defmt::warn!(
log::warn!(
target: "TC Handler",
"invalid data length {} for raw mem write detected",
data_len
);
@ -391,7 +390,12 @@ mod app {
return;
}
let data = &app_data[10..10 + data_len as usize];
defmt::info!("writing {} bytes at offset {} to NVM", data_len, offset);
log::info!(
target: "TC Handler",
"writing {} bytes at offset {} to NVM",
data_len,
offset
);
cx.local
.nvm
.write(offset as usize, data)
@ -402,7 +406,7 @@ mod app {
.verify(offset as usize, data)
.expect("NVM verification failed")
{
defmt::warn!("verification of data written to NVM failed");
log::warn!("verification of data written to NVM failed");
cx.local
.verif_reporter
.completion_failure(
@ -420,7 +424,9 @@ mod app {
.expect("completion success failed")
};
write_and_send(&tm);
defmt::info!("NVM operation done");
log::info!(
target: "TC Handler",
"NVM operation done");
}
}
}

View File

@ -1,3 +1,3 @@
#!/bin/bash
JLinkGDBServer -select USB -device VA10820 -endian little -if JTAG -speed auto \
-LocalhostOnly -jtagconf -1,-1
JLinkGDBServer -select USB -device Cortex-M0 -endian little -if JTAG -speed auto \
-LocalhostOnly

View File

@ -1,18 +0,0 @@
#!/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
telnet localhost 19021 | defmt-print -e "$BINARY"

21524
sections/sec-debug.txt Normal file

File diff suppressed because it is too large Load Diff

6312
sections/sec-release-lto.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,10 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [v0.2.1] 2025-03-07
- Bumped allowed va108xx-hal to v0.11
## [v0.2.0] 2025-02-17
- Bumped va108xx-hal to v0.10.0
@ -25,7 +21,3 @@ Docs patch
## [v0.1.0] 2025-02-13
Initial release
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-embassy-v0.2.1...HEAD
[v0.2.1]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-embassy-v0.2.0...va10xx-embassy-v0.2.1
[v0.2.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-embassy-v0.1.2...va10xx-embassy-v0.2.0

View File

@ -1,6 +1,6 @@
[package]
name = "va108xx-embassy"
version = "0.2.1"
version = "0.2.0"
edition = "2021"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
description = "Embassy-rs support for the Vorago VA108xx family of microcontrollers"
@ -20,7 +20,7 @@ embassy-time-queue-utils = "0.1"
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
va108xx-hal = { version = ">=0.10, <=0.11" }
va108xx-hal = { version = "0.11", path = "../va108xx-hal" }
[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies]
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }

View File

@ -8,14 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [v0.11.1] 2025-03-10
## Fixed
- Fix `embedded_io` UART implementation to implement the documented contract properly.
The implementation will now block until at least one byte is available or can be written, unless
the send or receive buffer is empty.
## [v0.11.0] 2025-03-07
## Changed
@ -261,7 +253,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- README with basic instructions how to set up own binary crate
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-hal-v0.11.0...HEAD
[v0.11.1]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-hal-v0.11.0...va108xx-hal-v0.11.1
[v0.11.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-hal-v0.10.0...va108xx-hal-v0.11.0
[v0.10.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-hal-v0.9.0...va108xx-hal-v0.10.0
[v0.9.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-hal-v0.8.0...va108xx-hal-v0.9.0

View File

@ -1,6 +1,6 @@
[package]
name = "va108xx-hal"
version = "0.11.1"
version = "0.11.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2021"
description = "HAL for the Vorago VA108xx family of microcontrollers"

View File

@ -1004,7 +1004,7 @@ where
/// * `sys_clk` - System clock
/// * `spi` - SPI bus to use
/// * `pins` - Pins to be used for SPI transactions. These pins are consumed
/// to ensure the pins can not be used for other purposes anymore
/// to ensure the pins can not be used for other purposes anymore
/// * `spi_cfg` - Configuration specific to the SPI bus
pub fn new(
syscfg: &mut pac::Sysconfig,

View File

@ -1,12 +1,5 @@
//! # API for the UART peripheral
//!
//! The core of this API are the [Uart], [UartBase], [Rx] and [Tx] structures.
//! The RX structure also has a dedicated [RxWithInterrupt] variant which allows reading the receiver
//! using interrupts.
//!
//! The [rx_asynch] and [tx_asynch] modules provide an asynchronous non-blocking API for the UART
//! peripheral.
//!
//! ## Examples
//!
//! - [UART simple example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/simple/examples/uart.rs)
@ -631,8 +624,8 @@ where
/// - `pins`: UART TX and RX pin tuple.
/// - `config`: UART specific configuration parameters like baudrate.
/// - `irq_cfg`: Optional interrupt configuration. This should be a valid value if the plan
/// is to use TX or RX functionality relying on interrupts. If only the blocking API without
/// any interrupt support is used, this can be [None].
/// is to use TX or RX functionality relying on interrupts. If only the blocking API without
/// any interrupt support is used, this can be [None].
pub fn new(
syscfg: &mut va108xx::Sysconfig,
sys_clk: impl Into<Hertz>,
@ -892,15 +885,7 @@ impl<Uart: Instance> embedded_hal_nb::serial::Read<u8> for Rx<Uart> {
impl<Uart: Instance> embedded_io::Read for Rx<Uart> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Ok(0);
}
let mut read = 0;
loop {
if self.0.rxstatus().read().rdavl().bit_is_set() {
break;
}
}
for byte in buf.iter_mut() {
match <Self as embedded_hal_nb::serial::Read<u8>>::read(self) {
Ok(w) => {
@ -1066,14 +1051,6 @@ impl<Uart: Instance> embedded_hal_nb::serial::Write<u8> for Tx<Uart> {
impl<Uart: Instance> embedded_io::Write for Tx<Uart> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Ok(0);
}
loop {
if self.0.txstatus().read().wrrdy().bit_is_set() {
break;
}
}
let mut written = 0;
for byte in buf.iter() {
match <Self as embedded_hal_nb::serial::Write<u8>>::write(self, *byte) {
@ -1082,7 +1059,7 @@ impl<Uart: Instance> embedded_io::Write for Tx<Uart> {
}
}
Ok(written)
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {

View File

@ -13,7 +13,7 @@ categories = ["embedded", "no-std", "hardware-support"]
[dependencies]
cortex-m = "0.7"
vcell = "0.1.3"
defmt = { version = "1", optional = true }
defmt = { version = "0.3", optional = true }
critical-section = { version = "1", optional = true }
[dependencies.cortex-m-rt]

View File

@ -8,11 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [v0.8.1] 2025-03-07
- Bumped allowed `va108xx-hal` dependency to 0.11
- Bumped `bitfield` dependency
## [v0.8.0] 2025-02-17
- Bumped `va108xx-hal` dependency to 0.10
@ -61,9 +56,3 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added basic accelerometer example. Board in not populated so it is not complete, but
it provides a starting point
- Added ADC base library and example building on the new max116xx-10bit device driver crate
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/vorago-reb1-v0.8.1...HEAD
[v0.8.1]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/vorago-reb1-v0.8.0...vorago-reb1-v0.8.1
[v0.8.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/vorago-reb1-v0.7.0...vorago-reb1-v0.8.0
[v0.7.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/vorago-reb1-v0.6.0...vorago-reb1-v0.7.0
[v0.6.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/vorago-reb1-v0.5.0...vorago-reb1-v0.6.0

View File

@ -1,6 +1,6 @@
[package]
name = "vorago-reb1"
version = "0.8.1"
version = "0.8.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2021"
description = "Board Support Crate for the Vorago REB1 development board"
@ -15,10 +15,10 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
embedded-hal = "1"
nb = "1"
bitfield = ">=0.17, <=0.19"
bitfield = ">=0.17, <=0.18"
max116xx-10bit = "0.3"
va108xx-hal = { version = ">=0.10, <=0.11", features = ["rt"] }
va108xx-hal = { version = ">=0.10, <=0.11", path = "../va108xx-hal", features = ["rt"] }
[features]
rt = ["va108xx-hal/rt"]