Function-like, trait-based interrupt handler registration.
This crate provides a method of delegating creation of occupations, and attempts to improve pains associated with creating registrations.
Usage
As an end-user of this crate, you will want to use the [take_nvic_interrupt
] and [take_exception
] macros. These generate implementors of the [NvicInterruptRegistration
] and [ExceptionRegistration
] traits respectively, which can be passed to functions that make use of interrupts.
To see information on how you can use [InterruptRegistration
], [NvicInterruptRegistration
] and [ExceptionRegistration
] refer to the docs on those traits.
The problem that this crate tries to solve.
To demonstrate the problem that this crate tries to solve, we will use an example use case.
Definitions
To help explain the use case of this crate, we use the following definitions:
- a registration: the function pointer placed in an interrupt vector, the declaration of an interrupt handler.
- an occupation: the code that should run when servicing an interrupt, the body of an interrupt handler.
The usecase
Our goal with the use case is:
- Configure the
SysTick
interrupt so that it triggers once every1337
cycles. - Increment a counter every time the
SysTick
interrupt occurs.
When using the cortex_m_rt
crate, we would do something like this:
#
#
use ;
And within the crate providing setup_systick_exception
and systick_reload
:
In this example:
- There is no semantic connection between
setup_systick_exception
and the registration/occupation besides naming and possibly documentation. - The responsibility of adding the correct occupation to the correct registration falls entirely on the person writing the program.
- The maintainer of the crate that provides
setup_systick_exception
andsystick_reload
has no control over the occupation or registration. - There is no need for a trampoline to setup up the interrupt handler.
A solution?
To represent registrations, the [InterruptRegistration
], [NvicInterruptRegistration
], and [ExceptionRegistration
] traits are provided. They can be used to insert occupations in a more dynamic way.
These traits allow for the following:
- Code that wishes to provide an occupation without directly creating a registration can be written by requiring that user code provides an registration.
- Code that wishes to provide an occupation can verify that a provided registration is correct for the to-be-created occupation.
To alleviate difficulties with creating registrations, the [take_nvic_interrupt
] and [take_exception
] proc-macros are provided. They perform the less self explanatory parts of the setting up a registration, and provide an implementor of [NvicInterruptRegistration
] and [ExceptionRegistration
], respectively.
A revised example
With these new tools, we can rewrite our code to look as follows:
#
use entry;
use SysTick;
static mut COUNTER: u32 = 0;
!
In the crate providing setup_systick_exception
:
# use ExceptionRegistration;
In the revised example:
- There is a more defined semantic connection between the registration and the occupation.
- The implementor of
setup_systick_exception
has full control over the occupation, and can optionally allow user code to perform some extra actions. - The implementor of
setup_systick_exception
can verify that the correct registration is passed to it. - A trampoline is now required in the interrupt handler, adding ~5 cycles of extra processing when an interrupt occurs.
Main differences
The main differences between the cortex-m-rt
approach and what cortex-m-interrupt
provides are the following:
cortex-m-interrupt
offers a way of creating clearer separation of responsibilities when it comes to registering interrupt handlers.- The traits provided by
cortex-m-interrupt
support a tighter semantic connection between creating a registration and creating an occupation. - The method provided by
cortex-m-rt
has slightly less overhead as it does not require a trampoline.