drivers: interrupt_controller: introduce STM32 EXTI driver
add peripheral lines support add EXTI interface Co-authored-by: Mathieu CHOPLAIN <mathieu.choplain@st.com> Signed-off-by: Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
This commit is contained in:
committed by
Chris Friedt
parent
5e727d7e83
commit
36ef80033c
@@ -7,6 +7,7 @@ zephyr_library_sources_ifdef(CONFIG_CAVS_ICTL intc_cavs.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DW_ICTL intc_dw.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_DW_ICTL_ACE intc_dw_ace.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_INTC_STM32 intc_gpio_stm32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EXTI_STM32 intc_exti_stm32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GD32_EXTI intc_gd32_exti.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GIC_V1 intc_gic.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GIC_V2 intc_gic.c)
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
# STM32 EXTI configuration
|
||||
|
||||
# Copyright (c) 2016 Open-RnD Sp. z o.o.
|
||||
# Copyright (c) 2025 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if SOC_FAMILY_STM32
|
||||
|
||||
config GPIO_INTC_STM32
|
||||
bool "GPIO Interrupt/Event Controller (EXTI) Driver for STM32 family of MCUs"
|
||||
config EXTI_STM32
|
||||
bool "STM32 External Interrupt/Event Controller (EXTI) Driver"
|
||||
default y
|
||||
depends on DT_HAS_ST_STM32_EXTI_ENABLED
|
||||
help
|
||||
Enable GPIO interrupt controller driver for STM32 family of MCUs
|
||||
Enable STM32 EXTI driver
|
||||
|
||||
config GPIO_INTC_STM32
|
||||
bool "STM32 GPIO Interrupt/Event Controller (EXTI) Driver"
|
||||
default y
|
||||
depends on EXTI_STM32
|
||||
help
|
||||
Enable STM32 GPIO interrupt controller driver
|
||||
|
||||
config GPIO_INTC_STM32WB0
|
||||
bool "GPIO Interrupt Controller Driver for STM32WB0 series"
|
||||
|
||||
361
drivers/interrupt_controller/intc_exti_stm32.c
Normal file
361
drivers/interrupt_controller/intc_exti_stm32.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
||||
* Copyright (c) 2017 RnDity Sp. z o.o.
|
||||
* Copyright (c) 2019-23 Linaro Limited
|
||||
* Copyright (C) 2025 Savoir-faire Linux, Inc.
|
||||
* Copyright (c) 2025 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief STM32 External Interrupt/Event Controller (EXTI) Driver
|
||||
*/
|
||||
|
||||
#include <soc.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/drivers/interrupt_controller/intc_exti_stm32.h>
|
||||
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
|
||||
|
||||
#include "stm32_hsem.h"
|
||||
#include "intc_exti_stm32_priv.h"
|
||||
|
||||
LOG_MODULE_REGISTER(exti_stm32, CONFIG_INTC_LOG_LEVEL);
|
||||
|
||||
#define IS_VALID_EXTI_LINE_NUM(line_num) ((line_num) < STM32_EXTI_TOTAL_LINES_NUM)
|
||||
|
||||
/*
|
||||
* The boilerplate for COND_CODE_x is needed because the values are not 0/1
|
||||
*/
|
||||
#if STM32_EXTI_TOTAL_LINES_NUM > 32
|
||||
#define HAS_LINES_32_63 1
|
||||
#if STM32_EXTI_TOTAL_LINES_NUM > 64
|
||||
#define HAS_LINES_64_95 1
|
||||
#endif /* STM32_EXTI_TOTAL_LINES_NUM > 64 */
|
||||
#endif /* STM32_EXTI_TOTAL_LINES_NUM > 32 */
|
||||
|
||||
#define EXTI_FN_HANDLER(_fn, line_num, line) \
|
||||
if (line_num < 32U) { \
|
||||
_fn(0_31, line); \
|
||||
IF_ENABLED(HAS_LINES_32_63, ( \
|
||||
} else if (line_num < 64U) { \
|
||||
_fn(32_63, line); \
|
||||
)) \
|
||||
IF_ENABLED(HAS_LINES_64_95, ( \
|
||||
} else if (line_num < 96U) { \
|
||||
_fn(64_95, line); \
|
||||
)) \
|
||||
} else { \
|
||||
LOG_ERR("Invalid line number %u", line_num); \
|
||||
__ASSERT_NO_MSG(0); \
|
||||
}
|
||||
|
||||
#define EXTI_FN_RET_HANDLER(_fn, ret, line_num, line) \
|
||||
if (line_num < 32U) { \
|
||||
*ret = _fn(0_31, line); \
|
||||
IF_ENABLED(HAS_LINES_32_63, ( \
|
||||
} else if (line_num < 64U) { \
|
||||
*ret = _fn(32_63, line); \
|
||||
)) \
|
||||
IF_ENABLED(HAS_LINES_64_95, ( \
|
||||
} else if (line_num < 96U) { \
|
||||
*ret = _fn(64_95, line); \
|
||||
)) \
|
||||
} else { \
|
||||
LOG_ERR("Invalid line number %u", line_num); \
|
||||
__ASSERT_NO_MSG(0); \
|
||||
}
|
||||
|
||||
|
||||
bool stm32_exti_is_pending(uint32_t line_num)
|
||||
{
|
||||
bool ret = false;
|
||||
const uint32_t line = exti_linenum_to_ll_exti_line(line_num);
|
||||
|
||||
if (!IS_VALID_EXTI_LINE_NUM(line_num)) {
|
||||
LOG_ERR("Invalid line number %u", line_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
|
||||
/*
|
||||
* Note: we can't use EXTI_FN_HANDLER here because we care
|
||||
* about the return value of EXTI_IS_ACTIVE_FLAG.
|
||||
*/
|
||||
EXTI_FN_RET_HANDLER(EXTI_IS_ACTIVE_FLAG, &ret, line_num, line);
|
||||
|
||||
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int stm32_exti_clear_pending(uint32_t line_num)
|
||||
{
|
||||
const uint32_t line = exti_linenum_to_ll_exti_line(line_num);
|
||||
|
||||
if (!IS_VALID_EXTI_LINE_NUM(line_num)) {
|
||||
LOG_ERR("Invalid line number %u", line_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
|
||||
EXTI_FN_HANDLER(EXTI_CLEAR_FLAG, line_num, line);
|
||||
|
||||
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stm32_exti_sw_interrupt(uint32_t line_num)
|
||||
{
|
||||
const uint32_t line = exti_linenum_to_ll_exti_line(line_num);
|
||||
|
||||
if (!IS_VALID_EXTI_LINE_NUM(line_num)) {
|
||||
LOG_ERR("Invalid line number %u", line_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
|
||||
EXTI_FN_HANDLER(EXTI_GENERATE_SWI, line_num, line);
|
||||
|
||||
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Enables the peripheral clock required to access EXTI registers */
|
||||
static int stm32_exti_enable_clocks(void)
|
||||
{
|
||||
/* Initialize to 0 for series where there is nothing to do. */
|
||||
int ret = 0;
|
||||
|
||||
#if DT_NODE_HAS_PROP(EXTI_NODE, clocks)
|
||||
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
|
||||
|
||||
if (!device_is_ready(clk)) {
|
||||
LOG_ERR("Clock control device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
const struct stm32_pclken pclken = {
|
||||
.bus = DT_CLOCKS_CELL(EXTI_NODE, bus),
|
||||
.enr = DT_CLOCKS_CELL(EXTI_NODE, bits)
|
||||
};
|
||||
|
||||
ret = clock_control_on(clk, (clock_control_subsys_t) &pclken);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the EXTI interrupt controller driver
|
||||
*/
|
||||
static int stm32_exti_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return stm32_exti_enable_clocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable EXTI interrupts.
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_enable_it(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_ENABLE_IT, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable EXTI interrupts.
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_disable_it(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_DISABLE_IT, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables rising trigger for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_enable_rising_trig(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_ENABLE_RISING_TRIG, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables rising trigger for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_disable_rising_trig(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_DISABLE_RISING_TRIG, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables falling trigger for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_enable_falling_trig(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_ENABLE_FALLING_TRIG, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables falling trigger for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_disable_falling_trig(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_DISABLE_FALLING_TRIG, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects EXTI trigger mode
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
* @param mode EXTI mode
|
||||
*/
|
||||
static void stm32_exti_select_line_trigger(uint32_t line_num, uint32_t line,
|
||||
uint32_t trg)
|
||||
{
|
||||
switch (trg) {
|
||||
case STM32_EXTI_TRIG_NONE:
|
||||
stm32_exti_disable_rising_trig(line_num, line);
|
||||
stm32_exti_disable_falling_trig(line_num, line);
|
||||
break;
|
||||
case STM32_EXTI_TRIG_RISING:
|
||||
stm32_exti_enable_rising_trig(line_num, line);
|
||||
stm32_exti_disable_falling_trig(line_num, line);
|
||||
break;
|
||||
case STM32_EXTI_TRIG_FALLING:
|
||||
stm32_exti_enable_falling_trig(line_num, line);
|
||||
stm32_exti_disable_rising_trig(line_num, line);
|
||||
break;
|
||||
case STM32_EXTI_TRIG_BOTH:
|
||||
stm32_exti_enable_rising_trig(line_num, line);
|
||||
stm32_exti_enable_falling_trig(line_num, line);
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported EXTI trigger 0x%X", trg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable EXTI event.
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_enable_event(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_ENABLE_EVENT, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable EXTI interrupts.
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
*/
|
||||
static void stm32_exti_disable_event(uint32_t line_num, uint32_t line)
|
||||
{
|
||||
EXTI_FN_HANDLER(EXTI_DISABLE_EVENT, line_num, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables external interrupt/event for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param line LL EXTI line
|
||||
* @param mode EXTI mode
|
||||
*/
|
||||
static void stm32_exti_set_mode(uint32_t line_num, uint32_t line,
|
||||
stm32_exti_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case STM32_EXTI_MODE_NONE:
|
||||
stm32_exti_disable_event(line_num, line);
|
||||
stm32_exti_disable_it(line_num, line);
|
||||
break;
|
||||
case STM32_EXTI_MODE_IT:
|
||||
stm32_exti_disable_event(line_num, line);
|
||||
stm32_exti_enable_it(line_num, line);
|
||||
break;
|
||||
case STM32_EXTI_MODE_EVENT:
|
||||
stm32_exti_disable_it(line_num, line);
|
||||
stm32_exti_enable_event(line_num, line);
|
||||
break;
|
||||
case STM32_EXTI_MODE_BOTH:
|
||||
stm32_exti_enable_it(line_num, line);
|
||||
stm32_exti_enable_event(line_num, line);
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported EXTI mode %u", mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int stm32_exti_enable(uint32_t line_num, stm32_exti_trigger_type trigger,
|
||||
stm32_exti_mode mode)
|
||||
{
|
||||
const uint32_t line = exti_linenum_to_ll_exti_line(line_num);
|
||||
|
||||
if (!IS_VALID_EXTI_LINE_NUM(line_num)) {
|
||||
LOG_ERR("Invalid line number %u", line_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
|
||||
stm32_exti_select_line_trigger(line_num, line, trigger);
|
||||
stm32_exti_set_mode(line_num, line, mode);
|
||||
|
||||
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stm32_exti_disable(uint32_t line_num)
|
||||
{
|
||||
const uint32_t line = exti_linenum_to_ll_exti_line(line_num);
|
||||
|
||||
if (!IS_VALID_EXTI_LINE_NUM(line_num)) {
|
||||
LOG_ERR("Invalid line number %u", line_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
|
||||
|
||||
stm32_exti_set_mode(line_num, line, STM32_EXTI_MODE_NONE);
|
||||
stm32_exti_select_line_trigger(line_num, line, STM32_EXTI_TRIG_NONE);
|
||||
|
||||
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEVICE_DT_DEFINE(EXTI_NODE, &stm32_exti_init,
|
||||
NULL, NULL, NULL,
|
||||
PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY,
|
||||
NULL);
|
||||
204
drivers/interrupt_controller/intc_exti_stm32_priv.h
Normal file
204
drivers/interrupt_controller/intc_exti_stm32_priv.h
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_PRIV_H_
|
||||
#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_PRIV_H_
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
#include <zephyr/drivers/interrupt_controller/intc_exti_stm32.h>
|
||||
|
||||
#include <stm32_ll_bus.h>
|
||||
#include <stm32_ll_exti.h>
|
||||
#include <stm32_ll_system.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* NOTE: This implementation currently does not support configurations where a
|
||||
* single CPU has access to multiple EXTI instances. Supporting multiple EXTI
|
||||
* instances per CPU (such as possible on STM32MP2 series with both M33 and M0+
|
||||
* cores) will require changes to this macro and potentially other parts of the
|
||||
* driver.
|
||||
*/
|
||||
#define EXTI_NODE DT_INST(0, st_stm32_exti)
|
||||
|
||||
/**
|
||||
* STM32MP1 has up to 96 EXTI lines (RM0475, Table 112. STM32MP13xx EXTI Events),
|
||||
* but some ranges contain only direct lines, so the LL functions that are
|
||||
* only valid for configurable lines are not provided for these ranges.
|
||||
* However, we are relying on all these functions being present as part of our
|
||||
* utility macros. Define dummy stubs for these functions to allow the main driver
|
||||
* to work properly on this special series.
|
||||
*
|
||||
* NOTE: These stubs are only for compatibility and will assert if called for
|
||||
* unsupported lines. Always ensure the correct line range is used.
|
||||
*/
|
||||
|
||||
#define STM32_EXTI_TOTAL_LINES_NUM DT_PROP(EXTI_NODE, num_lines)
|
||||
|
||||
/**
|
||||
* @brief Define CPU number suffix for STM32 series.
|
||||
*/
|
||||
#if (defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)) || \
|
||||
(defined(CONFIG_SOC_SERIES_STM32MP2X) && defined(CONFIG_CPU_CORTEX_M33))
|
||||
#define CPU_NR _C2
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32MP2X) && defined(CONFIG_CPU_CORTEX_M0)
|
||||
#define CPU_NR _C3
|
||||
#else
|
||||
/* NOTE: usually one CPU (e.g. C1) only is omitted and leaved empty */
|
||||
#define CPU_NR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Define EXTI_LL_INST for STM32MP2X series, since it may have multiple instances
|
||||
* For all other than STM32MP2X series the EXTI instance is defined within LL driver
|
||||
* itself s.t. EXTI_LL_INST will be empty.
|
||||
*/
|
||||
#if defined(CONFIG_SOC_SERIES_STM32MP2X)
|
||||
#define EXTI_LL_INST ((EXTI_TypeDef *)DT_REG_ADDR(EXTI_NODE)),
|
||||
#else /* CONFIG_SOC_SERIES_STM32MP2X */
|
||||
#define EXTI_LL_INST
|
||||
#endif /* CONFIG_SOC_SERIES_STM32MP2X */
|
||||
|
||||
|
||||
#define EXTI_LINE_NOT_SUPP_ASSERT(line) \
|
||||
{ \
|
||||
LOG_ERR("Unsupported line number %u", line); \
|
||||
__ASSERT_NO_MSG(0); \
|
||||
}
|
||||
|
||||
#define EXTI_LINE_NOP(line) \
|
||||
{ \
|
||||
ARG_UNUSED(line); \
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOC_SERIES_STM32MP1X) || defined(CONFIG_SOC_SERIES_STM32MP13X)
|
||||
|
||||
/*
|
||||
* NOTE: There is currently no other option than to define LL_ prefixed functions
|
||||
* that are missing in the original drivers as stubs for unsupported EXTI lines.
|
||||
* This is required for compatibility across all STM32 series, until a more
|
||||
* flexible solution is available.
|
||||
*/
|
||||
#define LL_EXTI_IsActiveRisingFlag_32_63(line) 0
|
||||
#define LL_EXTI_IsActiveFallingFlag_32_63(line) 0
|
||||
|
||||
#define LL_EXTI_ClearRisingFlag_32_63(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_ClearFallingFlag_32_63(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_GenerateSWI_32_63(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
|
||||
#define LL_EXTI_EnableRisingTrig_32_63(line) EXTI_LINE_NOP(line)
|
||||
#define LL_EXTI_EnableFallingTrig_32_63(line) EXTI_LINE_NOP(line)
|
||||
#define LL_EXTI_DisableRisingTrig_32_63(line) EXTI_LINE_NOP(line)
|
||||
#define LL_EXTI_DisableFallingTrig_32_63(line) EXTI_LINE_NOP(line)
|
||||
#define LL_EXTI_EnableEvent_32_63(line) EXTI_LINE_NOP(line)
|
||||
#define LL_EXTI_DisableEvent_32_63(line) EXTI_LINE_NOP(line)
|
||||
|
||||
#if defined(CONFIG_SOC_SERIES_STM32MP13X)
|
||||
|
||||
#define LL_EXTI_IsActiveRisingFlag_64_95(line) 0
|
||||
#define LL_EXTI_IsActiveFallingFlag_64_95(line) 0
|
||||
|
||||
#define LL_EXTI_ClearRisingFlag_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_ClearFallingFlag_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_GenerateSWI_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_EnableRisingTrig_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_DisableRisingTrig_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_EnableFallingTrig_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_DisableFallingTrig_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_EnableEvent_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
#define LL_EXTI_DisableEvent_64_95(line) EXTI_LINE_NOT_SUPP_ASSERT(line)
|
||||
|
||||
#endif /* !CONFIG_SOC_SERIES_STM32MP13X */
|
||||
|
||||
#endif /* CONFIG_SOC_SERIES_STM32MP1X || CONFIG_SOC_SERIES_STM32MP13X */
|
||||
|
||||
|
||||
/* Define general macros line-range independent */
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) || defined(CONFIG_SOC_SERIES_STM32MP2X)
|
||||
|
||||
#if defined(CONFIG_SOC_SERIES_STM32MP2X)
|
||||
|
||||
#define EXTI_IS_ACTIVE_RISING_FLAG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_IsActiveRisingFlag_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_IS_ACTIVE_FALLING_FLAG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_IsActiveFallingFlag_##line_range)(EXTI_LL_INST line)
|
||||
|
||||
#define EXTI_CLEAR_RISING_FLAG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_ClearRisingFlag_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_CLEAR_FALLING_FLAG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_ClearFallingFlag_##line_range)(EXTI_LL_INST line)
|
||||
|
||||
#else /* !CONFIG_SOC_SERIES_STM32MP2X */
|
||||
|
||||
#define EXTI_IS_ACTIVE_RISING_FLAG(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_IsActiveRisingFlag_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_IS_ACTIVE_FALLING_FLAG(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_IsActiveFallingFlag_##line_range)(EXTI_LL_INST line)
|
||||
|
||||
#define EXTI_CLEAR_RISING_FLAG(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_ClearRisingFlag_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_CLEAR_FALLING_FLAG(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_ClearFallingFlag_##line_range)(EXTI_LL_INST line)
|
||||
|
||||
#endif /* CONFIG_SOC_SERIES_STM32MP2X */
|
||||
|
||||
#define EXTI_CLEAR_FLAG(line_range, line) \
|
||||
{ \
|
||||
EXTI_CLEAR_RISING_FLAG(line_range, (line)); \
|
||||
EXTI_CLEAR_FALLING_FLAG(line_range, (line)); \
|
||||
}
|
||||
#define EXTI_IS_ACTIVE_FLAG(line_range, line) \
|
||||
(EXTI_IS_ACTIVE_RISING_FLAG(line_range, (line)) || \
|
||||
EXTI_IS_ACTIVE_FALLING_FLAG(line_range, (line)))
|
||||
|
||||
#else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) */
|
||||
|
||||
#define EXTI_CLEAR_FLAG(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_ClearFlag_##line_range)(line)
|
||||
#define EXTI_IS_ACTIVE_FLAG(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_IsActiveFlag_##line_range)(line)
|
||||
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) */
|
||||
|
||||
|
||||
/* Define general macros line-range independent */
|
||||
#define EXTI_ENABLE_IT(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_EnableIT_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_DISABLE_IT(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_DisableIT_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_ENABLE_EVENT(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_EnableEvent_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_DISABLE_EVENT(line_range, line) \
|
||||
CONCAT(LL, CPU_NR, _EXTI_DisableEvent_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_ENABLE_RISING_TRIG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_EnableRisingTrig_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_ENABLE_FALLING_TRIG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_EnableFallingTrig_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_DISABLE_FALLING_TRIG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_DisableFallingTrig_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_DISABLE_RISING_TRIG(line_range, line) \
|
||||
CONCAT(LL, _EXTI_DisableRisingTrig_##line_range)(EXTI_LL_INST line)
|
||||
#define EXTI_GENERATE_SWI(line_range, line) \
|
||||
CONCAT(LL, _EXTI_GenerateSWI_##line_range)(EXTI_LL_INST line)
|
||||
|
||||
/**
|
||||
* @returns LL_EXTI_LINE_n define corresponding to EXTI line number
|
||||
*/
|
||||
static inline uint32_t exti_linenum_to_ll_exti_line(uint32_t line_num)
|
||||
{
|
||||
return BIT(line_num % 32);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_PRIV_H_ */
|
||||
101
include/zephyr/drivers/interrupt_controller/intc_exti_stm32.h
Normal file
101
include/zephyr/drivers/interrupt_controller/intc_exti_stm32.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief STM32 EXTI interrupt controller API
|
||||
*
|
||||
* This API is used to interact with STM32 EXTI interrupt controller
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_H_
|
||||
#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_H_
|
||||
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief EXTI interrupt trigger type
|
||||
*/
|
||||
typedef enum {
|
||||
/* No trigger */
|
||||
STM32_EXTI_TRIG_NONE = 0x0,
|
||||
/* Trigger on rising edge */
|
||||
STM32_EXTI_TRIG_RISING = 0x1,
|
||||
/* Trigger on falling edge */
|
||||
STM32_EXTI_TRIG_FALLING = 0x2,
|
||||
/* Trigger on both rising and falling edge */
|
||||
STM32_EXTI_TRIG_BOTH = 0x3,
|
||||
} stm32_exti_trigger_type;
|
||||
|
||||
/**
|
||||
* @brief EXTI line mode
|
||||
*/
|
||||
typedef enum {
|
||||
/* Generate interrupts only */
|
||||
STM32_EXTI_MODE_IT = 0x0,
|
||||
/* Generate events only */
|
||||
STM32_EXTI_MODE_EVENT = 0x1,
|
||||
/* Generate interrupts and events */
|
||||
STM32_EXTI_MODE_BOTH = 0x2,
|
||||
/* Disable interrupts and events */
|
||||
STM32_EXTI_MODE_NONE = 0x3,
|
||||
} stm32_exti_mode;
|
||||
|
||||
/**
|
||||
* @brief Enable EXTI line.
|
||||
* @note The caller driver is responsible for registering an ISR and
|
||||
* enabling the corresponding interrupt if MODE_IT is selected.
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @param trigger EXTI trigger type (see @ref stm32_exti_trigger_type)
|
||||
* @param mode EXTI mode (see @ref stm32_exti_mode)
|
||||
* @returns 0 on success, -EINVAL if @p line_num is invalid
|
||||
*/
|
||||
int stm32_exti_enable(uint32_t line_num, stm32_exti_trigger_type trigger,
|
||||
stm32_exti_mode mode);
|
||||
|
||||
/**
|
||||
* @brief Disable EXTI line.
|
||||
* After this function has been called, EXTI line @p line_num will
|
||||
* not generate further interrupts or events.
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @returns 0 on success, -EINVAL if @p line is invalid
|
||||
*/
|
||||
int stm32_exti_disable(uint32_t line_num);
|
||||
|
||||
/**
|
||||
* @brief Checks interrupt pending bit for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @returns true if @p line is pending, false otherwise
|
||||
*/
|
||||
bool stm32_exti_is_pending(uint32_t line_num);
|
||||
|
||||
/**
|
||||
* @brief Clears interrupt pending bit for specified EXTI line
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @returns 0 on success, -EINVAL if @p line is invalid
|
||||
*/
|
||||
int stm32_exti_clear_pending(uint32_t line_num);
|
||||
|
||||
/**
|
||||
* @brief Generates SW interrupt for specified EXTI line number
|
||||
*
|
||||
* @param line_num EXTI line number
|
||||
* @returns 0 on success, -EINVAL if @p line is invalid
|
||||
*/
|
||||
int stm32_exti_sw_interrupt(uint32_t line_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_H_ */
|
||||
Reference in New Issue
Block a user