110 lines
4.4 KiB
Rust
110 lines
4.4 KiB
Rust
//! # Embassy-rs support for the Vorago VA108xx MCU family
|
|
//!
|
|
//! This repository contains the [embassy-rs](https://github.com/embassy-rs/embassy) support for
|
|
//! the VA108xx family. Currently, it contains the time driver to allow using embassy-rs. It uses
|
|
//! the TIM peripherals provided by the VA108xx family for this purpose.
|
|
//!
|
|
//! ## Usage
|
|
//!
|
|
//! This library exposes the [init] or the [init_with_custom_irqs] functions which set up the time
|
|
//! driver. This function must be called once at the start of the application.
|
|
//!
|
|
//! This implementation requires two TIM peripherals provided by the VA108xx device.
|
|
//! The user can freely specify the two used TIM peripheral by passing the concrete TIM instances
|
|
//! into the [init_with_custom_irqs] and [init] method.
|
|
//!
|
|
//! The application also requires two interrupt handlers to handle the timekeeper and alarm
|
|
//! interrupts. By default, this library will define the interrupt handler inside the library
|
|
//! itself by using the `irq-oc30-oc31` feature flag. This library exposes three combinations:
|
|
//!
|
|
//! - `irq-oc30-oc31`: Uses [pac::Interrupt::OC30] and [pac::Interrupt::OC31]
|
|
//! - `irq-oc29-oc30`: Uses [pac::Interrupt::OC29] and [pac::Interrupt::OC30]
|
|
//! - `irq-oc28-oc29`: Uses [pac::Interrupt::OC28] and [pac::Interrupt::OC20]
|
|
//!
|
|
//! You can disable the default features and then specify one of the features above to use the
|
|
//! documented combination of IRQs. It is also possible to specify custom IRQs by importing and
|
|
//! using the [embassy_time_driver_irqs] macro to declare the IRQ handlers in the
|
|
//! application code. If this is done, [init_with_custom_irqs] must be used
|
|
//! method to pass the IRQ numbers to the library.
|
|
//!
|
|
//! ## Examples
|
|
//!
|
|
//! [embassy example projects](https://egit.irs.uni-stuttgart.de/rust/va108xx-rs/src/branch/main/examples/embassy)
|
|
#![no_std]
|
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
|
|
#[cfg(feature = "irqs-in-lib")]
|
|
use va108xx_hal::pac::{self, interrupt};
|
|
use va108xx_hal::time::Hertz;
|
|
use va108xx_hal::timer::TimMarker;
|
|
use vorago_shared_periphs::embassy::time_driver;
|
|
|
|
/// Macro to define the IRQ handlers for the time driver.
|
|
///
|
|
/// By default, the code generated by this macro will be defined inside the library depending on
|
|
/// the feature flags specified. However, the macro is exported to allow users to specify the
|
|
/// interrupt handlers themselves.
|
|
///
|
|
/// Please note that you have to explicitely import the [macro@va108xx_hal::pac::interrupt]
|
|
/// macro in the application code in case this macro is used there.
|
|
#[macro_export]
|
|
macro_rules! embassy_time_driver_irqs {
|
|
(
|
|
timekeeper_irq = $timekeeper_irq:ident,
|
|
alarm_irq = $alarm_irq:ident
|
|
) => {
|
|
const TIMEKEEPER_IRQ: pac::Interrupt = pac::Interrupt::$timekeeper_irq;
|
|
|
|
#[interrupt]
|
|
#[allow(non_snake_case)]
|
|
fn $timekeeper_irq() {
|
|
// Safety: We call it once here.
|
|
unsafe { $crate::time_driver().on_interrupt_timekeeping() }
|
|
}
|
|
|
|
const ALARM_IRQ: pac::Interrupt = pac::Interrupt::$alarm_irq;
|
|
|
|
#[interrupt]
|
|
#[allow(non_snake_case)]
|
|
fn $alarm_irq() {
|
|
// Safety: We call it once here.
|
|
unsafe { $crate::time_driver().on_interrupt_alarm() }
|
|
}
|
|
};
|
|
}
|
|
|
|
// Provide three combinations of IRQs for the time driver by default.
|
|
|
|
#[cfg(feature = "irq-oc30-oc31")]
|
|
embassy_time_driver_irqs!(timekeeper_irq = OC31, alarm_irq = OC30);
|
|
#[cfg(feature = "irq-oc29-oc30")]
|
|
embassy_time_driver_irqs!(timekeeper_irq = OC30, alarm_irq = OC29);
|
|
#[cfg(feature = "irq-oc28-oc29")]
|
|
embassy_time_driver_irqs!(timekeeper_irq = OC29, alarm_irq = OC28);
|
|
|
|
/// Initialization method for embassy.
|
|
///
|
|
/// 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: TimMarker, AlarmTim: TimMarker>(
|
|
sysclk: Hertz,
|
|
timekeeper_tim: TimekeeperTim,
|
|
alarm_tim: AlarmTim,
|
|
) {
|
|
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: TimMarker, AlarmTim: TimMarker>(
|
|
sysclk: Hertz,
|
|
timekeeper_tim: TimekeeperTim,
|
|
alarm_tim: AlarmTim,
|
|
timekeeper_irq: pac::Interrupt,
|
|
alarm_irq: pac::Interrupt,
|
|
) {
|
|
time_driver().__init(sysclk, timekeeper_tim, alarm_tim, timekeeper_irq, alarm_irq)
|
|
}
|