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
  *

Reply via email to