Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23f0fa3b0b |
@@ -36,7 +36,7 @@ jobs:
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Install nextest
|
||||
uses: taiki-e/install-action@nextest
|
||||
- run: cargo nextest run -p va108xx-hal --no-tests=pass
|
||||
- run: cargo nextest run --all-features -p va108xx-hal --no-tests=pass
|
||||
# I think we can skip those on an embedded crate..
|
||||
# - run: cargo test --doc -p va108xx-hal
|
||||
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p va108xx --all-features
|
||||
- run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p va108xx-hal --features "defmt, embassy-oc30-oc31" --no-deps
|
||||
- run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p va108xx-hal --all-features --no-deps
|
||||
- run: RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p vorago-reb1 --no-deps
|
||||
|
||||
clippy:
|
||||
|
||||
@@ -70,7 +70,7 @@ clippy-shared-hal:
|
||||
[working-directory: 'va108xx']
|
||||
docs-va108xx:
|
||||
RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p va108xx --all-features
|
||||
RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p va108xx-hal --features "defmt, embassy-oc30-oc31" --no-deps
|
||||
RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p va108xx-hal --all-features --no-deps
|
||||
RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options" cargo +nightly doc -p vorago-reb1 --no-deps
|
||||
|
||||
[working-directory: 'va416xx']
|
||||
|
||||
@@ -4,6 +4,7 @@ members = [
|
||||
"vorago-reb1",
|
||||
"va108xx",
|
||||
"va108xx-hal",
|
||||
"va108xx-embassy",
|
||||
"examples/simple",
|
||||
"examples/rtic",
|
||||
"examples/embassy",
|
||||
|
||||
@@ -14,6 +14,8 @@ This workspace contains the following released crates:
|
||||
crate containing basic low-level register definition.
|
||||
- The [`va108xx-hal`](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/va108xx-hal)
|
||||
HAL crate containing higher-level abstractions on top of the PAC register crate.
|
||||
- The [`va108xx-embassy`](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/va108xx-embassy)
|
||||
crate containing support for running the embassy-rs asynchronous runtime.
|
||||
- The [`vorago-reb1`](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/vorago-reb1)
|
||||
BSP crate containing support for the REB1 development board.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ panic-probe = { version = "1", features = ["print-defmt"] }
|
||||
embedded-hal = "1"
|
||||
|
||||
[dependencies.va108xx-hal]
|
||||
version = "0.13"
|
||||
version = "0.12"
|
||||
features = ["rt"]
|
||||
path = "../va108xx-hal"
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ fn main() -> ! {
|
||||
delay_timer.delay_ms(500);
|
||||
}
|
||||
let ahb_freq: Hertz = 50.MHz();
|
||||
let mut syst_delay = cortex_m::delay::Delay::new(cp.SYST, ahb_freq.to_raw());
|
||||
let mut syst_delay = cortex_m::delay::Delay::new(cp.SYST, ahb_freq.raw());
|
||||
// Release image should be used to verify timings for pin PA0
|
||||
for _ in 0..5 {
|
||||
pa0.toggle();
|
||||
|
||||
@@ -15,12 +15,12 @@ num_enum = { version = "0.7", default-features = false }
|
||||
static_assertions = "1"
|
||||
|
||||
[dependencies.va108xx-hal]
|
||||
version = "0.13"
|
||||
version = "0.12"
|
||||
path = "../va108xx-hal"
|
||||
features = ["defmt"]
|
||||
|
||||
[dependencies.vorago-reb1]
|
||||
version = "0.10"
|
||||
version = "0.9"
|
||||
path = "../vorago-reb1"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -27,10 +27,11 @@ embassy-executor = { version = "0.10", features = [
|
||||
"executor-interrupt"
|
||||
]}
|
||||
|
||||
va108xx-hal = { version = "0.13", path = "../../va108xx-hal", features = ["defmt"] }
|
||||
va108xx-hal = { version = "0.12", path = "../../va108xx-hal", features = ["defmt"] }
|
||||
va108xx-embassy = { version = "0.3", path = "../../va108xx-embassy" }
|
||||
|
||||
[features]
|
||||
default = ["ticks-hz-1_000", "va108xx-hal/embassy-oc30-oc31"]
|
||||
default = ["ticks-hz-1_000", "va108xx-embassy/irq-oc30-oc31"]
|
||||
custom-irqs = []
|
||||
ticks-hz-1_000 = ["embassy-time/tick-hz-1_000"]
|
||||
ticks-hz-32_768 = ["embassy-time/tick-hz-32_768"]
|
||||
|
||||
@@ -61,7 +61,7 @@ async fn main(spawner: Spawner) {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Safety: Only called once here.
|
||||
va108xx_hal::embassy_time::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
|
||||
va108xx_embassy::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
|
||||
unsafe {
|
||||
cortex_m::interrupt::enable();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ async fn main(spawner: Spawner) {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Safety: Only called once here.
|
||||
va108xx_hal::embassy_time::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
|
||||
va108xx_embassy::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
|
||||
|
||||
let porta = PinsA::new(dp.porta);
|
||||
let mut led0 = Output::new(porta.pa10, PinState::Low);
|
||||
|
||||
@@ -41,7 +41,7 @@ async fn main(_spawner: Spawner) {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Safety: Only called once here.
|
||||
va108xx_hal::embassy_time::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
|
||||
va108xx_embassy::init(dp.tim23, dp.tim22, SYSCLK_FREQ);
|
||||
|
||||
let porta = PinsA::new(dp.porta);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use embassy_time::{Duration, Instant, Ticker};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "custom-irqs")] {
|
||||
use va108xx_hal::embassy_time_driver_irqs;
|
||||
use va108xx_embassy::embassy_time_driver_irqs;
|
||||
use va108xx_hal::pac::interrupt;
|
||||
embassy_time_driver_irqs!(timekeeper_irq = OC23, alarm_irq = OC24);
|
||||
}
|
||||
@@ -31,13 +31,13 @@ async fn main(_spawner: Spawner) {
|
||||
// Safety: Only called once here.
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(feature = "custom-irqs"))] {
|
||||
va108xx_hal::embassy_time::init(
|
||||
va108xx_embassy::init(
|
||||
dp.tim23,
|
||||
dp.tim22,
|
||||
SYSCLK_FREQ,
|
||||
);
|
||||
} else {
|
||||
va108xx_hal::embassy_time::init_with_custom_irqs(
|
||||
va108xx_embassy::init_with_custom_irqs(
|
||||
dp.tim23,
|
||||
dp.tim22,
|
||||
SYSCLK_FREQ,
|
||||
|
||||
@@ -9,10 +9,9 @@ embedded-io = "0.7"
|
||||
defmt-rtt = "1"
|
||||
defmt = "1"
|
||||
panic-probe = { version = "1", features = ["defmt"] }
|
||||
fugit = "0.4"
|
||||
rtic = { version = "2", features = ["thumbv6-backend"] }
|
||||
rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }
|
||||
ringbuf = { version = "0.5", default-features = false, features = ["portable-atomic"] }
|
||||
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
|
||||
|
||||
va108xx-hal = { version = "0.13", path = "../../va108xx-hal" }
|
||||
vorago-reb1 = { version = "0.10", path = "../../vorago-reb1" }
|
||||
va108xx-hal = { version = "0.12", path = "../../va108xx-hal" }
|
||||
vorago-reb1 = { version = "0.9", path = "../../vorago-reb1" }
|
||||
|
||||
@@ -43,7 +43,7 @@ mod app {
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
defmt::println!("-- Vorago Button IRQ Example --");
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.to_raw());
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let mode = DEFAULT_MODE;
|
||||
defmt::info!("Using {:?} mode", mode);
|
||||
|
||||
@@ -20,11 +20,11 @@ mod app {
|
||||
use panic_probe as _;
|
||||
// Import global logger.
|
||||
use defmt_rtt as _;
|
||||
use rtic_monotonics::fugit::ExtU32 as _;
|
||||
use rtic_monotonics::Monotonic;
|
||||
use va108xx_hal::{
|
||||
pac,
|
||||
pins::PinsA,
|
||||
prelude::*,
|
||||
uart::{self, RxWithInterrupt, Tx},
|
||||
InterruptConfig,
|
||||
};
|
||||
@@ -46,18 +46,15 @@ mod app {
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
defmt::println!("-- VA108xx UART Echo with IRQ example application--");
|
||||
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.to_raw());
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let dp = cx.device;
|
||||
let gpioa = PinsA::new(dp.porta);
|
||||
let tx = gpioa.pa9;
|
||||
let rx = gpioa.pa8;
|
||||
|
||||
let clock_config = uart::ClockConfig::calculate(
|
||||
SYSCLK_FREQ,
|
||||
fugit::HertzU32::from_raw(115200),
|
||||
uart::BaudMode::_16,
|
||||
);
|
||||
let clock_config =
|
||||
uart::ClockConfig::calculate(SYSCLK_FREQ, 115200.Hz(), uart::BaudMode::_16);
|
||||
let uart_config = uart::Config::new_with_clock_config(clock_config);
|
||||
let irq_uart = uart::Uart::new_with_interrupt_uart0(
|
||||
dp.uarta,
|
||||
|
||||
@@ -34,7 +34,7 @@ mod app {
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
defmt::println!("-- Vorago VA108xx RTIC template --");
|
||||
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.to_raw());
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let porta = PinsA::new(cx.device.porta);
|
||||
let led0 = Output::new(porta.pa10, PinState::Low);
|
||||
|
||||
@@ -16,6 +16,6 @@ embedded-io = "0.7"
|
||||
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }
|
||||
|
||||
[dependencies.va108xx-hal]
|
||||
version = "0.13"
|
||||
version = "0.12"
|
||||
path = "../../va108xx-hal"
|
||||
features = ["defmt"]
|
||||
|
||||
@@ -46,8 +46,8 @@ fn main() -> ! {
|
||||
}
|
||||
|
||||
let sys_clk: Hertz = 50.MHz();
|
||||
let cnt_ms = sys_clk.to_raw() / 1000 - 1;
|
||||
let cnt_sec = sys_clk.to_raw() - 1;
|
||||
let cnt_ms = sys_clk.raw() / 1000 - 1;
|
||||
let cnt_sec = sys_clk.raw() - 1;
|
||||
unsafe {
|
||||
dp.tim0.cnt_value().write(|w| w.bits(cnt_ms));
|
||||
dp.tim0.rst_value().write(|w| w.bits(cnt_ms));
|
||||
|
||||
@@ -12,27 +12,24 @@ defmt-rtt = { version = "1" }
|
||||
panic-probe = { version = "1", features = ["print-defmt"] }
|
||||
num_enum = { version = "0.7", default-features = false }
|
||||
cobs = { version = "0.5", default-features = false }
|
||||
# satrs = { version = "0.3.0-alpha.3", default-features = false, features = ["defmt"] }
|
||||
fugit = "0.4"
|
||||
satrs = { version = "0.3.0-alpha.3", default-features = false, features = ["defmt"] }
|
||||
arbitrary-int = "2"
|
||||
embassy-sync = "0.8"
|
||||
embassy-time = "0.5"
|
||||
static_cell = "2"
|
||||
spacepackets = { version = "0.17", default-features = false, features = ["defmt"] }
|
||||
serde = { version = "1", default-features = false }
|
||||
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
|
||||
# spacepackets = { version = "0.17", path = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", default-features = false, features = ["defmt"] }
|
||||
# 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"]}
|
||||
|
||||
rtic = { version = "2", features = ["thumbv6-backend"] }
|
||||
rtic-monotonics = { version = "2", features = ["cortex-m-systick"] }
|
||||
|
||||
[dependencies.va108xx-hal]
|
||||
version = "0.13"
|
||||
version = "0.12"
|
||||
path = "../va108xx-hal"
|
||||
features = ["defmt", "embassy-oc30-oc31"]
|
||||
features = ["defmt"]
|
||||
|
||||
[dependencies.vorago-reb1]
|
||||
version = "0.10"
|
||||
version = "0.9"
|
||||
path = "../vorago-reb1"
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[package]
|
||||
name = "shared"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -1,18 +0,0 @@
|
||||
#![no_std]
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, defmt::Format)]
|
||||
#[repr(u8)]
|
||||
enum AppSel {
|
||||
A = 0,
|
||||
B = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, defmt::Format)]
|
||||
pub enum Request {
|
||||
CorruptImageA,
|
||||
CorruptImageB,
|
||||
SetBootSlot(AppSel),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
||||
+153
-80
@@ -4,8 +4,13 @@
|
||||
#![no_std]
|
||||
|
||||
use defmt_rtt as _; // global logger
|
||||
use num_enum::TryFromPrimitive;
|
||||
use panic_probe as _;
|
||||
use va108xx_hal::time::Hertz;
|
||||
use ringbuf::{
|
||||
traits::{Consumer, Observer, Producer},
|
||||
StaticRb,
|
||||
};
|
||||
use va108xx_hal::prelude::*;
|
||||
|
||||
const SYSCLK_FREQ: Hertz = Hertz::from_raw(50_000_000);
|
||||
|
||||
@@ -19,8 +24,30 @@ const UART_BAUDRATE: u32 = 115200;
|
||||
const BOOT_NVM_MEMORY_ID: u8 = 1;
|
||||
const RX_DEBUGGING: bool = false;
|
||||
|
||||
const TC_PIPE_SIZE: usize = 1024;
|
||||
const TM_PIPE_SIZE: usize = 128;
|
||||
pub enum ActionId {
|
||||
CorruptImageA = 128,
|
||||
CorruptImageB = 129,
|
||||
SetBootSlot = 130,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, defmt::Format)]
|
||||
#[repr(u8)]
|
||||
enum AppSel {
|
||||
A = 0,
|
||||
B = 1,
|
||||
}
|
||||
|
||||
// Larger buffer for TC to be able to hold the possibly large memory write packets.
|
||||
const BUF_RB_SIZE_TC: usize = 1024;
|
||||
const SIZES_RB_SIZE_TC: usize = 16;
|
||||
|
||||
const BUF_RB_SIZE_TM: usize = 256;
|
||||
const SIZES_RB_SIZE_TM: usize = 16;
|
||||
|
||||
pub struct RingBufWrapper<const BUF_SIZE: usize, const SIZES_LEN: usize> {
|
||||
pub buf: StaticRb<u8, BUF_SIZE>,
|
||||
pub sizes: StaticRb<usize, SIZES_LEN>,
|
||||
}
|
||||
|
||||
pub const APP_A_START_ADDR: u32 = 0x3000;
|
||||
pub const APP_A_END_ADDR: u32 = 0x117FC;
|
||||
@@ -32,13 +59,21 @@ pub const PREFERRED_SLOT_OFFSET: u32 = 0x20000 - 1;
|
||||
#[rtic::app(device = pac, dispatchers = [OC20, OC21, OC22])]
|
||||
mod app {
|
||||
use super::*;
|
||||
use arbitrary_int::traits::Integer as _;
|
||||
use arbitrary_int::{u11, u14};
|
||||
use cortex_m::asm;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embedded_io::Write;
|
||||
use rtic::Mutex;
|
||||
use rtic_monotonics::systick::prelude::*;
|
||||
use satrs::pus::verification::{FailParams, VerificationReportCreator};
|
||||
use satrs::spacepackets::ecss::PusServiceId;
|
||||
use satrs::spacepackets::ecss::{
|
||||
tc::PusTcReader, tm::PusTmCreator, EcssEnumU8, PusPacket, WritablePusPacket,
|
||||
};
|
||||
use va108xx_hal::pins::PinsA;
|
||||
use va108xx_hal::spi::SpiClockConfig;
|
||||
use va108xx_hal::uart;
|
||||
use va108xx_hal::{pac, InterruptConfig};
|
||||
use va108xx_hal::uart::InterruptContextTimeoutOrMaxSize;
|
||||
use va108xx_hal::{pac, uart, InterruptConfig};
|
||||
use vorago_reb1::m95m01::M95M01;
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
||||
@@ -53,38 +88,39 @@ mod app {
|
||||
struct Local {
|
||||
uart_rx: uart::RxWithInterrupt,
|
||||
uart_tx: uart::Tx,
|
||||
rx_context: InterruptContextTimeoutOrMaxSize,
|
||||
verif_reporter: VerificationReportCreator,
|
||||
nvm: M95M01,
|
||||
tc_tx: embassy_sync::pipe::Writer<'static, CriticalSectionRawMutex, TC_PIPE_SIZE>,
|
||||
tc_rx: embassy_sync::pipe::Reader<'static, CriticalSectionRawMutex, TC_PIPE_SIZE>,
|
||||
tm_tx: embassy_sync::pipe::Writer<'static, CriticalSectionRawMutex, TM_PIPE_SIZE>,
|
||||
tm_rx: embassy_sync::pipe::Reader<'static, CriticalSectionRawMutex, TM_PIPE_SIZE>,
|
||||
}
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
struct Shared {
|
||||
// Having this shared allows multiple tasks to generate telemetry.
|
||||
tm_rb: RingBufWrapper<BUF_RB_SIZE_TM, SIZES_RB_SIZE_TM>,
|
||||
tc_rb: RingBufWrapper<BUF_RB_SIZE_TC, SIZES_RB_SIZE_TC>,
|
||||
}
|
||||
|
||||
rtic_monotonics::systick_monotonic!(Mono, 1000);
|
||||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
defmt::println!("-- Vorago flashloader --");
|
||||
|
||||
let periphs = cx.device;
|
||||
va108xx_hal::embassy_time::init(periphs.tim14, periphs.tim15, SYSCLK_FREQ);
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let dp = cx.device;
|
||||
let spi_clock_config = SpiClockConfig::new(2, 4);
|
||||
let nvm = M95M01::new(periphs.spic, spi_clock_config);
|
||||
let nvm = M95M01::new(dp.spic, spi_clock_config);
|
||||
|
||||
let gpioa = PinsA::new(periphs.porta);
|
||||
let gpioa = PinsA::new(dp.porta);
|
||||
let tx = gpioa.pa9;
|
||||
let rx = gpioa.pa8;
|
||||
|
||||
let clock_config = uart::ClockConfig::calculate(
|
||||
SYSCLK_FREQ,
|
||||
fugit::HertzU32::from_raw(UART_BAUDRATE),
|
||||
uart::BaudMode::_16,
|
||||
);
|
||||
let clock_config =
|
||||
uart::ClockConfig::calculate(SYSCLK_FREQ, UART_BAUDRATE.Hz(), uart::BaudMode::_16);
|
||||
let uart_config = uart::Config::new_with_clock_config(clock_config);
|
||||
let irq_uart = uart::Uart::new_with_interrupt_uart0(
|
||||
periphs.uarta,
|
||||
dp.uarta,
|
||||
tx,
|
||||
rx,
|
||||
uart_config,
|
||||
@@ -94,28 +130,30 @@ mod app {
|
||||
// Unwrap is okay, we explicitely set the interrupt ID.
|
||||
let mut rx = rx.into_rx_with_irq();
|
||||
|
||||
rx.start();
|
||||
tc_handler::spawn().unwrap();
|
||||
tm_tx_handler::spawn().unwrap();
|
||||
let verif_reporter = VerificationReportCreator::new(u11::new(0));
|
||||
|
||||
static TC_PIPE: static_cell::ConstStaticCell<
|
||||
embassy_sync::pipe::Pipe<CriticalSectionRawMutex, TC_PIPE_SIZE>,
|
||||
> = static_cell::ConstStaticCell::new(embassy_sync::pipe::Pipe::new());
|
||||
static TM_PIPE: static_cell::ConstStaticCell<
|
||||
embassy_sync::pipe::Pipe<CriticalSectionRawMutex, TM_PIPE_SIZE>,
|
||||
> = static_cell::ConstStaticCell::new(embassy_sync::pipe::Pipe::new());
|
||||
let (tc_rx, tc_tx) = TC_PIPE.take().split();
|
||||
let (tm_rx, tm_tx) = TM_PIPE.take().split();
|
||||
let mut rx_context = InterruptContextTimeoutOrMaxSize::new(MAX_TC_FRAME_SIZE);
|
||||
rx.read_fixed_len_or_timeout_based_using_irq(&mut rx_context)
|
||||
.expect("initiating UART RX failed");
|
||||
pus_tc_handler::spawn().unwrap();
|
||||
pus_tm_tx_handler::spawn().unwrap();
|
||||
(
|
||||
Shared {},
|
||||
Shared {
|
||||
tc_rb: RingBufWrapper {
|
||||
buf: StaticRb::default(),
|
||||
sizes: StaticRb::default(),
|
||||
},
|
||||
tm_rb: RingBufWrapper {
|
||||
buf: StaticRb::default(),
|
||||
sizes: StaticRb::default(),
|
||||
},
|
||||
},
|
||||
Local {
|
||||
uart_rx: rx,
|
||||
uart_tx: tx,
|
||||
rx_context,
|
||||
verif_reporter,
|
||||
nvm,
|
||||
tc_tx,
|
||||
tc_rx,
|
||||
tm_tx,
|
||||
tm_rx,
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -134,25 +172,66 @@ mod app {
|
||||
local = [
|
||||
cnt: u32 = 0,
|
||||
rx_buf: [u8; MAX_TC_FRAME_SIZE] = [0; MAX_TC_FRAME_SIZE],
|
||||
rx_context,
|
||||
uart_rx,
|
||||
tc_tx
|
||||
],
|
||||
shared = [tc_rb]
|
||||
)]
|
||||
fn uart_rx_irq(cx: uart_rx_irq::Context) {
|
||||
let mut buf: [u8; 16] = [0; 16];
|
||||
let result = cx.local.uart_rx.on_interrupt(&mut buf);
|
||||
if result.bytes_read > 0 {
|
||||
let mut written_so_far = 0;
|
||||
while written_so_far < result.bytes_read {
|
||||
let write_result = cx
|
||||
.local
|
||||
.tc_tx
|
||||
.try_write(&buf[written_so_far..result.bytes_read]);
|
||||
if write_result.is_err() {
|
||||
defmt::warn!("TC pipe full, dropping bytes");
|
||||
break;
|
||||
fn uart_rx_irq(mut cx: uart_rx_irq::Context) {
|
||||
match cx
|
||||
.local
|
||||
.uart_rx
|
||||
.on_interrupt_max_size_or_timeout_based(cx.local.rx_context, cx.local.rx_buf)
|
||||
{
|
||||
Ok(result) => {
|
||||
if RX_DEBUGGING {
|
||||
defmt::debug!("RX Info: {:?}", cx.local.rx_context);
|
||||
defmt::debug!("RX Result: {:?}", result);
|
||||
}
|
||||
written_so_far += write_result.unwrap();
|
||||
if result.complete() {
|
||||
// Check frame validity (must have COBS format) and decode the frame.
|
||||
// Currently, we expect a full frame or a frame received through a timeout
|
||||
// to be one COBS frame. We could parse for multiple COBS packets in one
|
||||
// frame, but the additional complexity is not necessary here..
|
||||
if cx.local.rx_buf[0] == 0 && cx.local.rx_buf[result.bytes_read - 1] == 0 {
|
||||
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");
|
||||
} else {
|
||||
let decoded_size = decoded_size.unwrap();
|
||||
let mut tc_rb_full = false;
|
||||
cx.shared.tc_rb.lock(|rb| {
|
||||
if rb.sizes.vacant_len() >= 1 && rb.buf.vacant_len() >= decoded_size
|
||||
{
|
||||
rb.sizes.try_push(decoded_size).unwrap();
|
||||
rb.buf.push_slice(&cx.local.rx_buf[1..1 + decoded_size]);
|
||||
} else {
|
||||
tc_rb_full = true;
|
||||
}
|
||||
});
|
||||
if tc_rb_full {
|
||||
defmt::warn!("COBS TC queue full");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
defmt::warn!(
|
||||
"COBS frame with invalid format, start and end bytes are not 0"
|
||||
);
|
||||
}
|
||||
|
||||
// Initiate next transfer.
|
||||
cx.local
|
||||
.uart_rx
|
||||
.read_fixed_len_or_timeout_based_using_irq(cx.local.rx_context)
|
||||
.expect("read operation failed");
|
||||
}
|
||||
if result.has_errors() {
|
||||
defmt::warn!("UART error: {:?}", result.errors.unwrap());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
defmt::warn!("UART error: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,35 +244,32 @@ mod app {
|
||||
src_data_buf: [u8; 16] = [0; 16],
|
||||
verif_buf: [u8; 32] = [0; 32],
|
||||
nvm,
|
||||
tc_rx
|
||||
verif_reporter
|
||||
],
|
||||
shared=[]
|
||||
shared=[tm_rb, tc_rb]
|
||||
)]
|
||||
async fn tc_handler(mut cx: tc_handler::Context) {
|
||||
async fn pus_tc_handler(mut cx: pus_tc_handler::Context) {
|
||||
loop {
|
||||
/*
|
||||
// Try to read a TC from the ring buffer.
|
||||
let packet_len = cx.shared.tc_rb.lock(|rb| rb.sizes.try_pop());
|
||||
if packet_len.is_none() {
|
||||
// Small delay, TCs might arrive very quickly.
|
||||
Mono::delay(20_u32.millis()).await;
|
||||
continue;
|
||||
}
|
||||
let packet_len = packet_len.unwrap();
|
||||
defmt::info!("received packet with length {}", packet_len);
|
||||
let popped_packet_len = cx
|
||||
.shared
|
||||
.tc_rb
|
||||
.lock(|rb| rb.buf.pop_slice(&mut cx.local.tc_buf[0..packet_len]));
|
||||
assert_eq!(popped_packet_len, packet_len);
|
||||
// Read a telecommand, now handle it.
|
||||
handle_valid_pus_tc(&mut cx);
|
||||
*/
|
||||
// Try to read a TC from the ring buffer.
|
||||
let packet_len = cx.shared.tc_rb.lock(|rb| rb.sizes.try_pop());
|
||||
if packet_len.is_none() {
|
||||
// Small delay, TCs might arrive very quickly.
|
||||
Mono::delay(20.millis()).await;
|
||||
continue;
|
||||
}
|
||||
let packet_len = packet_len.unwrap();
|
||||
defmt::info!("received packet with length {}", packet_len);
|
||||
let popped_packet_len = cx
|
||||
.shared
|
||||
.tc_rb
|
||||
.lock(|rb| rb.buf.pop_slice(&mut cx.local.tc_buf[0..packet_len]));
|
||||
assert_eq!(popped_packet_len, packet_len);
|
||||
// Read a telecommand, now handle it.
|
||||
handle_valid_pus_tc(&mut cx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn handle_valid_pus_tc(cx: &mut tc_handler::Context) {
|
||||
fn handle_valid_pus_tc(cx: &mut pus_tc_handler::Context) {
|
||||
let pus_tc = PusTcReader::new(cx.local.tc_buf);
|
||||
if let Err(e) = pus_tc {
|
||||
defmt::warn!("PUS TC error: {}", e);
|
||||
@@ -340,7 +416,6 @@ mod app {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[task(
|
||||
priority = 1,
|
||||
@@ -349,11 +424,10 @@ mod app {
|
||||
encoded_buf: [u8;MAX_TM_FRAME_SIZE] = [0; MAX_TM_FRAME_SIZE],
|
||||
uart_tx,
|
||||
],
|
||||
shared=[]
|
||||
shared=[tm_rb]
|
||||
)]
|
||||
async fn tm_tx_handler(mut cx: tm_tx_handler::Context) {
|
||||
async fn pus_tm_tx_handler(mut cx: pus_tm_tx_handler::Context) {
|
||||
loop {
|
||||
/*
|
||||
let mut occupied_len = cx.shared.tm_rb.lock(|rb| rb.sizes.occupied_len());
|
||||
while occupied_len > 0 {
|
||||
let next_size = cx.shared.tm_rb.lock(|rb| {
|
||||
@@ -375,7 +449,6 @@ mod app {
|
||||
Mono::delay(2.millis()).await;
|
||||
}
|
||||
Mono::delay(50.millis()).await;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["clippy", "llvm-tools"]
|
||||
target = "thumbv6m-none-eabi"
|
||||
@@ -0,0 +1,36 @@
|
||||
Change Log
|
||||
=======
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [unreleased]
|
||||
|
||||
## [v0.3.0] 2025-09-03
|
||||
|
||||
Bumped allowed va108xx-hal to v0.12
|
||||
|
||||
## [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
|
||||
- Remove `embassy` module, expose public functions in library root directly
|
||||
|
||||
|
||||
## [v0.1.2] and [v0.1.1] 2025-02-13
|
||||
|
||||
Docs patch
|
||||
|
||||
## [v0.1.0] 2025-02-13
|
||||
|
||||
Initial release
|
||||
|
||||
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-embassy-v0.3.0...HEAD
|
||||
[v0.3.0]: https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/compare/va108xx-embassy-v0.2.1...va10xx-embassy-v0.3.0
|
||||
[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
|
||||
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "va108xx-embassy"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||
description = "Embassy-rs support for the Vorago VA108xx family of microcontrollers"
|
||||
homepage = "https://egit.irs.uni-stuttgart.de/rust/vorago-rs"
|
||||
repository = "https://egit.irs.uni-stuttgart.de/rust/vorago-rs"
|
||||
license = "Apache-2.0"
|
||||
keywords = ["no-std", "hal", "cortex-m", "vorago", "va108xx"]
|
||||
categories = ["aerospace", "embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
vorago-shared-hal = { version = "0.2", path = "../../vorago-shared-hal", features = ["vor1x"] }
|
||||
va108xx-hal = { version = "0.12", path = "../va108xx-hal" }
|
||||
|
||||
[features]
|
||||
default = ["irq-oc30-oc31"]
|
||||
irqs-in-lib = []
|
||||
# This determines the reserved interrupt functions for the embassy time drivers. Only one
|
||||
# is allowed to be selected!
|
||||
irq-oc28-oc29 = ["irqs-in-lib"]
|
||||
irq-oc29-oc30 = ["irqs-in-lib"]
|
||||
irq-oc30-oc31 = ["irqs-in-lib"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["thumbv6m-none-eabi"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
@@ -1 +1,10 @@
|
||||
This crate was moved into `va108xx-hal`.
|
||||
[](https://crates.io/crates/va108xx-embassy)
|
||||
[](https://docs.rs/va108xx-embassy)
|
||||
|
||||
# Embassy-rs support for the Vorago VA108xx MCU family
|
||||
|
||||
This repository contains the [embassy-rs](https://github.com/embassy-rs/embassy) support for the
|
||||
VA108xx family. Currently, it contains the time driver to allow using embassy-rs. It uses the TIM
|
||||
peripherals provided by the VA108xx family for this purpose.
|
||||
|
||||
The documentation contains more information on how to use this crate.
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
export RUSTDOCFLAGS="--cfg docsrs --generate-link-to-definition -Z unstable-options"
|
||||
cargo +nightly doc --open
|
||||
@@ -23,20 +23,21 @@
|
||||
//!
|
||||
//! You can disable the default features and then specify one of the features above to use the
|
||||
//! documented combination of IRQs. It is also possible to specify custom IRQs by importing and
|
||||
//! using the [crate::embassy_time_driver_irqs] macro to declare the IRQ handlers in the
|
||||
//! using the [embassy_time_driver_irqs] macro to declare the IRQ handlers in the
|
||||
//! application code. If this is done, [init_with_custom_irqs] must be used
|
||||
//! method to pass the IRQ numbers to the library.
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! [embassy example projects](https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/branch/main/va108xx/examples/embassy)
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
#[cfg(feature = "_irqs-in-lib")]
|
||||
use crate::pac::{self, interrupt};
|
||||
use crate::time::Hertz;
|
||||
use crate::timer::TimInstance;
|
||||
|
||||
pub use vorago_shared_hal::embassy::time_driver;
|
||||
#[cfg(feature = "irqs-in-lib")]
|
||||
use va108xx_hal::pac::{self, interrupt};
|
||||
use va108xx_hal::time::Hertz;
|
||||
use va108xx_hal::timer::TimInstance;
|
||||
use vorago_shared_hal::embassy::time_driver;
|
||||
|
||||
/// Macro to define the IRQ handlers for the time driver.
|
||||
///
|
||||
@@ -44,7 +45,7 @@ pub use vorago_shared_hal::embassy::time_driver;
|
||||
/// the feature flags specified. However, the macro is exported to allow users to specify the
|
||||
/// interrupt handlers themselves.
|
||||
///
|
||||
/// Please note that you have to explicitely import the [macro@crate::pac::interrupt]
|
||||
/// Please note that you have to explicitely import the [macro@va108xx_hal::pac::interrupt]
|
||||
/// macro in the application code in case this macro is used there.
|
||||
#[macro_export]
|
||||
macro_rules! embassy_time_driver_irqs {
|
||||
@@ -58,7 +59,7 @@ macro_rules! embassy_time_driver_irqs {
|
||||
#[allow(non_snake_case)]
|
||||
fn $timekeeper_irq() {
|
||||
// Safety: We call it once here.
|
||||
unsafe { $crate::embassy_time::time_driver().on_interrupt_timekeeping() }
|
||||
unsafe { $crate::time_driver().on_interrupt_timekeeping() }
|
||||
}
|
||||
|
||||
const ALARM_IRQ: pac::Interrupt = pac::Interrupt::$alarm_irq;
|
||||
@@ -67,25 +68,25 @@ macro_rules! embassy_time_driver_irqs {
|
||||
#[allow(non_snake_case)]
|
||||
fn $alarm_irq() {
|
||||
// Safety: We call it once here.
|
||||
unsafe { $crate::embassy_time::time_driver().on_interrupt_alarm() }
|
||||
unsafe { $crate::time_driver().on_interrupt_alarm() }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Provide three combinations of IRQs for the time driver by default.
|
||||
|
||||
#[cfg(feature = "embassy-oc30-oc31")]
|
||||
#[cfg(feature = "irq-oc30-oc31")]
|
||||
embassy_time_driver_irqs!(timekeeper_irq = OC31, alarm_irq = OC30);
|
||||
#[cfg(feature = "embassy-oc29-oc30")]
|
||||
#[cfg(feature = "irq-oc29-oc30")]
|
||||
embassy_time_driver_irqs!(timekeeper_irq = OC30, alarm_irq = OC29);
|
||||
#[cfg(feature = "embassy-oc28-oc29")]
|
||||
#[cfg(feature = "irq-oc28-oc29")]
|
||||
embassy_time_driver_irqs!(timekeeper_irq = OC29, alarm_irq = OC28);
|
||||
|
||||
/// Initialization method for embassy.
|
||||
///
|
||||
/// This should be used if the interrupt handler is provided by the library, which is the
|
||||
/// default case.
|
||||
#[cfg(feature = "_irqs-in-lib")]
|
||||
#[cfg(feature = "irqs-in-lib")]
|
||||
pub fn init<TimekeeperTim: TimInstance, AlarmTim: TimInstance>(
|
||||
timekeeper_tim: TimekeeperTim,
|
||||
alarm_tim: AlarmTim,
|
||||
@@ -101,8 +102,8 @@ pub fn init_with_custom_irqs<TimekeeperTim: TimInstance, AlarmTim: TimInstance>(
|
||||
timekeeper_tim: TimekeeperTim,
|
||||
alarm_tim: AlarmTim,
|
||||
sysclk: Hertz,
|
||||
timekeeper_irq: crate::pac::Interrupt,
|
||||
alarm_irq: crate::pac::Interrupt,
|
||||
timekeeper_irq: pac::Interrupt,
|
||||
alarm_irq: pac::Interrupt,
|
||||
) {
|
||||
time_driver().__init(sysclk, timekeeper_tim, alarm_tim, timekeeper_irq, alarm_irq)
|
||||
}
|
||||
@@ -8,11 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [unreleased]
|
||||
|
||||
## [v0.13.0] 2026-05-18
|
||||
|
||||
- Bump `vorago-shared-hal` dependency to v0.3.
|
||||
- Integrate `va108xx-embassy` as a `embassy-time` module.
|
||||
|
||||
## [v0.12.0] 2025-09-03
|
||||
|
||||
## Changed
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[package]
|
||||
name = "va108xx-hal"
|
||||
version = "0.13.0"
|
||||
version = "0.12.0"
|
||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
description = "HAL for the Vorago VA108xx family of microcontrollers"
|
||||
homepage = "https://egit.irs.uni-stuttgart.de/rust/vorago-rs"
|
||||
repository = "https://egit.irs.uni-stuttgart.de/rust/vorago-rs"
|
||||
@@ -12,8 +12,8 @@ categories = ["aerospace", "embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-m = { version = "0.7", features = ["critical-section-single-core"]}
|
||||
vorago-shared-hal = { version = "0.3", path = "../../vorago-shared-hal", features = ["vor1x"] }
|
||||
fugit = "0.4"
|
||||
vorago-shared-hal = { version = "0.2", path = "../../vorago-shared-hal", features = ["vor1x"] }
|
||||
fugit = "0.3"
|
||||
thiserror = { version = "2", default-features = false }
|
||||
va108xx = { version = "0.6", path = "../va108xx", default-features = false, features = ["critical-section"] }
|
||||
defmt = { version = "1", optional = true }
|
||||
@@ -28,14 +28,6 @@ default = ["rt"]
|
||||
rt = ["va108xx/rt"]
|
||||
defmt = ["dep:defmt", "vorago-shared-hal/defmt", "va108xx/defmt"]
|
||||
|
||||
# Embassy time features
|
||||
_irqs-in-lib = []
|
||||
# This determines the reserved interrupt functions for the embassy time drivers. Only one
|
||||
# is allowed to be selected!
|
||||
embassy-oc30-oc31 = ["_irqs-in-lib"]
|
||||
embassy-oc29-oc30 = ["_irqs-in-lib"]
|
||||
embassy-oc28-oc29 = ["_irqs-in-lib"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
targets = ["thumbv6m-none-eabi"]
|
||||
|
||||
@@ -29,11 +29,9 @@ pub mod time;
|
||||
pub mod timer;
|
||||
pub mod uart;
|
||||
|
||||
pub mod embassy_time;
|
||||
|
||||
pub use vorago_shared_hal::{
|
||||
FunctionSelect, InterruptConfig, PeripheralSelect, disable_nvic_interrupt,
|
||||
enable_nvic_interrupt,
|
||||
disable_nvic_interrupt, enable_nvic_interrupt, FunctionSelect, InterruptConfig,
|
||||
PeripheralSelect,
|
||||
};
|
||||
|
||||
/// This is the NONE destination reigster value for the IRQSEL peripheral.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vorago-reb1"
|
||||
version = "0.10.0"
|
||||
version = "0.9.0"
|
||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||
edition = "2021"
|
||||
description = "Board Support Crate for the Vorago REB1 development board"
|
||||
@@ -11,20 +11,20 @@ keywords = ["no-std", "reb1", "cortex-m", "vorago", "va108xx"]
|
||||
categories = ["aerospace", "embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-m = { version = "0.7" }
|
||||
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7"
|
||||
embedded-hal = "1"
|
||||
nb = "1"
|
||||
bitbybit = "2"
|
||||
bitbybit = "1.3"
|
||||
arbitrary-int = "2"
|
||||
max116xx-10bit = "0.3"
|
||||
|
||||
va108xx-hal = { version = "0.13", path = "../va108xx-hal", features = ["rt"] }
|
||||
va108xx-hal = { version = "0.12", path = "../va108xx-hal", features = ["rt"] }
|
||||
|
||||
[features]
|
||||
rt = ["va108xx-hal/rt"]
|
||||
|
||||
[dev-dependencies]
|
||||
cortex-m-rt = "0.7"
|
||||
panic-halt = "1"
|
||||
nb = "1"
|
||||
rtt-target = "0.6"
|
||||
|
||||
@@ -270,37 +270,11 @@ fn boot_app(app_sel: AppSel, cp: &cortex_m::Peripherals) -> ! {
|
||||
cortex_m::asm::isb();
|
||||
unsafe {
|
||||
if app_sel == AppSel::A {
|
||||
cp.SCB.vtor.write(APP_A_START_ADDR);
|
||||
cortex_m::asm::bootload(APP_A_START_ADDR as *const u32);
|
||||
} else {
|
||||
cp.SCB.vtor.write(APP_B_START_ADDR);
|
||||
cortex_m::asm::bootload(APP_B_START_ADDR as *const u32);
|
||||
}
|
||||
}
|
||||
cortex_m::asm::dsb();
|
||||
cortex_m::asm::isb();
|
||||
vector_reset();
|
||||
}
|
||||
|
||||
pub fn vector_reset() -> ! {
|
||||
unsafe {
|
||||
// Set R0 to VTOR address (0xE000ED08)
|
||||
let vtor_address: u32 = 0xE000ED08;
|
||||
|
||||
// Load VTOR
|
||||
let vtor: u32 = *(vtor_address as *const u32);
|
||||
|
||||
// Load initial MSP value
|
||||
let initial_msp: u32 = *(vtor as *const u32);
|
||||
|
||||
// Set SP value (assume MSP is selected)
|
||||
core::arch::asm!("mov sp, {0}", in(reg) initial_msp);
|
||||
|
||||
// Load reset vector
|
||||
let reset_vector: u32 = *((vtor + 4) as *const u32);
|
||||
|
||||
// Branch to reset handler
|
||||
core::arch::asm!("bx {0}", in(reg) reset_vector);
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn setup_edac(syscfg: &mut pac::Sysconfig) {
|
||||
|
||||
@@ -41,7 +41,7 @@ mod app {
|
||||
.xtal_n_clk_with_src_freq(EXTCLK_FREQ)
|
||||
.freeze()
|
||||
.unwrap();
|
||||
Mono::start(cx.core.SYST, clocks.sysclk().to_raw());
|
||||
Mono::start(cx.core.SYST, clocks.sysclk().raw());
|
||||
let pinsg = PinsG::new(cx.device.portg);
|
||||
let led = Output::new(pinsg.pg5, PinState::Low);
|
||||
blinky::spawn().ok();
|
||||
|
||||
@@ -40,7 +40,7 @@ fn main() -> ! {
|
||||
.freeze()
|
||||
.unwrap();
|
||||
enable_and_init_irq_router();
|
||||
let mut delay = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().to_raw());
|
||||
let mut delay = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().raw());
|
||||
|
||||
let mut last_interrupt_counter = 0;
|
||||
let mut wdt_ctrl = Wdt::start(dp.watch_dog, &clocks, WDT_ROLLOVER_MS);
|
||||
|
||||
@@ -10,7 +10,6 @@ defmt-rtt = "1"
|
||||
defmt = "1"
|
||||
panic-probe = { version = "1", features = ["defmt"] }
|
||||
static_cell = "2"
|
||||
fugit = "0.4"
|
||||
ringbuf = { version = "0.4", default-features = false }
|
||||
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
|
||||
satrs = { version = "0.3.0-alpha.3", default-features = false, features = ["defmt"] }
|
||||
|
||||
@@ -97,12 +97,12 @@ mod app {
|
||||
use arbitrary_int::{u11, u14};
|
||||
use cortex_m::asm;
|
||||
use embedded_io::Write;
|
||||
use rtic_monotonics::{fugit::ExtU32, Monotonic};
|
||||
// Import panic provider.
|
||||
use panic_probe as _;
|
||||
// Import logger.
|
||||
use defmt_rtt as _;
|
||||
use rtic::Mutex;
|
||||
use rtic_monotonics::systick::prelude::*;
|
||||
use satrs::pus::verification::VerificationReportCreator;
|
||||
use satrs::spacepackets::ecss::PusServiceId;
|
||||
use satrs::spacepackets::ecss::{
|
||||
@@ -116,6 +116,7 @@ mod app {
|
||||
nvm::Nvm,
|
||||
pac,
|
||||
pins::PinsG,
|
||||
prelude::*,
|
||||
uart::{self, Uart},
|
||||
};
|
||||
|
||||
@@ -170,7 +171,7 @@ mod app {
|
||||
let clock_config = uart::ClockConfig::calculate_with_clocks(
|
||||
uart::Bank::Uart0,
|
||||
&clocks,
|
||||
fugit::HertzU32::from_raw(UART_BAUDRATE),
|
||||
UART_BAUDRATE.Hz(),
|
||||
uart::BaudMode::_16,
|
||||
);
|
||||
let uart_config = uart::Config::new_with_clock_config(clock_config);
|
||||
@@ -194,7 +195,7 @@ mod app {
|
||||
.init(StaticRb::<usize, SIZES_RB_SIZE_TC>::default())
|
||||
.split_ref();
|
||||
|
||||
Mono::start(cx.core.SYST, clocks.sysclk().to_raw());
|
||||
Mono::start(cx.core.SYST, clocks.sysclk().raw());
|
||||
CLOCKS.set(clocks).unwrap();
|
||||
|
||||
let mut rx = rx.into_rx_with_irq();
|
||||
|
||||
@@ -11,7 +11,7 @@ keywords = ["no-std", "hal", "cortex-m", "vorago", "va416xx"]
|
||||
categories = ["aerospace", "embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
vorago-shared-hal = { version = "0.3", path = "../../vorago-shared-hal", features = ["vor4x"] }
|
||||
vorago-shared-hal = { version = "0.2", path = "../../vorago-shared-hal", features = ["vor4x"] }
|
||||
va416xx-hal = { version = "0.6", path = "../va416xx-hal" }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -15,7 +15,7 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
va416xx = { version = "0.5", path = "../va416xx", features = ["critical-section"], default-features = false }
|
||||
derive-mmio = "0.6.1"
|
||||
static_assertions = "1.1"
|
||||
vorago-shared-hal = { version = "0.3", path = "../../vorago-shared-hal", features = ["vor4x"] }
|
||||
vorago-shared-hal = { version = "0.2", path = "../../vorago-shared-hal", features = ["vor4x"] }
|
||||
|
||||
libm = "0.2"
|
||||
nb = "1"
|
||||
@@ -24,7 +24,7 @@ num_enum = { version = "0.7", default-features = false }
|
||||
bitflags = "2"
|
||||
bitbybit = "2"
|
||||
arbitrary-int = "2"
|
||||
fugit = "0.4"
|
||||
fugit = "0.3"
|
||||
embedded-can = "0.4"
|
||||
embassy-sync = "0.8"
|
||||
thiserror = { version = "2", default-features = false }
|
||||
|
||||
@@ -150,19 +150,18 @@ impl ClockConfig {
|
||||
tseg2: u8,
|
||||
sjw: u8,
|
||||
) -> Result<ClockConfig, ClockConfigError> {
|
||||
if bitrate.to_raw() == 0 {
|
||||
if bitrate.raw() == 0 {
|
||||
return Err(ClockConfigError::BitrateIsZero);
|
||||
}
|
||||
let nominal_bit_time = 1 + tseg1 as u32 + tseg2 as u32;
|
||||
let prescaler = roundf(
|
||||
clocks.apb1().to_raw() as f32 / (bitrate.to_raw() as f32 * nominal_bit_time as f32),
|
||||
) as u32;
|
||||
let prescaler =
|
||||
roundf(clocks.apb1().raw() as f32 / (bitrate.raw() as f32 * nominal_bit_time as f32))
|
||||
as u32;
|
||||
if !(PRESCALER_MIN as u32..=PRESCALER_MAX as u32).contains(&prescaler) {
|
||||
return Err(ClockConfigError::CanNotFindPrescaler);
|
||||
}
|
||||
|
||||
let actual_bitrate =
|
||||
(clocks.apb1().to_raw() as f32) / (prescaler * nominal_bit_time) as f32;
|
||||
let actual_bitrate = (clocks.apb1().raw() as f32) / (prescaler * nominal_bit_time) as f32;
|
||||
let bitrate_deviation = calculate_bitrate_deviation(actual_bitrate, bitrate);
|
||||
if bitrate_deviation > MAX_BITRATE_DEVIATION {
|
||||
return Err(ClockConfigError::BitrateErrorTooLarge);
|
||||
@@ -270,17 +269,17 @@ pub const fn calculate_nominal_bit_time(
|
||||
target_bitrate: Hertz,
|
||||
prescaler: u8,
|
||||
) -> u32 {
|
||||
apb1_clock.to_raw() / (target_bitrate.to_raw() * prescaler as u32)
|
||||
apb1_clock.raw() / (target_bitrate.raw() * prescaler as u32)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn calculate_actual_bitrate(apb1_clock: Hertz, prescaler: u8, nom_bit_time: u32) -> f32 {
|
||||
apb1_clock.to_raw() as f32 / (prescaler as u32 * nom_bit_time) as f32
|
||||
apb1_clock.raw() as f32 / (prescaler as u32 * nom_bit_time) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn calculate_bitrate_deviation(actual_bitrate: f32, target_bitrate: Hertz) -> f32 {
|
||||
(actual_bitrate - target_bitrate.to_raw() as f32).abs() / target_bitrate.to_raw() as f32
|
||||
(actual_bitrate - target_bitrate.raw() as f32).abs() / target_bitrate.raw() as f32
|
||||
}
|
||||
|
||||
pub trait CanInstance {
|
||||
|
||||
@@ -94,9 +94,9 @@ pub struct PllConfig {
|
||||
pub const fn clock_after_division(clk: Hertz, div_sel: ClockDivisorSelect) -> Hertz {
|
||||
match div_sel {
|
||||
ClockDivisorSelect::Div1 => clk,
|
||||
ClockDivisorSelect::Div2 => Hertz::from_raw(clk.to_raw() / 2),
|
||||
ClockDivisorSelect::Div4 => Hertz::from_raw(clk.to_raw() / 4),
|
||||
ClockDivisorSelect::Div8 => Hertz::from_raw(clk.to_raw() / 8),
|
||||
ClockDivisorSelect::Div2 => Hertz::from_raw(clk.raw() / 2),
|
||||
ClockDivisorSelect::Div4 => Hertz::from_raw(clk.raw() / 4),
|
||||
ClockDivisorSelect::Div8 => Hertz::from_raw(clk.raw() / 8),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ impl ClockConfigurator {
|
||||
// ADC clock (must be 2-12.5 MHz)
|
||||
// NOTE: Not using divide by 1 or /2 ratio in REVA silicon because of triggering issue
|
||||
// For this reason, keep SYSCLK above 8MHz to have the ADC /4 ratio in range)
|
||||
if final_sysclk.to_raw() <= ADC_MAX_CLK.to_raw() * 4 {
|
||||
if final_sysclk.raw() <= ADC_MAX_CLK.raw() * 4 {
|
||||
self.clkgen.ctrl1().modify(|_, w| unsafe {
|
||||
w.adc_clk_div_sel().bits(AdcClockDivisorSelect::Div4 as u8)
|
||||
});
|
||||
|
||||
@@ -58,7 +58,7 @@ impl Wdt {
|
||||
|
||||
#[inline]
|
||||
pub fn set_freq(&mut self, freq_ms: u32) {
|
||||
let counter = (self.clock_freq.to_raw() / 1000) * freq_ms;
|
||||
let counter = (self.clock_freq.raw() / 1000) * freq_ms;
|
||||
self.wdt.wdogload().write(|w| unsafe { w.bits(counter) });
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [unreleased]
|
||||
|
||||
## [v0.3.0] 2026-05-18
|
||||
|
||||
### Added
|
||||
|
||||
- Add `is_high` and `is_low` for `InputPinAsync`.
|
||||
@@ -18,7 +16,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
### Changed
|
||||
|
||||
- Bumped `fugit` from v0.3 to v0.4
|
||||
- Added `RxWithInterrupt::steal`.
|
||||
- Renamed UART `Data` register `value` field to `data`
|
||||
- Improved type level support for resource management for SPI, PWM, UART.
|
||||
@@ -29,7 +26,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
### Fixed
|
||||
|
||||
- `Pull::Up` and `Pull::High` were inverted.
|
||||
- Removed HW CS pin provider implementation for PA23, PA22 and PA21, which are multi HW CS pins.
|
||||
- Added missing `AnyPin` trait impl for Multi HW CS pins.
|
||||
- Expose inner `Input` pin for `InputPinAsync`.
|
||||
@@ -57,7 +53,6 @@ Renamed to `vorago-shared-hal`
|
||||
|
||||
Init commit.
|
||||
|
||||
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/vorago-rs/vorago-shared-hal/compare/v0.3.0...HEAD
|
||||
[v0.3.0]: https://egit.irs.uni-stuttgart.de/rust/vorago-rs/src/tag/vorago-shared-hal-v0.3.0
|
||||
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/vorago-shared-hal/compare/v0.2.0...HEAD
|
||||
[v0.2.0]: https://egit.irs.uni-stuttgart.de/rust/vorago-shared-hal/compare/v0.1.0...v0.2.0
|
||||
[v0.1.0]: https://egit.irs.uni-stuttgart.de/rust/vorago-shared-hal/src/tag/v0.1.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vorago-shared-hal"
|
||||
version = "0.3.0"
|
||||
version = "0.2.0"
|
||||
description = "Peripheral HAL components shared between Vorago families"
|
||||
edition = "2024"
|
||||
homepage = "https://egit.irs.uni-stuttgart.de/rust/vorago-rs"
|
||||
@@ -25,7 +25,7 @@ embedded-io-async = "0.7"
|
||||
raw-slicee = "0.1"
|
||||
thiserror = { version = "2", default-features = false }
|
||||
paste = "1"
|
||||
fugit = "0.4"
|
||||
fugit = "0.3"
|
||||
defmt = { version = "1", optional = true }
|
||||
va108xx = { version = "0.6", path = "../va108xx/va108xx", default-features = false, optional = true }
|
||||
va416xx = { version = "0.5", path = "../va416xx/va416xx", default-features = false, optional = true }
|
||||
|
||||
@@ -79,9 +79,7 @@ impl TimerDriver {
|
||||
let mut timekeeper_reg_block = unsafe { TimekeeperTim::ID.steal_regs() };
|
||||
let mut alarm_tim_reg_block = unsafe { AlarmTim::ID.steal_regs() };
|
||||
// Initiate scale value here. This is required to convert timer ticks back to a timestamp.
|
||||
SCALE
|
||||
.set((sysclk.to_raw() / TICK_HZ as u32) as u64)
|
||||
.unwrap();
|
||||
SCALE.set((sysclk.raw() / TICK_HZ as u32) as u64).unwrap();
|
||||
timekeeper_reg_block.write_reset_value(u32::MAX);
|
||||
// Decrementing counter.
|
||||
timekeeper_reg_block.write_count_value(u32::MAX);
|
||||
@@ -139,7 +137,7 @@ impl TimerDriver {
|
||||
// Initiate scale value here. This is required to convert timer ticks back to a timestamp.
|
||||
|
||||
SCALE
|
||||
.set((TimekeeperTim::clock(clocks).to_raw() / TICK_HZ as u32) as u64)
|
||||
.set((TimekeeperTim::clock(clocks).raw() / TICK_HZ as u32) as u64)
|
||||
.unwrap();
|
||||
timekeeper_regs.write_reset_value(u32::MAX);
|
||||
// Decrementing counter.
|
||||
|
||||
@@ -149,12 +149,12 @@ fn calc_clk_div_generic(
|
||||
speed_mode: I2cSpeed,
|
||||
) -> Result<u8, ClockTooSlowForFastI2cError> {
|
||||
if speed_mode == I2cSpeed::Regular100khz {
|
||||
Ok(((ref_clk.to_raw() / CLK_100K.to_raw() / 20) - 1) as u8)
|
||||
Ok(((ref_clk.raw() / CLK_100K.raw() / 20) - 1) as u8)
|
||||
} else {
|
||||
if ref_clk.to_raw() < MIN_CLK_400K.to_raw() {
|
||||
if ref_clk.raw() < MIN_CLK_400K.raw() {
|
||||
return Err(ClockTooSlowForFastI2cError);
|
||||
}
|
||||
Ok(((ref_clk.to_raw() / CLK_400K.to_raw() / 25) - 1) as u8)
|
||||
Ok(((ref_clk.raw() / CLK_400K.raw() / 25) - 1) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ pub enum FilterClockSelect {
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Pull {
|
||||
Down = 0,
|
||||
Up = 1,
|
||||
Up = 0,
|
||||
Down = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
|
||||
@@ -164,10 +164,10 @@ impl<Mode> PwmPin<Mode> {
|
||||
pub fn set_period(&mut self, period: impl Into<Hertz>) {
|
||||
self.current_period = period.into();
|
||||
// Avoid division by 0
|
||||
if self.current_period.to_raw() == 0 {
|
||||
if self.current_period.raw() == 0 {
|
||||
return;
|
||||
}
|
||||
self.current_rst_val = self.ref_clk.to_raw() / self.current_period.to_raw();
|
||||
self.current_rst_val = self.ref_clk.raw() / self.current_period.raw();
|
||||
self.regs.write_reset_value(self.current_rst_val);
|
||||
}
|
||||
|
||||
|
||||
@@ -499,11 +499,11 @@ pub fn clk_div_for_target_clock(sys_clk: Hertz, spi_clk: Hertz) -> Option<u16> {
|
||||
}
|
||||
|
||||
// Step 1: Calculate raw divider.
|
||||
let raw_div = sys_clk.to_raw() / spi_clk.to_raw();
|
||||
let remainder = sys_clk.to_raw() % spi_clk.to_raw();
|
||||
let raw_div = sys_clk.raw() / spi_clk.raw();
|
||||
let remainder = sys_clk.raw() % spi_clk.raw();
|
||||
|
||||
// Step 2: Round up if necessary.
|
||||
let mut rounded_div = if remainder * 2 >= spi_clk.to_raw() {
|
||||
let mut rounded_div = if remainder * 2 >= spi_clk.raw() {
|
||||
raw_div + 1
|
||||
} else {
|
||||
raw_div
|
||||
|
||||
@@ -406,7 +406,7 @@ impl CountdownTimer {
|
||||
pub fn load(&mut self, timeout: impl Into<Hertz>) {
|
||||
self.disable();
|
||||
self.curr_freq = timeout.into();
|
||||
self.rst_val = self.ref_clk.to_raw() / self.curr_freq.to_raw();
|
||||
self.rst_val = self.ref_clk.raw() / self.curr_freq.raw();
|
||||
self.set_reload(self.rst_val);
|
||||
self.set_count(self.rst_val);
|
||||
}
|
||||
@@ -497,7 +497,7 @@ impl CountdownTimer {
|
||||
//
|
||||
impl embedded_hal::delay::DelayNs for CountdownTimer {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
let ticks = (u64::from(ns)) * (u64::from(self.ref_clk.to_raw())) / 1_000_000_000;
|
||||
let ticks = (u64::from(ns)) * (u64::from(self.ref_clk.raw())) / 1_000_000_000;
|
||||
|
||||
let full_cycles = ticks >> 32;
|
||||
let mut last_count;
|
||||
|
||||
@@ -161,11 +161,11 @@ impl ClockConfig {
|
||||
// This is the calculation: (64.0 * (x - integer_part as f32) + 0.5) as u32 without floating
|
||||
// point calculations.
|
||||
let multiplier = baud_mode.multiplier();
|
||||
let frac = ((ref_clk.to_raw() % (baudrate.to_raw() * multiplier)) * 64
|
||||
+ (baudrate.to_raw() * (multiplier / 2)))
|
||||
/ (baudrate.to_raw() * multiplier);
|
||||
let frac = ((ref_clk.raw() % (baudrate.raw() * multiplier)) * 64
|
||||
+ (baudrate.raw() * (multiplier / 2)))
|
||||
/ (baudrate.raw() * multiplier);
|
||||
// Calculations here are derived from chapter 4.8.5 (p.79) of the datasheet.
|
||||
let integer_div = ref_clk.to_raw() / (baudrate.to_raw() * multiplier);
|
||||
let integer_div = ref_clk.raw() / (baudrate.raw() * multiplier);
|
||||
Self {
|
||||
frac: u6::new(frac as u8),
|
||||
div: u18::new(integer_div),
|
||||
|
||||
Reference in New Issue
Block a user