This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit b245cc17624e53f9a4f33d29d40e502e33254894 Author: Liam Howatt <[email protected]> AuthorDate: Thu Aug 13 09:06:28 2026 -0400 arch/arm/stm32h5: Add EXTI GPIO support. Copy the stm32u5 implementation, add necessary port configuration for the MUXs. Signed-off-by: Liam Howatt <[email protected]> Co-authored-by: Nathan Best <[email protected]> Co-authored-by: Randy Rossi <[email protected]> --- arch/arm/src/stm32h5/CMakeLists.txt | 3 +- arch/arm/src/stm32h5/Make.defs | 2 +- arch/arm/src/stm32h5/hardware/stm32_exti.h | 89 ++++++++++++ arch/arm/src/stm32h5/stm32_exti.h | 155 +++++++++++++++++++++ arch/arm/src/stm32h5/stm32_exti_gpio.c | 214 +++++++++++++++++++++++++++++ arch/arm/src/stm32h5/stm32_gpio.h | 23 ++++ 6 files changed, 484 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/stm32h5/CMakeLists.txt b/arch/arm/src/stm32h5/CMakeLists.txt index 249a64c3136..8ae49dc10ca 100644 --- a/arch/arm/src/stm32h5/CMakeLists.txt +++ b/arch/arm/src/stm32h5/CMakeLists.txt @@ -41,7 +41,8 @@ list( stm32_pwr.c stm32_timerisr.c stm32_lse.c - stm32_lsi.c) + stm32_lsi.c + stm32_exti_gpio.c) if(CONFIG_STM32_USART) list(APPEND SRCS stm32_serial.c) diff --git a/arch/arm/src/stm32h5/Make.defs b/arch/arm/src/stm32h5/Make.defs index fd569978cb4..67de7e860aa 100644 --- a/arch/arm/src/stm32h5/Make.defs +++ b/arch/arm/src/stm32h5/Make.defs @@ -38,7 +38,7 @@ endif CHIP_CSRCS += stm32_gpio.c stm32_irq.c stm32_lowputc.c stm32_rcc.c CHIP_CSRCS += stm32_start.c stm32_pwr.c stm32_timerisr.c -CHIP_CSRCS += stm32_lse.c stm32_lsi.c +CHIP_CSRCS += stm32_lse.c stm32_lsi.c stm32_exti_gpio.c ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y) CHIP_CSRCS += stm32_idle.c diff --git a/arch/arm/src/stm32h5/hardware/stm32_exti.h b/arch/arm/src/stm32h5/hardware/stm32_exti.h new file mode 100644 index 00000000000..b4df54763aa --- /dev/null +++ b/arch/arm/src/stm32h5/hardware/stm32_exti.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/hardware/stm32_exti.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32_EXTI_H +#define __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32_EXTI_RTSR1_OFFSET 0x0000 /* Rising Trigger Selection 1 */ +#define STM32_EXTI_FTSR1_OFFSET 0x0004 /* Falling Trigger Selection 1 */ +#define STM32_EXTI_SWIER1_OFFSET 0x0008 /* Software Interrupt Event 1 */ +#define STM32_EXTI_RPR1_OFFSET 0x000c /* Rising Edge Pending 1 */ +#define STM32_EXTI_FPR1_OFFSET 0x0010 /* Falling Edge Pending 1 */ +#define STM32_EXTI_SECCFGR1_OFFSET 0x0014 /* Security Configuration 1 */ +#define STM32_EXTI_PRIVCFGR1_OFFSET 0x0018 /* Privilege Configuration 1 */ +#define STM32_EXTI_RTSR2_OFFSET 0x0020 /* Rising Trigger Selection 2 */ +#define STM32_EXTI_FTSR2_OFFSET 0x0024 /* Falling Trigger Selection 2 */ +#define STM32_EXTI_SWIER2_OFFSET 0x0028 /* Software Interrupt Event 2 */ +#define STM32_EXTI_RPR2_OFFSET 0x002c /* Rising Edge Pending 2 */ +#define STM32_EXTI_FPR2_OFFSET 0x0030 /* Falling Edge Pending 2 */ +#define STM32_EXTI_SECCFGR2_OFFSET 0x0034 /* Security Configuration 2 */ +#define STM32_EXTI_PRIVCFGR2_OFFSET 0x0038 /* Privilege Configuration 2 */ +#define STM32_EXTI_EXTICR1_OFFSET 0x0060 /* External Interrupt Selection 1 */ +#define STM32_EXTI_EXTICR2_OFFSET 0x0064 /* External Interrupt Selection 2 */ +#define STM32_EXTI_EXTICR3_OFFSET 0x0068 /* External Interrupt Selection 3 */ +#define STM32_EXTI_EXTICR4_OFFSET 0x006C /* External Interrupt Selection 4 */ +#define STM32_EXTI_LOCKR_OFFSET 0x0070 /* Lock */ +#define STM32_EXTI_IMR1_OFFSET 0x0080 /* CPU Wakeup with Interrupt Mask 1 */ +#define STM32_EXTI_EMR1_OFFSET 0x0084 /* CPU Wakeup with Event Mask 1 */ +#define STM32_EXTI_IMR2_OFFSET 0x0090 /* CPU Wakeup with Interrupt Mask 2 */ +#define STM32_EXTI_EMR2_OFFSET 0x0094 /* CPU Wakeup with Event Mask 2 */ + +/* Register Addresses *******************************************************/ + +#define STM32_EXTI_RTSR1 (STM32_EXTI_BASE + STM32_EXTI_RTSR1_OFFSET) +#define STM32_EXTI_FTSR1 (STM32_EXTI_BASE + STM32_EXTI_FTSR1_OFFSET) +#define STM32_EXTI_SWIER1 (STM32_EXTI_BASE + STM32_EXTI_SWIER1_OFFSET) +#define STM32_EXTI_RPR1 (STM32_EXTI_BASE + STM32_EXTI_RPR1_OFFSET) +#define STM32_EXTI_FPR1 (STM32_EXTI_BASE + STM32_EXTI_FPR1_OFFSET) +#define STM32_EXTI_SECCFGR1 (STM32_EXTI_BASE + STM32_EXTI_SECCFGR1_OFFSET) +#define STM32_EXTI_PRIVCFGR1 (STM32_EXTI_BASE + STM32_EXTI_PRIVCFGR1_OFFSET) +#define STM32_EXTI_RTSR2 (STM32_EXTI_BASE + STM32_EXTI_RTSR2_OFFSET) +#define STM32_EXTI_FTSR2 (STM32_EXTI_BASE + STM32_EXTI_FTSR2_OFFSET) +#define STM32_EXTI_SWIER2 (STM32_EXTI_BASE + STM32_EXTI_SWIER2_OFFSET) +#define STM32_EXTI_RPR2 (STM32_EXTI_BASE + STM32_EXTI_RPR2_OFFSET) +#define STM32_EXTI_FPR2 (STM32_EXTI_BASE + STM32_EXTI_FPR2_OFFSET) +#define STM32_EXTI_SECCFGR2 (STM32_EXTI_BASE + STM32_EXTI_SECCFGR2_OFFSET) +#define STM32_EXTI_PRIVCFGR2 (STM32_EXTI_BASE + STM32_EXTI_PRIVCFGR2_OFFSET) +#define STM32_EXTI_EXTICR1 (STM32_EXTI_BASE + STM32_EXTI_EXTICR1_OFFSET) +#define STM32_EXTI_EXTICR2 (STM32_EXTI_BASE + STM32_EXTI_EXTICR2_OFFSET) +#define STM32_EXTI_EXTICR3 (STM32_EXTI_BASE + STM32_EXTI_EXTICR3_OFFSET) +#define STM32_EXTI_EXTICR4 (STM32_EXTI_BASE + STM32_EXTI_EXTICR4_OFFSET) +#define STM32_EXTI_LOCKR (STM32_EXTI_BASE + STM32_EXTI_LOCKR_OFFSET) +#define STM32_EXTI_IMR1 (STM32_EXTI_BASE + STM32_EXTI_IMR1_OFFSET) +#define STM32_EXTI_EMR1 (STM32_EXTI_BASE + STM32_EXTI_EMR1_OFFSET) +#define STM32_EXTI_IMR2 (STM32_EXTI_BASE + STM32_EXTI_IMR2_OFFSET) +#define STM32_EXTI_EMR2 (STM32_EXTI_BASE + STM32_EXTI_EMR2_OFFSET) + +#endif /* __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32_EXTI_H */ diff --git a/arch/arm/src/stm32h5/stm32_exti.h b/arch/arm/src/stm32h5/stm32_exti.h new file mode 100644 index 00000000000..7e20aa28d6a --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_exti.h @@ -0,0 +1,155 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_exti.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32H5_STM32_EXTI_H +#define __ARCH_ARM_SRC_STM32H5_STM32_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/irq.h> + +#include "chip.h" +#include "hardware/stm32_exti.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * pinset - GPIO pin configuration + * risingedge - Enables interrupt on rising edges + * fallingedge - Enables interrupt on falling edges + * event - Generate event when set + * func - When non-NULL, generate interrupt + * arg - Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) is returned on success, otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg); + +/**************************************************************************** + * Name: stm32_exti_alarm + * + * Description: + * Sets/clears EXTI alarm interrupt. + * + * Input Parameters: + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int stm32_exti_alarm(bool risingedge, bool fallingedge, bool event, + xcpt_t func, void *arg); +#endif + +/**************************************************************************** + * Name: stm32_exti_wakeup + * + * Description: + * Sets/clears EXTI wakeup interrupt. + * + * Input Parameters: + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +int stm32_exti_wakeup(bool risingedge, bool fallingedge, bool event, + xcpt_t func, void *arg); +#endif + +/**************************************************************************** + * Name: stm32_exti_comp + * + * Description: + * Sets/clears comparator based events and interrupt triggers. + * + * Input Parameters: + * - cmp: comparator + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) returned on success; a negated errno value is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32_COMP +int stm32_exti_comp(int cmp, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32H5_STM32_EXTI_H */ diff --git a/arch/arm/src/stm32h5/stm32_exti_gpio.c b/arch/arm/src/stm32h5/stm32_exti_gpio.c new file mode 100644 index 00000000000..81e44b35d3e --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_exti_gpio.c @@ -0,0 +1,214 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_exti_gpio.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/irq.h> +#include <nuttx/arch.h> + +#include <stdint.h> +#include <stdbool.h> +#include <assert.h> +#include <errno.h> +#include <nuttx/debug.h> + +#include <arch/irq.h> + +#include "arm_internal.h" +#include "chip.h" +#include "stm32_gpio.h" +#include "stm32_exti.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gpio_callback_s +{ + xcpt_t callback; /* Callback entry point */ + void *arg; /* The argument that accompanies the callback */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Interrupt handlers attached to each EXTI */ + +static struct gpio_callback_s g_gpio_handlers[16]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Interrupt Service Routine - Dispatcher + ****************************************************************************/ + +static int stm32_exti0_15_isr(int irq, void *context, void *arg) +{ + int ret = OK; + int exti; + + exti = irq - STM32_IRQ_EXTI0; + DEBUGASSERT((exti >= 0) && (exti <= 15)); + + /* Clear the pending interrupt for both rising and falling edges. */ + + putreg32(0x0001 << exti, STM32_EXTI_RPR1); + putreg32(0x0001 << exti, STM32_EXTI_FPR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[exti].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[exti].callback; + void *cbarg = g_gpio_handlers[exti].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * pinset - GPIO pin configuration + * risingedge - Enables interrupt on rising edges + * fallingedge - Enables interrupt on falling edges + * event - Generate event when set + * func - When non-NULL, generate interrupt + * arg - Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) is returned on success, otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg) +{ + uint32_t pin = pinset & GPIO_PIN_MASK; + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t exti = 1 << pin; + int irq = STM32_IRQ_EXTI0 + pin; + int ret; + + g_gpio_handlers[pin].callback = func; + g_gpio_handlers[pin].arg = arg; + + /* Set the mux for this EXTI to the correct bank */ + + /* Which EXTICR# does this port land on? (0-3) */ + + uint32_t exticrn = pin / 4; + + /* Which EXTI## field does this port land on? (0-3) */ + + uint32_t shift = (pin % 4) * 8; + + /* Shift our clear and set bits into place */ + + uint32_t extin_clrbits = 0b11111111 << shift; + uint32_t extin_setbits; + + if (func) + { + extin_setbits = port << shift; + } + else + { + extin_setbits = 0; + } + + /* Set or clear the MUX port according to the given port */ + + uint32_t reg = STM32_EXTI_BASE + STM32_EXTI_EXTICR1_OFFSET + + (0x04 * exticrn); + modifyreg32(reg, extin_clrbits, extin_setbits); + + /* Install external interrupt handlers */ + + if (func) + { + irq_attach(irq, stm32_exti0_15_isr, NULL); + up_enable_irq(irq); + } + else + { + /* remove any leftover callback */ + + ret = irq_detach(irq); + if (ret < 0) + { + return ret; + } + + /* disable the interrupt */ + + up_disable_irq(irq); + } + + /* Configure GPIO, enable EXTI line enabled if event or interrupt is + * enabled. + */ + + if (event || func) + { + pinset |= GPIO_EXTI; + } + + stm32_configgpio(pinset); + + /* Configure rising/falling edges */ + + modifyreg32(STM32_EXTI_RTSR1, + risingedge ? 0 : exti, + risingedge ? exti : 0); + modifyreg32(STM32_EXTI_FTSR1, + fallingedge ? 0 : exti, + fallingedge ? exti : 0); + + /* Enable Events and Interrupts */ + + modifyreg32(STM32_EXTI_EMR1, + event ? 0 : exti, + event ? exti : 0); + modifyreg32(STM32_EXTI_IMR1, + func ? 0 : exti, + func ? exti : 0); + + return OK; +} diff --git a/arch/arm/src/stm32h5/stm32_gpio.h b/arch/arm/src/stm32h5/stm32_gpio.h index ec2caefa305..4be301eec4d 100644 --- a/arch/arm/src/stm32h5/stm32_gpio.h +++ b/arch/arm/src/stm32h5/stm32_gpio.h @@ -307,6 +307,29 @@ void stm32_gpiowrite(uint32_t pinset, bool value); bool stm32_gpioread(uint32_t pinset); +/**************************************************************************** + * Name: stm32_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * pinset - GPIO pin configuration + * risingedge - Enables interrupt on rising edges + * fallingedge - Enables interrupt on falling edges + * event - Generate event when set + * func - When non-NULL, generate interrupt + * arg - Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) is returned on success, otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg); + /**************************************************************************** * Function: stm32_gpioinit *
