Monorepo for Rust support of VA416XX family of radiation hardened MCUs
This commit is contained in:
18
examples/simple/Cargo.toml
Normal file
18
examples/simple/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "simple_examples"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m-rt = "0.7"
|
||||
va416xx-hal = { path = "../../va416xx-hal" }
|
||||
panic-rtt-target = { version = "0.1.3" }
|
||||
rtt-target = { version = "0.5" }
|
||||
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
embedded-hal = "1"
|
||||
embedded-hal-nb = "1"
|
||||
nb = "1"
|
||||
embedded-io = "0.6"
|
||||
panic-halt = "0.2"
|
||||
vorago-peb1 = { path = "../../vorago-peb1" }
|
||||
accelerometer = "0.12"
|
33
examples/simple/examples/blinky-pac.rs
Normal file
33
examples/simple/examples/blinky-pac.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! Simple blinky example
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use panic_halt as _;
|
||||
use va416xx_hal::pac;
|
||||
|
||||
// Mask for the LED
|
||||
const LED_PG5: u32 = 1 << 5;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
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) });
|
||||
for _ in 0..10 {
|
||||
dp.portg.clrout().write(|w| unsafe { w.bits(LED_PG5) });
|
||||
cortex_m::asm::delay(2_000_000);
|
||||
dp.portg.setout().write(|w| unsafe { w.bits(LED_PG5) });
|
||||
cortex_m::asm::delay(2_000_000);
|
||||
}
|
||||
loop {
|
||||
dp.portg.togout().write(|w| unsafe { w.bits(LED_PG5) });
|
||||
cortex_m::asm::delay(2_000_000);
|
||||
}
|
||||
}
|
24
examples/simple/examples/blinky.rs
Normal file
24
examples/simple/examples/blinky.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! Simple blinky example using the HAL
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::digital::StatefulOutputPin;
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va416xx_hal::{gpio::PinsG, pac};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("VA416xx HAL blinky example");
|
||||
|
||||
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 mut delay = CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM0);
|
||||
loop {
|
||||
cortex_m::asm::delay(2_000_000);
|
||||
led.toggle().ok();
|
||||
}
|
||||
}
|
88
examples/simple/examples/peb1-accelerometer.rs
Normal file
88
examples/simple/examples/peb1-accelerometer.rs
Normal file
@ -0,0 +1,88 @@
|
||||
//! Example code for the PEB1 development board accelerometer.
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use accelerometer::{Accelerometer, RawAccelerometer};
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::delay::DelayNs;
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::{
|
||||
i2c,
|
||||
pac::{self},
|
||||
prelude::*,
|
||||
pwm::CountdownTimer,
|
||||
};
|
||||
use vorago_peb1::lis2dh12::{self, detect_i2c_addr, FullScale, Odr};
|
||||
|
||||
pub enum DisplayMode {
|
||||
Raw,
|
||||
Normalized,
|
||||
}
|
||||
|
||||
const DISPLAY_MODE: DisplayMode = DisplayMode::Normalized;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
rprintln!("-- Vorago PEB1 accelerometer example --");
|
||||
// Use the external clock connected to XTAL_N.
|
||||
let clocks = dp
|
||||
.clkgen
|
||||
.constrain()
|
||||
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
|
||||
.freeze(&mut dp.sysconfig)
|
||||
.unwrap();
|
||||
let mut i2c_master = i2c::I2cMaster::new(
|
||||
dp.i2c0,
|
||||
&mut dp.sysconfig,
|
||||
i2c::MasterConfig::default(),
|
||||
&clocks,
|
||||
i2c::I2cSpeed::Regular100khz,
|
||||
)
|
||||
.expect("creating I2C master failed");
|
||||
let mut delay_provider = CountdownTimer::new(&mut dp.sysconfig, 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.
|
||||
let mut accelerometer = vorago_peb1::accelerometer::new_with_i2cm(i2c_master, slave_addr)
|
||||
.expect("creating accelerometer driver failed");
|
||||
let device_id = accelerometer.get_device_id().unwrap();
|
||||
accelerometer
|
||||
.set_mode(lis2dh12::reg::Mode::Normal)
|
||||
.expect("setting mode failed");
|
||||
accelerometer
|
||||
.set_odr(Odr::Hz100)
|
||||
.expect("setting ODR failed");
|
||||
accelerometer
|
||||
.set_fs(FullScale::G4)
|
||||
.expect("setting full scale failed");
|
||||
// This function also enabled BDU.
|
||||
accelerometer
|
||||
.enable_temp(true)
|
||||
.expect("enabling temperature sensor failed");
|
||||
rprintln!("Device ID: 0x{:02X}", device_id);
|
||||
// Start reading the accelerometer periodically.
|
||||
loop {
|
||||
let temperature = accelerometer
|
||||
.get_temp_outf()
|
||||
.expect("reading temperature failed");
|
||||
match DISPLAY_MODE {
|
||||
DisplayMode::Normalized => {
|
||||
let value = accelerometer
|
||||
.accel_norm()
|
||||
.expect("reading normalized accelerometer data failed");
|
||||
rprintln!("Accel Norm F32x3: {:.06?} | Temp {} °C", value, temperature);
|
||||
}
|
||||
DisplayMode::Raw => {
|
||||
let value_raw = accelerometer
|
||||
.accel_raw()
|
||||
.expect("reading raw accelerometer data failed");
|
||||
rprintln!("Accel Raw F32x3: {:?} | Temp {} °C", value_raw, temperature);
|
||||
}
|
||||
}
|
||||
delay_provider.delay_ms(100);
|
||||
}
|
||||
}
|
81
examples/simple/examples/pwm.rs
Normal file
81
examples/simple/examples/pwm.rs
Normal file
@ -0,0 +1,81 @@
|
||||
//! Simple PWM example
|
||||
#![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};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::{
|
||||
gpio::PinsA,
|
||||
pac,
|
||||
prelude::*,
|
||||
pwm::{self, get_duty_from_percent, CountdownTimer, PwmA, PwmB, ReducedPwmPin},
|
||||
};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- VA108xx PWM example application--");
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Use the external clock connected to XTAL_N.
|
||||
let clocks = dp
|
||||
.clkgen
|
||||
.constrain()
|
||||
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
|
||||
.freeze(&mut dp.sysconfig)
|
||||
.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 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
|
||||
while current_duty_cycle < 1.0 {
|
||||
delay_timer.delay_ms(400);
|
||||
current_duty_cycle += 0.02;
|
||||
counter += 1;
|
||||
if counter % 10 == 0 {
|
||||
rprintln!("current duty cycle: {}", current_duty_cycle);
|
||||
}
|
||||
|
||||
reduced_pin
|
||||
.set_duty_cycle(get_duty_from_percent(current_duty_cycle))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Switch to PWMB and decrease the window with a high signal from 100 % to 0 %
|
||||
// continously
|
||||
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);
|
||||
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 {
|
||||
delay_timer.delay_ms(400);
|
||||
lower_limit += 0.01;
|
||||
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());
|
||||
}
|
||||
reduced_pin = ReducedPwmPin::<PwmA>::from(pwmb);
|
||||
}
|
||||
}
|
36
examples/simple/examples/rtt-log.rs
Normal file
36
examples/simple/examples/rtt-log.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// 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 va416xx_hal::pac;
|
||||
|
||||
// Mask for the LED
|
||||
const LED_PG5: u32 = 1 << 5;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
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) });
|
||||
|
||||
rtt_init_print!();
|
||||
rprintln!("VA416xx RTT Demo");
|
||||
let mut counter = 0;
|
||||
loop {
|
||||
rprintln!("{}: 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);
|
||||
}
|
||||
}
|
96
examples/simple/examples/spi.rs
Normal file
96
examples/simple/examples/spi.rs
Normal file
@ -0,0 +1,96 @@
|
||||
//! SPI example application.
|
||||
//!
|
||||
//! If you do not use the loopback mode, MOSI and MISO need to be tied together on the board.
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::spi::{Mode, SpiBus, MODE_0};
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::spi::{Spi, TransferConfig};
|
||||
use va416xx_hal::{
|
||||
gpio::{PinsB, PinsC},
|
||||
pac,
|
||||
prelude::*,
|
||||
spi::SpiConfig,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum ExampleSelect {
|
||||
// Enter loopback mode. It is not necessary to tie MOSI/MISO together for this
|
||||
Loopback,
|
||||
// Send a test buffer and print everything received. You need to tie together MOSI/MISO in this
|
||||
// mode.
|
||||
TestBuffer,
|
||||
}
|
||||
|
||||
const EXAMPLE_SEL: ExampleSelect = ExampleSelect::Loopback;
|
||||
const SPI_SPEED_KHZ: u32 = 1000;
|
||||
const SPI_MODE: Mode = MODE_0;
|
||||
const BLOCKMODE: bool = true;
|
||||
const FILL_WORD: u8 = 0x0f;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- VA108xx SPI example application--");
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
// Use the external clock connected to XTAL_N.
|
||||
let clocks = dp
|
||||
.clkgen
|
||||
.constrain()
|
||||
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
|
||||
.freeze(&mut dp.sysconfig)
|
||||
.unwrap();
|
||||
let mut delay_sysclk = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().raw());
|
||||
|
||||
let pins_b = PinsB::new(&mut dp.sysconfig, dp.portb);
|
||||
let pins_c = PinsC::new(&mut dp.sysconfig, dp.portc);
|
||||
// Configure SPI1 pins.
|
||||
let (sck, miso, mosi) = (
|
||||
pins_b.pb15.into_funsel_1(),
|
||||
pins_c.pc0.into_funsel_1(),
|
||||
pins_c.pc1.into_funsel_1(),
|
||||
);
|
||||
|
||||
let mut spi_cfg = SpiConfig::default();
|
||||
if EXAMPLE_SEL == ExampleSelect::Loopback {
|
||||
spi_cfg = spi_cfg.loopback(true)
|
||||
}
|
||||
let transfer_cfg =
|
||||
TransferConfig::new_no_hw_cs(SPI_SPEED_KHZ.kHz(), SPI_MODE, BLOCKMODE, false);
|
||||
// Create SPI peripheral.
|
||||
let mut spi0 = Spi::new(
|
||||
dp.spi0,
|
||||
(sck, miso, mosi),
|
||||
&clocks,
|
||||
spi_cfg,
|
||||
&mut dp.sysconfig,
|
||||
Some(&transfer_cfg.downgrade()),
|
||||
);
|
||||
spi0.set_fill_word(FILL_WORD);
|
||||
loop {
|
||||
let mut tx_buf: [u8; 3] = [1, 2, 3];
|
||||
let mut rx_buf: [u8; 3] = [0; 3];
|
||||
// Can't really verify correct reply here.
|
||||
spi0.write(&[0x42]).expect("write failed");
|
||||
// Need small delay.. otherwise we will read back the sent byte (which we don't want here).
|
||||
// The write function will return as soon as all bytes were shifted out, ignoring the
|
||||
// reply bytes.
|
||||
delay_sysclk.delay_us(50);
|
||||
// Because of the loopback mode, we should get back the fill word here.
|
||||
spi0.read(&mut rx_buf[0..1]).unwrap();
|
||||
assert_eq!(rx_buf[0], FILL_WORD);
|
||||
|
||||
spi0.transfer_in_place(&mut tx_buf)
|
||||
.expect("SPI transfer_in_place failed");
|
||||
assert_eq!([1, 2, 3], tx_buf);
|
||||
spi0.transfer(&mut rx_buf, &tx_buf)
|
||||
.expect("SPI transfer failed");
|
||||
assert_eq!(rx_buf, tx_buf);
|
||||
delay_sysclk.delay_ms(500);
|
||||
}
|
||||
}
|
68
examples/simple/examples/timer-ticks.rs
Normal file
68
examples/simple/examples/timer-ticks.rs
Normal file
@ -0,0 +1,68 @@
|
||||
//! MS and Second counter implemented using the TIM0 and TIM1 peripheral
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use core::cell::Cell;
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use cortex_m_rt::entry;
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::{
|
||||
pac::{self, interrupt},
|
||||
prelude::*,
|
||||
timer::{default_ms_irq_handler, set_up_ms_tick, CountdownTimer, MS_COUNTER},
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
enum LibType {
|
||||
Pac,
|
||||
Hal,
|
||||
}
|
||||
|
||||
static SEC_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
let mut last_ms = 0;
|
||||
rprintln!("-- Vorago system ticks using timers --");
|
||||
// Use the external clock connected to XTAL_N.
|
||||
let clocks = dp
|
||||
.clkgen
|
||||
.constrain()
|
||||
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
|
||||
.freeze(&mut dp.sysconfig)
|
||||
.unwrap();
|
||||
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.start(1.Hz());
|
||||
second_timer.listen();
|
||||
loop {
|
||||
let current_ms = cortex_m::interrupt::free(|cs| MS_COUNTER.borrow(cs).get());
|
||||
if current_ms - last_ms >= 1000 {
|
||||
last_ms = current_ms;
|
||||
rprintln!("MS counter: {}", current_ms);
|
||||
let second = cortex_m::interrupt::free(|cs| SEC_COUNTER.borrow(cs).get());
|
||||
rprintln!("Second counter: {}", second);
|
||||
}
|
||||
cortex_m::asm::delay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
#[allow(non_snake_case)]
|
||||
fn TIM0() {
|
||||
default_ms_irq_handler()
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
#[allow(non_snake_case)]
|
||||
fn TIM1() {
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
let mut sec = SEC_COUNTER.borrow(cs).get();
|
||||
sec += 1;
|
||||
SEC_COUNTER.borrow(cs).set(sec);
|
||||
});
|
||||
}
|
57
examples/simple/examples/uart.rs
Normal file
57
examples/simple/examples/uart.rs
Normal file
@ -0,0 +1,57 @@
|
||||
// UART example application. Sends a test string over a UART and then enters
|
||||
// echo mode
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal_nb::serial::Read;
|
||||
use embedded_io::Write;
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::clock::ClkgenExt;
|
||||
use va416xx_hal::time::Hertz;
|
||||
use va416xx_hal::{gpio::PinsG, pac, uart};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- VA416xx UART example application--");
|
||||
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Use the external clock connected to XTAL_N.
|
||||
let clocks = dp
|
||||
.clkgen
|
||||
.constrain()
|
||||
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
|
||||
.freeze(&mut dp.sysconfig)
|
||||
.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 uart0 = uart::Uart::new(
|
||||
dp.uart0,
|
||||
(tx, rx),
|
||||
Hertz::from_raw(115200),
|
||||
&mut dp.sysconfig,
|
||||
&clocks,
|
||||
);
|
||||
let (mut tx, mut rx) = uart0.split();
|
||||
writeln!(tx, "Hello World\n\r").unwrap();
|
||||
loop {
|
||||
// Echo what is received on the serial link.
|
||||
match nb::block!(rx.read()) {
|
||||
Ok(recvd) => {
|
||||
if let Err(e) = embedded_hal_nb::serial::Write::write(&mut tx, recvd) {
|
||||
rprintln!("UART TX error: {:?}", e);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
rprintln!("UART RX error {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
examples/simple/examples/wdt.rs
Normal file
79
examples/simple/examples/wdt.rs
Normal file
@ -0,0 +1,79 @@
|
||||
// Code to test the watchdog timer.
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use core::cell::Cell;
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use cortex_m_rt::entry;
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use simple_examples::peb1;
|
||||
use va416xx_hal::pac::{self, interrupt};
|
||||
use va416xx_hal::prelude::*;
|
||||
use va416xx_hal::wdt::WdtController;
|
||||
|
||||
static WDT_INTRPT_COUNT: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[allow(dead_code)]
|
||||
enum TestMode {
|
||||
// Watchdog is fed by main loop, which runs with high period.
|
||||
FedByMain,
|
||||
// Watchdog is fed by watchdog IRQ.
|
||||
FedByIrq,
|
||||
AllowReset,
|
||||
}
|
||||
const TEST_MODE: TestMode = TestMode::FedByMain;
|
||||
const WDT_ROLLOVER_MS: u32 = 100;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- VA416xx WDT example application--");
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Use the external clock connected to XTAL_N.
|
||||
let clocks = dp
|
||||
.clkgen
|
||||
.constrain()
|
||||
.xtal_n_clk_with_src_freq(peb1::EXTCLK_FREQ)
|
||||
.freeze(&mut dp.sysconfig)
|
||||
.unwrap();
|
||||
let mut delay_sysclk = cortex_m::delay::Delay::new(cp.SYST, clocks.apb0().raw());
|
||||
|
||||
let mut last_interrupt_counter = 0;
|
||||
let mut wdt_ctrl =
|
||||
WdtController::start(&mut dp.sysconfig, dp.watch_dog, &clocks, WDT_ROLLOVER_MS);
|
||||
wdt_ctrl.enable_reset();
|
||||
loop {
|
||||
if TEST_MODE != TestMode::AllowReset {
|
||||
wdt_ctrl.feed();
|
||||
}
|
||||
let interrupt_counter = cortex_m::interrupt::free(|cs| WDT_INTRPT_COUNT.borrow(cs).get());
|
||||
if interrupt_counter > last_interrupt_counter {
|
||||
rprintln!("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),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
#[allow(non_snake_case)]
|
||||
fn WATCHDOG() {
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
WDT_INTRPT_COUNT
|
||||
.borrow(cs)
|
||||
.set(WDT_INTRPT_COUNT.borrow(cs).get() + 1);
|
||||
});
|
||||
let wdt = unsafe { pac::WatchDog::steal() };
|
||||
// Clear interrupt.
|
||||
if TEST_MODE != TestMode::AllowReset {
|
||||
wdt.wdogintclr().write(|w| unsafe { w.bits(1) });
|
||||
}
|
||||
}
|
11
examples/simple/src/lib.rs
Normal file
11
examples/simple/src/lib.rs
Normal file
@ -0,0 +1,11 @@
|
||||
#![no_std]
|
||||
|
||||
/// PEB1 board specific configuration.
|
||||
pub mod peb1 {
|
||||
use va416xx_hal::time::Hertz;
|
||||
|
||||
// The clock on the PEB1 board has a 20 MHz clock which is increased to 40 MHz with a configurable
|
||||
// PLL by default.
|
||||
pub const EXTCLK_FREQ: Hertz = Hertz::from_raw(40_000_000);
|
||||
pub const XTAL_FREQ: Hertz = Hertz::from_raw(10_000_000);
|
||||
}
|
13
examples/simple/src/main.rs
Normal file
13
examples/simple/src/main.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//! Dummy app which does not do anything.
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use panic_rtt_target as _;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user