Rework exti module to use a simpler API

The "specific" lines configuration would not work due to index error in
the callback configuration. While fixing the error, simplifying the API
by moving the afio calls to the calling context seemed a cleaner way to
do things
This commit is contained in:
Steins7 2024-08-04 19:38:24 +02:00
parent ba9bc57a49
commit 7ab6622908
2 changed files with 33 additions and 101 deletions

View File

@ -11,7 +11,6 @@
#include "exti_regs.h" #include "exti_regs.h"
#include "nvic.h" #include "nvic.h"
#include "afio.h"
//--local definitions----------------------------------------------------------- //--local definitions-----------------------------------------------------------
@ -24,13 +23,11 @@ static ExtiCallback callbacks[19];
//--public functions------------------------------------------------------------ //--public functions------------------------------------------------------------
void exti_configure(enum ExtiLine line_mask, enum GpioPort port, void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask,
enum ExtiConfig config_mask, ExtiCallback callback) ExtiCallback callback)
{ {
exti_reset(line_mask); exti_reset(line_mask);
afio_map_exti(line_mask, port);
//configure edge detections //configure edge detections
if (config_mask & EXTI_CONFIG_RISING_EDGE) { if (config_mask & EXTI_CONFIG_RISING_EDGE) {
regs->RTSR.word |= line_mask; regs->RTSR.word |= line_mask;
@ -48,7 +45,7 @@ void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
regs->EMR.word |= line_mask; regs->EMR.word |= line_mask;
if (callback) { if (callback) {
//register callbacks for each line selected //register callbacks for each line selected
for (uint8_t i = 0; i < 16; ++i) { for (uint8_t i = 0; i < 19; ++i) {
if (line_mask & (0x1 << i)) { if (line_mask & (0x1 << i)) {
callbacks[i] = callback; callbacks[i] = callback;
} }
@ -66,6 +63,15 @@ void exti_configure(enum ExtiLine line_mask, enum GpioPort port,
if (line_mask & 0x7c00) { if (line_mask & 0x7c00) {
nvic_enable(NVIC_IRQ_EXTI15_10); nvic_enable(NVIC_IRQ_EXTI15_10);
} }
if (line_mask & EXTI_LINE_PVD) {
nvic_enable(NVIC_IRQ_PVD);
}
if (line_mask & EXTI_LINE_RTC) {
nvic_enable(NVIC_IRQ_RTC_ALARM);
}
if (line_mask & EXTI_LINE_USB) {
nvic_enable(NVIC_IRQ_USB_WAKEUP);
}
//enable irqs in last to avoid triggers during config //enable irqs in last to avoid triggers during config
regs->IMR.word |= line_mask; regs->IMR.word |= line_mask;
@ -94,56 +100,6 @@ void exti_reset(enum ExtiLine line_mask)
nvic_disable(NVIC_IRQ_EXTI15_10); nvic_disable(NVIC_IRQ_EXTI15_10);
} }
afio_map_exti(0xFFFF, 0x0);
}
void exti_configure_specific(enum ExtiLineSpecific line_mask,
enum ExtiConfig config_mask, ExtiCallback callback)
{
//reset is identical to normal lines
exti_reset_specific(line_mask);
//configure edge detections
if (config_mask & EXTI_CONFIG_RISING_EDGE) {
regs->RTSR.word |= line_mask;
} else {
regs->RTSR.word &= ~line_mask;
}
if (config_mask & EXTI_CONFIG_FALLING_EDGE) {
regs->FTSR.word |= line_mask;
} else {
regs->FTSR.word &= ~line_mask;
}
//reconfigure events/irqs
regs->EMR.word |= line_mask;
if (callback) {
//register callbacks for each line selected
for (uint8_t i = 0; i < 16; ++i) {
if (line_mask & (0x1 << i)) {
callbacks[i] = callback;
}
}
//enable interrupts lines in nvic
if (line_mask & EXTI_LINE_PVD) {
nvic_enable(NVIC_IRQ_PVD);
}
if (line_mask & EXTI_LINE_RTC) {
nvic_enable(NVIC_IRQ_RTC_ALARM);
}
if (line_mask & EXTI_LINE_USB) {
nvic_enable(NVIC_IRQ_USB_WAKEUP);
}
//enable irqs in last to avoid triggers during config
regs->IMR.word |= line_mask;
}
}
void exti_reset_specific(enum ExtiLineSpecific line_mask)
{
//disable events/irqs //disable events/irqs
regs->IMR.word &= ~line_mask; regs->IMR.word &= ~line_mask;
regs->EMR.word &= ~line_mask; regs->EMR.word &= ~line_mask;
@ -163,6 +119,7 @@ void exti_reset_specific(enum ExtiLineSpecific line_mask)
} }
} }
void exti_reset_peripheral(void) void exti_reset_peripheral(void)
{ {
//reset peripheral config //reset peripheral config
@ -182,8 +139,6 @@ void exti_reset_peripheral(void)
nvic_disable(NVIC_IRQ_PVD); nvic_disable(NVIC_IRQ_PVD);
nvic_disable(NVIC_IRQ_RTC_ALARM); nvic_disable(NVIC_IRQ_RTC_ALARM);
nvic_disable(NVIC_IRQ_USB_WAKEUP); nvic_disable(NVIC_IRQ_USB_WAKEUP);
afio_map_exti(0xFFFF, 0x0);
} }
//--local functions------------------------------------------------------------- //--local functions-------------------------------------------------------------

View File

@ -10,16 +10,11 @@
//--includes-------------------------------------------------------------------- //--includes--------------------------------------------------------------------
#include "stdint.h"
#include "stdbool.h"
#include "gpio.h"
//--type definitions------------------------------------------------------------ //--type definitions------------------------------------------------------------
/** /**
* Available exti lines. These lines correspond to gpios * Available exti lines. The numbered lines correspond to gpios while the
* remaining are directly mapped to peripherals
*/ */
enum ExtiLine { enum ExtiLine {
EXTI_LINE_0 = (0x1 << 0), EXTI_LINE_0 = (0x1 << 0),
@ -38,12 +33,6 @@ enum ExtiLine {
EXTI_LINE_13 = (0x1 << 13), EXTI_LINE_13 = (0x1 << 13),
EXTI_LINE_14 = (0x1 << 14), EXTI_LINE_14 = (0x1 << 14),
EXTI_LINE_15 = (0x1 << 15), EXTI_LINE_15 = (0x1 << 15),
};
/**
* Available exti lines. These lines correspond to specific peripherals
*/
enum ExtiLineSpecific {
EXTI_LINE_PVD = (0x1 << 16), EXTI_LINE_PVD = (0x1 << 16),
EXTI_LINE_RTC = (0x1 << 17), EXTI_LINE_RTC = (0x1 << 17),
EXTI_LINE_USB = (0x1 << 18), EXTI_LINE_USB = (0x1 << 18),
@ -64,43 +53,31 @@ typedef void (*ExtiCallback)(void);
//--functions------------------------------------------------------------------- //--functions-------------------------------------------------------------------
/** /**
* Configure lines on a single GPIO port. The ExtiLine enum can be used as a * Configure lines to call a single callback. The ExtiLine enum can be used as a
* mask to configure multiple lines at the same time. Every line can only be * mask to configure multiple lines at the same time.
* configured for a single port, reconfiguring it will override the previous
* configuration. Each line is linked to the pins of the same id (ex : pin 1 for
* exti 1). When possible, it is recommanded to use the lowest id possible for
* better performance. The ExtiConfig enum can be used as mask. If no callback
* is specified, the interrupt won't be enabled, but an event will still be sent
* to wake the cpu up.
* *
* Note: wich port is linked to a line can be changed atfer the fact using * Every numbered line must be linked to a gpio port using afio_map_exti(). Each
* afio_map_exti() * line is linked to the pins of the same id (ex : pin 1 for exti 1). When
* possible, it is recommended to use the lowest id possible for better
* performance. Each pin must be configured independently through the gpio
* driver module
*
* The remaining lines are linked to specific peripherals which must be
* configured independently through the corresponding driver module.
*
* The ExtiConfig enum can be used as mask. If no callback is specified, the
* interrupt won't be enabled, but an event will still be sent to wake the cpu
* up.
*/ */
void exti_configure(enum ExtiLine line_mask, enum GpioPort port, void exti_configure(enum ExtiLine line_mask, enum ExtiConfig config_mask,
enum ExtiConfig config_mask, ExtiCallback callback); ExtiCallback callback);
/** /**
* Resets lines. The ExtiLine enum can be used as a mask to configure multiple * Resets lines. The ExtiLine enum can be used as a mask to reset multiple lines
* lines at the same time * at the same time
*/ */
void exti_reset(enum ExtiLine line_mask); void exti_reset(enum ExtiLine line_mask);
/**
* Configure lines for specific, non-gpio peripherals. The ExtiLineSpecific enum
* can be used as a mask to configure multiple lines at the same time. The
* ExtiConfig enum can be used as mask. If no callback is specified, the
* interrupt won't be enabled, but an event will still be sent to wake the cpu
* up
*/
void exti_configure_specific(enum ExtiLineSpecific line_mask,
enum ExtiConfig config_mask, ExtiCallback callback);
/**
* Resets lines for specific, non-gpio peripherals. The ExtiLineSpecific enum
* can be used as a mask to configure multiple lines at the same time.
*/
void exti_reset_specific(enum ExtiLineSpecific line_mask);
/** /**
* Resets all lines. The exti peripheral is returned to its reset configuration * Resets all lines. The exti peripheral is returned to its reset configuration
*/ */