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 2020/07/18 17:23:13 UTC

[incubator-nuttx] branch master updated (ac7e5de -> f91372c)

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

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


    from ac7e5de  libxx: Integrate uClibc++ latest official release
     new e5be32a  arch/stm32f7: Fixes bug in tickless driver where the compare register is set to a value less than the current time.
     new f91372c  stm32_tickless.c: Fix formatting issues.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/stm32/stm32_tickless.c   | 38 +++++++++++++++--------------
 arch/arm/src/stm32f7/stm32_tickless.c | 46 +++++++++++++++++++++++++++++------
 2 files changed, 59 insertions(+), 25 deletions(-)


[incubator-nuttx] 01/02: arch/stm32f7: Fixes bug in tickless driver where the compare register is set to a value less than the current time.

Posted by xi...@apache.org.
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 e5be32ac211fd1634681e8ac5a8b438f14ecdd66
Author: Anthony Merlino <an...@vergeaero.com>
AuthorDate: Tue Jul 7 16:02:04 2020 -0400

    arch/stm32f7: Fixes bug in tickless driver where the compare register is set to a value less than the current time.
---
 arch/arm/src/stm32f7/stm32_tickless.c | 45 ++++++++++++++++++++++++++++++-----
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/arch/arm/src/stm32f7/stm32_tickless.c b/arch/arm/src/stm32f7/stm32_tickless.c
index 977410a..02a29c3 100644
--- a/arch/arm/src/stm32f7/stm32_tickless.c
+++ b/arch/arm/src/stm32f7/stm32_tickless.c
@@ -139,7 +139,7 @@ struct stm32_tickless_s
   volatile bool pending;           /* True: pending task */
   uint32_t period;                 /* Interval period */
   uint32_t base;
-#if CONFIG_SCHED_TICKLESS_ALARM
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
   uint64_t last_alrm;
 #endif
 };
@@ -394,6 +394,17 @@ static int stm32_tickless_handler(int irq, void *context, void *arg)
 }
 
 /****************************************************************************
+ * Name: stm32_get_counter
+ *
+ ****************************************************************************/
+
+static uint64_t stm32_get_counter(void)
+{
+  return ((uint64_t)g_tickless.overflow << 32) |
+         STM32_TIM_GETCOUNTER(g_tickless.tch);
+}
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -988,22 +999,43 @@ int up_timer_start(FAR const struct timespec *ts)
 }
 #endif
 
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
 int up_alarm_start(FAR const struct timespec *ts)
 {
+  size_t offset = 1;
   uint64_t tm = ((uint64_t)ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec) /
                 NSEC_PER_TICK;
-  uint64_t counter = ((uint64_t)g_tickless.overflow << 32) |
-                     STM32_TIM_GETCOUNTER(g_tickless.tch);
-
-  g_tickless.last_alrm = tm;
+  irqstate_t flags;
 
-  int32_t diff = tm / NSEC_PER_TICK + counter;
+  flags = enter_critical_section();
 
   STM32_TIM_SETCOMPARE(g_tickless.tch, CONFIG_STM32F7_TICKLESS_CHANNEL, tm);
 
   stm32_tickless_ackint(g_tickless.channel);
   stm32_tickless_enableint(CONFIG_STM32F7_TICKLESS_CHANNEL);
 
+  g_tickless.pending = true;
+
+  /* We must protect for a race condition here with very small differences
+   * between the time of the alarm and the time now. We must ensure that the
+   * compare register is set, and interrupts are enabled BEFORE the rising edge
+   * of the clock when COUNT==COMPARE. Otherwise, we cannot be sure we are 
+   * going to get the interrupt. If we didn't catch this case, we wouldn't
+   * interrupt until a full loop of the clock.
+   * 
+   * Since we can't make assumptions about the clock speed and tick rate,
+   * we simply keep adding an offset to the current time, until we can leave
+   * certain that the interrupt is going to fire as soon as we leave the
+   * critical section.
+   */
+
+  while (tm <= stm32_get_counter())
+    {
+      tm = stm32_get_counter() + offset++;
+      STM32_TIM_SETCOMPARE(g_tickless.tch, CONFIG_STM32F7_TICKLESS_CHANNEL, tm);
+    }
+
+  leave_critical_section(flags);
   return OK;
 }
 
@@ -1019,5 +1051,6 @@ int up_alarm_cancel(FAR struct timespec *ts)
 
   return 0;
 }
+#endif
 
 #endif /* CONFIG_SCHED_TICKLESS */


[incubator-nuttx] 02/02: stm32_tickless.c: Fix formatting issues.

Posted by xi...@apache.org.
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 f91372c09dcb9c7e28ec45d344dbc58cfd1cc81b
Author: Anthony Merlino <an...@vergeaero.com>
AuthorDate: Tue Jul 7 19:50:24 2020 -0400

    stm32_tickless.c: Fix formatting issues.
---
 arch/arm/src/stm32/stm32_tickless.c   | 38 ++++++++++++++++++-----------------
 arch/arm/src/stm32f7/stm32_tickless.c | 17 ++++++++--------
 2 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/arch/arm/src/stm32/stm32_tickless.c b/arch/arm/src/stm32/stm32_tickless.c
index f131a9db..36e65dd 100644
--- a/arch/arm/src/stm32/stm32_tickless.c
+++ b/arch/arm/src/stm32/stm32_tickless.c
@@ -34,6 +34,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  *
  ****************************************************************************/
+
 /****************************************************************************
  * Tickless OS Support.
  *
@@ -56,6 +57,7 @@
  *     logic when the interval timer expires.
  *
  ****************************************************************************/
+
 /****************************************************************************
  * STM32 Timer Usage
  *
@@ -142,39 +144,39 @@ static struct stm32_tickless_s g_tickless;
  * Private Functions
  ****************************************************************************/
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_getreg16
  *
  * Description:
  *   Get a 16-bit register value by offset
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline uint16_t stm32_getreg16(uint8_t offset)
 {
   return getreg16(g_tickless.base + offset);
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_putreg16
  *
  * Description:
  *   Put a 16-bit register value by offset
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline void stm32_putreg16(uint8_t offset, uint16_t value)
 {
   putreg16(value, g_tickless.base + offset);
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_modifyreg16
  *
  * Description:
  *   Modify a 16-bit register value by offset
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline void stm32_modifyreg16(uint8_t offset, uint16_t clearbits,
                                      uint16_t setbits)
@@ -182,45 +184,45 @@ static inline void stm32_modifyreg16(uint8_t offset, uint16_t clearbits,
   modifyreg16(g_tickless.base + offset, clearbits, setbits);
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_tickless_enableint
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline void stm32_tickless_enableint(int channel)
 {
   stm32_modifyreg16(STM32_BTIM_DIER_OFFSET, 0, 1 << channel);
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_tickless_disableint
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline void stm32_tickless_disableint(int channel)
 {
   stm32_modifyreg16(STM32_BTIM_DIER_OFFSET, 1 << channel, 0);
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_tickless_ackint
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline void stm32_tickless_ackint(int channel)
 {
   stm32_putreg16(STM32_BTIM_SR_OFFSET, ~(1 << channel));
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_tickless_getint
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline uint16_t stm32_tickless_getint(void)
 {
   return stm32_getreg16(STM32_BTIM_SR_OFFSET);
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32_tickless_setchannel
- ************************************************************************************/
+ ****************************************************************************/
 
 static int stm32_tickless_setchannel(uint8_t channel)
 {
@@ -795,8 +797,8 @@ int up_timer_cancel(FAR struct timespec *ts)
       return OK;
     }
 
-  /* Yes.. Get the timer counter and period registers and disable the compare interrupt.
-   *
+  /* Yes.. Get the timer counter and period registers and disable the compare
+   * interrupt.
    */
 
   tmrinfo("Cancelling...\n");
diff --git a/arch/arm/src/stm32f7/stm32_tickless.c b/arch/arm/src/stm32f7/stm32_tickless.c
index 02a29c3..a35b4f4 100644
--- a/arch/arm/src/stm32f7/stm32_tickless.c
+++ b/arch/arm/src/stm32f7/stm32_tickless.c
@@ -34,6 +34,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  *
  ****************************************************************************/
+
 /****************************************************************************
  * Tickless OS Support.
  *
@@ -223,7 +224,7 @@ static inline void stm32_tickless_ackint(int channel)
 
 /****************************************************************************
  * Name: stm32_tickless_getint
- ******************************************************************************/
+ ****************************************************************************/
 
 static inline uint16_t stm32_tickless_getint(void)
 {
@@ -1016,13 +1017,10 @@ int up_alarm_start(FAR const struct timespec *ts)
 
   g_tickless.pending = true;
 
-  /* We must protect for a race condition here with very small differences
-   * between the time of the alarm and the time now. We must ensure that the
-   * compare register is set, and interrupts are enabled BEFORE the rising edge
-   * of the clock when COUNT==COMPARE. Otherwise, we cannot be sure we are 
-   * going to get the interrupt. If we didn't catch this case, we wouldn't
-   * interrupt until a full loop of the clock.
-   * 
+  /* If we have already passed this time, there is a chance we didn't set the
+   * compare register in time and we've missed the interrupt. If we don't
+   * catch this case, we won't interrupt until a full loop of the clock.
+   *
    * Since we can't make assumptions about the clock speed and tick rate,
    * we simply keep adding an offset to the current time, until we can leave
    * certain that the interrupt is going to fire as soon as we leave the
@@ -1032,7 +1030,8 @@ int up_alarm_start(FAR const struct timespec *ts)
   while (tm <= stm32_get_counter())
     {
       tm = stm32_get_counter() + offset++;
-      STM32_TIM_SETCOMPARE(g_tickless.tch, CONFIG_STM32F7_TICKLESS_CHANNEL, tm);
+      STM32_TIM_SETCOMPARE(g_tickless.tch, CONFIG_STM32F7_TICKLESS_CHANNEL,
+                           tm);
     }
 
   leave_critical_section(flags);