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.
- 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-24 14:05:02 +02:00
parent d641f3943f
commit 935ee9dbb1
52 changed files with 602 additions and 9305 deletions

View File

@ -17,20 +17,12 @@ embedded-io = "0.6"
panic-halt = "1"
accelerometer = "0.12"
va416xx-hal = { version = "0.5", features = ["va41630", "defmt"] }
va416xx-hal = { version = "0.5", path = "../../va416xx-hal", features = ["va41630", "defmt"] }
[dependencies.vorago-peb1]
path = "../../vorago-peb1"
optional = true
[dependencies.rtic]
version = "2"
features = ["thumbv7-backend"]
[dependencies.rtic-monotonics]
version = "2"
features = ["cortex-m-systick"]
[features]
default = ["va41630"]
va41630 = ["va416xx-hal/va41630", "has-adc-dac"]

View File

@ -12,8 +12,8 @@ use embedded_hal::delay::DelayNs;
use simple_examples::peb1;
use va416xx_hal::{
adc::{Adc, ChannelSelect, ChannelValue, MultiChannelSelect},
clock::ClockConfigurator,
pac,
prelude::*,
timer::CountdownTimer,
};
@ -24,17 +24,15 @@ const ENABLE_BUF_PRINTOUT: bool = false;
fn main() -> ! {
defmt::println!("VA416xx ADC example");
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
let adc = Adc::new_with_channel_tag(&mut dp.sysconfig, dp.adc, &clocks);
let mut delay_provider = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks);
let adc = Adc::new_with_channel_tag(dp.adc, &clocks);
let mut delay = CountdownTimer::new(dp.tim0, &clocks);
let mut read_buf: [ChannelValue; 8] = [ChannelValue::default(); 8];
loop {
let single_value = adc
@ -70,6 +68,6 @@ fn main() -> ! {
assert_eq!(read_buf[0].channel(), ChannelSelect::AnIn0);
assert_eq!(read_buf[1].channel(), ChannelSelect::AnIn2);
assert_eq!(read_buf[2].channel(), ChannelSelect::TempSensor);
delay_provider.delay_ms(500);
delay.delay_ms(500);
}
}

View File

@ -8,15 +8,19 @@ use panic_probe as _;
use defmt_rtt as _;
use cortex_m_rt::entry;
use va416xx_hal::{gpio::PinsG, pac};
use va416xx_hal::{
gpio::{Output, PinState},
pac,
pins::PinsG,
};
#[entry]
fn main() -> ! {
defmt::println!("VA416xx HAL blinky example");
let mut dp = pac::Peripherals::take().unwrap();
let portg = PinsG::new(&mut dp.sysconfig, dp.portg);
let mut led = portg.pg5.into_readable_push_pull_output();
let dp = pac::Peripherals::take().unwrap();
let portg = PinsG::new(dp.portg);
let mut led = Output::new(portg.pg5, PinState::Low);
loop {
cortex_m::asm::delay(2_000_000);
led.toggle();

View File

@ -10,7 +10,7 @@ use defmt_rtt as _;
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use simple_examples::peb1;
use va416xx_hal::{adc::Adc, dac::Dac, pac, prelude::*, timer::CountdownTimer};
use va416xx_hal::{adc::Adc, clock::ClockConfigurator, dac::Dac, pac, timer::CountdownTimer};
const DAC_INCREMENT: u16 = 256;
@ -30,18 +30,15 @@ const APP_MODE: AppMode = AppMode::DacAndAdc;
fn main() -> ! {
defmt::println!("VA416xx DAC/ADC example");
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
let mut dac = None;
if APP_MODE == AppMode::DacOnly || APP_MODE == AppMode::DacAndAdc {
dac = Some(Dac::new(
&mut dp.sysconfig,
dp.dac0,
va416xx_hal::dac::DacSettling::Apb2Times100,
&clocks,
@ -49,12 +46,12 @@ fn main() -> ! {
}
let mut adc = None;
if APP_MODE == AppMode::AdcOnly || APP_MODE == AppMode::DacAndAdc {
adc = Some(Adc::new(&mut dp.sysconfig, dp.adc, &clocks));
adc = Some(Adc::new(dp.adc, &clocks));
}
let mut delay_provider = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks);
let mut delay_provider = CountdownTimer::new(dp.tim0, &clocks);
let mut current_val = 0;
loop {
if let Some(dac) = &dac {
if let Some(dac) = &mut dac {
defmt::info!("loading DAC with value {}", current_val);
dac.load_and_trigger_manually(current_val)
.expect("loading DAC value failed");

View File

@ -6,6 +6,7 @@
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use va416xx_hal::clock::ClockConfigurator;
use core::cell::Cell;
@ -15,11 +16,8 @@ use embedded_hal::delay::DelayNs;
use simple_examples::peb1;
use va416xx_hal::dma::{Dma, DmaCfg, DmaChannel, DmaCtrlBlock};
use va416xx_hal::irq_router::enable_and_init_irq_router;
use va416xx_hal::pac::{self, interrupt};
use va416xx_hal::timer::CountdownTimer;
use va416xx_hal::{
pac::{self, interrupt},
prelude::*,
};
static DMA_DONE_FLAG: Mutex<Cell<bool>> = Mutex::new(Cell::new(false));
static DMA_ACTIVE_FLAG: Mutex<Cell<bool>> = Mutex::new(Cell::new(false));
@ -40,26 +38,23 @@ static mut DMA_DEST_BUF: [u16; 36] = [0; 36];
fn main() -> ! {
defmt::println!("VA416xx DMA example");
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
enable_and_init_irq_router(&mut dp.sysconfig, &dp.irq_router);
enable_and_init_irq_router();
// Safety: The DMA control block has an alignment rule of 128 and we constructed it directly
// statically.
let dma = Dma::new(
&mut dp.sysconfig,
dp.dma,
DmaCfg::default(),
core::ptr::addr_of_mut!(DMA_CTRL_BLOCK),
)
.expect("error creating DMA");
let (mut dma0, _, _, _) = dma.split();
let mut delay_ms = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks);
let mut delay_ms = CountdownTimer::new(dp.tim0, &clocks);
let mut src_buf_8_bit: [u8; 65] = [0; 65];
let mut dest_buf_8_bit: [u8; 65] = [0; 65];
let mut src_buf_32_bit: [u32; 17] = [0; 17];
@ -90,7 +85,7 @@ fn transfer_example_8_bit(
src_buf: &mut [u8; 65],
dest_buf: &mut [u8; 65],
dma0: &mut DmaChannel,
delay_ms: &mut CountdownTimer<pac::Tim0>,
delay: &mut CountdownTimer,
) {
(0..64).for_each(|i| {
src_buf[i] = i as u8;
@ -132,7 +127,7 @@ fn transfer_example_8_bit(
defmt::info!("8-bit transfer done");
break;
}
delay_ms.delay_ms(1);
delay.delay_ms(1);
}
(0..64).for_each(|i| {
assert_eq!(dest_buf[i], i as u8);
@ -142,7 +137,7 @@ fn transfer_example_8_bit(
dest_buf.fill(0);
}
fn transfer_example_16_bit(dma0: &mut DmaChannel, delay_ms: &mut CountdownTimer<pac::Tim0>) {
fn transfer_example_16_bit(dma0: &mut DmaChannel, delay_ms: &mut CountdownTimer) {
let dest_buf_ref = unsafe { &mut *core::ptr::addr_of_mut!(DMA_DEST_BUF[0..33]) };
unsafe {
// Set values scaled from 0 to 65535 to verify this is really a 16-bit transfer.
@ -207,7 +202,7 @@ fn transfer_example_32_bit(
src_buf: &mut [u32; 17],
dest_buf: &mut [u32; 17],
dma0: &mut DmaChannel,
delay_ms: &mut CountdownTimer<pac::Tim0>,
delay_ms: &mut CountdownTimer,
) {
// Set values scaled from 0 to 65535 to verify this is really a 16-bit transfer.
(0..16).for_each(|i| {

View File

@ -12,10 +12,11 @@ use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use simple_examples::peb1;
use va416xx_hal::{
clock::ClockConfigurator,
i2c,
pac::{self},
prelude::*,
pwm::CountdownTimer,
timer::CountdownTimer,
};
use vorago_peb1::lis2dh12::{self, detect_i2c_addr, FullScale, Odr};
@ -31,21 +32,18 @@ fn main() -> ! {
let mut dp = pac::Peripherals::take().unwrap();
defmt::println!("-- Vorago PEB1 accelerometer example --");
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
let mut i2c_master = i2c::I2cMaster::new(
dp.i2c0,
&mut dp.sysconfig,
i2c::MasterConfig::default(),
&clocks,
i2c::MasterConfig::default(),
i2c::I2cSpeed::Regular100khz,
)
.expect("creating I2C master failed");
let mut delay_provider = CountdownTimer::new(&mut dp.sysconfig, dp.tim1, &clocks);
let mut delay_provider = CountdownTimer::new(dp.tim1, &clocks);
// Detect the I2C address of the accelerometer by scanning all possible values.
let slave_addr = detect_i2c_addr(&mut i2c_master).expect("detecting I2C address failed");
// Create the accelerometer driver using the PEB1 BSP.
@ -53,7 +51,7 @@ fn main() -> ! {
.expect("creating accelerometer driver failed");
let device_id = accelerometer.get_device_id().unwrap();
accelerometer
.set_mode(lis2dh12::reg::Mode::Normal)
.set_mode(lis2dh12::Mode::Normal)
.expect("setting mode failed");
accelerometer
.set_odr(Odr::Hz100)
@ -65,7 +63,7 @@ fn main() -> ! {
accelerometer
.enable_temp(true)
.expect("enabling temperature sensor failed");
rprintln!("Device ID: 0x{:02X}", device_id);
defmt::info!("Device ID: 0x{:02X}", device_id);
// Start reading the accelerometer periodically.
loop {
let temperature = accelerometer
@ -76,13 +74,25 @@ fn main() -> ! {
let value = accelerometer
.accel_norm()
.expect("reading normalized accelerometer data failed");
rprintln!("Accel Norm F32x3: {:.06?} | Temp {} °C", value, temperature);
defmt::info!(
"Accel Norm F32x3 {{ x: {:05}, y: {:05}, z:{:05}}} | Temp {} °C",
value.x,
value.y,
value.z,
temperature
);
}
DisplayMode::Raw => {
let value_raw = accelerometer
.accel_raw()
.expect("reading raw accelerometer data failed");
rprintln!("Accel Raw F32x3: {:?} | Temp {} °C", value_raw, temperature);
defmt::info!(
"Accel Raw I32x3 {{ x: {:05}, y: {:05}, z:{:05}}} | Temp {} °C",
value_raw.x,
value_raw.y,
value_raw.z,
temperature
);
}
}
delay_provider.delay_ms(100);

View File

@ -1,4 +1,6 @@
//! Simple PWM example
//!
//! Outputs a PWM waveform on pin PG2.
#![no_main]
#![no_std]
@ -10,41 +12,34 @@ use panic_probe as _;
use defmt_rtt as _;
use simple_examples::peb1;
use va416xx_hal::{
gpio::PinsA,
clock::ClockConfigurator,
pac,
pins::PinsG,
prelude::*,
pwm::{self, get_duty_from_percent, PwmA, PwmB, ReducedPwmPin},
pwm::{get_duty_from_percent, PwmA, PwmB, PwmPin},
timer::CountdownTimer,
};
#[entry]
fn main() -> ! {
defmt::println!("-- VA108xx PWM example application--");
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
let mut pwm = pwm::PwmPin::new(
(pinsa.pa3.into_funsel_1(), dp.tim3),
&mut dp.sysconfig,
&clocks,
10.Hz(),
);
let mut delay_timer = CountdownTimer::new(&mut dp.sysconfig, dp.tim0, &clocks);
let pinsg = PinsG::new(dp.portg);
let mut pwm = PwmPin::new(pinsg.pg2, dp.tim9, &clocks, 10.Hz()).unwrap();
let mut delay_timer = CountdownTimer::new(dp.tim0, &clocks);
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
@ -56,8 +51,7 @@ fn main() -> ! {
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();
}
@ -66,7 +60,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 {
@ -78,6 +72,6 @@ fn main() -> ! {
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,38 +0,0 @@
// Code to test RTT logger functionality.
#![no_main]
#![no_std]
// Import panic provider.
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use cortex_m_rt::entry;
use va416xx_hal::pac;
// Mask for the LED
const LED_PG5: u32 = 1 << 5;
#[entry]
fn main() -> ! {
defmt::println!("VA416xx RTT Demo");
let dp = pac::Peripherals::take().unwrap();
// Enable all peripheral clocks
dp.sysconfig
.peripheral_clk_enable()
.modify(|_, w| unsafe { w.bits(0xffffffff) });
dp.portg.dir().modify(|_, w| unsafe { w.bits(LED_PG5) });
dp.portg
.datamask()
.modify(|_, w| unsafe { w.bits(LED_PG5) });
let mut counter = 0;
loop {
defmt::info!("{}: Hello, world!", counter);
// Still toggle LED. If there are issues with the RTT log, the LED
// blinking ensures that the application is actually running.
dp.portg.togout().write(|w| unsafe { w.bits(LED_PG5) });
counter += 1;
cortex_m::asm::delay(10_000_000);
}
}

View File

@ -3,6 +3,7 @@
//! If you do not use the loopback mode, MOSI and MISO need to be tied together on the board.
#![no_main]
#![no_std]
use embedded_hal::delay::DelayNs;
// Import panic provider.
use panic_probe as _;
// Import logger.
@ -11,11 +12,12 @@ use defmt_rtt as _;
use cortex_m_rt::entry;
use embedded_hal::spi::{Mode, SpiBus, MODE_0};
use simple_examples::peb1;
use va416xx_hal::clock::ClockConfigurator;
use va416xx_hal::spi::{Spi, SpiClkConfig};
use va416xx_hal::timer::CountdownTimer;
use va416xx_hal::{
gpio::{PinsB, PinsC},
pac,
prelude::*,
pins::{PinsB, PinsC},
spi::SpiConfig,
time::Hertz,
};
@ -37,29 +39,20 @@ const FILL_WORD: u8 = 0x0f;
#[entry]
fn main() -> ! {
defmt::println!("-- VA108xx SPI example application--");
let cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
let mut delay_sysclk = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().raw());
let mut delay = CountdownTimer::new(dp.tim1, &clocks);
let pins_b = PinsB::new(&mut dp.sysconfig, dp.portb);
let pins_c = PinsC::new(&mut dp.sysconfig, dp.portc);
// Configure SPI0 pins.
let (sck, miso, mosi) = (
pins_b.pb15.into_funsel_1(),
pins_c.pc0.into_funsel_1(),
pins_c.pc1.into_funsel_1(),
);
let pins_b = PinsB::new(dp.portb);
let pins_c = PinsC::new(dp.portc);
let mut spi_cfg = SpiConfig::default()
.clk_cfg(
SpiClkConfig::from_clk(Hertz::from_raw(SPI_SPEED_KHZ), &clocks)
SpiClkConfig::from_clks(&clocks, Hertz::from_raw(SPI_SPEED_KHZ))
.expect("invalid target clock"),
)
.mode(SPI_MODE)
@ -68,13 +61,7 @@ fn main() -> ! {
spi_cfg = spi_cfg.loopback(true)
}
// Create SPI peripheral.
let mut spi0 = Spi::new(
&mut dp.sysconfig,
&clocks,
dp.spi0,
(sck, miso, mosi),
spi_cfg,
);
let mut spi0 = Spi::new(dp.spi0, (pins_b.pb15, pins_c.pc0, pins_c.pc1), spi_cfg).unwrap();
spi0.set_fill_word(FILL_WORD);
loop {
let tx_buf: [u8; 4] = [1, 2, 3, 0];
@ -95,6 +82,6 @@ fn main() -> ! {
spi0.transfer(&mut rx_buf, &tx_buf)
.expect("SPI transfer failed");
assert_eq!(rx_buf, [1, 2, 3, 0]);
delay_sysclk.delay_ms(500);
delay.delay_ms(500);
}
}

View File

@ -6,16 +6,16 @@ use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use core::cell::Cell;
use core::sync::atomic::{AtomicU32, Ordering};
use cortex_m::asm;
use cortex_m_rt::entry;
use critical_section::Mutex;
use simple_examples::peb1;
use va416xx_hal::{
clock::ClockConfigurator,
irq_router::enable_and_init_irq_router,
pac::{self, interrupt},
prelude::*,
timer::{default_ms_irq_handler, set_up_ms_tick, CountdownTimer, MS_COUNTER},
timer::CountdownTimer,
};
#[allow(dead_code)]
@ -24,32 +24,33 @@ 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() -> ! {
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let mut last_ms = 0;
defmt::println!("-- Vorago system ticks using timers --");
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
enable_and_init_irq_router(&mut dp.sysconfig, &dp.irq_router);
let _ = set_up_ms_tick(&mut dp.sysconfig, dp.tim0, &clocks);
let mut second_timer = CountdownTimer::new(&mut dp.sysconfig, dp.tim1, &clocks);
second_timer.listen();
enable_and_init_irq_router();
let mut ms_timer = CountdownTimer::new(dp.tim0, &clocks);
ms_timer.enable_interrupt(true);
ms_timer.start(1.Hz());
let mut second_timer = CountdownTimer::new(dp.tim1, &clocks);
second_timer.enable_interrupt(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(Ordering::Relaxed);
if current_ms >= last_ms + 1000 {
// To prevent drift.
last_ms += 1000;
defmt::info!("MS counter: {}", current_ms);
let second = critical_section::with(|cs| SEC_COUNTER.borrow(cs).get());
let second = SEC_COUNTER.load(Ordering::Relaxed);
defmt::info!("Second counter: {}", second);
}
asm::delay(1000);
@ -59,15 +60,11 @@ fn main() -> ! {
#[interrupt]
#[allow(non_snake_case)]
fn TIM0() {
default_ms_irq_handler()
MS_COUNTER.fetch_add(1, Ordering::Relaxed);
}
#[interrupt]
#[allow(non_snake_case)]
fn TIM1() {
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, Ordering::Relaxed);
}

View File

@ -11,35 +11,33 @@ use cortex_m_rt::entry;
use embedded_hal_nb::serial::Read;
use embedded_io::Write;
use simple_examples::peb1;
use va416xx_hal::clock::ClkgenExt;
use va416xx_hal::clock::ClockConfigurator;
use va416xx_hal::pins::PinsG;
use va416xx_hal::time::Hertz;
use va416xx_hal::{gpio::PinsG, pac, uart};
use va416xx_hal::{pac, uart};
#[entry]
fn main() -> ! {
defmt::println!("-- VA416xx UART example application--");
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
let gpiob = PinsG::new(&mut dp.sysconfig, dp.portg);
let tx = gpiob.pg0.into_funsel_1();
let rx = gpiob.pg1.into_funsel_1();
let gpiog = PinsG::new(dp.portg);
let uart0 = uart::Uart::new(
&mut dp.sysconfig,
dp.uart0,
(tx, rx),
Hertz::from_raw(115200),
gpiog.pg0,
gpiog.pg1,
&clocks,
);
Hertz::from_raw(115200).into(),
)
.unwrap();
let (mut tx, mut rx) = uart0.split();
writeln!(tx, "Hello World\n\r").unwrap();
loop {

View File

@ -5,17 +5,16 @@
use panic_probe as _;
// Import logger.
use defmt_rtt as _;
use va416xx_hal::clock::ClockConfigurator;
use core::cell::Cell;
use core::sync::atomic::{AtomicU32, Ordering};
use cortex_m_rt::entry;
use critical_section::Mutex;
use simple_examples::peb1;
use va416xx_hal::irq_router::enable_and_init_irq_router;
use va416xx_hal::pac::{self, interrupt};
use va416xx_hal::prelude::*;
use va416xx_hal::wdt::Wdt;
static WDT_INTRPT_COUNT: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
static WDT_INTRPT_COUNT: AtomicU32 = AtomicU32::new(0);
#[derive(Debug, PartialEq, Eq)]
#[allow(dead_code)]
@ -33,33 +32,37 @@ const WDT_ROLLOVER_MS: u32 = 100;
fn main() -> ! {
defmt::println!("-- VA416xx WDT example application--");
let cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
// Use the external clock connected to XTAL_N.
let clocks = dp
.clkgen
.constrain()
let clocks = ClockConfigurator::new(dp.clkgen)
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
.freeze(&mut dp.sysconfig)
.freeze()
.unwrap();
enable_and_init_irq_router(&mut dp.sysconfig, &dp.irq_router);
let mut delay_sysclk = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().raw());
enable_and_init_irq_router();
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(&mut dp.sysconfig, dp.watch_dog, &clocks, WDT_ROLLOVER_MS);
let mut wdt_ctrl = Wdt::start(dp.watch_dog, &clocks, WDT_ROLLOVER_MS);
wdt_ctrl.enable_reset();
let log_divisor = 25;
let mut counter: u32 = 0;
loop {
counter = counter.wrapping_add(1);
if counter % log_divisor == 0 {
defmt::info!("wdt example main loop alive");
}
if TEST_MODE != TestMode::AllowReset {
wdt_ctrl.feed();
}
let interrupt_counter = critical_section::with(|cs| WDT_INTRPT_COUNT.borrow(cs).get());
let interrupt_counter = WDT_INTRPT_COUNT.load(Ordering::Relaxed);
if interrupt_counter > last_interrupt_counter {
defmt::info!("interrupt counter has increased to {}", interrupt_counter);
last_interrupt_counter = interrupt_counter;
}
match TEST_MODE {
TestMode::FedByMain => delay_sysclk.delay_ms(WDT_ROLLOVER_MS / 5),
TestMode::FedByIrq => delay_sysclk.delay_ms(WDT_ROLLOVER_MS),
TestMode::FedByMain => delay.delay_ms(WDT_ROLLOVER_MS / 5),
TestMode::FedByIrq => delay.delay_ms(WDT_ROLLOVER_MS),
_ => (),
}
}
@ -68,11 +71,7 @@ fn main() -> ! {
#[interrupt]
#[allow(non_snake_case)]
fn WATCHDOG() {
critical_section::with(|cs| {
WDT_INTRPT_COUNT
.borrow(cs)
.set(WDT_INTRPT_COUNT.borrow(cs).get() + 1);
});
WDT_INTRPT_COUNT.fetch_add(1, Ordering::Relaxed);
let wdt = unsafe { pac::WatchDog::steal() };
// Clear interrupt.
if TEST_MODE != TestMode::AllowReset {