move to updated API
This commit is contained in:
parent
dfe34e965f
commit
121b467fb9
@ -16,9 +16,11 @@ static_assertions = "1"
|
||||
|
||||
[dependencies.va108xx-hal]
|
||||
version = "0.11"
|
||||
path = "../va108xx-hal"
|
||||
|
||||
[dependencies.vorago-reb1]
|
||||
version = "0.8"
|
||||
path = "../vorago-reb1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -104,11 +104,11 @@ fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- VA108xx bootloader --");
|
||||
}
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let mut timer = CountdownTimer::new(&mut dp.sysconfig, CLOCK_FREQ, dp.tim0);
|
||||
let mut timer = CountdownTimer::new(CLOCK_FREQ, dp.tim0);
|
||||
|
||||
let mut nvm = M95M01::new(&mut dp.sysconfig, CLOCK_FREQ, dp.spic);
|
||||
let mut nvm = M95M01::new(CLOCK_FREQ, dp.spic);
|
||||
|
||||
if FLASH_SELF {
|
||||
let mut first_four_bytes: [u8; 4] = [0; 4];
|
||||
@ -186,7 +186,7 @@ fn check_own_crc(
|
||||
sysconfig: &pac::Sysconfig,
|
||||
cp: &cortex_m::Peripherals,
|
||||
nvm: &mut NvmWrapper,
|
||||
timer: &mut CountdownTimer<pac::Tim0>,
|
||||
timer: &mut CountdownTimer,
|
||||
) {
|
||||
let crc_exp = unsafe { (BOOTLOADER_CRC_ADDR as *const u16).read_unaligned().to_be() };
|
||||
// I'd prefer to use [core::slice::from_raw_parts], but that is problematic
|
||||
@ -276,7 +276,7 @@ fn boot_app(
|
||||
syscfg: &pac::Sysconfig,
|
||||
cp: &cortex_m::Peripherals,
|
||||
app_sel: AppSel,
|
||||
timer: &mut CountdownTimer<pac::Tim0>,
|
||||
timer: &mut CountdownTimer,
|
||||
) -> ! {
|
||||
if DEBUG_PRINTOUTS && RTT_PRINTOUT {
|
||||
rprintln!("booting app {:?}", app_sel);
|
||||
|
@ -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_high() {
|
||||
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,13 +24,14 @@ 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,
|
||||
rx_asynch::{on_interrupt_rx, RxAsync},
|
||||
Bank, RxAsyncOverwriting, Tx,
|
||||
RxAsyncOverwriting, Tx, UartId,
|
||||
},
|
||||
InterruptConfig,
|
||||
};
|
||||
@ -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(UartId::A, &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(UartId::B, &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,10 +17,11 @@ 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},
|
||||
uart::{self, on_interrupt_tx, TxAsync, UartId},
|
||||
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(UartId::A);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -22,5 +22,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" }
|
||||
|
@ -9,10 +9,10 @@ mod app {
|
||||
use rtt_target::{rprintln, rtt_init_default, set_print_channel};
|
||||
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;
|
||||
@ -61,39 +61,28 @@ mod app {
|
||||
rprintln!("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 })
|
||||
}
|
||||
|
||||
@ -119,11 +108,6 @@ mod app {
|
||||
}
|
||||
}
|
||||
|
||||
#[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]");
|
||||
|
@ -20,17 +20,13 @@ mod app {
|
||||
use rtic_monotonics::Monotonic;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{
|
||||
gpio::PinsA,
|
||||
pac,
|
||||
prelude::*,
|
||||
uart::{self, RxWithInterrupt, Tx},
|
||||
InterruptConfig,
|
||||
pac, pins::PinsA, prelude::*, uart::{self, RxWithInterrupt, Tx}, InterruptConfig
|
||||
};
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
rx: RxWithInterrupt<pac::Uarta>,
|
||||
tx: Tx<pac::Uarta>,
|
||||
rx: RxWithInterrupt,
|
||||
tx: Tx,
|
||||
}
|
||||
|
||||
#[shared]
|
||||
@ -47,19 +43,18 @@ mod app {
|
||||
|
||||
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();
|
||||
|
||||
|
@ -11,15 +11,15 @@ mod app {
|
||||
use rtic_monotonics::Monotonic;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{
|
||||
gpio::{OutputReadablePushPull, Pin, PinsA, PA10, PA6, PA7},
|
||||
pac,
|
||||
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 +28,16 @@ mod app {
|
||||
rtic_monotonics::systick_monotonic!(Mono, 1_000);
|
||||
|
||||
#[init]
|
||||
fn init(mut cx: init::Context) -> (Shared, Local) {
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- 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 })
|
||||
}
|
||||
|
@ -17,7 +17,9 @@ cortex-m-semihosting = "0.5.0"
|
||||
|
||||
[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()
|
||||
}
|
||||
|
@ -15,38 +15,27 @@ use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{
|
||||
pac::{self, interrupt},
|
||||
prelude::*,
|
||||
timer::{
|
||||
default_ms_irq_handler, set_up_ms_delay_provider, CascadeCtrl, CascadeSource,
|
||||
CountdownTimer, Event, InterruptConfig,
|
||||
},
|
||||
timer::{CascadeCtrl, 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));
|
||||
static CSD_TGT_1: Mutex<RefCell<Option<CountdownTimer>>> = Mutex::new(RefCell::new(None));
|
||||
static CSD_TGT_2: Mutex<RefCell<Option<CountdownTimer>>> = Mutex::new(RefCell::new(None));
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- 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).auto_disable(true);
|
||||
cascade_triggerer.enable_interupt(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).auto_deactivate(true);
|
||||
cascade_target_1
|
||||
.cascade_0_source(CascadeSource::Tim(3))
|
||||
.expect("Configuring cascade source for TIM4 failed");
|
||||
@ -60,19 +49,13 @@ fn main() -> ! {
|
||||
// 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_interupt(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).auto_deactivate(true);
|
||||
// Set TIM4 as cascade source
|
||||
cascade_target_2
|
||||
.cascade_1_source(CascadeSource::Tim(4))
|
||||
@ -86,12 +69,7 @@ fn main() -> ! {
|
||||
// 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_interupt(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());
|
||||
@ -115,11 +93,6 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn OC0() {
|
||||
default_ms_irq_handler()
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn OC1() {
|
||||
static mut IDX: u32 = 0;
|
||||
|
@ -7,33 +7,27 @@ use embedded_hal::{delay::DelayNs, pwm::SetDutyCycle};
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
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);
|
||||
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
|
||||
@ -45,8 +39,7 @@ fn main() -> ! {
|
||||
rprintln!("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 +48,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 {
|
||||
@ -67,6 +60,6 @@ fn main() -> ! {
|
||||
rprintln!("Lower limit: {}", pwmb.pwmb_lower_limit());
|
||||
rprintln!("Upper limit: {}", pwmb.pwmb_upper_limit());
|
||||
}
|
||||
reduced_pin = ReducedPwmPin::<PwmA>::from(pwmb);
|
||||
pwm = PwmPin::<PwmA>::from(pwmb);
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ use embedded_hal::{
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{
|
||||
gpio::{PinsA, PinsB},
|
||||
pac::{self, interrupt},
|
||||
pins::{PinsA, PinsB},
|
||||
prelude::*,
|
||||
spi::{self, Spi, SpiBase, SpiClkConfig, TransferConfigWithHwcs},
|
||||
timer::{default_ms_irq_handler, set_up_ms_tick},
|
||||
spi::{self, configure_pin_as_hw_cs_pin, Spi, SpiClkConfig, TransferConfig},
|
||||
timer::CountdownTimer,
|
||||
InterruptConfig,
|
||||
};
|
||||
|
||||
@ -46,20 +46,15 @@ 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,
|
||||
);
|
||||
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 spia_ref: RefCell<Option<SpiBase<pac::Spia, u8>>> = RefCell::new(None);
|
||||
//let spib_ref: RefCell<Option<SpiBase<pac::Spib, u8>>> = RefCell::new(None);
|
||||
let spi = None;
|
||||
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 +62,82 @@ fn main() -> ! {
|
||||
}
|
||||
|
||||
// Set up the SPI peripheral
|
||||
match SPI_BUS_SEL {
|
||||
let 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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
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();
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
#[allow(non_snake_case)]
|
||||
fn OC0() {
|
||||
default_ms_irq_handler()
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ use va108xx_hal::{
|
||||
pac::{self, interrupt},
|
||||
prelude::*,
|
||||
time::Hertz,
|
||||
timer::{
|
||||
default_ms_irq_handler, set_up_ms_tick, CountdownTimer, Event, InterruptConfig, MS_COUNTER,
|
||||
},
|
||||
timer::{default_ms_irq_handler, CountdownTimer, Event, InterruptConfig, MS_COUNTER},
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -66,21 +64,11 @@ 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_interupt(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_interupt(InterruptConfig::new(interrupt::OC1, true, true));
|
||||
second_timer.start(1.Hz());
|
||||
}
|
||||
}
|
||||
|
@ -15,25 +15,20 @@ 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};
|
||||
use va108xx_hal::{pac, pins::PinsA, prelude::*, uart};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- 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();
|
||||
|
@ -29,6 +29,7 @@ rtic-sync = {version = "1", features = ["defmt-03"]}
|
||||
|
||||
[dependencies.va108xx-hal]
|
||||
version = "0.11"
|
||||
path = "../va108xx-hal"
|
||||
features = ["defmt"]
|
||||
|
||||
[dependencies.vorago-reb1]
|
||||
|
@ -68,7 +68,7 @@ mod app {
|
||||
use spacepackets::ecss::{
|
||||
tc::PusTcReader, tm::PusTmCreator, EcssEnumU8, PusPacket, WritablePusPacket,
|
||||
};
|
||||
use va108xx_hal::gpio::PinsA;
|
||||
use va108xx_hal::pins::PinsA;
|
||||
use va108xx_hal::uart::IrqContextTimeoutOrMaxSize;
|
||||
use va108xx_hal::{pac, uart, InterruptConfig};
|
||||
use vorago_reb1::m95m01::M95M01;
|
||||
@ -83,8 +83,8 @@ mod app {
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
uart_rx: uart::RxWithInterrupt<pac::Uarta>,
|
||||
uart_tx: uart::Tx<pac::Uarta>,
|
||||
uart_rx: uart::RxWithInterrupt,
|
||||
uart_tx: uart::Tx,
|
||||
rx_context: IrqContextTimeoutOrMaxSize,
|
||||
verif_reporter: VerificationReportCreator,
|
||||
nvm: M95M01,
|
||||
@ -108,18 +108,18 @@ mod app {
|
||||
let mut dp = cx.device;
|
||||
let nvm = M95M01::new(&mut dp.sysconfig, SYSCLK_FREQ, dp.spic);
|
||||
|
||||
let gpioa = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let tx = gpioa.pa9.into_funsel_2();
|
||||
let rx = gpioa.pa8.into_funsel_2();
|
||||
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),
|
||||
UART_BAUDRATE.Hz(),
|
||||
UART_BAUDRATE.Hz().into(),
|
||||
InterruptConfig::new(pac::Interrupt::OC0, true, true),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
let (tx, rx) = irq_uart.split();
|
||||
// Unwrap is okay, we explicitely set the interrupt ID.
|
||||
let mut rx = rx.into_rx_with_irq();
|
||||
|
@ -20,7 +20,7 @@ embassy-time-queue-utils = "0.1"
|
||||
|
||||
once_cell = { version = "1", default-features = false, features = ["critical-section"] }
|
||||
|
||||
va108xx-hal = { version = ">=0.10, <=0.11" }
|
||||
va108xx-hal = { version = ">=0.10, <=0.11", path = "../va108xx-hal" }
|
||||
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies]
|
||||
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"] }
|
||||
|
@ -45,7 +45,7 @@ use va108xx_hal::{
|
||||
clock::enable_peripheral_clock,
|
||||
enable_nvic_interrupt, pac,
|
||||
prelude::*,
|
||||
timer::{enable_tim_clk, get_tim_raw, TimRegInterface, ValidTim},
|
||||
timer::{enable_tim_clk, get_tim_raw, TimMarker, TimRegInterface},
|
||||
PeripheralSelect,
|
||||
};
|
||||
|
||||
@ -109,48 +109,28 @@ pub fn time_driver() -> &'static TimerDriver {
|
||||
/// This should be used if the interrupt handler is provided by the library, which is the
|
||||
/// default case.
|
||||
#[cfg(feature = "irqs-in-lib")]
|
||||
pub fn init<TimekeeperTim: TimRegInterface + ValidTim, AlarmTim: TimRegInterface + ValidTim>(
|
||||
syscfg: &mut pac::Sysconfig,
|
||||
irqsel: &pac::Irqsel,
|
||||
sysclk: impl Into<Hertz>,
|
||||
pub fn init<TimekeeperTim: TimRegInterface + TimMarker, AlarmTim: TimRegInterface + TimMarker>(
|
||||
sysclk: Hertz,
|
||||
timekeeper_tim: TimekeeperTim,
|
||||
alarm_tim: AlarmTim,
|
||||
) {
|
||||
TIME_DRIVER.init(
|
||||
syscfg,
|
||||
irqsel,
|
||||
sysclk,
|
||||
timekeeper_tim,
|
||||
alarm_tim,
|
||||
TIMEKEEPER_IRQ,
|
||||
ALARM_IRQ,
|
||||
)
|
||||
TIME_DRIVER.init(sysclk, timekeeper_tim, alarm_tim, TIMEKEEPER_IRQ, ALARM_IRQ)
|
||||
}
|
||||
|
||||
/// Initialization method for embassy when using custom IRQ handlers.
|
||||
///
|
||||
/// Requires an explicit [pac::Interrupt] argument for the timekeeper and alarm IRQs.
|
||||
pub fn init_with_custom_irqs<
|
||||
TimekeeperTim: TimRegInterface + ValidTim,
|
||||
AlarmTim: TimRegInterface + ValidTim,
|
||||
TimekeeperTim: TimRegInterface + TimMarker,
|
||||
AlarmTim: TimRegInterface + TimMarker,
|
||||
>(
|
||||
syscfg: &mut pac::Sysconfig,
|
||||
irqsel: &pac::Irqsel,
|
||||
sysclk: impl Into<Hertz>,
|
||||
sysclk: Hertz,
|
||||
timekeeper_tim: TimekeeperTim,
|
||||
alarm_tim: AlarmTim,
|
||||
timekeeper_irq: pac::Interrupt,
|
||||
alarm_irq: pac::Interrupt,
|
||||
) {
|
||||
TIME_DRIVER.init(
|
||||
syscfg,
|
||||
irqsel,
|
||||
sysclk,
|
||||
timekeeper_tim,
|
||||
alarm_tim,
|
||||
timekeeper_irq,
|
||||
alarm_irq,
|
||||
)
|
||||
TIME_DRIVER.init(sysclk, timekeeper_tim, alarm_tim, timekeeper_irq, alarm_irq)
|
||||
}
|
||||
|
||||
struct AlarmState {
|
||||
@ -180,11 +160,9 @@ pub struct TimerDriver {
|
||||
|
||||
impl TimerDriver {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn init<TimekeeperTim: TimRegInterface + ValidTim, AlarmTim: TimRegInterface + ValidTim>(
|
||||
fn init<TimekeeperTim: TimRegInterface + TimMarker, AlarmTim: TimRegInterface + TimMarker>(
|
||||
&self,
|
||||
syscfg: &mut pac::Sysconfig,
|
||||
irqsel: &pac::Irqsel,
|
||||
sysclk: impl Into<Hertz>,
|
||||
sysclk: Hertz,
|
||||
timekeeper_tim: TimekeeperTim,
|
||||
alarm_tim: AlarmTim,
|
||||
timekeeper_irq: pac::Interrupt,
|
||||
@ -193,13 +171,12 @@ impl TimerDriver {
|
||||
if ALARM_TIM.get().is_some() || TIMEKEEPER_TIM.get().is_some() {
|
||||
return;
|
||||
}
|
||||
ALARM_TIM.set(AlarmTim::TIM_ID).ok();
|
||||
TIMEKEEPER_TIM.set(TimekeeperTim::TIM_ID).ok();
|
||||
enable_peripheral_clock(syscfg, PeripheralSelect::Irqsel);
|
||||
enable_tim_clk(syscfg, timekeeper_tim.tim_id());
|
||||
ALARM_TIM.set(AlarmTim::ID.raw_id()).ok();
|
||||
TIMEKEEPER_TIM.set(TimekeeperTim::ID.raw_id()).ok();
|
||||
enable_peripheral_clock(PeripheralSelect::Irqsel);
|
||||
enable_tim_clk(timekeeper_tim.raw_id());
|
||||
let timekeeper_reg_block = timekeeper_tim.reg_block();
|
||||
let alarm_tim_reg_block = alarm_tim.reg_block();
|
||||
let sysclk = sysclk.into();
|
||||
// Initiate scale value here. This is required to convert timer ticks back to a timestamp.
|
||||
SCALE.set((sysclk.raw() / TICK_HZ as u32) as u64).unwrap();
|
||||
timekeeper_reg_block
|
||||
@ -209,9 +186,10 @@ impl TimerDriver {
|
||||
timekeeper_reg_block
|
||||
.cnt_value()
|
||||
.write(|w| unsafe { w.bits(u32::MAX) });
|
||||
let irqsel = unsafe { va108xx_hal::pac::Irqsel::steal() };
|
||||
// Switch on. Timekeeping should always be done.
|
||||
irqsel
|
||||
.tim0(timekeeper_tim.tim_id() as usize)
|
||||
.tim0(timekeeper_tim.raw_id() as usize)
|
||||
.write(|w| unsafe { w.bits(timekeeper_irq as u32) });
|
||||
unsafe {
|
||||
enable_nvic_interrupt(timekeeper_irq);
|
||||
@ -223,7 +201,7 @@ impl TimerDriver {
|
||||
.enable()
|
||||
.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
enable_tim_clk(syscfg, alarm_tim.tim_id());
|
||||
enable_tim_clk(alarm_tim.raw_id());
|
||||
|
||||
// Explicitely disable alarm timer until needed.
|
||||
alarm_tim_reg_block.ctrl().modify(|_, w| {
|
||||
@ -235,7 +213,7 @@ impl TimerDriver {
|
||||
enable_nvic_interrupt(alarm_irq);
|
||||
}
|
||||
irqsel
|
||||
.tim0(alarm_tim.tim_id() as usize)
|
||||
.tim0(alarm_tim.raw_id() as usize)
|
||||
.write(|w| unsafe { w.bits(alarm_irq as u32) });
|
||||
}
|
||||
|
||||
|
@ -2,24 +2,13 @@
|
||||
//!
|
||||
//! This also includes functionality to enable the peripheral clocks
|
||||
use crate::time::Hertz;
|
||||
use crate::PeripheralSelect;
|
||||
use cortex_m::interrupt::{self, Mutex};
|
||||
use once_cell::unsync::OnceCell;
|
||||
|
||||
static SYS_CLOCK: Mutex<OnceCell<Hertz>> = Mutex::new(OnceCell::new());
|
||||
pub use vorago_shared_periphs::gpio::FilterClkSel;
|
||||
pub use vorago_shared_periphs::sysconfig::{disable_peripheral_clock, enable_peripheral_clock};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum FilterClkSel {
|
||||
SysClk = 0,
|
||||
Clk1 = 1,
|
||||
Clk2 = 2,
|
||||
Clk3 = 3,
|
||||
Clk4 = 4,
|
||||
Clk5 = 5,
|
||||
Clk6 = 6,
|
||||
Clk7 = 7,
|
||||
}
|
||||
static SYS_CLOCK: Mutex<OnceCell<Hertz>> = Mutex::new(OnceCell::new());
|
||||
|
||||
/// The Vorago in powered by an external clock which might have different frequencies.
|
||||
/// The clock can be set here so it can be used by other software components as well.
|
||||
@ -61,5 +50,3 @@ pub fn set_clk_div_register(syscfg: &mut va108xx::Sysconfig, clk_sel: FilterClkS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use vorago_shared_periphs::sysconfig::{disable_peripheral_clock, enable_peripheral_clock};
|
||||
|
@ -307,7 +307,7 @@ impl<I2C> I2cBase<I2C> {
|
||||
|
||||
impl<I2c: Instance> I2cBase<I2c> {
|
||||
pub fn new(
|
||||
sysclk: Hertz,
|
||||
sys_clk: Hertz,
|
||||
i2c: I2c,
|
||||
speed_mode: I2cSpeed,
|
||||
ms_cfg: Option<&MasterConfig>,
|
||||
@ -315,10 +315,7 @@ impl<I2c: Instance> I2cBase<I2c> {
|
||||
) -> Result<Self, ClockTooSlowForFastI2cError> {
|
||||
enable_peripheral_clock(I2c::PERIPH_SEL);
|
||||
|
||||
let mut i2c_base = I2cBase {
|
||||
i2c,
|
||||
sys_clk: sysclk.into(),
|
||||
};
|
||||
let mut i2c_base = I2cBase { i2c, sys_clk };
|
||||
if let Some(ms_cfg) = ms_cfg {
|
||||
i2c_base.cfg_master(ms_cfg);
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
pub use vorago_shared_periphs::gpio::{Pin, PinId, PinMarker, Port};
|
||||
use vorago_shared_periphs::sysconfig::reset_peripheral_for_cycles;
|
||||
|
||||
use crate::{sysconfig::reset_peripheral_for_cycles, PeripheralSelect};
|
||||
pub use crate::gpio::{Pin, PinId, PinIdProvider, Port};
|
||||
|
||||
use crate::sealed::Sealed;
|
||||
use crate::PeripheralSelect;
|
||||
|
||||
pub trait PinMarker: Sealed {
|
||||
const ID: PinId;
|
||||
}
|
||||
|
||||
macro_rules! pin_id {
|
||||
($Id:ident, $Port:path, $num:literal) => {
|
||||
@ -11,14 +18,18 @@ macro_rules! pin_id {
|
||||
pub enum $Id {}
|
||||
|
||||
impl $crate::sealed::Sealed for $Id {}
|
||||
impl PinMarker for $Id {
|
||||
const ID: PinId = PinId::new($Port, $num);
|
||||
impl PinIdProvider for $Id {
|
||||
const ID: PinId = PinId::new_unchecked($Port, $num);
|
||||
}
|
||||
|
||||
impl PinMarker for Pin<$Id> {
|
||||
const ID: PinId = $Id::ID;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<I: PinMarker + crate::sealed::Sealed> crate::sealed::Sealed for Pin<I> {}
|
||||
impl<I: PinIdProvider + Sealed> Sealed for Pin<I> {}
|
||||
|
||||
pin_id!(Pa0, Port::A, 0);
|
||||
pin_id!(Pa1, Port::A, 1);
|
||||
|
@ -8,10 +8,11 @@
|
||||
use core::convert::Infallible;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use vorago_shared_periphs::PeripheralSelect;
|
||||
|
||||
use crate::clock::enable_peripheral_clock;
|
||||
use crate::pac;
|
||||
use crate::time::Hertz;
|
||||
use crate::timer::{TimId, TimPeripheralMarker, TimPin, TimRegInterface};
|
||||
use crate::timer::{TimId, TimMarker, TimPin, TimRegInterface};
|
||||
|
||||
const DUTY_MAX: u16 = u16::MAX;
|
||||
|
||||
@ -56,9 +57,8 @@ pub struct PwmPin<Mode = PwmA> {
|
||||
|
||||
impl<Mode> PwmPin<Mode> {
|
||||
/// Create a new strongly typed PWM pin
|
||||
pub fn new<Pin: TimPin, Tim: TimPeripheralMarker + TimRegInterface>(
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
sys_clk: impl Into<Hertz> + Copy,
|
||||
pub fn new<Pin: TimPin, Tim: TimMarker + TimRegInterface>(
|
||||
sys_clk: Hertz,
|
||||
pin_and_tim: (Pin, Tim),
|
||||
initial_period: impl Into<Hertz> + Copy,
|
||||
) -> Result<Self, TimMissmatchError> {
|
||||
@ -74,12 +74,13 @@ impl<Mode> PwmPin<Mode> {
|
||||
current_lower_limit: 0,
|
||||
current_period: initial_period.into(),
|
||||
current_rst_val: 0,
|
||||
sys_clk: sys_clk.into(),
|
||||
sys_clk,
|
||||
mode: PhantomData,
|
||||
};
|
||||
enable_peripheral_clock(crate::clock::PeripheralClocks::Gpio);
|
||||
enable_peripheral_clock(crate::clock::PeripheralClocks::Ioconfig);
|
||||
sys_cfg
|
||||
enable_peripheral_clock(PeripheralSelect::Gpio);
|
||||
enable_peripheral_clock(PeripheralSelect::Ioconfig);
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.tim_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | pin_and_tim.1.mask_32()) });
|
||||
pin.enable_pwm_a();
|
||||
|
@ -9,13 +9,22 @@
|
||||
//! - [Blocking SPI example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/simple/examples/spi.rs)
|
||||
//! - [REB1 ADC example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/max11519-adc.rs)
|
||||
//! - [REB1 EEPROM library](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/src/m95m01.rs)
|
||||
use crate::{clock::enable_peripheral_clock, pac, time::Hertz, PeripheralSelect};
|
||||
use crate::{
|
||||
clock::enable_peripheral_clock, pac, pins::PinMarker, sealed::Sealed, time::Hertz,
|
||||
PeripheralSelect,
|
||||
};
|
||||
use core::{convert::Infallible, fmt::Debug, marker::PhantomData, ops::Deref};
|
||||
use embedded_hal::spi::{Mode, MODE_0};
|
||||
use pins::{HwCsProvider, PinMiso, PinMosi, PinSck};
|
||||
use vorago_shared_periphs::gpio::IoPeriphPin;
|
||||
|
||||
pub mod pins;
|
||||
|
||||
pub fn configure_pin_as_hw_cs_pin<P: PinMarker + HwCsProvider>(_pin: P) -> HwChipSelectId {
|
||||
IoPeriphPin::new(P::ID, P::FUN_SEL, None);
|
||||
P::CS_ID
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Defintions
|
||||
//==================================================================================================
|
||||
@ -41,7 +50,7 @@ pub enum HwChipSelectId {
|
||||
Id7 = 7,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum SpiId {
|
||||
A,
|
||||
@ -80,7 +89,7 @@ pub type SpiRegBlock = pac::spia::RegisterBlock;
|
||||
|
||||
/// Common trait implemented by all PAC peripheral access structures. The register block
|
||||
/// format is the same for all SPI blocks.
|
||||
pub trait SpiPeripheralMarker: Deref<Target = SpiRegBlock> {
|
||||
pub trait SpiMarker: Deref<Target = SpiRegBlock> + Sealed {
|
||||
const ID: SpiId;
|
||||
const PERIPH_SEL: PeripheralSelect;
|
||||
|
||||
@ -92,7 +101,7 @@ pub trait SpiPeripheralMarker: Deref<Target = SpiRegBlock> {
|
||||
}
|
||||
}
|
||||
|
||||
impl SpiPeripheralMarker for pac::Spia {
|
||||
impl SpiMarker for pac::Spia {
|
||||
const ID: SpiId = SpiId::A;
|
||||
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi0;
|
||||
|
||||
@ -101,8 +110,9 @@ impl SpiPeripheralMarker for pac::Spia {
|
||||
Self::ptr()
|
||||
}
|
||||
}
|
||||
impl Sealed for pac::Spia {}
|
||||
|
||||
impl SpiPeripheralMarker for pac::Spib {
|
||||
impl SpiMarker for pac::Spib {
|
||||
const ID: SpiId = SpiId::B;
|
||||
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi1;
|
||||
|
||||
@ -111,8 +121,9 @@ impl SpiPeripheralMarker for pac::Spib {
|
||||
Self::ptr()
|
||||
}
|
||||
}
|
||||
impl Sealed for pac::Spib {}
|
||||
|
||||
impl SpiPeripheralMarker for pac::Spic {
|
||||
impl SpiMarker for pac::Spic {
|
||||
const ID: SpiId = SpiId::C;
|
||||
const PERIPH_SEL: PeripheralSelect = PeripheralSelect::Spi2;
|
||||
|
||||
@ -121,6 +132,7 @@ impl SpiPeripheralMarker for pac::Spic {
|
||||
Self::ptr()
|
||||
}
|
||||
}
|
||||
impl Sealed for pac::Spic {}
|
||||
|
||||
//==================================================================================================
|
||||
// Config
|
||||
@ -134,17 +146,6 @@ pub trait TransferConfigProvider {
|
||||
fn hw_cs_id(&self) -> u8;
|
||||
}
|
||||
|
||||
/*
|
||||
/// This struct contains all configuration parameter which are transfer specific
|
||||
/// and might change for transfers to different SPI slaves
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct TransferConfigWithHwcs<HwCs> {
|
||||
pub hw_cs: Option<HwCs>,
|
||||
pub cfg: TransferConfig,
|
||||
}
|
||||
*/
|
||||
|
||||
/// Type erased variant of the transfer configuration. This is required to avoid generics in
|
||||
/// the SPI constructor.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -163,80 +164,26 @@ pub struct TransferConfig {
|
||||
pub hw_cs: Option<HwChipSelectId>,
|
||||
}
|
||||
|
||||
/*
|
||||
impl TransferConfigWithHwcs<NoneT> {
|
||||
pub fn new_no_hw_cs(
|
||||
impl TransferConfig {
|
||||
pub fn new_with_hw_cs(
|
||||
clk_cfg: Option<SpiClkConfig>,
|
||||
mode: Option<Mode>,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
sod: bool,
|
||||
hw_cs_id: HwChipSelectId,
|
||||
) -> Self {
|
||||
TransferConfigWithHwcs {
|
||||
hw_cs: None,
|
||||
cfg: TransferConfig {
|
||||
clk_cfg,
|
||||
mode,
|
||||
sod,
|
||||
blockmode,
|
||||
bmstall,
|
||||
hw_cs: HwChipSelectId::Invalid,
|
||||
},
|
||||
TransferConfig {
|
||||
clk_cfg,
|
||||
mode,
|
||||
sod,
|
||||
blockmode,
|
||||
bmstall,
|
||||
hw_cs: Some(hw_cs_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<HwCs: HwCsProvider> TransferConfigWithHwcs<HwCs> {
|
||||
pub fn new(
|
||||
clk_cfg: Option<SpiClkConfig>,
|
||||
mode: Option<Mode>,
|
||||
hw_cs: Option<HwCs>,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
sod: bool,
|
||||
) -> Self {
|
||||
TransferConfigWithHwcs {
|
||||
hw_cs,
|
||||
cfg: TransferConfig {
|
||||
clk_cfg,
|
||||
mode,
|
||||
sod,
|
||||
blockmode,
|
||||
bmstall,
|
||||
hw_cs: HwCs::CS_ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downgrade(self) -> TransferConfig {
|
||||
self.cfg
|
||||
}
|
||||
}
|
||||
|
||||
impl<HwCs: HwCsProvider> TransferConfigProvider for TransferConfigWithHwcs<HwCs> {
|
||||
/// Slave Output Disable
|
||||
fn sod(&mut self, sod: bool) {
|
||||
self.cfg.sod = sod;
|
||||
}
|
||||
|
||||
fn blockmode(&mut self, blockmode: bool) {
|
||||
self.cfg.blockmode = blockmode;
|
||||
}
|
||||
|
||||
fn mode(&mut self, mode: Mode) {
|
||||
self.cfg.mode = Some(mode);
|
||||
}
|
||||
|
||||
fn clk_cfg(&mut self, clk_cfg: SpiClkConfig) {
|
||||
self.cfg.clk_cfg = Some(clk_cfg);
|
||||
}
|
||||
|
||||
fn hw_cs_id(&self) -> u8 {
|
||||
HwCs::CS_ID as u8
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@ -373,25 +320,6 @@ pub trait SpiLowLevel {
|
||||
fn read_fifo_unchecked(&mut self) -> u32;
|
||||
}
|
||||
|
||||
pub struct Spi<Word = u8> {
|
||||
id: SpiId,
|
||||
reg_block: *mut SpiRegBlock,
|
||||
cfg: SpiConfig,
|
||||
sys_clk: Hertz,
|
||||
/// Fill word for read-only SPI transactions.
|
||||
pub fill_word: Word,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
word: PhantomData<Word>,
|
||||
}
|
||||
|
||||
/*
|
||||
pub struct Spi<, Pins, Word = u8> {
|
||||
inner: SpiBase<SpiInstance, Word>,
|
||||
pins: Pins,
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline(always)]
|
||||
pub fn mode_to_cpo_cph_bit(mode: embedded_hal::spi::Mode) -> (bool, bool) {
|
||||
match mode {
|
||||
@ -510,28 +438,69 @@ pub fn clk_div_for_target_clock(
|
||||
Some(rounded_div as u16)
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("peripheral or peripheral pin ID is not consistent")]
|
||||
pub struct SpiIdMissmatchError;
|
||||
|
||||
/// SPI peripheral driver structure.
|
||||
pub struct Spi<Word = u8> {
|
||||
id: SpiId,
|
||||
reg_block: *mut SpiRegBlock,
|
||||
cfg: SpiConfig,
|
||||
sys_clk: Hertz,
|
||||
/// Fill word for read-only SPI transactions.
|
||||
fill_word: Word,
|
||||
blockmode: bool,
|
||||
bmstall: bool,
|
||||
word: PhantomData<Word>,
|
||||
}
|
||||
|
||||
impl<Word: WordProvider> Spi<Word>
|
||||
where
|
||||
<Word as TryFrom<u32>>::Error: core::fmt::Debug,
|
||||
{
|
||||
/// Create a new SPI struct
|
||||
///
|
||||
/// You can delete the pin type information by calling the
|
||||
/// [`downgrade`](Self::downgrade) function
|
||||
/// Create a new SPI struct.
|
||||
///
|
||||
/// ## Arguments
|
||||
/// * `syscfg` - Can be passed optionally to enable the peripheral clock
|
||||
/// * `sys_clk` - System clock
|
||||
/// * `spi` - SPI bus to use
|
||||
/// * `pins` - Pins to be used for SPI transactions. These pins are consumed
|
||||
/// to ensure the pins can not be used for other purposes anymore
|
||||
/// * `spi_cfg` - Configuration specific to the SPI bus
|
||||
pub fn new<SpiI: SpiPeripheralMarker, Sck: PinSck, Miso: PinMiso, Mosi: PinMosi>(
|
||||
sys_clk: impl Into<Hertz>,
|
||||
pub fn new_for_rom<SpiI: SpiMarker>(
|
||||
sys_clk: Hertz,
|
||||
spi: SpiI,
|
||||
spi_cfg: SpiConfig,
|
||||
) -> Result<Self, SpiIdMissmatchError> {
|
||||
if SpiI::ID != SpiId::C {
|
||||
return Err(SpiIdMissmatchError);
|
||||
}
|
||||
Ok(Self::new_generic(sys_clk, spi, spi_cfg))
|
||||
}
|
||||
/// Create a new SPI struct.
|
||||
///
|
||||
/// ## Arguments
|
||||
/// * `sys_clk` - System clock
|
||||
/// * `spi` - SPI bus to use
|
||||
/// * `pins` - Pins to be used for SPI transactions. These pins are consumed
|
||||
/// to ensure the pins can not be used for other purposes anymore
|
||||
/// * `spi_cfg` - Configuration specific to the SPI bus
|
||||
pub fn new<SpiI: SpiMarker, Sck: PinSck, Miso: PinMiso, Mosi: PinMosi>(
|
||||
sys_clk: Hertz,
|
||||
spi: SpiI,
|
||||
_pins: (Sck, Miso, Mosi),
|
||||
spi_cfg: SpiConfig,
|
||||
) -> Self {
|
||||
) -> Result<Self, SpiIdMissmatchError> {
|
||||
if SpiI::ID != Sck::SPI_ID || SpiI::ID != Miso::SPI_ID || SpiI::ID != Mosi::SPI_ID {
|
||||
return Err(SpiIdMissmatchError);
|
||||
}
|
||||
IoPeriphPin::new(Sck::ID, Sck::FUN_SEL, None);
|
||||
IoPeriphPin::new(Miso::ID, Miso::FUN_SEL, None);
|
||||
IoPeriphPin::new(Mosi::ID, Mosi::FUN_SEL, None);
|
||||
Ok(Self::new_generic(sys_clk, spi, spi_cfg))
|
||||
}
|
||||
|
||||
pub fn new_generic<SpiI: SpiMarker>(sys_clk: Hertz, spi: SpiI, spi_cfg: SpiConfig) -> Self {
|
||||
enable_peripheral_clock(SpiI::PERIPH_SEL);
|
||||
let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(spi_cfg.init_mode);
|
||||
spi.ctrl0().write(|w| {
|
||||
@ -568,7 +537,7 @@ where
|
||||
id: SpiI::ID,
|
||||
reg_block: spi.reg_block(),
|
||||
cfg: spi_cfg,
|
||||
sys_clk: sys_clk.into(),
|
||||
sys_clk,
|
||||
fill_word: Default::default(),
|
||||
bmstall: spi_cfg.bmstall,
|
||||
blockmode: spi_cfg.blockmode,
|
||||
@ -596,6 +565,10 @@ where
|
||||
.write(|w| unsafe { w.bits(cfg.prescale_val as u32) });
|
||||
}
|
||||
|
||||
pub fn set_fill_word(&mut self, fill_word: Word) {
|
||||
self.fill_word = fill_word;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cfg_clock_from_div(&mut self, div: u16) -> Result<(), SpiClkConfigError> {
|
||||
let val = spi_clk_config_from_div(div)?;
|
||||
@ -633,6 +606,10 @@ where
|
||||
}
|
||||
|
||||
/// Configure the hardware chip select given a hardware chip select ID.
|
||||
///
|
||||
/// The pin also needs to be configured to be used as a HW CS pin. This can be done
|
||||
/// by using the [configure_pin_as_hw_cs_pin] function which also returns the
|
||||
/// corresponding [HwChipSelectId].
|
||||
#[inline]
|
||||
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId) {
|
||||
self.reg_block_mut().ctrl1().modify(|_, w| {
|
||||
@ -644,13 +621,6 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
/// Configure the hardware chip select given a physical hardware CS pin.
|
||||
#[inline]
|
||||
pub fn cfg_hw_cs_with_pin<HwCs: HwCsProvider>(&mut self, _: &HwCs) {
|
||||
// TODO: Error handling.
|
||||
self.cfg_hw_cs(HwCs::CS_ID);
|
||||
}
|
||||
|
||||
/// Disables the hardware chip select functionality. This can be used when performing
|
||||
/// external chip select handling, for example with GPIO pins.
|
||||
#[inline]
|
||||
|
@ -1,32 +1,33 @@
|
||||
use vorago_shared_periphs::gpio::{PinId, PinIdProvider};
|
||||
use vorago_shared_periphs::FunSel;
|
||||
|
||||
use crate::{
|
||||
pins::{
|
||||
Pa10, Pa11, Pa12, Pa13, Pa14, Pa15, Pa16, Pa17, Pa18, Pa19, Pa20, Pa21, Pa22, Pa23, Pa24,
|
||||
Pa25, Pa26, Pa27, Pa28, Pa29, Pa30, Pa31, Pb0, Pb1, Pb10, Pb11, Pb12, Pb13, Pb14, Pb15,
|
||||
Pb16, Pb17, Pb18, Pb19, Pb2, Pb22, Pb23, Pb3, Pb4, Pb5, Pb6, Pb7, Pb8, Pb9, Pin,
|
||||
Pb16, Pb17, Pb18, Pb19, Pb2, Pb22, Pb23, Pb3, Pb4, Pb5, Pb6, Pb7, Pb8, Pb9, Pin, PinMarker,
|
||||
},
|
||||
sealed::Sealed,
|
||||
};
|
||||
|
||||
use super::{HwChipSelectId, SpiId};
|
||||
|
||||
pub trait PinSck: Sealed {
|
||||
pub trait PinSck: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
|
||||
pub trait PinMosi: Sealed {
|
||||
pub trait PinMosi: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
|
||||
pub trait PinMiso: Sealed {
|
||||
pub trait PinMiso: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
|
||||
pub trait HwCsProvider: Sealed {
|
||||
pub trait HwCsProvider: PinMarker {
|
||||
const SPI_ID: SpiId;
|
||||
const FUN_SEL: FunSel;
|
||||
const CS_ID: HwChipSelectId;
|
||||
@ -48,7 +49,7 @@ macro_rules! hw_cs_multi_pin {
|
||||
// name of the newtype wrapper struct
|
||||
$name:ident,
|
||||
// Pb0
|
||||
$pin_id:path,
|
||||
$pin_id:ident,
|
||||
// SpiId::B
|
||||
$spi_id:path,
|
||||
// FunSel::Sel1
|
||||
@ -71,6 +72,10 @@ macro_rules! hw_cs_multi_pin {
|
||||
|
||||
impl Sealed for $name {}
|
||||
|
||||
impl PinMarker for $name {
|
||||
const ID: PinId = <$pin_id as PinIdProvider>::ID;
|
||||
}
|
||||
|
||||
impl HwCsProvider for $name {
|
||||
const SPI_ID: SpiId = $spi_id;
|
||||
const FUN_SEL: FunSel = $fun_sel;
|
||||
@ -185,7 +190,7 @@ impl PinMosi for Pin<Pa19> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel2;
|
||||
}
|
||||
impl PinMosi for Pin<Pa18> {
|
||||
impl PinMiso for Pin<Pa18> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel2;
|
||||
}
|
||||
@ -202,7 +207,7 @@ impl PinMosi for Pin<Pb18> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
impl PinMosi for Pin<Pb17> {
|
||||
impl PinMiso for Pin<Pb17> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
@ -215,7 +220,7 @@ impl PinMosi for Pin<Pb4> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
impl PinMosi for Pin<Pb3> {
|
||||
impl PinMiso for Pin<Pb3> {
|
||||
const SPI_ID: SpiId = SpiId::B;
|
||||
const FUN_SEL: FunSel = FunSel::Sel1;
|
||||
}
|
||||
@ -330,6 +335,7 @@ hw_cs_multi_pin!(
|
||||
|
||||
// SPIC
|
||||
|
||||
/*
|
||||
// Dummy pin defintion for the ROM SCK.
|
||||
pub struct RomSck;
|
||||
// Dummy pin defintion for the ROM MOSI.
|
||||
@ -358,6 +364,7 @@ impl PinMiso for RomMiso {
|
||||
const FUN_SEL: FunSel = FunSel::Sel0;
|
||||
}
|
||||
impl Sealed for RomCs {}
|
||||
*/
|
||||
|
||||
hw_cs_pins!(
|
||||
SpiId::C,
|
||||
@ -408,9 +415,11 @@ hw_cs_multi_pin!(
|
||||
HwChipSelectId::Id4
|
||||
);
|
||||
|
||||
/*
|
||||
impl HwCsProvider for RomCs {
|
||||
const CS_ID: HwChipSelectId = HwChipSelectId::Id0;
|
||||
const SPI_ID: SpiId = SpiId::C;
|
||||
/// Function select does not make sense here, just select default value.
|
||||
const FUN_SEL: FunSel = FunSel::Sel0;
|
||||
}
|
||||
*/
|
||||
|
@ -1,5 +1,3 @@
|
||||
use crate::PeripheralSelect;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct InvalidCounterResetVal(pub(crate) ());
|
||||
@ -40,26 +38,6 @@ pub fn disable_ram_scrubbing() {
|
||||
syscfg.ram_scrub().write(|w| unsafe { w.bits(0) });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_peripheral_reset(periph_sel: PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn deassert_peripheral_reset(periph_sel: PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
pub fn reset_peripheral_for_cycles(periph_sel: PeripheralSelect, cycles: u32) {
|
||||
assert_peripheral_reset(periph_sel);
|
||||
cortex_m::asm::delay(cycles);
|
||||
deassert_peripheral_reset(periph_sel);
|
||||
}
|
||||
|
||||
pub use vorago_shared_periphs::sysconfig::{disable_peripheral_clock, enable_peripheral_clock};
|
||||
pub use vorago_shared_periphs::sysconfig::{
|
||||
assert_peripheral_reset, disable_peripheral_clock, enable_peripheral_clock,
|
||||
};
|
||||
|
@ -16,17 +16,13 @@ use crate::{
|
||||
sealed::Sealed,
|
||||
time::Hertz,
|
||||
};
|
||||
use core::cell::Cell;
|
||||
use critical_section::Mutex;
|
||||
use fugit::RateExtU32;
|
||||
use vorago_shared_periphs::{
|
||||
gpio::{Pin, PinMarker},
|
||||
gpio::{Pin, PinIdProvider},
|
||||
ioconfig::regs::FunSel,
|
||||
Port,
|
||||
};
|
||||
|
||||
pub static MS_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
|
||||
|
||||
/// Get the peripheral block of a TIM peripheral given the index.
|
||||
///
|
||||
/// This function panics if the given index is greater than 23.
|
||||
@ -170,17 +166,23 @@ pub trait TimPin: Sealed {
|
||||
const TIM_ID: TimId;
|
||||
}
|
||||
|
||||
pub trait TimPeripheralMarker: Sealed {
|
||||
pub trait TimMarker: Sealed {
|
||||
// TIM ID ranging from 0 to 23 for 24 TIM peripherals
|
||||
const ID: TimId;
|
||||
}
|
||||
|
||||
macro_rules! tim_marker {
|
||||
($TIMX:path, $ID:expr) => {
|
||||
impl TimPeripheralMarker for $TIMX {
|
||||
impl TimMarker for $TIMX {
|
||||
const ID: TimId = TimId($ID);
|
||||
}
|
||||
|
||||
unsafe impl TimRegInterface for $TIMX {
|
||||
fn raw_id(&self) -> u8 {
|
||||
Self::ID.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Sealed for $TIMX {}
|
||||
};
|
||||
}
|
||||
@ -210,13 +212,13 @@ tim_marker!(pac::Tim21, 21);
|
||||
tim_marker!(pac::Tim22, 22);
|
||||
tim_marker!(pac::Tim23, 23);
|
||||
|
||||
pub trait ValidTimAndPin<Pin: TimPin, Tim: TimPeripheralMarker>: Sealed {}
|
||||
pub trait ValidTimAndPin<Pin: TimPin, Tim: TimMarker>: Sealed {}
|
||||
|
||||
macro_rules! pin_and_tim {
|
||||
($Px:ident, $FunSel:path, $ID:expr) => {
|
||||
impl TimPin for Pin<$Px>
|
||||
where
|
||||
$Px: PinMarker,
|
||||
$Px: PinIdProvider,
|
||||
{
|
||||
const PORT: Port = $Px::ID.port();
|
||||
const OFFSET: usize = $Px::ID.offset();
|
||||
@ -368,7 +370,7 @@ unsafe impl TimRegInterface for CountdownTimer {
|
||||
|
||||
impl CountdownTimer {
|
||||
/// Configures a TIM peripheral as a periodic count down timer
|
||||
pub fn new<Tim: TimPeripheralMarker>(sys_clk: Hertz, _tim: Tim) -> Self {
|
||||
pub fn new<Tim: TimMarker>(sys_clk: Hertz, _tim: Tim) -> Self {
|
||||
enable_tim_clk(Tim::ID.raw_id());
|
||||
let cd_timer = CountdownTimer {
|
||||
tim: Tim::ID,
|
||||
@ -593,6 +595,10 @@ impl CountdownTimer {
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Delay implementations
|
||||
//==================================================================================================
|
||||
//
|
||||
impl embedded_hal::delay::DelayNs for CountdownTimer {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
let ticks = (u64::from(ns)) * (u64::from(self.sys_clk.raw())) / 1_000_000_000;
|
||||
@ -647,59 +653,6 @@ impl embedded_hal::delay::DelayNs for CountdownTimer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_up_ms_delay_provider(sys_clk: Hertz, tim: impl TimPeripheralMarker) -> CountdownTimer {
|
||||
let mut provider = CountdownTimer::new(sys_clk, tim);
|
||||
provider.start(1000.Hz());
|
||||
provider
|
||||
}
|
||||
|
||||
/// This function can be called in a specified interrupt handler to increment
|
||||
/// the MS counter
|
||||
pub fn default_ms_irq_handler() {
|
||||
critical_section::with(|cs| {
|
||||
let mut ms = MS_COUNTER.borrow(cs).get();
|
||||
ms += 1;
|
||||
MS_COUNTER.borrow(cs).set(ms);
|
||||
});
|
||||
}
|
||||
|
||||
/// Get the current MS tick count
|
||||
pub fn get_ms_ticks() -> u32 {
|
||||
critical_section::with(|cs| MS_COUNTER.borrow(cs).get())
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Delay implementations
|
||||
//==================================================================================================
|
||||
|
||||
/*
|
||||
pub struct DelayMs(CountdownTimer<pac::Tim0>);
|
||||
|
||||
impl DelayMs {
|
||||
pub fn new(timer: CountdownTimer<pac::Tim0>) -> Option<Self> {
|
||||
if timer.curr_freq() != Hertz::from_raw(1000) || !timer.listening() {
|
||||
return None;
|
||||
}
|
||||
Some(Self(timer))
|
||||
}
|
||||
}
|
||||
|
||||
/// This assumes that the user has already set up a MS tick timer in TIM0 as a system tick
|
||||
/// with [`set_up_ms_delay_provider`]
|
||||
impl embedded_hal::delay::DelayNs for DelayMs {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
let ns_as_ms = ns / 1_000_000;
|
||||
if self.0.curr_freq() != Hertz::from_raw(1000) || !self.0.listening() {
|
||||
return;
|
||||
}
|
||||
let start_time = get_ms_ticks();
|
||||
while get_ms_ticks() - start_time < ns_as_ms {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[inline(always)]
|
||||
pub fn enable_tim_clk(idx: u8) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
|
@ -14,7 +14,10 @@
|
||||
//! - [Flashloader exposing a CCSDS interface via UART](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/flashloader)
|
||||
use core::{convert::Infallible, ops::Deref};
|
||||
use fugit::RateExtU32;
|
||||
use vorago_shared_periphs::{gpio::Pin, FunSel, InterruptConfig};
|
||||
use vorago_shared_periphs::{
|
||||
gpio::{IoPeriphPin, Pin},
|
||||
FunSel, InterruptConfig,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
clock::enable_peripheral_clock,
|
||||
@ -22,7 +25,7 @@ use crate::{
|
||||
pac::{self, uarta as uart_base},
|
||||
pins::{
|
||||
Pa16, Pa17, Pa18, Pa19, Pa2, Pa26, Pa27, Pa3, Pa30, Pa31, Pa8, Pa9, Pb18, Pb19, Pb20, Pb21,
|
||||
Pb22, Pb23, Pb6, Pb7, Pb8, Pb9,
|
||||
Pb22, Pb23, Pb6, Pb7, Pb8, Pb9, PinMarker,
|
||||
},
|
||||
time::Hertz,
|
||||
PeripheralSelect,
|
||||
@ -55,11 +58,11 @@ impl UartId {
|
||||
// Type-Level support
|
||||
//==================================================================================================
|
||||
|
||||
pub trait TxPin {
|
||||
pub trait TxPin: PinMarker {
|
||||
const UART_ID: UartId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
pub trait RxPin {
|
||||
pub trait RxPin: PinMarker {
|
||||
const UART_ID: UartId;
|
||||
const FUN_SEL: FunSel;
|
||||
}
|
||||
@ -557,6 +560,8 @@ impl Uart {
|
||||
if UartI::ID != TxPinI::UART_ID || UartI::ID != RxPinI::UART_ID {
|
||||
return Err(UartIdMissmatchError);
|
||||
}
|
||||
IoPeriphPin::new(TxPinI::ID, TxPinI::FUN_SEL, None);
|
||||
IoPeriphPin::new(RxPinI::ID, TxPinI::FUN_SEL, None);
|
||||
crate::clock::enable_peripheral_clock(UartI::PERIPH_SEL);
|
||||
|
||||
let reg_block = unsafe { UartI::reg_block() };
|
||||
|
@ -411,10 +411,10 @@ impl<const N: usize> embedded_io_async::Read for RxAsyncOverwriting<N> {
|
||||
critical_section::with(|cs| {
|
||||
let queue = inner.shared_consumer.borrow(cs);
|
||||
if queue.borrow().as_ref().unwrap().len() == 0 {
|
||||
RX_HAS_DATA[id as usize].store(false, Ordering::Relaxed);
|
||||
RX_HAS_DATA[id].store(false, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
let _guard = ActiveReadGuard(id as usize);
|
||||
let _guard = ActiveReadGuard(id);
|
||||
let mut handle_data_in_queue = |inner: &mut RxAsyncOverwritingInner<N>| {
|
||||
critical_section::with(|cs| {
|
||||
let mut consumer_ref = inner.shared_consumer.borrow(cs).borrow_mut();
|
||||
|
@ -15,10 +15,11 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7"
|
||||
embedded-hal = "1"
|
||||
nb = "1"
|
||||
bitfield = ">=0.17, <=0.19"
|
||||
bitbybit = "1.3"
|
||||
arbitrary-int = "1.3"
|
||||
max116xx-10bit = "0.3"
|
||||
|
||||
va108xx-hal = { version = ">=0.10, <=0.11", features = ["rt"] }
|
||||
va108xx-hal = { version = ">=0.10, <=0.11", path = "../va108xx-hal", features = ["rt"] }
|
||||
|
||||
[features]
|
||||
rt = ["va108xx-hal/rt"]
|
||||
|
@ -4,16 +4,16 @@ use cortex_m_rt::entry;
|
||||
use embedded_hal::delay::DelayNs;
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{pac, prelude::*, timer::set_up_ms_delay_provider};
|
||||
use va108xx_hal::{pac, prelude::*, timer::CountdownTimer};
|
||||
use vorago_reb1::temp_sensor::Adt75TempSensor;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- Vorago Temperature Sensor and I2C Example --");
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
||||
let mut temp_sensor = Adt75TempSensor::new(&mut dp.sysconfig, 50.MHz(), dp.i2ca)
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let mut delay = CountdownTimer::new(50.MHz(), dp.tim0);
|
||||
let mut temp_sensor = Adt75TempSensor::new(50.MHz(), dp.i2ca)
|
||||
.expect("Creating temperature sensor struct failed");
|
||||
loop {
|
||||
let temp = temp_sensor
|
||||
|
@ -9,13 +9,14 @@ use embedded_hal::delay::DelayNs;
|
||||
use embedded_hal::spi::{SpiBus, MODE_3};
|
||||
use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::spi::SpiClkConfig;
|
||||
use va108xx_hal::gpio::{Output, PinState};
|
||||
use va108xx_hal::pins::PinsA;
|
||||
use va108xx_hal::spi::{configure_pin_as_hw_cs_pin, SpiClkConfig};
|
||||
use va108xx_hal::timer::CountdownTimer;
|
||||
use va108xx_hal::{
|
||||
gpio::PinsA,
|
||||
pac,
|
||||
prelude::*,
|
||||
spi::{Spi, SpiConfig},
|
||||
timer::set_up_ms_delay_provider,
|
||||
};
|
||||
|
||||
const READ_MASK: u8 = 1 << 7;
|
||||
@ -29,19 +30,19 @@ const PWR_MEASUREMENT_MODE_MASK: u8 = 1 << 3;
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- Vorago Accelerometer Example --");
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
||||
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
let pinsa = PinsA::new(dp.porta);
|
||||
let mut delay = CountdownTimer::new(50.MHz(), dp.tim0);
|
||||
let (sck, mosi, miso) = (
|
||||
pinsa.pa20.into_funsel_2(),
|
||||
pinsa.pa19.into_funsel_2(),
|
||||
pinsa.pa18.into_funsel_2(),
|
||||
pinsa.pa20,
|
||||
pinsa.pa19,
|
||||
pinsa.pa18,
|
||||
);
|
||||
let cs_pin = pinsa.pa16.into_funsel_2();
|
||||
let cs_pin = pinsa.pa16;
|
||||
let hw_cs_id = configure_pin_as_hw_cs_pin(cs_pin);
|
||||
|
||||
// Need to set the ADC chip select low
|
||||
let mut adc_cs = pinsa.pa17.into_push_pull_output();
|
||||
adc_cs.set_high();
|
||||
Output::new(pinsa.pa17, PinState::Low);
|
||||
|
||||
let spi_cfg = SpiConfig::default()
|
||||
.clk_cfg(
|
||||
@ -50,13 +51,12 @@ fn main() -> ! {
|
||||
.mode(MODE_3)
|
||||
.slave_output_disable(true);
|
||||
let mut spi = Spi::new(
|
||||
&mut dp.sysconfig,
|
||||
50.MHz(),
|
||||
dp.spib,
|
||||
(sck, miso, mosi),
|
||||
spi_cfg,
|
||||
);
|
||||
spi.cfg_hw_cs_with_pin(&cs_pin);
|
||||
).unwrap();
|
||||
spi.cfg_hw_cs(hw_cs_id);
|
||||
|
||||
let mut tx_rx_buf: [u8; 3] = [0; 3];
|
||||
tx_rx_buf[0] = READ_MASK | DEVID_REG;
|
||||
|
@ -10,10 +10,10 @@ use panic_rtt_target as _;
|
||||
use rtt_target::{rprintln, rtt_init_print};
|
||||
use va108xx_hal::{
|
||||
clock::{set_clk_div_register, FilterClkSel},
|
||||
gpio::{FilterType, InterruptEdge, PinsA},
|
||||
gpio::{FilterType, InterruptEdge},
|
||||
pac::{self, interrupt},
|
||||
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;
|
||||
@ -35,18 +35,18 @@ fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
rprintln!("-- Vorago Button IRQ Example --");
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let pinsa = PinsA::new(dp.porta);
|
||||
let edge_irq = match PRESS_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 PRESS_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(
|
||||
@ -54,18 +54,7 @@ fn main() -> ! {
|
||||
InterruptConfig::new(pac::interrupt::OC15, true, true),
|
||||
);
|
||||
|
||||
set_up_ms_tick(
|
||||
InterruptConfig::new(pac::Interrupt::OC0, true, true),
|
||||
&mut dp.sysconfig,
|
||||
Some(&mut dp.irqsel),
|
||||
50.MHz(),
|
||||
dp.tim0,
|
||||
);
|
||||
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();
|
||||
}
|
||||
@ -79,11 +68,6 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn OC0() {
|
||||
default_ms_irq_handler();
|
||||
}
|
||||
|
||||
#[interrupt]
|
||||
fn OC15() {
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
|
@ -9,7 +9,13 @@
|
||||
use cortex_m_rt::entry;
|
||||
use embedded_hal::delay::DelayNs;
|
||||
use panic_halt as _;
|
||||
use va108xx_hal::{gpio::PinsA, pac, prelude::*, timer::set_up_ms_delay_provider};
|
||||
use va108xx_hal::{
|
||||
gpio::{Output, PinState},
|
||||
pac,
|
||||
pins::PinsA,
|
||||
prelude::*,
|
||||
timer::CountdownTimer,
|
||||
};
|
||||
use vorago_reb1::leds::Leds;
|
||||
|
||||
// REB LED pin definitions. All on port A
|
||||
@ -26,7 +32,7 @@ enum LibType {
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
let lib_type = LibType::Bsp;
|
||||
|
||||
@ -60,11 +66,11 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
LibType::Hal => {
|
||||
let pins = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
let mut led1 = pins.pa10.into_readable_push_pull_output();
|
||||
let mut led2 = pins.pa7.into_readable_push_pull_output();
|
||||
let mut led3 = pins.pa6.into_readable_push_pull_output();
|
||||
let mut delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
||||
let pins = PinsA::new(dp.porta);
|
||||
let mut led1 = Output::new(pins.pa10, PinState::Low);
|
||||
let mut led2 = Output::new(pins.pa7, PinState::Low);
|
||||
let mut led3 = Output::new(pins.pa6, PinState::Low);
|
||||
let mut delay = CountdownTimer::new(50.MHz(), dp.tim0);
|
||||
for _ in 0..10 {
|
||||
led1.set_low();
|
||||
led2.set_low();
|
||||
@ -83,13 +89,9 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
LibType::Bsp => {
|
||||
let pinsa = PinsA::new(&mut dp.sysconfig, dp.porta);
|
||||
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 delay = set_up_ms_delay_provider(&mut dp.sysconfig, 50.MHz(), dp.tim0);
|
||||
let pinsa = PinsA::new(dp.porta);
|
||||
let mut leds = Leds::new(pinsa.pa10, pinsa.pa7, pinsa.pa6);
|
||||
let mut delay = CountdownTimer::new(50.MHz(), dp.tim0);
|
||||
for _ in 0..10 {
|
||||
// Blink all LEDs quickly
|
||||
for led in leds.iter_mut() {
|
||||
|
@ -5,16 +5,18 @@
|
||||
//! - [Button Blinky with IRQs](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-irq.rs)
|
||||
//! - [Button Blinky with IRQs and RTIC](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-rtic.rs)
|
||||
use va108xx_hal::{
|
||||
gpio::{FilterClkSel, FilterType, InputFloating, InterruptEdge, InterruptLevel, Pin, PA11},
|
||||
clock::FilterClkSel,
|
||||
gpio::{FilterType, Input, InterruptEdge, InterruptLevel, Pin},
|
||||
pins::Pa11,
|
||||
InterruptConfig,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Button(pub Pin<PA11, InputFloating>);
|
||||
pub struct Button(pub Input);
|
||||
|
||||
impl Button {
|
||||
pub fn new(pin: Pin<PA11, InputFloating>) -> Button {
|
||||
Button(pin)
|
||||
pub fn new(pin: Pin<Pa11>) -> Button {
|
||||
Button(Input::new_floating(pin))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -6,20 +6,20 @@
|
||||
//! - [Button Blinky using IRQs](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-irq.rs)
|
||||
//! - [Button Blinky using IRQs and RTIC](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/blinky-button-rtic.rs)
|
||||
use va108xx_hal::{
|
||||
gpio::dynpin::DynPin,
|
||||
gpio::pin::{Pin, PushPullOutput, PA10, PA6, PA7},
|
||||
gpio::{Output, PinState},
|
||||
pins::{Pa10, Pa6, Pa7, Pin},
|
||||
};
|
||||
|
||||
pub type LD2 = Pin<PA10, PushPullOutput>;
|
||||
pub type LD3 = Pin<PA7, PushPullOutput>;
|
||||
pub type LD4 = Pin<PA6, PushPullOutput>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Leds(pub [Led; 3]);
|
||||
|
||||
impl Leds {
|
||||
pub fn new(led_pin1: LD2, led_pin2: LD3, led_pin3: LD4) -> Leds {
|
||||
Leds([led_pin1.into(), led_pin2.into(), led_pin3.into()])
|
||||
pub fn new(led_pin1: Pin<Pa10>, led_pin2: Pin<Pa7>, led_pin3: Pin<Pa6>) -> Leds {
|
||||
Leds([
|
||||
Led(Output::new(led_pin1, PinState::Low)),
|
||||
Led(Output::new(led_pin2, PinState::Low)),
|
||||
Led(Output::new(led_pin3, PinState::Low)),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,38 +52,24 @@ impl core::ops::IndexMut<usize> for Leds {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Led(pub DynPin);
|
||||
|
||||
macro_rules! ctor {
|
||||
($($ldx:ident),+) => {
|
||||
$(
|
||||
impl From<$ldx> for Led {
|
||||
fn from(led: $ldx) -> Self {
|
||||
Led(led.into())
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
ctor!(LD2, LD3, LD4);
|
||||
pub struct Led(Output);
|
||||
|
||||
impl Led {
|
||||
/// Turns the LED off. Setting the pin high actually turns the LED off
|
||||
#[inline]
|
||||
pub fn off(&mut self) {
|
||||
self.0.set_high().ok();
|
||||
self.0.set_high();
|
||||
}
|
||||
|
||||
/// Turns the LED on. Setting the pin low actually turns the LED on
|
||||
#[inline]
|
||||
pub fn on(&mut self) {
|
||||
self.0.set_low().ok();
|
||||
self.0.set_low();
|
||||
}
|
||||
|
||||
/// Toggles the LED
|
||||
#[inline]
|
||||
pub fn toggle(&mut self) {
|
||||
self.0.toggle().ok();
|
||||
self.0.toggle();
|
||||
}
|
||||
}
|
||||
|
@ -7,20 +7,25 @@
|
||||
//! # Example
|
||||
//!
|
||||
//! - [REB1 EEPROM example](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/vorago-reb1/examples/nvm.rs)
|
||||
use arbitrary_int::{u2, u3};
|
||||
use core::convert::Infallible;
|
||||
use embedded_hal::spi::SpiBus;
|
||||
|
||||
pub const PAGE_SIZE: usize = 256;
|
||||
|
||||
bitfield::bitfield! {
|
||||
pub struct StatusReg(u8);
|
||||
impl Debug;
|
||||
u8;
|
||||
pub status_register_write_protect, _: 7;
|
||||
pub zero_segment, _: 6, 4;
|
||||
pub block_protection_bits, set_block_protection_bits: 3, 2;
|
||||
pub write_enable_latch, _: 1;
|
||||
pub write_in_progress, _: 0;
|
||||
#[bitbybit::bitfield(u8)]
|
||||
#[derive(Debug)]
|
||||
pub struct StatusReg {
|
||||
#[bit(7, r)]
|
||||
status_register_write_protect: bool,
|
||||
#[bits(4..=6, r)]
|
||||
zero_segment: u3,
|
||||
#[bits(2..=3, rw)]
|
||||
block_protection_bits: u2,
|
||||
#[bit(1, r)]
|
||||
write_enable_latch: bool,
|
||||
#[bit(0, r)]
|
||||
write_in_progress: bool,
|
||||
}
|
||||
|
||||
// Registers.
|
||||
@ -43,10 +48,10 @@ use regs::*;
|
||||
use va108xx_hal::{
|
||||
pac,
|
||||
prelude::*,
|
||||
spi::{RomMiso, RomMosi, RomSck, Spi, SpiClkConfig, SpiConfig, BMSTART_BMSTOP_MASK},
|
||||
spi::{Spi, SpiClkConfig, SpiConfig, SpiLowLevel, BMSTART_BMSTOP_MASK},
|
||||
};
|
||||
|
||||
pub type RomSpi = Spi<pac::Spic, (RomSck, RomMiso, RomMosi), u8>;
|
||||
pub type RomSpi = Spi<u8>;
|
||||
|
||||
/// Driver for the ST device M95M01 EEPROM memory.
|
||||
///
|
||||
@ -59,14 +64,13 @@ pub struct M95M01 {
|
||||
pub struct PageBoundaryExceededError;
|
||||
|
||||
impl M95M01 {
|
||||
pub fn new(syscfg: &mut pac::Sysconfig, sys_clk: impl Into<Hertz>, spi: pac::Spic) -> Self {
|
||||
let spi = RomSpi::new(
|
||||
syscfg,
|
||||
pub fn new(sys_clk: Hertz, spi: pac::Spic) -> Self {
|
||||
let spi = RomSpi::new_for_rom(
|
||||
sys_clk,
|
||||
spi,
|
||||
(RomSck, RomMiso, RomMosi),
|
||||
SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)),
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
let mut spi_dev = Self { spi };
|
||||
spi_dev.clear_block_protection().unwrap();
|
||||
spi_dev
|
||||
@ -74,7 +78,7 @@ impl M95M01 {
|
||||
|
||||
pub fn release(mut self) -> pac::Spic {
|
||||
self.set_block_protection().unwrap();
|
||||
self.spi.release().0
|
||||
unsafe { pac::Spic::steal() }
|
||||
}
|
||||
|
||||
// Wait until the write-in-progress state is cleared. This exposes a [nb] API, so this function
|
||||
@ -90,7 +94,7 @@ impl M95M01 {
|
||||
pub fn read_status_reg(&mut self) -> Result<StatusReg, Infallible> {
|
||||
let mut write_read: [u8; 2] = [regs::RDSR, 0x00];
|
||||
self.spi.transfer_in_place(&mut write_read)?;
|
||||
Ok(StatusReg(write_read[1]))
|
||||
Ok(StatusReg::new_with_raw_value(write_read[1]))
|
||||
}
|
||||
|
||||
pub fn write_enable(&mut self) -> Result<(), Infallible> {
|
||||
@ -104,10 +108,10 @@ impl M95M01 {
|
||||
}
|
||||
|
||||
pub fn set_block_protection(&mut self) -> Result<(), Infallible> {
|
||||
let mut reg = StatusReg(0);
|
||||
reg.set_block_protection_bits(0b11);
|
||||
let mut reg = StatusReg::new_with_raw_value(0);
|
||||
reg.set_block_protection_bits(u2::new(0b11));
|
||||
self.write_enable()?;
|
||||
self.spi.write(&[WRSR, reg.0])
|
||||
self.spi.write(&[WRSR, reg.raw_value()])
|
||||
}
|
||||
|
||||
fn common_init_write_and_read(&mut self, address: usize, reg: u8) -> Result<(), Infallible> {
|
||||
|
@ -9,7 +9,7 @@ use max116xx_10bit::{
|
||||
Error, ExternallyClocked, InternallyClockedInternallyTimedSerialInterface, Max116xx10Bit,
|
||||
Max116xx10BitEocExt, VoltageRefMode, WithWakeupDelay, WithoutWakeupDelay,
|
||||
};
|
||||
use va108xx_hal::gpio::{Floating, Input, Pin, PA14};
|
||||
use va108xx_hal::gpio::Input;
|
||||
|
||||
pub type Max11619ExternallyClockedNoWakeup<Spi> =
|
||||
Max116xx10Bit<Spi, ExternallyClocked, WithoutWakeupDelay>;
|
||||
@ -17,7 +17,6 @@ pub type Max11619ExternallyClockedWithWakeup<Spi> =
|
||||
Max116xx10Bit<Spi, ExternallyClocked, WithWakeupDelay>;
|
||||
pub type Max11619InternallyClocked<Spi, Eoc> =
|
||||
Max116xx10BitEocExt<Spi, Eoc, InternallyClockedInternallyTimedSerialInterface>;
|
||||
pub type EocPin = Pin<PA14, Input<Floating>>;
|
||||
|
||||
pub const AN0_CHANNEL: u8 = 0;
|
||||
pub const AN1_CHANNEL: u8 = 1;
|
||||
@ -44,9 +43,9 @@ pub fn max11619_externally_clocked_with_wakeup<Spi: SpiDevice>(
|
||||
|
||||
pub fn max11619_internally_clocked<Spi: SpiDevice>(
|
||||
spi: Spi,
|
||||
eoc: EocPin,
|
||||
eoc: Input,
|
||||
v_ref: VoltageRefMode,
|
||||
) -> Result<Max11619InternallyClocked<Spi, EocPin>, Error<Spi::Error, Infallible>> {
|
||||
) -> Result<Max11619InternallyClocked<Spi, Input>, Error<Spi::Error, Infallible>> {
|
||||
let mut adc = Max116xx10Bit::max11619(spi)?
|
||||
.into_int_clkd_int_timed_through_ser_if_without_wakeup(v_ref, eoc)?;
|
||||
adc.reset(false)?;
|
||||
|
@ -48,15 +48,10 @@ impl From<Error> for AdtInitError {
|
||||
}
|
||||
|
||||
impl Adt75TempSensor {
|
||||
pub fn new(
|
||||
sys_cfg: &mut pac::Sysconfig,
|
||||
sys_clk: impl Into<Hertz> + Copy,
|
||||
i2ca: pac::I2ca,
|
||||
) -> Result<Self, Error> {
|
||||
pub fn new(sys_clk: Hertz, i2ca: pac::I2ca) -> Result<Self, Error> {
|
||||
let mut sensor = Adt75TempSensor {
|
||||
// The master construction can not fail for regular I2C speed.
|
||||
sensor_if: I2cMaster::new(
|
||||
sys_cfg,
|
||||
sys_clk,
|
||||
i2ca,
|
||||
MasterConfig::default(),
|
||||
|
@ -102,8 +102,7 @@ impl InputPinFuture {
|
||||
) -> Self {
|
||||
let (waker_group, edge_detection_group) =
|
||||
Self::pin_group_to_waker_and_edge_detection_group(pin.id().port());
|
||||
edge_detection_group[pin.id().offset() as usize]
|
||||
.store(false, core::sync::atomic::Ordering::Relaxed);
|
||||
edge_detection_group[pin.id().offset()].store(false, core::sync::atomic::Ordering::Relaxed);
|
||||
pin.configure_edge_interrupt(edge);
|
||||
#[cfg(feature = "vor1x")]
|
||||
pin.enable_interrupt(InterruptConfig::new(irq, true, true));
|
||||
@ -128,7 +127,7 @@ impl Future for InputPinFuture {
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Self::Output> {
|
||||
let idx = self.id.offset() as usize;
|
||||
let idx = self.id.offset();
|
||||
self.waker_group[idx].register(cx.waker());
|
||||
if self.edge_detection_group[idx].swap(false, core::sync::atomic::Ordering::Relaxed) {
|
||||
return core::task::Poll::Ready(());
|
||||
|
@ -1,5 +1,7 @@
|
||||
pub use embedded_hal::digital::PinState;
|
||||
|
||||
use crate::ioconfig::FilterClkSel;
|
||||
use crate::ioconfig::FilterType;
|
||||
#[cfg(feature = "vor1x")]
|
||||
use crate::{PeripheralSelect, sysconfig::enable_peripheral_clock};
|
||||
|
||||
@ -27,15 +29,28 @@ pub enum InterruptLevel {
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PinId {
|
||||
port: Port,
|
||||
offset: usize,
|
||||
offset: u8,
|
||||
}
|
||||
|
||||
impl PinId {
|
||||
pub const fn new_unchecked(port: Port, offset: usize) -> Self {
|
||||
if offset >= port.max_offset() {
|
||||
panic!("Pin ID construction: offset is out of range");
|
||||
}
|
||||
PinId {
|
||||
port,
|
||||
offset: offset as u8,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn new(port: Port, offset: usize) -> Result<Self, InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { offset, port });
|
||||
}
|
||||
Ok(PinId { port, offset })
|
||||
Ok(PinId {
|
||||
port,
|
||||
offset: offset as u8,
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn port(&self) -> Port {
|
||||
@ -43,7 +58,7 @@ impl PinId {
|
||||
}
|
||||
|
||||
pub const fn offset(&self) -> usize {
|
||||
self.offset
|
||||
self.offset as usize
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +68,15 @@ pub struct LowLevelGpio {
|
||||
id: PinId,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for LowLevelGpio {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("LowLevelGpio")
|
||||
.field("gpio", &self.gpio.port())
|
||||
.field("id", &self.id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl LowLevelGpio {
|
||||
pub fn new(id: PinId) -> Self {
|
||||
LowLevelGpio {
|
||||
@ -78,23 +102,17 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_input_floating(&mut self) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
});
|
||||
self.gpio.modify_dir(|mut dir| {
|
||||
dir &= !(1 << self.id.offset());
|
||||
dir
|
||||
@ -102,24 +120,18 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_input_with_pull(&mut self, pull: Pull) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(pull);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(pull);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
});
|
||||
self.gpio.modify_dir(|mut dir| {
|
||||
dir &= !(1 << self.id.offset());
|
||||
dir
|
||||
@ -127,23 +139,17 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_output_push_pull(&mut self, init_level: PinState) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
});
|
||||
match init_level {
|
||||
PinState::Low => self.gpio.write_clr_out(self.mask_32()),
|
||||
PinState::High => self.gpio.write_set_out(self.mask_32()),
|
||||
@ -155,24 +161,18 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_output_open_drain(&mut self, init_level: PinState) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(true);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(Pull::Up);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(true);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(Pull::Up);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
});
|
||||
let mask32 = self.mask_32();
|
||||
match init_level {
|
||||
PinState::Low => self.gpio.write_clr_out(mask32),
|
||||
@ -185,22 +185,16 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_peripheral_pin(&mut self, fun_sel: FunSel, pull: Option<Pull>) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(fun_sel);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(pull.is_some());
|
||||
config.set_pull_dir(pull.unwrap_or(Pull::Up));
|
||||
config.set_invert_output(false);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(fun_sel);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(pull.is_some());
|
||||
config.set_pull_dir(pull.unwrap_or(Pull::Up));
|
||||
config.set_invert_output(false);
|
||||
config
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -295,6 +289,79 @@ impl LowLevelGpio {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure which edge or level type triggers an interrupt
|
||||
#[inline]
|
||||
pub fn configure_level_interrupt(&mut self, level: InterruptLevel) {
|
||||
let mask32 = self.mask_32();
|
||||
self.gpio.modify_irq_sen(|mut value| {
|
||||
value |= mask32;
|
||||
value
|
||||
});
|
||||
if level == InterruptLevel::Low {
|
||||
self.gpio.modify_irq_evt(|mut value| {
|
||||
value &= !mask32;
|
||||
value
|
||||
});
|
||||
} else {
|
||||
self.gpio.modify_irq_evt(|mut value| {
|
||||
value |= mask32;
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Only useful for input pins
|
||||
#[inline]
|
||||
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_filter_type(filter);
|
||||
config.set_filter_clk_sel(clksel);
|
||||
config
|
||||
});
|
||||
}
|
||||
|
||||
/// Only useful for output pins.
|
||||
#[inline]
|
||||
pub fn configure_pulse_mode(&mut self, enable: bool, default_state: PinState) {
|
||||
self.gpio.modify_pulse(|mut value| {
|
||||
if enable {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
self.gpio.modify_pulsebase(|mut value| {
|
||||
if default_state == PinState::High {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
/// Only useful for output pins
|
||||
#[inline]
|
||||
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||
self.gpio.modify_delay1(|mut value| {
|
||||
if delay_1 {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
self.gpio.modify_delay2(|mut value| {
|
||||
if delay_2 {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
/// Configure the IRQSEL peripheral for this particular pin with the given interrupt ID.
|
||||
pub fn configure_irqsel(&mut self, id: va108xx::Interrupt) {
|
||||
@ -304,12 +371,12 @@ impl LowLevelGpio {
|
||||
// Set the correct interrupt number in the IRQSEL register
|
||||
super::Port::A => {
|
||||
irqsel
|
||||
.porta0(self.id().offset() as usize)
|
||||
.porta0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(id as u32) });
|
||||
}
|
||||
super::Port::B => {
|
||||
irqsel
|
||||
.portb0(self.id().offset() as usize)
|
||||
.portb0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(id as u32) });
|
||||
}
|
||||
}
|
||||
@ -324,12 +391,12 @@ impl LowLevelGpio {
|
||||
// Set the correct interrupt number in the IRQSEL register
|
||||
super::Port::A => {
|
||||
irqsel
|
||||
.porta0(self.id().offset() as usize)
|
||||
.porta0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(u32::MAX) });
|
||||
}
|
||||
super::Port::B => {
|
||||
irqsel
|
||||
.portb0(self.id().offset() as usize)
|
||||
.portb0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(u32::MAX) });
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,22 @@
|
||||
use core::convert::Infallible;
|
||||
|
||||
pub use crate::ioconfig::{FilterClkSel, FilterType, regs::FunSel};
|
||||
pub use embedded_hal::digital::PinState;
|
||||
pub use ll::PinId;
|
||||
pub use ll::{Port, Pull};
|
||||
|
||||
use crate::ioconfig::regs::FunSel;
|
||||
pub use ll::{InterruptEdge, InterruptLevel, PinId, Port, Pull};
|
||||
|
||||
pub mod asynch;
|
||||
pub mod ll;
|
||||
pub mod regs;
|
||||
|
||||
pub trait PinMarker {
|
||||
pub trait PinIdProvider {
|
||||
const ID: ll::PinId;
|
||||
}
|
||||
|
||||
pub struct Pin<I: PinMarker> {
|
||||
pub struct Pin<I: PinIdProvider> {
|
||||
phantom: core::marker::PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I: PinMarker> Pin<I> {
|
||||
impl<I: PinIdProvider> Pin<I> {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
@ -27,10 +25,11 @@ impl<I: PinMarker> Pin<I> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Output(ll::LowLevelGpio);
|
||||
|
||||
impl Output {
|
||||
pub fn new<I: PinMarker>(_pin: Pin<I>, init_level: PinState) -> Self {
|
||||
pub fn new<I: PinIdProvider>(_pin: Pin<I>, init_level: PinState) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_output_push_pull(init_level);
|
||||
Output(ll)
|
||||
@ -65,6 +64,12 @@ impl Output {
|
||||
pub fn is_set_low(&self) -> bool {
|
||||
self.0.is_set_low()
|
||||
}
|
||||
|
||||
/// Toggle pin output with dedicated HW feature.
|
||||
#[inline]
|
||||
pub fn toggle(&mut self) {
|
||||
self.0.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for Output {
|
||||
@ -99,16 +104,17 @@ impl embedded_hal::digital::StatefulOutputPin for Output {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Input(ll::LowLevelGpio);
|
||||
|
||||
impl Input {
|
||||
pub fn new_floating<I: PinMarker>(_pin: Pin<I>) -> Self {
|
||||
pub fn new_floating<I: PinIdProvider>(_pin: Pin<I>) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_input_floating();
|
||||
Input(ll)
|
||||
}
|
||||
|
||||
pub fn new_with_pull<I: PinMarker>(_pin: Pin<I>, pull: Pull) -> Self {
|
||||
pub fn new_with_pull<I: PinIdProvider>(_pin: Pin<I>, pull: Pull) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_input_with_pull(pull);
|
||||
Input(ll)
|
||||
@ -126,10 +132,25 @@ impl Input {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_edge_interrupt(&mut self, edge: ll::InterruptEdge) {
|
||||
pub fn configure_edge_interrupt(&mut self, edge: InterruptEdge) {
|
||||
self.0.configure_edge_interrupt(edge);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_level_interrupt(&mut self, edge: InterruptLevel) {
|
||||
self.0.configure_level_interrupt(edge);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||
self.0.configure_delay(delay_1, delay_2);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
||||
self.0.configure_filter_type(filter, clksel);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_low(&self) -> bool {
|
||||
self.0.is_low()
|
||||
@ -155,6 +176,7 @@ impl embedded_hal::digital::InputPin for Input {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PinMode {
|
||||
InputFloating,
|
||||
InputWithPull(Pull),
|
||||
@ -172,13 +194,14 @@ impl PinMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Flex {
|
||||
ll: ll::LowLevelGpio,
|
||||
mode: PinMode,
|
||||
}
|
||||
|
||||
impl Flex {
|
||||
pub fn new<I: PinMarker>(_pin: Pin<I>) -> Self {
|
||||
pub fn new<I: PinIdProvider>(_pin: Pin<I>) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_input_floating();
|
||||
Flex {
|
||||
@ -287,12 +310,22 @@ pub struct IoPeriphPin {
|
||||
}
|
||||
|
||||
impl IoPeriphPin {
|
||||
pub fn new<I: PinMarker>(_pin: Pin<I>, fun_sel: FunSel, pull: Option<Pull>) -> Self {
|
||||
pub fn new_with_pin<I: PinIdProvider>(
|
||||
_pin: Pin<I>,
|
||||
fun_sel: FunSel,
|
||||
pull: Option<Pull>,
|
||||
) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_peripheral_pin(fun_sel, pull);
|
||||
IoPeriphPin { ll, fun_sel }
|
||||
}
|
||||
|
||||
pub fn new(pin_id: PinId, fun_sel: FunSel, pull: Option<Pull>) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(pin_id);
|
||||
ll.configure_as_peripheral_pin(fun_sel, pull);
|
||||
IoPeriphPin { ll, fun_sel }
|
||||
}
|
||||
|
||||
pub fn port(&self) -> Port {
|
||||
self.ll.port()
|
||||
}
|
||||
|
@ -1 +1,3 @@
|
||||
pub use regs::{FilterClkSel, FilterType};
|
||||
|
||||
pub mod regs;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{InvalidOffsetError, NUM_PORT_A, NUM_PORT_B};
|
||||
use crate::{NUM_PORT_A, NUM_PORT_B, gpio::PinId};
|
||||
#[cfg(feature = "vor4x")]
|
||||
use crate::{NUM_PORT_DEFAULT, NUM_PORT_G};
|
||||
|
||||
@ -73,7 +73,7 @@ pub struct Config {
|
||||
#[bit(6, rw)]
|
||||
invert_input: bool,
|
||||
#[bits(3..=5, rw)]
|
||||
filter_sel: FilterClkSel,
|
||||
filter_clk_sel: FilterClkSel,
|
||||
#[bits(0..=2, rw)]
|
||||
filter_type: Option<FilterType>,
|
||||
}
|
||||
@ -134,24 +134,9 @@ impl IoConfig {
|
||||
}
|
||||
|
||||
impl MmioIoConfig<'_> {
|
||||
pub fn read_pin_config(
|
||||
&self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
) -> Result<Config, InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { port, offset });
|
||||
}
|
||||
Ok(unsafe { self.read_pin_config_unchecked(port, offset) })
|
||||
}
|
||||
|
||||
/// This function does NOT perform any bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this function with an invalid offset can lead to undefined behaviour.
|
||||
pub unsafe fn read_pin_config_unchecked(&self, port: crate::Port, offset: usize) -> Config {
|
||||
match port {
|
||||
pub fn read_pin_config(&self, id: PinId) -> Config {
|
||||
let offset = id.offset();
|
||||
match id.port() {
|
||||
crate::Port::A => unsafe { self.read_port_a_unchecked(offset) },
|
||||
crate::Port::B => unsafe { self.read_port_b_unchecked(offset) },
|
||||
#[cfg(feature = "vor4x")]
|
||||
@ -167,63 +152,14 @@ impl MmioIoConfig<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_pin_config<F: FnOnce(Config) -> Config>(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
f: F,
|
||||
) -> Result<(), InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { port, offset });
|
||||
}
|
||||
unsafe { self.modify_pin_config_unchecked(port, offset, f) };
|
||||
Ok(())
|
||||
pub fn modify_pin_config<F: FnOnce(Config) -> Config>(&mut self, id: PinId, f: F) {
|
||||
let config = self.read_pin_config(id);
|
||||
self.write_pin_config(id, f(config))
|
||||
}
|
||||
|
||||
/// This function does NOT perform any bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this function with an invalid offset can lead to undefined behaviour.
|
||||
pub unsafe fn modify_pin_config_unchecked<F: FnOnce(Config) -> Config>(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
mut f: F,
|
||||
) {
|
||||
unsafe {
|
||||
let config = self.read_pin_config_unchecked(port, offset);
|
||||
self.write_pin_config_unchecked(port, offset, f(config))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_pin_config(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
config: Config,
|
||||
) -> Result<(), InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { port, offset });
|
||||
}
|
||||
unsafe {
|
||||
self.write_pin_config_unchecked(port, offset, config);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function does NOT perform any bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this function with an invalid offset can lead to undefined behaviour.
|
||||
pub unsafe fn write_pin_config_unchecked(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
config: Config,
|
||||
) {
|
||||
match port {
|
||||
pub fn write_pin_config(&mut self, id: PinId, config: Config) {
|
||||
let offset = id.offset();
|
||||
match id.port() {
|
||||
crate::Port::A => unsafe { self.write_port_a_unchecked(offset, config) },
|
||||
crate::Port::B => unsafe { self.write_port_b_unchecked(offset, config) },
|
||||
#[cfg(feature = "vor4x")]
|
||||
|
0
vorago-shared-periphs/src/pins.rs
Normal file
0
vorago-shared-periphs/src/pins.rs
Normal file
@ -15,3 +15,29 @@ pub fn disable_peripheral_clock(clock: crate::PeripheralSelect) {
|
||||
.peripheral_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << clock as u8)) });
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
#[inline]
|
||||
pub fn assert_peripheral_reset(periph_sel: crate::PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
#[inline]
|
||||
pub fn deassert_peripheral_reset(periph_sel: crate::PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
#[inline]
|
||||
pub fn reset_peripheral_for_cycles(periph_sel: crate::PeripheralSelect, cycles: u32) {
|
||||
assert_peripheral_reset(periph_sel);
|
||||
cortex_m::asm::delay(cycles);
|
||||
deassert_peripheral_reset(periph_sel);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user