Skip to content

External Interrupt/Event Controller (EXTI)

lbuild module: modm:platform:exti

This driver provides an API for configuring all EXTI lines via register access. Note that you need to pass a mask, which allows you to configure multiple EXTI lines at once.

A typical use-case is to trigger on multiple GPIO inputs:

// all trigger on both edges
Exti::setTriggers<GpioA0, GpioC4, GpioD6>(Exti::Trigger::BothEdges);
// Sets the specific GPIO port per line
Exti::setTriggerSources<GpioA0, GpioC4, GpioD6>();

// Enables EXTI4 and EXTI9_5 IRQ handlers with the same priority of 10!
Exti::enableVectors<GpioC4, GpioD6>(10);
// Sets a different priority for EXTI0
Exti::enableVector<GpioA0>(5);
// Enable all interrupts at the same time
Exti::enableInterrupts<GpioA0, GpioC4, GpioD6>();

// You must manually define the IRQ handlers but *only*
// if you disable the `with_handlers` option!
MODM_ISR(EXTI0) { Exti::acknowledgeFlags<GpioA0>(); }
MODM_ISR(EXTI4) { Exti::acknowledgeFlags<GpioC4>(); }
MODM_ISR(EXTI9_5) { Exti::acknowledgeFlags<GpioD6>(); }

Note that you can also use this to configure more than just GPIO trigger sources, you can configure all other device specific EXTI lines as well. However, you need to manually configure the NVIC vector and possibly also configure the sending peripheral separately.

// Configure the RTC peripheral to send the tamper event
// Line 21 is the RTC tamper alert on STM32F4x6
Exti::setTrigger(1ul << 21, Exti::Trigger::RisingEdge);
Exti::enableInterrupts(1ul << 21);
// Manually enable the RTC_Alarm IRQ
NVIC_SetPriority(RTC_Alarm_IRQn, 10);
NVIC_EnableIRQ(RTC_Alarm_IRQn);
// Different IRQ naming scheme, not EXTI_RTC!
MODM_ISR(RTC_Alarm) {}

You can also trigger events instead of interrupts to facilitate WFE.

Exti::setTrigger(1ul << 21, Exti::Trigger::FallingEdge);
Exti::enableEvents(1ul << 21);

This module is only available for stm32.

Options

with_handlers

Use callbacks for GPIO lines

To simplify the external IRQ management of external GPIO triggers, you can use the connect method to attach a void(uint8_t) callback to EXTI lines 0-15, which gets passed the triggered line number as an argument:

Exti::connect<GpioA0>(Exti::Trigger::FallingEdge,
                      [count=uint32_t(0)](uint8_t line) mutable
{
    MODM_LOG_INFO << "Line " << line << " triggered " << ++count << " times!" << modm::endl;
});
// to disable the handler and IRQ later
Exti::disconnect<GpioA0>();

Duplicate Symbols for EXTI_IRQHandler

This option internally defines all MODM_ISR(EXTI*) IRQs, so you cannot define them anymore in your application!

The callback is implemented using modm::inplace_function, therefore uses no heap, but has a fixed storage size of sizeof(void*) by default. You can increase this storage size by defining a new global storage size MODM_EXTI_HANDLER_STORAGE=bytes in your project.xml:

<library>
  <collectors>
    <collect name="modm:build:cppdefines">MODM_EXTI_HANDLER_STORAGE=12</collect>
  </collectors>
</library>

Default: yes
Inputs: [yes, no]

Dependencies

modm:platform:exti modm_platform_exti modm: platform: exti modm_cmsis_device modm: cmsis: device modm_platform_exti->modm_cmsis_device modm_platform_gpio modm: platform: gpio modm_platform_exti->modm_platform_gpio modm_utils modm: utils modm_platform_exti->modm_utils

Limited availability: Check with 'lbuild discover' if this module is available for your target!