drivers: intc: stm32: make stm32_exti_line_t opaque

This commit makes the contents of the stm32_exti_line_t data type opaque to
the EXTI GPIO interrupt controller API users. The GPIO driver is updated
to comply with this API change.

N.B.: while some assertions are removed as part of this commit, they were
broken since forever anyways, so nothing of value is lost.

Signed-off-by: Mathieu Choplain <mathieu.choplain@st.com>
This commit is contained in:
Mathieu Choplain 2024-08-03 18:51:53 +02:00 committed by Anas Nashif
parent 0551825ca3
commit 5cd274ce48
3 changed files with 93 additions and 60 deletions

View file

@ -39,11 +39,11 @@ LOG_MODULE_REGISTER(stm32, CONFIG_GPIO_LOG_LEVEL);
/**
* @brief EXTI interrupt callback
*/
static void gpio_stm32_isr(stm32_exti_line_t line, void *arg)
static void gpio_stm32_isr(gpio_port_pins_t pin, void *arg)
{
struct gpio_stm32_data *data = arg;
gpio_fire_callbacks(&data->cb, data->dev, BIT(line));
gpio_fire_callbacks(&data->cb, data->dev, pin);
}
/**
@ -505,24 +505,26 @@ static int gpio_stm32_pin_interrupt_configure(const struct device *dev,
{
const struct gpio_stm32_config *cfg = dev->config;
struct gpio_stm32_data *data = dev->data;
const stm32_exti_line_t exti_line =
stm32_exti_get_pin_exti_line(cfg->port, pin);
uint32_t edge = 0;
int err = 0;
#ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
if (mode == GPIO_INT_MODE_DISABLE_ONLY) {
stm32_exti_disable(pin);
stm32_exti_disable(exti_line);
goto exit;
} else if (mode == GPIO_INT_MODE_ENABLE_ONLY) {
stm32_exti_enable(pin);
stm32_exti_enable(exti_line);
goto exit;
}
#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
if (mode == GPIO_INT_MODE_DISABLED) {
if (stm32_exti_get_line_src_port(pin) == cfg->port) {
stm32_exti_disable(pin);
stm32_exti_unset_callback(pin);
stm32_exti_trigger(pin, STM32_EXTI_TRIG_NONE);
stm32_exti_disable(exti_line);
stm32_exti_unset_callback(exti_line);
stm32_exti_trigger(exti_line, STM32_EXTI_TRIG_NONE);
}
/* else: No irq source configured for pin. Nothing to disable */
goto exit;
@ -534,7 +536,7 @@ static int gpio_stm32_pin_interrupt_configure(const struct device *dev,
goto exit;
}
if (stm32_exti_set_callback(pin, gpio_stm32_isr, data) != 0) {
if (stm32_exti_set_callback(exti_line, gpio_stm32_isr, data) != 0) {
err = -EBUSY;
goto exit;
}
@ -556,9 +558,9 @@ static int gpio_stm32_pin_interrupt_configure(const struct device *dev,
stm32_exti_set_line_src_port(pin, cfg->port);
stm32_exti_trigger(pin, edge);
stm32_exti_trigger(exti_line, edge);
stm32_exti_enable(pin);
stm32_exti_enable(exti_line);
exit:
return err;

View file

@ -77,19 +77,14 @@ static inline uint32_t stm32_exti_linenum_to_src_cfg_line(gpio_pin_t linenum)
*/
static inline int stm32_exti_is_pending(stm32_exti_line_t line)
{
if (line < NUM_EXTI_LINES) {
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
return (LL_EXTI_IsActiveRisingFlag_0_31(BIT(line)) ||
LL_EXTI_IsActiveFallingFlag_0_31(BIT(line)));
return (LL_EXTI_IsActiveRisingFlag_0_31(line) ||
LL_EXTI_IsActiveFallingFlag_0_31(line));
#elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
return LL_C2_EXTI_IsActiveFlag_0_31(BIT(line));
return LL_C2_EXTI_IsActiveFlag_0_31(line);
#else
return LL_EXTI_IsActiveFlag_0_31(BIT(line));
return LL_EXTI_IsActiveFlag_0_31(line);
#endif
} else {
__ASSERT_NO_MSG(0);
return 0;
}
}
/**
@ -99,18 +94,30 @@ static inline int stm32_exti_is_pending(stm32_exti_line_t line)
*/
static inline void stm32_exti_clear_pending(stm32_exti_line_t line)
{
if (line < NUM_EXTI_LINES) {
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
LL_EXTI_ClearRisingFlag_0_31(BIT(line));
LL_EXTI_ClearFallingFlag_0_31(BIT(line));
LL_EXTI_ClearRisingFlag_0_31(line);
LL_EXTI_ClearFallingFlag_0_31(line);
#elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
LL_C2_EXTI_ClearFlag_0_31(BIT(line));
LL_C2_EXTI_ClearFlag_0_31(line);
#else
LL_EXTI_ClearFlag_0_31(BIT(line));
LL_EXTI_ClearFlag_0_31(line);
#endif
} else {
__ASSERT_NO_MSG(0);
}
}
/**
* @returns the LL_EXTI_LINE_n define for EXTI line number @p linenum
*/
static inline stm32_exti_line_t linenum_to_ll_exti_line(gpio_pin_t linenum)
{
return BIT(linenum);
}
/**
* @returns EXTI line number for LL_EXTI_LINE_n define
*/
static inline gpio_pin_t ll_exti_line_to_linenum(stm32_exti_line_t line)
{
return LOG2(line);
}
/**
@ -126,21 +133,25 @@ static void stm32_exti_isr(const void *exti_range)
struct stm32_exti_data *data = dev->data;
const struct stm32_exti_range *range = exti_range;
stm32_exti_line_t line;
uint32_t line_num;
/* see which bits are set */
for (uint8_t i = 0; i <= range->len; i++) {
line = range->start + i;
line_num = range->start + i;
line = linenum_to_ll_exti_line(line_num);
/* check if interrupt is pending */
if (stm32_exti_is_pending(line) != 0) {
/* clear pending interrupt */
stm32_exti_clear_pending(line);
/* run callback only if one is registered */
if (!data->cb[line].cb) {
if (!data->cb[line_num].cb) {
continue;
}
data->cb[line].cb(line, data->cb[line].data);
/* `line` can be passed as-is because LL_EXTI_LINE_n is (1 << n) */
data->cb[line_num].cb(line, data->cb[line_num].data);
}
}
}
@ -227,21 +238,39 @@ DEVICE_DT_DEFINE(EXTI_NODE, &stm32_exti_init,
* @brief EXTI GPIO interrupt controller API implementation
*/
/**
* @internal
* STM32 EXTI driver:
* The type @ref stm32_exti_line_t is used to hold the LL_EXTI_LINE_xxx
* defines of the LL EXTI API that corresponds to the provided pin.
*
* The port is not part of these definitions because port configuration
* is done via different APIs, which use the LL_<PPP>_EXTI_LINE_xxx defines
* returned by @ref stm32_exti_linenum_to_src_cfg_line instead.
* @endinternal
*/
stm32_exti_line_t stm32_exti_get_pin_exti_line(uint32_t port, gpio_pin_t pin)
{
ARG_UNUSED(port);
return linenum_to_ll_exti_line(pin);
}
void stm32_exti_enable(stm32_exti_line_t line)
{
int irqnum = 0;
unsigned int irqnum;
uint32_t line_num = ll_exti_line_to_linenum(line);
__ASSERT_NO_MSG(line < NUM_EXTI_LINES);
__ASSERT_NO_MSG(line_num < NUM_EXTI_LINES);
/* Get matching exti irq provided line thanks to irq_table */
irqnum = exti_irq_table[line];
irqnum = exti_irq_table[line_num];
__ASSERT_NO_MSG(irqnum != 0xFF);
/* Enable requested line interrupt */
#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
LL_C2_EXTI_EnableIT_0_31(BIT(line));
LL_C2_EXTI_EnableIT_0_31(line);
#else
LL_EXTI_EnableIT_0_31(BIT(line));
LL_EXTI_EnableIT_0_31(line);
#endif
/* Enable exti irq interrupt */
@ -250,39 +279,33 @@ void stm32_exti_enable(stm32_exti_line_t line)
void stm32_exti_disable(stm32_exti_line_t line)
{
if (line < NUM_EXTI_LINES) {
#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
LL_C2_EXTI_DisableIT_0_31(BIT(line));
LL_C2_EXTI_DisableIT_0_31(line);
#else
LL_EXTI_DisableIT_0_31(BIT(line));
LL_EXTI_DisableIT_0_31(line);
#endif
} else {
__ASSERT_NO_MSG(0);
}
}
void stm32_exti_trigger(stm32_exti_line_t line, uint32_t trigger)
{
__ASSERT_NO_MSG(line < NUM_EXTI_LINES);
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
switch (trigger) {
case STM32_EXTI_TRIG_NONE:
LL_EXTI_DisableRisingTrig_0_31(BIT(line));
LL_EXTI_DisableFallingTrig_0_31(BIT(line));
LL_EXTI_DisableRisingTrig_0_31(line);
LL_EXTI_DisableFallingTrig_0_31(line);
break;
case STM32_EXTI_TRIG_RISING:
LL_EXTI_EnableRisingTrig_0_31(BIT(line));
LL_EXTI_DisableFallingTrig_0_31(BIT(line));
LL_EXTI_EnableRisingTrig_0_31(line);
LL_EXTI_DisableFallingTrig_0_31(line);
break;
case STM32_EXTI_TRIG_FALLING:
LL_EXTI_EnableFallingTrig_0_31(BIT(line));
LL_EXTI_DisableRisingTrig_0_31(BIT(line));
LL_EXTI_EnableFallingTrig_0_31(line);
LL_EXTI_DisableRisingTrig_0_31(line);
break;
case STM32_EXTI_TRIG_BOTH:
LL_EXTI_EnableRisingTrig_0_31(BIT(line));
LL_EXTI_EnableFallingTrig_0_31(BIT(line));
LL_EXTI_EnableRisingTrig_0_31(line);
LL_EXTI_EnableFallingTrig_0_31(line);
break;
default:
__ASSERT_NO_MSG(0);
@ -295,18 +318,19 @@ int stm32_exti_set_callback(stm32_exti_line_t line, stm32_exti_callback_t cb, vo
{
const struct device *const dev = DEVICE_DT_GET(EXTI_NODE);
struct stm32_exti_data *data = dev->data;
uint32_t line_num = ll_exti_line_to_linenum(line);
if ((data->cb[line].cb == cb) && (data->cb[line].data == arg)) {
if ((data->cb[line_num].cb == cb) && (data->cb[line_num].data == arg)) {
return 0;
}
/* if callback already exists/maybe-running return busy */
if (data->cb[line].cb != NULL) {
if (data->cb[line_num].cb != NULL) {
return -EBUSY;
}
data->cb[line].cb = cb;
data->cb[line].data = arg;
data->cb[line_num].cb = cb;
data->cb[line_num].data = arg;
return 0;
}
@ -315,9 +339,10 @@ void stm32_exti_unset_callback(stm32_exti_line_t line)
{
const struct device *const dev = DEVICE_DT_GET(EXTI_NODE);
struct stm32_exti_data *data = dev->data;
uint32_t line_num = ll_exti_line_to_linenum(line);
data->cb[line].cb = NULL;
data->cb[line].data = NULL;
data->cb[line_num].cb = NULL;
data->cb[line_num].data = NULL;
}
void stm32_exti_set_line_src_port(gpio_pin_t line, uint32_t port)

View file

@ -25,10 +25,16 @@
#include <zephyr/drivers/gpio.h>
/**
* @brief Type representing an EXTI line number
* @brief Opaque type representing an EXTI line
*/
typedef uint32_t stm32_exti_line_t;
/**
* @brief Get the EXTI interrupt line value corresponding
* to specified @p pin of GPIO port @p port
*/
stm32_exti_line_t stm32_exti_get_pin_exti_line(uint32_t port, gpio_pin_t pin);
/**
* @brief Enable EXTI interrupts for specified line
*
@ -68,12 +74,12 @@ void stm32_exti_trigger(stm32_exti_line_t line, uint32_t trg);
/**
* @brief EXTI interrupt callback function signature
*
* @param line Triggered EXTI interrupt line
* @param pin GPIO pin on which interrupt occurred
* @param user @p data provided to @ref stm32_exti_set_callback
*
* @note This callback is invoked in ISR context.
*/
typedef void (*stm32_exti_callback_t)(stm32_exti_line_t line, void *user);
typedef void (*stm32_exti_callback_t)(gpio_port_pins_t pin, void *user);
/**
* @brief Set callback invoked when an interrupt occurs on specified EXTI line