1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/* callback.rs
*
* Developed by Tim Walls <tim.walls@snowgoons.com>
* Copyright (c) All Rights Reserved, Tim Walls
*/
//! Reasonably generic way of dealing with callbacks from interrupt handlers.
//!
// Imports ===================================================================
use core::any::Any;
// Declarations ==============================================================
/**
* Represents a callback function from an interrupt service routine.
*/
#[derive(Copy,Clone,Debug)]
pub enum IsrCallback<F,R>
{
/// No Operation - dummy callback that evaluates to a fixed constant return
/// value.
Nop(R),
/// A function/closure callback. This will be called when the interrupt
/// service routine needs it; the function signature is context dependent,
/// however the last parameter will always be an `Option<&'static dyn Any>`
/// user-data field, which will be given a `None` value.
/// The first parameter must be an isolation token
/// ([`avr_oxide::concurrency::Isolated`])
Function(F),
/// A function/closure callback. This will be called when the interrupt
/// service routine needs it; the function signature is context dependent,
/// however the last parameter will always be an `Option<&'static dyn Any>`
/// user-data field, into which the given data will be passed as Some()
/// value.
/// The first parameter must be an isolation token
/// ([`avr_oxide::concurrency::Isolated`])
WithData(F, *const dyn Any)
}
// Code ======================================================================
#[doc(hidden)]
#[macro_export]
macro_rules! isr_cb_invoke {
($isotoken:expr, $cb:expr, $($params:expr),*) => {
{
let cb : avr_oxide::hal::generic::callback::IsrCallback<_,_> = $cb;
match cb {
avr_oxide::hal::generic::callback::IsrCallback::Nop(r) => r,
avr_oxide::hal::generic::callback::IsrCallback::Function(f) => (f)($isotoken, $($params),*, Option::None),
avr_oxide::hal::generic::callback::IsrCallback::WithData(f,d) => (f)($isotoken, $($params),*, Option::Some(d))
}
}
}
}
impl<F,R> IsrCallback<F,R> {
/**
* Return true iff this callback is a no-op function. We can use this to
* drive optimisations like disabling the interrupt routine entirely.
*/
pub fn is_nop(&self) -> bool {
match self {
IsrCallback::Nop(_) => true,
IsrCallback::Function(_) => false,
IsrCallback::WithData(_, _) => false
}
}
}
// Tests =====================================================================