This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch releases/13.1
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit fc25a7f4ed7ae4b71463ef6b919ae210c273dcb2
Author: raiden00pl <[email protected]>
AuthorDate: Thu Sep 24 15:32:29 2026 +0200

    arm/nrf52,nrf53,nrf91: fix GPIOTE driver bugs
    
    - set_port_event checked the wrong port when deciding whether the
      PORT interrupt can be disabled
    - set_event could pick a free channel instead of the one already
      assigned to the pin
    - LATCH registers were cleared by writing zeros
    - header declared nrfxx_gpio_set_task for a function defined as
      nrfxx_gpiote_set_task
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 arch/arm/src/nrf52/nrf52_gpiote.c | 46 ++++++++++++++++++++++++++-------------
 arch/arm/src/nrf52/nrf52_gpiote.h |  4 ++--
 arch/arm/src/nrf53/nrf53_gpiote.c | 44 +++++++++++++++++++++++++------------
 arch/arm/src/nrf53/nrf53_gpiote.h |  4 ++--
 arch/arm/src/nrf91/nrf91_gpiote.c | 46 ++++++++++++++++++++++++++-------------
 arch/arm/src/nrf91/nrf91_gpiote.h |  4 ++--
 6 files changed, 98 insertions(+), 50 deletions(-)

diff --git a/arch/arm/src/nrf52/nrf52_gpiote.c 
b/arch/arm/src/nrf52/nrf52_gpiote.c
index a552bd606b5..33c2e30fc68 100644
--- a/arch/arm/src/nrf52/nrf52_gpiote.c
+++ b/arch/arm/src/nrf52/nrf52_gpiote.c
@@ -315,7 +315,7 @@ void nrf52_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg)
 
       for (i = 0; i < NRF52_GPIO_NPORTS; i++)
         {
-          if (g_gpiote_port_callback[port].callback)
+          if (g_gpiote_port_callback[i].callback)
             {
               break;
             }
@@ -465,27 +465,43 @@ int nrf52_gpiote_set_event(uint32_t pinset,
 
   flags = enter_critical_section();
 
-  /* Get free channel or channel already used by pinset */
+  /* Get channel already used by pinset */
 
   for (i = 0; i < GPIOTE_CHANNELS; i++)
     {
-      if (g_gpiote_ch_callbacks[i].callback == NULL ||
+      if (g_gpiote_ch_callbacks[i].callback != NULL &&
           g_gpiote_ch_callbacks[i].pinset == pinset)
         {
-          g_gpiote_ch_callbacks[i].pinset = pinset;
+          break;
+        }
+    }
+
+  /* Otherwise get a free channel */
+
+  if (i == GPIOTE_CHANNELS && func != NULL)
+    {
+      for (i = 0; i < GPIOTE_CHANNELS; i++)
+        {
+          if (g_gpiote_ch_callbacks[i].callback == NULL)
+            {
+              break;
+            }
+        }
+    }
 
-          /* Configure channel */
+  if (i < GPIOTE_CHANNELS)
+    {
+      g_gpiote_ch_callbacks[i].pinset = pinset;
 
-          nrf52_gpiote_set_ch_event(pinset, i,
-                                    risingedge, fallingedge,
-                                    func, arg);
+      /* Configure channel */
 
-          /* Return the channel index */
+      nrf52_gpiote_set_ch_event(pinset, i,
+                                risingedge, fallingedge,
+                                func, arg);
 
-          ret = i;
+      /* Return the channel index */
 
-          break;
-        }
+      ret = i;
     }
 
   leave_critical_section(flags);
@@ -494,7 +510,7 @@ int nrf52_gpiote_set_event(uint32_t pinset,
 }
 
 /****************************************************************************
- * Name: nrf52_gpio_set_task
+ * Name: nrf52_gpiote_set_task
  *
  * Description:
  *   Configure GPIO in TASK mode (to be controlled via tasks).
@@ -579,10 +595,10 @@ int nrf52_gpiote_init(void)
 {
   /* Clear LATCH register(s) */
 
-  putreg32(0, NRF52_GPIO_P0_BASE + NRF52_GPIO_LATCH_OFFSET);
+  putreg32(0xffffffff, NRF52_GPIO_P0_BASE + NRF52_GPIO_LATCH_OFFSET);
 
 #ifdef CONFIG_NRF52_HAVE_PORT1
-  putreg32(0, NRF52_GPIO_P1_BASE + NRF52_GPIO_LATCH_OFFSET);
+  putreg32(0xffffffff, NRF52_GPIO_P1_BASE + NRF52_GPIO_LATCH_OFFSET);
 #endif
 
   /* Reset GPIOTE data */
diff --git a/arch/arm/src/nrf52/nrf52_gpiote.h 
b/arch/arm/src/nrf52/nrf52_gpiote.h
index b36bd0ec458..6ea8f1ab1fb 100644
--- a/arch/arm/src/nrf52/nrf52_gpiote.h
+++ b/arch/arm/src/nrf52/nrf52_gpiote.h
@@ -144,7 +144,7 @@ void nrf52_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg);
 #endif
 
 /****************************************************************************
- * Name: nrf52_gpio_set_task
+ * Name: nrf52_gpiote_set_task
  *
  * Description:
  *   Configure GPIO in TASK mode (to be controlled via tasks).
@@ -162,7 +162,7 @@ void nrf52_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg);
  *
  ****************************************************************************/
 
-void nrf52_gpio_set_task(uint32_t pinset, int channel,
+void nrf52_gpiote_set_task(uint32_t pinset, int channel,
                         bool output_high, enum nrf52_gpiote_outcfg_e outcfg);
 
 /****************************************************************************
diff --git a/arch/arm/src/nrf53/nrf53_gpiote.c 
b/arch/arm/src/nrf53/nrf53_gpiote.c
index 4099afe9221..1a9b8de0dce 100644
--- a/arch/arm/src/nrf53/nrf53_gpiote.c
+++ b/arch/arm/src/nrf53/nrf53_gpiote.c
@@ -352,7 +352,7 @@ void nrf53_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg)
 
       for (i = 0; i < NRF53_GPIO_NPORTS; i++)
         {
-          if (g_gpiote_port_callback[port].callback)
+          if (g_gpiote_port_callback[i].callback)
             {
               break;
             }
@@ -506,25 +506,41 @@ int nrf53_gpiote_set_event(uint32_t pinset,
 
   flags = enter_critical_section();
 
-  /* Get free channel or channel already used by pinset */
+  /* Get channel already used by pinset */
 
   for (i = 0; i < GPIOTE_CHANNELS; i++)
     {
-      if (g_gpiote_ch_callbacks[i].callback == NULL ||
+      if (g_gpiote_ch_callbacks[i].callback != NULL &&
           g_gpiote_ch_callbacks[i].pinset == pinset)
         {
-          g_gpiote_ch_callbacks[i].pinset = pinset;
+          break;
+        }
+    }
+
+  /* Otherwise get a free channel */
+
+  if (i == GPIOTE_CHANNELS && func != NULL)
+    {
+      for (i = 0; i < GPIOTE_CHANNELS; i++)
+        {
+          if (g_gpiote_ch_callbacks[i].callback == NULL)
+            {
+              break;
+            }
+        }
+    }
 
-          nrf53_gpiote_set_ch_event(pinset, i,
-                                    risingedge, fallingedge,
-                                    func, arg);
+  if (i < GPIOTE_CHANNELS)
+    {
+      g_gpiote_ch_callbacks[i].pinset = pinset;
 
-          /* Return the channel index */
+      nrf53_gpiote_set_ch_event(pinset, i,
+                                risingedge, fallingedge,
+                                func, arg);
 
-          ret = i;
+      /* Return the channel index */
 
-          break;
-        }
+      ret = i;
     }
 
   leave_critical_section(flags);
@@ -533,7 +549,7 @@ int nrf53_gpiote_set_event(uint32_t pinset,
 }
 
 /****************************************************************************
- * Name: nrf53_gpio_set_task
+ * Name: nrf53_gpiote_set_task
  *
  * Description:
  *   Configure GPIO in TASK mode (to be controlled via tasks).
@@ -626,8 +642,8 @@ int nrf53_gpiote_init(void)
 {
   /* Clear LATCH register(s) */
 
-  putreg32(0, NRF53_GPIO_P0_BASE + NRF53_GPIO_LATCH_OFFSET);
-  putreg32(0, NRF53_GPIO_P1_BASE + NRF53_GPIO_LATCH_OFFSET);
+  putreg32(0xffffffff, NRF53_GPIO_P0_BASE + NRF53_GPIO_LATCH_OFFSET);
+  putreg32(0xffffffff, NRF53_GPIO_P1_BASE + NRF53_GPIO_LATCH_OFFSET);
 
   /* Reset GPIOTE data */
 
diff --git a/arch/arm/src/nrf53/nrf53_gpiote.h 
b/arch/arm/src/nrf53/nrf53_gpiote.h
index 630727ff0b3..f7071c355d0 100644
--- a/arch/arm/src/nrf53/nrf53_gpiote.h
+++ b/arch/arm/src/nrf53/nrf53_gpiote.h
@@ -140,7 +140,7 @@ void nrf53_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg);
 #endif
 
 /****************************************************************************
- * Name: nrf53_gpio_set_task
+ * Name: nrf53_gpiote_set_task
  *
  * Description:
  *   Configure GPIO in TASK mode (to be controlled via tasks).
@@ -158,7 +158,7 @@ void nrf53_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg);
  *
  ****************************************************************************/
 
-void nrf53_gpio_set_task(uint32_t pinset, int channel,
+void nrf53_gpiote_set_task(uint32_t pinset, int channel,
                         bool output_high, enum nrf53_gpiote_outcfg_e outcfg);
 
 /****************************************************************************
diff --git a/arch/arm/src/nrf91/nrf91_gpiote.c 
b/arch/arm/src/nrf91/nrf91_gpiote.c
index 36fb06b5e3c..71ae787d060 100644
--- a/arch/arm/src/nrf91/nrf91_gpiote.c
+++ b/arch/arm/src/nrf91/nrf91_gpiote.c
@@ -326,7 +326,7 @@ void nrf91_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg)
 
       for (i = 0; i < NRF91_GPIO_NPORTS; i++)
         {
-          if (g_gpiote_port_callback[port].callback)
+          if (g_gpiote_port_callback[i].callback)
             {
               break;
             }
@@ -476,27 +476,43 @@ int nrf91_gpiote_set_event(uint32_t pinset,
 
   flags = enter_critical_section();
 
-  /* Get free channel or channel already used by pinset */
+  /* Get channel already used by pinset */
 
   for (i = 0; i < GPIOTE_CHANNELS; i++)
     {
-      if (g_gpiote_ch_callbacks[i].callback == NULL ||
+      if (g_gpiote_ch_callbacks[i].callback != NULL &&
           g_gpiote_ch_callbacks[i].pinset == pinset)
         {
-          g_gpiote_ch_callbacks[i].pinset = pinset;
+          break;
+        }
+    }
+
+  /* Otherwise get a free channel */
+
+  if (i == GPIOTE_CHANNELS && func != NULL)
+    {
+      for (i = 0; i < GPIOTE_CHANNELS; i++)
+        {
+          if (g_gpiote_ch_callbacks[i].callback == NULL)
+            {
+              break;
+            }
+        }
+    }
 
-          /* Configure channel */
+  if (i < GPIOTE_CHANNELS)
+    {
+      g_gpiote_ch_callbacks[i].pinset = pinset;
 
-          nrf91_gpiote_set_ch_event(pinset, i,
-                                    risingedge, fallingedge,
-                                    func, arg);
+      /* Configure channel */
 
-          /* Return the channel index */
+      nrf91_gpiote_set_ch_event(pinset, i,
+                                risingedge, fallingedge,
+                                func, arg);
 
-          ret = i;
+      /* Return the channel index */
 
-          break;
-        }
+      ret = i;
     }
 
   leave_critical_section(flags);
@@ -505,7 +521,7 @@ int nrf91_gpiote_set_event(uint32_t pinset,
 }
 
 /****************************************************************************
- * Name: nrf91_gpio_set_task
+ * Name: nrf91_gpiote_set_task
  *
  * Description:
  *   Configure GPIO in TASK mode (to be controlled via tasks).
@@ -590,10 +606,10 @@ int nrf91_gpiote_init(void)
 {
   /* Clear LATCH register(s) */
 
-  putreg32(0, NRF91_GPIO_P0_BASE + NRF91_GPIO_LATCH_OFFSET);
+  putreg32(0xffffffff, NRF91_GPIO_P0_BASE + NRF91_GPIO_LATCH_OFFSET);
 
 #ifdef CONFIG_NRF91_HAVE_PORT1
-  putreg32(0, NRF91_GPIO_P1_BASE + NRF91_GPIO_LATCH_OFFSET);
+  putreg32(0xffffffff, NRF91_GPIO_P1_BASE + NRF91_GPIO_LATCH_OFFSET);
 #endif
 
   /* Reset GPIOTE data */
diff --git a/arch/arm/src/nrf91/nrf91_gpiote.h 
b/arch/arm/src/nrf91/nrf91_gpiote.h
index ed82dd3759c..ae837a622d7 100644
--- a/arch/arm/src/nrf91/nrf91_gpiote.h
+++ b/arch/arm/src/nrf91/nrf91_gpiote.h
@@ -144,7 +144,7 @@ void nrf91_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg);
 #endif
 
 /****************************************************************************
- * Name: nrf91_gpio_set_task
+ * Name: nrf91_gpiote_set_task
  *
  * Description:
  *   Configure GPIO in TASK mode (to be controlled via tasks).
@@ -162,7 +162,7 @@ void nrf91_gpiote_set_port_event(uint32_t pinset, xcpt_t 
func, void *arg);
  *
  ****************************************************************************/
 
-void nrf91_gpio_set_task(uint32_t pinset, int channel,
+void nrf91_gpiote_set_task(uint32_t pinset, int channel,
                         bool output_high, enum nrf91_gpiote_outcfg_e outcfg);
 
 /****************************************************************************

Reply via email to