init new shared periph crate
This commit is contained in:
@ -29,7 +29,7 @@ embassy-executor = { version = "0.7", features = [
|
||||
"executor-interrupt"
|
||||
]}
|
||||
|
||||
va108xx-hal = { version = "0.11", features = ["defmt"] }
|
||||
va108xx-hal = { version = "0.11", path = "../../va108xx-hal", features = ["defmt"] }
|
||||
va108xx-embassy = { version = "0.2" }
|
||||
|
||||
[features]
|
||||
|
@ -12,11 +12,10 @@ use embassy_sync::channel::{Receiver, Sender};
|
||||
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, channel::Channel};
|
||||
use embassy_time::{Duration, Instant, Timer};
|
||||
use embedded_hal_async::digital::Wait;
|
||||
use va108xx_hal::gpio::{
|
||||
on_interrupt_for_async_gpio_for_port, InputDynPinAsync, InputPinAsync, PinsB, Port,
|
||||
};
|
||||
use va108xx_hal::gpio::asynch::{on_interrupt_for_async_gpio_for_port, InputPinAsync};
|
||||
use va108xx_hal::gpio::{Input, Output, PinState, Port};
|
||||
use va108xx_hal::pins::{PinsA, PinsB};
|
||||
use va108xx_hal::{
|
||||
gpio::{DynPin, PinsA},
|
||||
pac::{self, interrupt},
|
||||
prelude::*,
|
||||
};
|
||||
@ -71,30 +70,28 @@ async fn main(spawner: Spawner) {
|
||||
dp.tim22,
|
||||
);
|
||||
|
||||
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let portb = PinsB::new(&mut dp.sysconfig, dp.portb);
|
||||
let mut led0 = porta.pa10.into_readable_push_pull_output();
|
||||
let out_pa0 = porta.pa0.into_readable_push_pull_output();
|
||||
let in_pa1 = porta.pa1.into_floating_input();
|
||||
let out_pb22 = portb.pb22.into_readable_push_pull_output();
|
||||
let in_pb23 = portb.pb23.into_floating_input();
|
||||
let porta = PinsA::new(dp.porta);
|
||||
let portb = PinsB::new(dp.portb);
|
||||
let mut led0 = Output::new(porta.pa10, PinState::Low);
|
||||
let out_pa0 = Output::new(porta.pa0, PinState::Low);
|
||||
let in_pa1 = Input::new_floating(porta.pa1);
|
||||
let out_pb22 = Output::new(portb.pb22, PinState::Low);
|
||||
let in_pb23 = Input::new_floating(portb.pb23);
|
||||
|
||||
let in_pa1_async = InputPinAsync::new(in_pa1, pac::Interrupt::OC10);
|
||||
let out_pa0_dyn = out_pa0.downgrade();
|
||||
let in_pb23_async = InputDynPinAsync::new(in_pb23.downgrade(), PB22_TO_PB23_IRQ).unwrap();
|
||||
let out_pb22_dyn = out_pb22.downgrade();
|
||||
let in_pb23_async = InputPinAsync::new(in_pb23, PB22_TO_PB23_IRQ);
|
||||
|
||||
spawner
|
||||
.spawn(output_task(
|
||||
"PA0 to PA1",
|
||||
out_pa0_dyn,
|
||||
out_pa0,
|
||||
CHANNEL_PA0_PA1.receiver(),
|
||||
))
|
||||
.unwrap();
|
||||
spawner
|
||||
.spawn(output_task(
|
||||
"PB22 to PB23",
|
||||
out_pb22_dyn,
|
||||
out_pb22,
|
||||
CHANNEL_PB22_TO_PB23.receiver(),
|
||||
))
|
||||
.unwrap();
|
||||
@ -207,7 +204,7 @@ async fn check_pin_to_pin_async_ops(
|
||||
#[embassy_executor::task(pool_size = 2)]
|
||||
async fn output_task(
|
||||
ctx: &'static str,
|
||||
mut out: DynPin,
|
||||
mut out: Output,
|
||||
receiver: Receiver<'static, ThreadModeRawMutex, GpioCmd, 3>,
|
||||
) {
|
||||
loop {
|
||||
@ -216,25 +213,25 @@ async fn output_task(
|
||||
match next_cmd.cmd_type {
|
||||
GpioCmdType::SetHigh => {
|
||||
defmt::info!("{}: Set output high", ctx);
|
||||
out.set_high().unwrap();
|
||||
out.set_high();
|
||||
}
|
||||
GpioCmdType::SetLow => {
|
||||
defmt::info!("{}: Set output low", ctx);
|
||||
out.set_low().unwrap();
|
||||
out.set_low();
|
||||
}
|
||||
GpioCmdType::RisingEdge => {
|
||||
defmt::info!("{}: Rising edge", ctx);
|
||||
if !out.is_low().unwrap() {
|
||||
out.set_low().unwrap();
|
||||
if !out.is_set_low() {
|
||||
out.set_low();
|
||||
}
|
||||
out.set_high().unwrap();
|
||||
out.set_high();
|
||||
}
|
||||
GpioCmdType::FallingEdge => {
|
||||
defmt::info!("{}: Falling edge", ctx);
|
||||
if !out.is_high().unwrap() {
|
||||
out.set_high().unwrap();
|
||||
if !out.is_set_high() {
|
||||
out.set_high();
|
||||
}
|
||||
out.set_low().unwrap();
|
||||
out.set_low();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,9 @@ use embedded_io::Write;
|
||||
use embedded_io_async::Read;
|
||||
use heapless::spsc::{Consumer, Producer, Queue};
|
||||
use va108xx_hal::{
|
||||
gpio::PinsA,
|
||||
gpio::{Output, PinState},
|
||||
pac::{self, interrupt},
|
||||
pins::PinsA,
|
||||
prelude::*,
|
||||
uart::{
|
||||
self, on_interrupt_rx_overwriting,
|
||||
@ -62,34 +63,34 @@ async fn main(spawner: Spawner) {
|
||||
dp.tim22,
|
||||
);
|
||||
|
||||
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let mut led0 = porta.pa10.into_readable_push_pull_output();
|
||||
let mut led1 = porta.pa7.into_readable_push_pull_output();
|
||||
let mut led2 = porta.pa6.into_readable_push_pull_output();
|
||||
let porta = PinsA::new(dp.porta);
|
||||
let mut led0 = Output::new(porta.pa10, PinState::Low);
|
||||
let mut led1 = Output::new(porta.pa7, PinState::Low);
|
||||
let mut led2 = Output::new(porta.pa6, PinState::Low);
|
||||
|
||||
let tx_uart_a = porta.pa9.into_funsel_2();
|
||||
let rx_uart_a = porta.pa8.into_funsel_2();
|
||||
let tx_uart_a = porta.pa9;
|
||||
let rx_uart_a = porta.pa8;
|
||||
|
||||
let uarta = uart::Uart::new_with_interrupt(
|
||||
&mut dp.sysconfig,
|
||||
50.MHz(),
|
||||
dp.uarta,
|
||||
(tx_uart_a, rx_uart_a),
|
||||
115200.Hz(),
|
||||
115200.Hz().into(),
|
||||
InterruptConfig::new(pac::Interrupt::OC2, true, true),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let tx_uart_b = porta.pa3.into_funsel_2();
|
||||
let rx_uart_b = porta.pa2.into_funsel_2();
|
||||
let tx_uart_b = porta.pa3;
|
||||
let rx_uart_b = porta.pa2;
|
||||
|
||||
let uartb = uart::Uart::new_with_interrupt(
|
||||
&mut dp.sysconfig,
|
||||
50.MHz(),
|
||||
dp.uartb,
|
||||
(tx_uart_b, rx_uart_b),
|
||||
115200.Hz(),
|
||||
115200.Hz().into(),
|
||||
InterruptConfig::new(pac::Interrupt::OC3, true, true),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
let (mut tx_uart_a, rx_uart_a) = uarta.split();
|
||||
let (tx_uart_b, rx_uart_b) = uartb.split();
|
||||
let (prod_uart_a, cons_uart_a) = QUEUE_UART_A.take().split();
|
||||
@ -123,7 +124,7 @@ async fn main(spawner: Spawner) {
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn uart_b_task(mut async_rx: RxAsyncOverwriting<pac::Uartb, 256>, mut tx: Tx<pac::Uartb>) {
|
||||
async fn uart_b_task(mut async_rx: RxAsyncOverwriting<256>, mut tx: Tx) {
|
||||
let mut buf = [0u8; 256];
|
||||
loop {
|
||||
defmt::info!("Current time UART B: {}", Instant::now().as_secs());
|
||||
@ -144,7 +145,7 @@ async fn uart_b_task(mut async_rx: RxAsyncOverwriting<pac::Uartb, 256>, mut tx:
|
||||
fn OC2() {
|
||||
let mut prod =
|
||||
critical_section::with(|cs| PRODUCER_UART_A.borrow(cs).borrow_mut().take().unwrap());
|
||||
let errors = on_interrupt_rx(Bank::A, &mut prod);
|
||||
let errors = on_interrupt_rx(Bank::Uart0, &mut prod);
|
||||
critical_section::with(|cs| *PRODUCER_UART_A.borrow(cs).borrow_mut() = Some(prod));
|
||||
// In a production app, we could use a channel to send the errors to the main task.
|
||||
if let Err(errors) = errors {
|
||||
@ -157,7 +158,7 @@ fn OC2() {
|
||||
fn OC3() {
|
||||
let mut prod =
|
||||
critical_section::with(|cs| PRODUCER_UART_B.borrow(cs).borrow_mut().take().unwrap());
|
||||
let errors = on_interrupt_rx_overwriting(Bank::B, &mut prod, &CONSUMER_UART_B);
|
||||
let errors = on_interrupt_rx_overwriting(Bank::Uart1, &mut prod, &CONSUMER_UART_B);
|
||||
critical_section::with(|cs| *PRODUCER_UART_B.borrow(cs).borrow_mut() = Some(prod));
|
||||
// In a production app, we could use a channel to send the errors to the main task.
|
||||
if let Err(errors) = errors {
|
||||
|
@ -17,8 +17,9 @@ use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Instant, Ticker};
|
||||
use embedded_io_async::Write;
|
||||
use va108xx_hal::{
|
||||
gpio::PinsA,
|
||||
gpio::{Output, PinState},
|
||||
pac::{self, interrupt},
|
||||
pins::PinsA,
|
||||
prelude::*,
|
||||
uart::{self, on_interrupt_tx, Bank, TxAsync},
|
||||
InterruptConfig,
|
||||
@ -49,22 +50,23 @@ async fn main(_spawner: Spawner) {
|
||||
dp.tim22,
|
||||
);
|
||||
|
||||
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let mut led0 = porta.pa10.into_readable_push_pull_output();
|
||||
let mut led1 = porta.pa7.into_readable_push_pull_output();
|
||||
let mut led2 = porta.pa6.into_readable_push_pull_output();
|
||||
let porta = PinsA::new(dp.porta);
|
||||
|
||||
let tx = porta.pa9.into_funsel_2();
|
||||
let rx = porta.pa8.into_funsel_2();
|
||||
let mut led0 = Output::new(porta.pa10, PinState::Low);
|
||||
let mut led1 = Output::new(porta.pa7, PinState::Low);
|
||||
let mut led2 = Output::new(porta.pa6, PinState::Low);
|
||||
|
||||
let tx = porta.pa9;
|
||||
let rx = porta.pa8;
|
||||
|
||||
let uarta = uart::Uart::new_with_interrupt(
|
||||
&mut dp.sysconfig,
|
||||
50.MHz(),
|
||||
dp.uarta,
|
||||
(tx, rx),
|
||||
115200.Hz(),
|
||||
115200.Hz().into(),
|
||||
InterruptConfig::new(pac::Interrupt::OC2, true, true),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
let (tx, _rx) = uarta.split();
|
||||
let mut async_tx = TxAsync::new(tx);
|
||||
let mut ticker = Ticker::every(Duration::from_secs(1));
|
||||
@ -89,5 +91,5 @@ async fn main(_spawner: Spawner) {
|
||||
#[interrupt]
|
||||
#[allow(non_snake_case)]
|
||||
fn OC2() {
|
||||
on_interrupt_tx(Bank::A);
|
||||
on_interrupt_tx(Bank::Uart0);
|
||||
}
|
||||
|
@ -12,7 +12,12 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
use va108xx_hal::{gpio::PinsA, pac, prelude::*};
|
||||
use va108xx_hal::{
|
||||
gpio::{Output, PinState},
|
||||
pac,
|
||||
pins::PinsA,
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
const SYSCLK_FREQ: Hertz = Hertz::from_raw(50_000_000);
|
||||
|
||||
@ -35,8 +40,6 @@ async fn main(_spawner: Spawner) {
|
||||
);
|
||||
} else {
|
||||
va108xx_embassy::init_with_custom_irqs(
|
||||
&mut dp.sysconfig,
|
||||
&dp.irqsel,
|
||||
SYSCLK_FREQ,
|
||||
dp.tim23,
|
||||
dp.tim22,
|
||||
@ -46,10 +49,10 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
}
|
||||
|
||||
let porta = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let mut led0 = porta.pa10.into_readable_push_pull_output();
|
||||
let mut led1 = porta.pa7.into_readable_push_pull_output();
|
||||
let mut led2 = porta.pa6.into_readable_push_pull_output();
|
||||
let porta = PinsA::new(dp.porta);
|
||||
let mut led0 = Output::new(porta.pa10, PinState::Low);
|
||||
let mut led1 = Output::new(porta.pa7, PinState::Low);
|
||||
let mut led2 = Output::new(porta.pa6, PinState::Low);
|
||||
let mut ticker = Ticker::every(Duration::from_secs(1));
|
||||
loop {
|
||||
ticker.next().await;
|
||||
|
@ -8,8 +8,9 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7"
|
||||
embedded-hal = "1"
|
||||
embedded-io = "0.6"
|
||||
rtt-target = "0.6"
|
||||
panic-rtt-target = "0.2"
|
||||
defmt-rtt = "0.4"
|
||||
defmt = "1"
|
||||
panic-probe = { version = "1", 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.
|
||||
@ -22,5 +23,5 @@ rtic-sync = { version = "1.3", features = ["defmt-03"] }
|
||||
once_cell = {version = "1", default-features = false, features = ["critical-section"]}
|
||||
ringbuf = { version = "0.4.7", default-features = false, features = ["portable-atomic"] }
|
||||
|
||||
va108xx-hal = { version = "0.11" }
|
||||
vorago-reb1 = { version = "0.8" }
|
||||
va108xx-hal = { version = "0.11", path = "../../va108xx-hal" }
|
||||
vorago-reb1 = { version = "0.8", path = "../../vorago-reb1" }
|
||||
|
@ -4,34 +4,29 @@
|
||||
|
||||
#[rtic::app(device = pac)]
|
||||
mod app {
|
||||
use panic_rtt_target as _;
|
||||
use rtic_example::SYSCLK_FREQ;
|
||||
use rtt_target::{rprintln, rtt_init_default, set_print_channel};
|
||||
// Import panic provider.
|
||||
use panic_probe as _;
|
||||
// Import global logger.
|
||||
use defmt_rtt as _;
|
||||
use va108xx_hal::{
|
||||
clock::{set_clk_div_register, FilterClkSel},
|
||||
gpio::{FilterType, InterruptEdge, PinsA},
|
||||
gpio::{FilterType, InterruptEdge},
|
||||
pac,
|
||||
prelude::*,
|
||||
timer::{default_ms_irq_handler, set_up_ms_tick, InterruptConfig},
|
||||
pins::PinsA,
|
||||
timer::InterruptConfig,
|
||||
};
|
||||
use vorago_reb1::button::Button;
|
||||
use vorago_reb1::leds::Leds;
|
||||
|
||||
rtic_monotonics::systick_monotonic!(Mono, 1_000);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, defmt::Format)]
|
||||
pub enum PressMode {
|
||||
Toggle,
|
||||
Keep,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CfgMode {
|
||||
Prompt,
|
||||
Fixed,
|
||||
}
|
||||
|
||||
const CFG_MODE: CfgMode = CfgMode::Fixed;
|
||||
// You can change the press mode here
|
||||
const DEFAULT_MODE: PressMode = PressMode::Toggle;
|
||||
|
||||
@ -47,53 +42,35 @@ mod app {
|
||||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
let channels = rtt_init_default!();
|
||||
set_print_channel(channels.up.0);
|
||||
rprintln!("-- Vorago Button IRQ Example --");
|
||||
defmt::println!("-- Vorago Button IRQ Example --");
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let mode = match CFG_MODE {
|
||||
// Ask mode from user via RTT
|
||||
CfgMode::Prompt => prompt_mode(channels.down.0),
|
||||
// Use mode hardcoded in `DEFAULT_MODE`
|
||||
CfgMode::Fixed => DEFAULT_MODE,
|
||||
};
|
||||
rprintln!("Using {:?} mode", mode);
|
||||
let mode = DEFAULT_MODE;
|
||||
defmt::info!("Using {:?} mode", mode);
|
||||
|
||||
let mut dp = cx.device;
|
||||
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let pinsa = PinsA::new(dp.porta);
|
||||
let edge_irq = match mode {
|
||||
PressMode::Toggle => InterruptEdge::HighToLow,
|
||||
PressMode::Keep => InterruptEdge::BothEdges,
|
||||
};
|
||||
|
||||
// Configure an edge interrupt on the button and route it to interrupt vector 15
|
||||
let mut button = Button::new(pinsa.pa11.into_floating_input());
|
||||
let mut button = Button::new(pinsa.pa11);
|
||||
|
||||
if mode == PressMode::Toggle {
|
||||
// This filter debounces the switch for edge based interrupts
|
||||
button.configure_filter_type(FilterType::FilterFourClockCycles, FilterClkSel::Clk1);
|
||||
button.configure_filter_type(FilterType::FilterFourCycles, FilterClkSel::Clk1);
|
||||
set_clk_div_register(&mut dp.sysconfig, FilterClkSel::Clk1, 50_000);
|
||||
}
|
||||
button.configure_and_enable_edge_interrupt(
|
||||
edge_irq,
|
||||
InterruptConfig::new(pac::interrupt::OC15, true, true),
|
||||
);
|
||||
let mut leds = Leds::new(
|
||||
pinsa.pa10.into_push_pull_output(),
|
||||
pinsa.pa7.into_push_pull_output(),
|
||||
pinsa.pa6.into_push_pull_output(),
|
||||
);
|
||||
let mut leds = Leds::new(pinsa.pa10, pinsa.pa7, pinsa.pa6);
|
||||
for led in leds.iter_mut() {
|
||||
led.off();
|
||||
}
|
||||
set_up_ms_tick(
|
||||
InterruptConfig::new(pac::Interrupt::OC0, true, true),
|
||||
&mut dp.sysconfig,
|
||||
Some(&mut dp.irqsel),
|
||||
50.MHz(),
|
||||
dp.tim0,
|
||||
);
|
||||
(Shared {}, Local { leds, button, mode })
|
||||
}
|
||||
|
||||
@ -118,26 +95,4 @@ mod app {
|
||||
leds[0].on();
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = OC0)]
|
||||
fn ms_tick(_cx: ms_tick::Context) {
|
||||
default_ms_irq_handler();
|
||||
}
|
||||
|
||||
fn prompt_mode(mut down_channel: rtt_target::DownChannel) -> PressMode {
|
||||
rprintln!("Using prompt mode");
|
||||
rprintln!("Please enter the mode [0: Toggle, 1: Keep]");
|
||||
let mut read_buf: [u8; 16] = [0; 16];
|
||||
let mut read;
|
||||
loop {
|
||||
read = down_channel.read(&mut read_buf);
|
||||
for &byte in &read_buf[..read] {
|
||||
match byte as char {
|
||||
'0' => return PressMode::Toggle,
|
||||
'1' => return PressMode::Keep,
|
||||
_ => continue, // Ignore other characters
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
#[rtic::app(device = pac)]
|
||||
mod app {
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_default};
|
||||
// Import panic provider.
|
||||
use panic_probe as _;
|
||||
// Import global logger.
|
||||
use defmt_rtt as _;
|
||||
use va108xx_hal::pac;
|
||||
|
||||
#[local]
|
||||
@ -16,8 +18,7 @@ mod app {
|
||||
|
||||
#[init]
|
||||
fn init(_ctx: init::Context) -> (Shared, Local) {
|
||||
rtt_init_default!();
|
||||
rprintln!("-- Vorago RTIC template --");
|
||||
defmt::println!("-- Vorago RTIC template --");
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! More complex UART application
|
||||
//! More complex UART application on UART PA8 (TX) and PA9 (RX).
|
||||
//!
|
||||
//! Uses the IRQ capabilities of the VA10820 peripheral and the RTIC framework to poll the UART in
|
||||
//! a non-blocking way. All received data will be sent back to the sender.
|
||||
@ -14,14 +14,16 @@ const RX_RING_BUF_SIZE: usize = 1024;
|
||||
mod app {
|
||||
use super::*;
|
||||
use embedded_io::Write;
|
||||
use panic_rtt_target as _;
|
||||
use ringbuf::traits::{Consumer, Observer, Producer};
|
||||
use rtic_example::SYSCLK_FREQ;
|
||||
// Import panic provider.
|
||||
use panic_probe as _;
|
||||
// Import global logger.
|
||||
use defmt_rtt as _;
|
||||
use rtic_monotonics::Monotonic;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{
|
||||
gpio::PinsA,
|
||||
pac,
|
||||
pins::PinsA,
|
||||
prelude::*,
|
||||
uart::{self, RxWithInterrupt, Tx},
|
||||
InterruptConfig,
|
||||
@ -29,8 +31,8 @@ mod app {
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
rx: RxWithInterrupt<pac::Uarta>,
|
||||
tx: Tx<pac::Uarta>,
|
||||
rx: RxWithInterrupt,
|
||||
tx: Tx,
|
||||
}
|
||||
|
||||
#[shared]
|
||||
@ -42,24 +44,23 @@ mod app {
|
||||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- VA108xx UART Echo with IRQ example application--");
|
||||
defmt::println!("-- VA108xx UART Echo with IRQ example application--");
|
||||
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let mut dp = cx.device;
|
||||
let gpioa = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let tx = gpioa.pa9.into_funsel_2();
|
||||
let rx = gpioa.pa8.into_funsel_2();
|
||||
let dp = cx.device;
|
||||
let gpioa = PinsA::new(dp.porta);
|
||||
let tx = gpioa.pa9;
|
||||
let rx = gpioa.pa8;
|
||||
|
||||
let irq_uart = uart::Uart::new_with_interrupt(
|
||||
&mut dp.sysconfig,
|
||||
SYSCLK_FREQ,
|
||||
dp.uarta,
|
||||
(tx, rx),
|
||||
115200.Hz(),
|
||||
115200.Hz().into(),
|
||||
InterruptConfig::new(pac::Interrupt::OC3, true, true),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
let (tx, rx) = irq_uart.split();
|
||||
let mut rx = rx.into_rx_with_irq();
|
||||
|
||||
@ -104,7 +105,7 @@ mod app {
|
||||
}
|
||||
if ringbuf_full {
|
||||
// Could also drop oldest data, but that would require the consumer to be shared.
|
||||
rprintln!("buffer full, data was dropped");
|
||||
defmt::println!("buffer full, data was dropped");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,21 +5,24 @@
|
||||
#[rtic::app(device = pac, dispatchers = [OC31, OC30, OC29])]
|
||||
mod app {
|
||||
use cortex_m::asm;
|
||||
use panic_rtt_target as _;
|
||||
use rtic_example::SYSCLK_FREQ;
|
||||
use rtic_monotonics::systick::prelude::*;
|
||||
use rtic_monotonics::Monotonic;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
// Import panic provider.
|
||||
use panic_probe as _;
|
||||
// Import global logger.
|
||||
use defmt_rtt as _;
|
||||
use va108xx_hal::{
|
||||
gpio::{OutputReadablePushPull, Pin, PinsA, PA10, PA6, PA7},
|
||||
gpio::{Output, PinState},
|
||||
pac,
|
||||
pins::PinsA,
|
||||
};
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
led0: Pin<PA10, OutputReadablePushPull>,
|
||||
led1: Pin<PA7, OutputReadablePushPull>,
|
||||
led2: Pin<PA6, OutputReadablePushPull>,
|
||||
led0: Output,
|
||||
led1: Output,
|
||||
led2: Output,
|
||||
}
|
||||
|
||||
#[shared]
|
||||
@ -28,16 +31,15 @@ mod app {
|
||||
rtic_monotonics::systick_monotonic!(Mono, 1_000);
|
||||
|
||||
#[init]
|
||||
fn init(mut cx: init::Context) -> (Shared, Local) {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- Vorago VA108xx RTIC template --");
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
defmt::println!("-- Vorago VA108xx RTIC template --");
|
||||
|
||||
Mono::start(cx.core.SYST, SYSCLK_FREQ.raw());
|
||||
|
||||
let porta = PinsA::new(&mut cx.device.sysconfig, cx.device.porta);
|
||||
let led0 = porta.pa10.into_readable_push_pull_output();
|
||||
let led1 = porta.pa7.into_readable_push_pull_output();
|
||||
let led2 = porta.pa6.into_readable_push_pull_output();
|
||||
let porta = PinsA::new(cx.device.porta);
|
||||
let led0 = Output::new(porta.pa10, PinState::Low);
|
||||
let led1 = Output::new(porta.pa7, PinState::Low);
|
||||
let led2 = Output::new(porta.pa6, PinState::Low);
|
||||
blinky::spawn().ok();
|
||||
(Shared {}, Local { led0, led1, led2 })
|
||||
}
|
||||
@ -56,7 +58,7 @@ mod app {
|
||||
)]
|
||||
async fn blinky(cx: blinky::Context) {
|
||||
loop {
|
||||
rprintln!("toggling LEDs");
|
||||
defmt::println!("toggling LEDs");
|
||||
cx.local.led0.toggle();
|
||||
cx.local.led1.toggle();
|
||||
cx.local.led2.toggle();
|
||||
|
@ -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"
|
||||
|
@ -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(50.MHz(), dp.tim1);
|
||||
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()
|
||||
}
|
||||
|
@ -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(50.MHz(), dp.tim0);
|
||||
|
||||
// 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(50.MHz(), dp.tim3);
|
||||
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(50.MHz(), dp.tim4);
|
||||
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(50.MHz(), dp.tim5);
|
||||
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;
|
||||
}
|
||||
|
@ -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(50.MHz(), (pinsa.pa3, dp.tim3), 10.Hz()).unwrap();
|
||||
let mut delay = CountdownTimer::new(50.MHz(), dp.tim0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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(50.MHz(), dp.tim0);
|
||||
|
||||
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(50.MHz(), 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(50.MHz(), 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(50.MHz(), 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()
|
||||
}
|
||||
|
@ -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(50.MHz(), dp.tim2);
|
||||
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(get_sys_clock().unwrap(), dp.tim0);
|
||||
ms_timer.enable_interrupt(InterruptConfig::new(interrupt::OC0, true, true));
|
||||
ms_timer.start(1.kHz());
|
||||
let mut second_timer = CountdownTimer::new(get_sys_clock().unwrap(), dp.tim1);
|
||||
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);
|
||||
}
|
||||
|
@ -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(50.MHz(), dp.uarta, (tx, rx), 115200.Hz().into())
|
||||
.unwrap();
|
||||
|
||||
let (mut tx, mut rx) = uart.split();
|
||||
writeln!(tx, "Hello World\r").unwrap();
|
||||
|
@ -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]
|
||||
|
Reference in New Issue
Block a user