Rework library structure

Changed:

- Move most library components to new [`vorago-shared-periphs`](https://egit.irs.uni-stuttgart.de/rust/vorago-shared-periphs)
  which is mostly re-exported in this crate.
- All HAL API constructors now have a more consistent argument order: PAC structures and resource
  management structures first, then clock configuration, then any other configuration.
- Overhaul and simplification of several HAL APIs. The system configuration and IRQ router
  peripheral instance generally does not need to be passed to HAL API anymore.
- All HAL drivers are now type erased. The constructors will still expect and consume the PAC
  singleton component for resource management purposes, but are not cached anymore.
- Refactoring of GPIO library to be more inline with embassy GPIO API.

Added:

- I2C clock timeout feature support.
This commit is contained in:
2025-04-12 17:01:53 +02:00
parent 5b2ded51f9
commit 1825cc1cdb
63 changed files with 718 additions and 9119 deletions

View File

@ -7,17 +7,21 @@ edition = "2021"
cortex-m = {version = "0.7", features = ["critical-section-single-core"]}
cortex-m-rt = "0.7"
panic-halt = "1"
panic-rtt-target = "0.2"
critical-section = "1"
rtt-target = "0.6"
defmt-rtt = "0.4"
defmt = "1"
panic-probe = { version = "1", features = ["defmt"] }
embedded-hal = "1"
embedded-hal-nb = "1"
embedded-io = "0.6"
cortex-m-semihosting = "0.5.0"
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }
[dependencies.va108xx-hal]
version = "0.11"
path = "../../va108xx-hal"
features = ["defmt"]
[dependencies.vorago-reb1]
path = "../../vorago-reb1"
version = "0.8"

View File

@ -10,52 +10,37 @@ use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_halt as _;
use va108xx_hal::{
gpio::PinsA,
pac::{self, interrupt},
gpio::{Output, PinState},
pac::{self},
pins::PinsA,
prelude::*,
timer::DelayMs,
timer::{default_ms_irq_handler, set_up_ms_tick, CountdownTimer},
InterruptConfig,
timer::CountdownTimer,
};
#[entry]
fn main() -> ! {
let mut dp = pac::Peripherals::take().unwrap();
let mut delay_ms = DelayMs::new(set_up_ms_tick(
InterruptConfig::new(interrupt::OC0, true, true),
&mut dp.sysconfig,
Some(&mut dp.irqsel),
50.MHz(),
dp.tim0,
))
.unwrap();
let mut delay_tim1 = CountdownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim1);
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
let mut led1 = porta.pa10.into_readable_push_pull_output();
let mut led2 = porta.pa7.into_readable_push_pull_output();
let mut led3 = porta.pa6.into_readable_push_pull_output();
let dp = pac::Peripherals::take().unwrap();
let mut delay = CountdownTimer::new(dp.tim1, 50.MHz());
let porta = PinsA::new(dp.porta);
let mut led1 = Output::new(porta.pa10, PinState::Low);
let mut led2 = Output::new(porta.pa7, PinState::Low);
let mut led3 = Output::new(porta.pa6, PinState::Low);
for _ in 0..10 {
led1.set_low();
led2.set_low();
led3.set_low();
delay_ms.delay_ms(200);
delay.delay_ms(200);
led1.set_high();
led2.set_high();
led3.set_high();
delay_tim1.delay_ms(200);
delay.delay_ms(200);
}
loop {
led1.toggle();
delay_ms.delay_ms(200);
delay.delay_ms(200);
led2.toggle();
delay_tim1.delay_ms(200);
delay.delay_ms(200);
led3.toggle();
delay_ms.delay_ms(200);
delay.delay_ms(200);
}
}
#[interrupt]
#[allow(non_snake_case)]
fn OC0() {
default_ms_irq_handler()
}

View File

@ -6,92 +6,68 @@
#![no_std]
#![allow(non_snake_case)]
use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
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 va108xx_hal::{
pac::{self, interrupt},
prelude::*,
timer::{
default_ms_irq_handler, set_up_ms_delay_provider, CascadeCtrl, CascadeSource,
CountdownTimer, Event, InterruptConfig,
},
timer::{CascadeControl, CascadeSelect, CascadeSource, CountdownTimer, InterruptConfig},
};
static CSD_TGT_1: Mutex<RefCell<Option<CountdownTimer<pac::Tim4>>>> =
Mutex::new(RefCell::new(None));
static CSD_TGT_2: Mutex<RefCell<Option<CountdownTimer<pac::Tim5>>>> =
Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx Cascade example application--");
defmt::println!("-- VA108xx Cascade example application--");
let mut dp = pac::Peripherals::take().unwrap();
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
let dp = pac::Peripherals::take().unwrap();
let mut delay = CountdownTimer::new(dp.tim0, 50.MHz());
// Will be started periodically to trigger a cascade
let mut cascade_triggerer =
CountdownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim3).auto_disable(true);
cascade_triggerer.listen(
Event::TimeOut,
InterruptConfig::new(pac::Interrupt::OC1, true, false),
Some(&mut dp.irqsel),
Some(&mut dp.sysconfig),
);
let mut cascade_triggerer = CountdownTimer::new(dp.tim3, 50.MHz());
cascade_triggerer.auto_disable(true);
cascade_triggerer.enable_interrupt(InterruptConfig::new(pac::Interrupt::OC1, true, false));
cascade_triggerer.enable();
// First target for cascade
let mut cascade_target_1 =
CountdownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim4).auto_deactivate(true);
let mut cascade_target_1 = CountdownTimer::new(dp.tim4, 50.MHz());
cascade_target_1.auto_deactivate(true);
cascade_target_1
.cascade_0_source(CascadeSource::Tim(3))
.expect("Configuring cascade source for TIM4 failed");
let mut csd_cfg = CascadeCtrl {
enb_start_src_csd0: true,
.cascade_source(CascadeSelect::Csd0, CascadeSource::Tim(3))
.unwrap();
let mut csd_cfg = CascadeControl {
enable_src_0: true,
trigger_mode_0: true,
..Default::default()
};
// Use trigger mode here
csd_cfg.trg_csd0 = true;
cascade_target_1.cascade_control(csd_cfg);
// Normally it should already be sufficient to activate IRQ in the CTRL
// register but a full interrupt is use here to display print output when
// the timer expires
cascade_target_1.listen(
Event::TimeOut,
InterruptConfig::new(pac::Interrupt::OC2, true, false),
Some(&mut dp.irqsel),
Some(&mut dp.sysconfig),
);
cascade_target_1.enable_interrupt(InterruptConfig::new(pac::Interrupt::OC2, true, false));
// The counter will only activate when the cascade signal is coming in so
// it is okay to call start here to set the reset value
cascade_target_1.start(1.Hz());
// Activated by first cascade target
let mut cascade_target_2 =
CountdownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim5).auto_deactivate(true);
let mut cascade_target_2 = CountdownTimer::new(dp.tim5, 50.MHz());
cascade_target_2.auto_deactivate(true);
// Set TIM4 as cascade source
cascade_target_2
.cascade_1_source(CascadeSource::Tim(4))
.expect("Configuring cascade source for TIM5 failed");
.cascade_source(CascadeSelect::Csd1, CascadeSource::Tim(4))
.unwrap();
csd_cfg = CascadeCtrl::default();
csd_cfg.enb_start_src_csd1 = true;
csd_cfg = CascadeControl::default();
csd_cfg.enable_src_1 = true;
// Use trigger mode here
csd_cfg.trg_csd1 = true;
csd_cfg.trigger_mode_1 = true;
cascade_target_2.cascade_control(csd_cfg);
// Normally it should already be sufficient to activate IRQ in the CTRL
// register but a full interrupt is use here to display print output when
// the timer expires
cascade_target_2.listen(
Event::TimeOut,
InterruptConfig::new(pac::Interrupt::OC3, true, false),
Some(&mut dp.irqsel),
Some(&mut dp.sysconfig),
);
cascade_target_2.enable_interrupt(InterruptConfig::new(pac::Interrupt::OC3, true, false));
// The counter will only activate when the cascade signal is coming in so
// it is okay to call start here to set the reset value
cascade_target_2.start(1.Hz());
@ -103,40 +79,31 @@ fn main() -> ! {
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC2);
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC3);
}
// Make both cascade targets accessible from the IRQ handler with the Mutex dance
cortex_m::interrupt::free(|cs| {
CSD_TGT_1.borrow(cs).replace(Some(cascade_target_1));
CSD_TGT_2.borrow(cs).replace(Some(cascade_target_2));
});
loop {
rprintln!("-- Triggering cascade in 0.5 seconds --");
defmt::info!("-- Triggering cascade in 0.5 seconds --");
cascade_triggerer.start(2.Hz());
delay.delay_ms(5000);
}
}
#[interrupt]
fn OC0() {
default_ms_irq_handler()
}
#[interrupt]
fn OC1() {
static mut IDX: u32 = 0;
rprintln!("{}: Cascade triggered timed out", &IDX);
defmt::info!("{}: Cascade trigger timed out", &IDX);
*IDX += 1;
}
#[interrupt]
fn OC2() {
static mut IDX: u32 = 0;
rprintln!("{}: First cascade target timed out", &IDX);
defmt::info!("{}: First cascade target timed out", &IDX);
*IDX += 1;
}
#[interrupt]
fn OC3() {
static mut IDX: u32 = 0;
rprintln!("{}: Second cascade target timed out", &IDX);
defmt::info!("{}: Second cascade target timed out", &IDX);
*IDX += 1;
}

View File

@ -1,39 +1,36 @@
//! Simple PWM example
//!
//! Outputs a PWM waveform on pin PA3.
#![no_main]
#![no_std]
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 va108xx_hal::{
gpio::PinsA,
pac,
pins::PinsA,
prelude::*,
pwm::{self, get_duty_from_percent, PwmA, PwmB, ReducedPwmPin},
timer::set_up_ms_delay_provider,
pwm::{self, get_duty_from_percent, PwmA, PwmB, PwmPin},
timer::CountdownTimer,
};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx PWM example application--");
let mut dp = pac::Peripherals::take().unwrap();
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
let mut pwm = pwm::PwmPin::new(
&mut dp.sysconfig,
50.MHz(),
(pinsa.pa3.into_funsel_1(), dp.tim3),
10.Hz(),
);
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
defmt::println!("-- VA108xx PWM example application--");
let dp = pac::Peripherals::take().unwrap();
let pinsa = PinsA::new(dp.porta);
let mut pwm = pwm::PwmPin::new(pinsa.pa3, dp.tim3, 50.MHz(), 10.Hz()).unwrap();
let mut delay = CountdownTimer::new(dp.tim0, 50.MHz());
let mut current_duty_cycle = 0.0;
pwm.set_duty_cycle(get_duty_from_percent(current_duty_cycle))
.unwrap();
pwm.enable();
// Delete type information, increased code readibility for the rest of the code
let mut reduced_pin = ReducedPwmPin::from(pwm);
loop {
let mut counter = 0;
// Increase duty cycle continuously
@ -42,11 +39,10 @@ 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
.set_duty_cycle(get_duty_from_percent(current_duty_cycle))
pwm.set_duty_cycle(get_duty_from_percent(current_duty_cycle))
.unwrap();
}
@ -55,7 +51,7 @@ fn main() -> ! {
current_duty_cycle = 0.0;
let mut upper_limit = 1.0;
let mut lower_limit = 0.0;
let mut pwmb: ReducedPwmPin<PwmB> = ReducedPwmPin::from(reduced_pin);
let mut pwmb: PwmPin<PwmB> = PwmPin::from(pwm);
pwmb.set_pwmb_lower_limit(get_duty_from_percent(lower_limit));
pwmb.set_pwmb_upper_limit(get_duty_from_percent(upper_limit));
while lower_limit < 0.5 {
@ -64,9 +60,9 @@ 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);
pwm = PwmPin::<PwmA>::from(pwmb);
}
}

View File

@ -1,20 +0,0 @@
//! Code to test RTT logger functionality
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal as _;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108XX RTT example --");
let mut counter = 0;
loop {
rprintln!("{}: Hello, world!", counter);
counter += 1;
cortex_m::asm::delay(25_000_000);
}
}

View File

@ -1,23 +1,21 @@
//! SPI example application
#![no_main]
#![no_std]
use core::cell::RefCell;
use cortex_m_rt::entry;
use embedded_hal::{
delay::DelayNs,
spi::{Mode, SpiBus, MODE_0},
};
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 va108xx_hal::{
gpio::{PinsA, PinsB},
pac::{self, interrupt},
pac,
pins::{PinsA, PinsB},
prelude::*,
spi::{self, Spi, SpiBase, SpiClkConfig, TransferConfigWithHwcs},
timer::{default_ms_irq_handler, set_up_ms_tick},
InterruptConfig,
spi::{self, configure_pin_as_hw_cs_pin, Spi, SpiClkConfig, TransferConfig},
timer::CountdownTimer,
};
#[derive(PartialEq, Debug)]
@ -43,23 +41,14 @@ const FILL_WORD: u8 = 0x0f;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx SPI example application--");
let mut dp = pac::Peripherals::take().unwrap();
let mut delay = set_up_ms_tick(
InterruptConfig::new(interrupt::OC0, true, true),
&mut dp.sysconfig,
Some(&mut dp.irqsel),
50.MHz(),
dp.tim0,
);
defmt::println!("-- VA108xx SPI example application--");
let dp = pac::Peripherals::take().unwrap();
let mut delay = CountdownTimer::new(dp.tim0, 50.MHz());
let spi_clk_cfg = SpiClkConfig::from_clk(50.MHz(), SPI_SPEED_KHZ.kHz())
.expect("creating SPI clock config failed");
let spia_ref: RefCell<Option<SpiBase<pac::Spia, u8>>> = RefCell::new(None);
let spib_ref: RefCell<Option<SpiBase<pac::Spib, u8>>> = RefCell::new(None);
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
let pinsb = PinsB::new(&mut dp.sysconfig, dp.portb);
let pinsa = PinsA::new(dp.porta);
let pinsb = PinsB::new(dp.portb);
let mut spi_cfg = spi::SpiConfig::default();
if EXAMPLE_SEL == ExampleSelect::Loopback {
@ -67,158 +56,82 @@ fn main() -> ! {
}
// Set up the SPI peripheral
match SPI_BUS_SEL {
let mut spi = match SPI_BUS_SEL {
SpiBusSelect::SpiAPortA => {
let (sck, mosi, miso) = (
pinsa.pa31.into_funsel_1(),
pinsa.pa30.into_funsel_1(),
pinsa.pa29.into_funsel_1(),
);
let mut spia = Spi::new(
&mut dp.sysconfig,
50.MHz(),
dp.spia,
(sck, miso, mosi),
spi_cfg,
);
let (sck, mosi, miso) = (pinsa.pa31, pinsa.pa30, pinsa.pa29);
let mut spia = Spi::new(dp.spia, (sck, miso, mosi), spi_cfg).unwrap();
spia.set_fill_word(FILL_WORD);
spia_ref.borrow_mut().replace(spia.downgrade());
spia
}
SpiBusSelect::SpiAPortB => {
let (sck, mosi, miso) = (
pinsb.pb9.into_funsel_2(),
pinsb.pb8.into_funsel_2(),
pinsb.pb7.into_funsel_2(),
);
let mut spia = Spi::new(
&mut dp.sysconfig,
50.MHz(),
dp.spia,
(sck, miso, mosi),
spi_cfg,
);
let (sck, mosi, miso) = (pinsb.pb9, pinsb.pb8, pinsb.pb7);
let mut spia = Spi::new(dp.spia, (sck, miso, mosi), spi_cfg).unwrap();
spia.set_fill_word(FILL_WORD);
spia_ref.borrow_mut().replace(spia.downgrade());
spia
}
SpiBusSelect::SpiBPortB => {
let (sck, mosi, miso) = (
pinsb.pb5.into_funsel_1(),
pinsb.pb4.into_funsel_1(),
pinsb.pb3.into_funsel_1(),
);
let mut spib = Spi::new(
&mut dp.sysconfig,
50.MHz(),
dp.spib,
(sck, miso, mosi),
spi_cfg,
);
let (sck, mosi, miso) = (pinsb.pb5, pinsb.pb4, pinsb.pb3);
let mut spib = Spi::new(dp.spib, (sck, miso, mosi), spi_cfg).unwrap();
spib.set_fill_word(FILL_WORD);
spib_ref.borrow_mut().replace(spib.downgrade());
spib
}
}
};
// Configure transfer specific properties here
match SPI_BUS_SEL {
SpiBusSelect::SpiAPortA | SpiBusSelect::SpiAPortB => {
if let Some(ref mut spi) = *spia_ref.borrow_mut() {
let transfer_cfg = TransferConfigWithHwcs::new_no_hw_cs(
Some(spi_clk_cfg),
Some(SPI_MODE),
BLOCKMODE,
true,
false,
);
spi.cfg_transfer(&transfer_cfg);
}
let transfer_cfg = TransferConfig {
clk_cfg: Some(spi_clk_cfg),
mode: Some(SPI_MODE),
sod: true,
blockmode: BLOCKMODE,
bmstall: true,
hw_cs: None,
};
spi.cfg_transfer(&transfer_cfg);
}
SpiBusSelect::SpiBPortB => {
if let Some(ref mut spi) = *spib_ref.borrow_mut() {
let hw_cs_pin = pinsb.pb2.into_funsel_1();
let transfer_cfg = TransferConfigWithHwcs::new(
Some(spi_clk_cfg),
Some(SPI_MODE),
Some(hw_cs_pin),
BLOCKMODE,
true,
false,
);
spi.cfg_transfer(&transfer_cfg);
}
let hw_cs_pin = configure_pin_as_hw_cs_pin(pinsb.pb2);
let transfer_cfg = TransferConfig {
clk_cfg: Some(spi_clk_cfg),
mode: Some(SPI_MODE),
sod: false,
blockmode: BLOCKMODE,
bmstall: true,
hw_cs: Some(hw_cs_pin),
};
spi.cfg_transfer(&transfer_cfg);
}
}
// Application logic
loop {
let mut reply_buf: [u8; 8] = [0; 8];
match SPI_BUS_SEL {
SpiBusSelect::SpiAPortA | SpiBusSelect::SpiAPortB => {
if let Some(ref mut spi) = *spia_ref.borrow_mut() {
// Can't really verify correct reply here.
spi.write(&[0x42]).expect("write failed");
// Because of the loopback mode, we should get back the fill word here.
spi.read(&mut reply_buf[0..1]).unwrap();
assert_eq!(reply_buf[0], FILL_WORD);
delay.delay_ms(500_u32);
// Can't really verify correct reply here.
spi.write(&[0x42]).expect("write failed");
// Because of the loopback mode, we should get back the fill word here.
spi.read(&mut reply_buf[0..1]).unwrap();
assert_eq!(reply_buf[0], FILL_WORD);
delay.delay_ms(500_u32);
let tx_buf: [u8; 3] = [0x01, 0x02, 0x03];
spi.transfer(&mut reply_buf[0..3], &tx_buf).unwrap();
assert_eq!(tx_buf, reply_buf[0..3]);
rprintln!(
"Received reply: {}, {}, {}",
reply_buf[0],
reply_buf[1],
reply_buf[2]
);
delay.delay_ms(500_u32);
let tx_buf: [u8; 3] = [0x01, 0x02, 0x03];
spi.transfer(&mut reply_buf[0..3], &tx_buf).unwrap();
assert_eq!(tx_buf, reply_buf[0..3]);
defmt::info!(
"Received reply: {}, {}, {}",
reply_buf[0],
reply_buf[1],
reply_buf[2]
);
delay.delay_ms(500_u32);
let mut tx_rx_buf: [u8; 3] = [0x03, 0x02, 0x01];
spi.transfer_in_place(&mut tx_rx_buf).unwrap();
rprintln!(
"Received reply: {}, {}, {}",
tx_rx_buf[0],
tx_rx_buf[1],
tx_rx_buf[2]
);
assert_eq!(&tx_rx_buf[0..3], &[0x03, 0x02, 0x01]);
}
}
SpiBusSelect::SpiBPortB => {
if let Some(ref mut spi) = *spib_ref.borrow_mut() {
// Can't really verify correct reply here.
spi.write(&[0x42]).expect("write failed");
// Because of the loopback mode, we should get back the fill word here.
spi.read(&mut reply_buf[0..1]).unwrap();
assert_eq!(reply_buf[0], FILL_WORD);
delay.delay_ms(500_u32);
let tx_buf: [u8; 3] = [0x01, 0x02, 0x03];
spi.transfer(&mut reply_buf[0..3], &tx_buf).unwrap();
assert_eq!(tx_buf, reply_buf[0..3]);
rprintln!(
"Received reply: {}, {}, {}",
reply_buf[0],
reply_buf[1],
reply_buf[2]
);
delay.delay_ms(500_u32);
let mut tx_rx_buf: [u8; 3] = [0x03, 0x02, 0x01];
spi.transfer_in_place(&mut tx_rx_buf).unwrap();
rprintln!(
"Received reply: {}, {}, {}",
tx_rx_buf[0],
tx_rx_buf[1],
tx_rx_buf[2]
);
assert_eq!(&tx_rx_buf[0..3], &[0x03, 0x02, 0x01]);
}
}
}
let mut tx_rx_buf: [u8; 3] = [0x03, 0x02, 0x01];
spi.transfer_in_place(&mut tx_rx_buf).unwrap();
defmt::info!(
"Received reply: {}, {}, {}",
tx_rx_buf[0],
tx_rx_buf[1],
tx_rx_buf[2]
);
assert_eq!(&tx_rx_buf[0..3], &[0x03, 0x02, 0x01]);
}
}
#[interrupt]
#[allow(non_snake_case)]
fn OC0() {
default_ms_irq_handler()
}

View File

@ -2,19 +2,19 @@
#![no_main]
#![no_std]
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 embedded_hal::delay::DelayNs;
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use portable_atomic::AtomicU32;
use va108xx_hal::{
clock::{get_sys_clock, set_sys_clock},
pac::{self, interrupt},
prelude::*,
time::Hertz,
timer::{
default_ms_irq_handler, set_up_ms_tick, CountdownTimer, Event, InterruptConfig, MS_COUNTER,
},
timer::{CountdownTimer, InterruptConfig},
};
#[allow(dead_code)]
@ -23,14 +23,15 @@ enum LibType {
Hal,
}
static SEC_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
static MS_COUNTER: AtomicU32 = AtomicU32::new(0);
static SEC_COUNTER: AtomicU32 = AtomicU32::new(0);
#[entry]
fn main() -> ! {
rtt_init_print!();
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let mut delay = CountdownTimer::new(dp.tim2, 50.MHz());
let mut last_ms = 0;
rprintln!("-- Vorago system ticks using timers --");
defmt::info!("-- Vorago system ticks using timers --");
set_sys_clock(50.MHz());
let lib_type = LibType::Hal;
match lib_type {
@ -66,34 +67,24 @@ fn main() -> ! {
}
}
LibType::Hal => {
set_up_ms_tick(
InterruptConfig::new(interrupt::OC0, true, true),
&mut dp.sysconfig,
Some(&mut dp.irqsel),
50.MHz(),
dp.tim0,
);
let mut second_timer =
CountdownTimer::new(&mut dp.sysconfig, get_sys_clock().unwrap(), dp.tim1);
second_timer.listen(
Event::TimeOut,
InterruptConfig::new(interrupt::OC1, true, true),
Some(&mut dp.irqsel),
Some(&mut dp.sysconfig),
);
let mut ms_timer = CountdownTimer::new(dp.tim0, get_sys_clock().unwrap());
ms_timer.enable_interrupt(InterruptConfig::new(interrupt::OC0, true, true));
ms_timer.start(1.kHz());
let mut second_timer = CountdownTimer::new(dp.tim1, get_sys_clock().unwrap());
second_timer.enable_interrupt(InterruptConfig::new(interrupt::OC1, true, true));
second_timer.start(1.Hz());
}
}
loop {
let current_ms = critical_section::with(|cs| MS_COUNTER.borrow(cs).get());
let current_ms = MS_COUNTER.load(portable_atomic::Ordering::Relaxed);
if current_ms - last_ms >= 1000 {
// To prevent drift.
last_ms += 1000;
rprintln!("MS counter: {}", current_ms);
let second = critical_section::with(|cs| SEC_COUNTER.borrow(cs).get());
rprintln!("Second counter: {}", second);
defmt::info!("MS counter: {}", current_ms);
let second = SEC_COUNTER.load(portable_atomic::Ordering::Relaxed);
defmt::info!("Second counter: {}", second);
}
cortex_m::asm::delay(10000);
delay.delay_ms(50);
}
}
@ -107,15 +98,11 @@ fn unmask_irqs() {
#[interrupt]
#[allow(non_snake_case)]
fn OC0() {
default_ms_irq_handler()
MS_COUNTER.fetch_add(1, portable_atomic::Ordering::Relaxed);
}
#[interrupt]
#[allow(non_snake_case)]
fn OC1() {
critical_section::with(|cs| {
let mut sec = SEC_COUNTER.borrow(cs).get();
sec += 1;
SEC_COUNTER.borrow(cs).set(sec);
});
SEC_COUNTER.fetch_add(1, portable_atomic::Ordering::Relaxed);
}

View File

@ -13,27 +13,23 @@
use cortex_m_rt::entry;
use embedded_hal_nb::{nb, serial::Read};
use embedded_io::Write as _;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{gpio::PinsA, pac, prelude::*, uart};
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use va108xx_hal::{pac, pins::PinsA, prelude::*, uart};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx UART example application--");
defmt::println!("-- VA108xx UART example application--");
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let gpioa = PinsA::new(&mut dp.sysconfig, dp.porta);
let tx = gpioa.pa9.into_funsel_2();
let rx = gpioa.pa8.into_funsel_2();
let uart = uart::Uart::new_without_interrupt(
&mut dp.sysconfig,
50.MHz(),
dp.uarta,
(tx, rx),
115200.Hz(),
);
let gpioa = PinsA::new(dp.porta);
let tx = gpioa.pa9;
let rx = gpioa.pa8;
let uart =
uart::Uart::new_without_interrupt(dp.uarta, tx, rx, 50.MHz(), 115200.Hz().into()).unwrap();
let (mut tx, mut rx) = uart.split();
writeln!(tx, "Hello World\r").unwrap();

View File

@ -3,7 +3,7 @@
#![no_std]
use cortex_m_rt::entry;
use panic_rtt_target as _;
use panic_probe as _;
use va108xx_hal as _;
#[entry]