You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/02/25 19:23:26 UTC

[incubator-nuttx] 03/03: xtensa/esp32s2: Fix Scheduler CPU Load feature using Oneshot Timer

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

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 6a12befcd59c6e328da704cd3cc8afde72d6d3b6
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Fri Feb 25 10:10:15 2022 -0300

    xtensa/esp32s2: Fix Scheduler CPU Load feature using Oneshot Timer
    
    Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
 arch/xtensa/src/esp32s2/esp32s2_oneshot.c          | 32 +++++++++++-----------
 .../xtensa/src/esp32s2/esp32s2_oneshot_lowerhalf.c | 16 +++++++----
 2 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/xtensa/src/esp32s2/esp32s2_oneshot.c b/arch/xtensa/src/esp32s2/esp32s2_oneshot.c
index ced51d2..70c25968 100644
--- a/arch/xtensa/src/esp32s2/esp32s2_oneshot.c
+++ b/arch/xtensa/src/esp32s2/esp32s2_oneshot.c
@@ -85,20 +85,15 @@ static int esp32s2_oneshot_handler(int irq, void *context, void *arg);
 static int esp32s2_oneshot_handler(int irq, void *context, void *arg)
 {
   int ret = OK;
-  struct esp32s2_oneshot_s *oneshot =
-    (struct esp32s2_oneshot_s *)arg;
+  struct esp32s2_oneshot_s *oneshot = (struct esp32s2_oneshot_s *)arg;
+  oneshot_handler_t handler;
+  void *handler_arg;
 
-  DEBUGASSERT(oneshot != NULL && oneshot->handler != NULL);
+  DEBUGASSERT(oneshot != NULL);
+  DEBUGASSERT(oneshot->handler != NULL);
 
   tmrinfo("Oneshot handler triggered\n");
 
-  /* Stop timer
-   * Note: It's not necessary to disable the alarm because
-   * it automatically disables each time it expires.
-   */
-
-  ESP32S2_TIM_STOP(oneshot->tim);
-
   /* Disable interrupts */
 
   ESP32S2_TIM_DISABLEINT(oneshot->tim);
@@ -107,19 +102,24 @@ static int esp32s2_oneshot_handler(int irq, void *context, void *arg)
 
   ret = ESP32S2_TIM_SETISR(oneshot->tim, NULL, NULL);
 
-  /* Call the callback */
+  /* Clear the Interrupt */
 
-  oneshot->handler((void *)oneshot->arg);
+  ESP32S2_TIM_ACKINT(oneshot->tim);
 
-  /* Restore state */
+  /* The timer is no longer running */
 
   oneshot->running = false;
+
+  /* Forward the event, clearing out any vestiges */
+
+  handler          = (oneshot_handler_t)oneshot->handler;
   oneshot->handler = NULL;
-  oneshot->arg = NULL;
+  handler_arg      = (void *)oneshot->arg;
+  oneshot->arg     = NULL;
 
-  /* Clear the Interrupt */
+  /* Call the callback */
 
-  ESP32S2_TIM_ACKINT(oneshot->tim);
+  handler(handler_arg);
 
   return ret;
 }
diff --git a/arch/xtensa/src/esp32s2/esp32s2_oneshot_lowerhalf.c b/arch/xtensa/src/esp32s2/esp32s2_oneshot_lowerhalf.c
index 935779d..78954b1 100644
--- a/arch/xtensa/src/esp32s2/esp32s2_oneshot_lowerhalf.c
+++ b/arch/xtensa/src/esp32s2/esp32s2_oneshot_lowerhalf.c
@@ -114,20 +114,26 @@ static void esp32s2_oneshot_lh_handler(void *arg)
 {
   struct esp32s2_oneshot_lowerhalf_s *priv =
     (struct esp32s2_oneshot_lowerhalf_s *)arg;
+  oneshot_callback_t callback;
+  FAR void *cb_arg;
 
   DEBUGASSERT(priv != NULL);
   DEBUGASSERT(priv->callback != NULL);
 
   tmrinfo("Oneshot LH handler triggered\n");
 
-  /* Call the callback */
+  /* Sample and nullify BEFORE executing callback (in case the callback
+   * restarts the oneshot).
+   */
 
-  priv->callback(&priv->lh, priv->arg);
+  callback       = priv->callback;
+  cb_arg         = priv->arg;
+  priv->callback = NULL;
+  priv->arg      = NULL;
 
-  /* Restore state */
+  /* Then perform the callback */
 
-  priv->callback = NULL;
-  priv->arg = NULL;
+  callback(&priv->lh, cb_arg);
 }
 
 /****************************************************************************