Add embassy example
All checks were successful
Rust/va416xx-rs/pipeline/pr-main This commit looks good
All checks were successful
Rust/va416xx-rs/pipeline/pr-main This commit looks good
This commit is contained in:
@ -25,6 +25,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Fixes for the SPI implementation where the clock divider values were not calculated
|
||||
correctly
|
||||
- Fixes for UART IRQ handler implementation
|
||||
- Add new IRQ router initialization method `irq_router::enable_and_init_irq_router`. This method
|
||||
also sets the initial values of some registers to 0 where the datasheet and the actual reset
|
||||
value are inconsistent, which can lead to weird bugs like IRQs not being triggered properly.
|
||||
|
||||
## Added
|
||||
|
||||
|
@ -12,6 +12,7 @@ categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
|
||||
critical-section = "1"
|
||||
nb = "1"
|
||||
paste = "1"
|
||||
embedded-hal-nb = "1"
|
||||
|
@ -494,7 +494,7 @@ pub struct Clocks {
|
||||
|
||||
impl Clocks {
|
||||
/// Returns the frequency of the HBO clock
|
||||
pub fn hbo(&self) -> Hertz {
|
||||
pub const fn hbo(&self) -> Hertz {
|
||||
HBO_FREQ
|
||||
}
|
||||
|
||||
@ -504,23 +504,23 @@ impl Clocks {
|
||||
}
|
||||
|
||||
/// Returns system clock divied by 2.
|
||||
pub fn apb1(&self) -> Hertz {
|
||||
pub const fn apb1(&self) -> Hertz {
|
||||
self.apb1
|
||||
}
|
||||
|
||||
/// Returns system clock divied by 4.
|
||||
pub fn apb2(&self) -> Hertz {
|
||||
pub const fn apb2(&self) -> Hertz {
|
||||
self.apb2
|
||||
}
|
||||
|
||||
/// Returns the system (core) frequency
|
||||
pub fn sysclk(&self) -> Hertz {
|
||||
pub const fn sysclk(&self) -> Hertz {
|
||||
self.sysclk
|
||||
}
|
||||
|
||||
/// Returns the ADC clock frequency which has a separate divider.
|
||||
#[cfg(not(feature = "va41628"))]
|
||||
pub fn adc_clk(&self) -> Hertz {
|
||||
pub const fn adc_clk(&self) -> Hertz {
|
||||
self.adc_clk
|
||||
}
|
||||
}
|
||||
|
18
va416xx-hal/src/irq_router.rs
Normal file
18
va416xx-hal/src/irq_router.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use crate::{
|
||||
clock::{PeripheralSelect, SyscfgExt},
|
||||
pac,
|
||||
};
|
||||
|
||||
pub fn enable_and_init_irq_router(sysconfig: &mut pac::Sysconfig, irq_router: &pac::IrqRouter) {
|
||||
sysconfig.enable_peripheral_clock(PeripheralSelect::IrqRouter);
|
||||
sysconfig.assert_periph_reset_for_two_cycles(PeripheralSelect::IrqRouter);
|
||||
unsafe {
|
||||
irq_router.dmasel0().write_with_zero(|w| w);
|
||||
irq_router.dmasel1().write_with_zero(|w| w);
|
||||
irq_router.dmasel2().write_with_zero(|w| w);
|
||||
irq_router.dmasel3().write_with_zero(|w| w);
|
||||
irq_router.adcsel().write_with_zero(|w| w);
|
||||
irq_router.dacsel0().write_with_zero(|w| w);
|
||||
irq_router.dacsel1().write_with_zero(|w| w);
|
||||
}
|
||||
}
|
@ -1,3 +1,26 @@
|
||||
//! This is the **H**ardware **A**bstraction **L**ayer (HAL) for the VA416xx MCU family.
|
||||
//!
|
||||
//! It is an additional hardware abstraction on top of the [peripheral access API](https://egit.irs.uni-stuttgart.de/rust/va416xx-rs/src/branch/main/va416xx).
|
||||
|
||||
//! It is the result of reading the datasheet for the device and encoding a type-safe layer over the
|
||||
//! raw PAC. This crate also implements traits specified by the
|
||||
//! [embedded-hal](https://github.com/rust-embedded/embedded-hal) project, making it compatible with
|
||||
//! various drivers in the embedded rust ecosystem.
|
||||
|
||||
//! You have to enable one of the following device features to use this crate depending on
|
||||
//! which chip you are using:
|
||||
|
||||
//! - `va41630`
|
||||
//! - `va41629`
|
||||
//! - `va41628`
|
||||
//! - `va41620`
|
||||
//!
|
||||
//! When using this HAL and writing applications for the VA416xx family in general, it is strongly
|
||||
//! recommended that you set up the clock properly, because the default internal HBO clock
|
||||
//! is not very accurate. You can use the [crate::clock] module for this. If you are working
|
||||
//! with interrupts, it is strongly recommended to set up the IRQ router with the
|
||||
//! [crate::irq_router] module at the very least because that peripheral has confusing and/or
|
||||
//! faulty register reset values which might leads to weird bugs and glitches.
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#[cfg(test)]
|
||||
@ -22,6 +45,7 @@ pub mod dma;
|
||||
pub mod edac;
|
||||
pub mod gpio;
|
||||
pub mod i2c;
|
||||
pub mod irq_router;
|
||||
pub mod nvm;
|
||||
pub mod pwm;
|
||||
pub mod spi;
|
||||
|
@ -5,7 +5,8 @@
|
||||
//! - [Timer MS and Second Tick Example](https://github.com/us-irs/va416xx-rs/blob/main/examples/simple/examples/timer-ticks.rs)
|
||||
use core::cell::Cell;
|
||||
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use cortex_m::asm;
|
||||
use critical_section::Mutex;
|
||||
|
||||
use crate::clock::Clocks;
|
||||
use crate::gpio::{
|
||||
@ -169,6 +170,14 @@ macro_rules! tim_markers {
|
||||
};
|
||||
}
|
||||
|
||||
pub const fn const_clock<Tim: ValidTim + ?Sized>(_: &Tim, clocks: &Clocks) -> Hertz {
|
||||
if Tim::TIM_ID <= 15 {
|
||||
clocks.apb1()
|
||||
} else {
|
||||
clocks.apb2()
|
||||
}
|
||||
}
|
||||
|
||||
tim_markers!(
|
||||
(pac::Tim0, 0, pac::Interrupt::TIM0),
|
||||
(pac::Tim1, 1, pac::Interrupt::TIM1),
|
||||
@ -328,19 +337,27 @@ valid_pin_and_tims!(
|
||||
///
|
||||
/// Only the bit related to the corresponding TIM peripheral is modified
|
||||
#[inline]
|
||||
fn assert_tim_reset(syscfg: &mut pac::Sysconfig, tim_id: u8) {
|
||||
pub fn assert_tim_reset(syscfg: &mut pac::Sysconfig, tim_id: u8) {
|
||||
syscfg
|
||||
.tim_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << tim_id as u32)) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn deassert_tim_reset(syscfg: &mut pac::Sysconfig, tim_id: u8) {
|
||||
pub fn deassert_tim_reset(syscfg: &mut pac::Sysconfig, tim_id: u8) {
|
||||
syscfg
|
||||
.tim_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << tim_id as u32)) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_tim_reset_for_two_cycles(syscfg: &mut pac::Sysconfig, tim_id: u8) {
|
||||
assert_tim_reset(syscfg, tim_id);
|
||||
asm::nop();
|
||||
asm::nop();
|
||||
deassert_tim_reset(syscfg, tim_id);
|
||||
}
|
||||
|
||||
pub type TimRegBlock = pac::tim0::RegisterBlock;
|
||||
|
||||
/// Register interface.
|
||||
@ -481,7 +498,7 @@ pub struct CountdownTimer<TIM: ValidTim> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enable_tim_clk(syscfg: &mut pac::Sysconfig, idx: u8) {
|
||||
pub fn enable_tim_clk(syscfg: &mut pac::Sysconfig, idx: u8) {
|
||||
syscfg
|
||||
.tim_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << idx)) });
|
||||
@ -579,9 +596,10 @@ impl<Tim: ValidTim> CountdownTimer<Tim> {
|
||||
pub fn load(&mut self, timeout: impl Into<Hertz>) {
|
||||
self.tim.reg().ctrl().modify(|_, w| w.enable().clear_bit());
|
||||
self.curr_freq = timeout.into();
|
||||
self.rst_val = self.clock.raw() / self.curr_freq.raw();
|
||||
self.rst_val = (self.clock.raw() / self.curr_freq.raw()) - 1;
|
||||
self.set_reload(self.rst_val);
|
||||
self.set_count(0);
|
||||
// Decrementing counter, to set the reset value.
|
||||
self.set_count(self.rst_val);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -601,7 +619,7 @@ impl<Tim: ValidTim> CountdownTimer<Tim> {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn enable(&mut self) {
|
||||
self.tim.reg().ctrl().modify(|_, w| w.enable().set_bit());
|
||||
self.tim.reg().enable().write(|w| unsafe { w.bits(1) });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -778,7 +796,7 @@ pub fn set_up_ms_tick<Tim: ValidTim>(
|
||||
/// This function can be called in a specified interrupt handler to increment
|
||||
/// the MS counter
|
||||
pub fn default_ms_irq_handler() {
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
critical_section::with(|cs| {
|
||||
let mut ms = MS_COUNTER.borrow(cs).get();
|
||||
ms += 1;
|
||||
MS_COUNTER.borrow(cs).set(ms);
|
||||
@ -787,7 +805,7 @@ pub fn default_ms_irq_handler() {
|
||||
|
||||
/// Get the current MS tick count
|
||||
pub fn get_ms_ticks() -> u32 {
|
||||
cortex_m::interrupt::free(|cs| MS_COUNTER.borrow(cs).get())
|
||||
critical_section::with(|cs| MS_COUNTER.borrow(cs).get())
|
||||
}
|
||||
|
||||
pub struct DelayMs<Tim: ValidTim = pac::Tim0>(CountdownTimer<Tim>);
|
||||
|
Reference in New Issue
Block a user