//! # 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( 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( 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) }