You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2021/06/15 10:33:13 UTC

[mynewt-core] branch master updated: pic32: Fix tick timer handling

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

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new f2478be  pic32: Fix tick timer handling
f2478be is described below

commit f2478bead7dea495fc9f0a9678a8e9ed8f757023
Author: Jerzy Kasenberg <je...@apache.org>
AuthorDate: Mon Jun 14 21:42:36 2021 +0200

    pic32: Fix tick timer handling
    
    Tick timer interrupt handler assumed it was execute before
    next tick interrupt should be fired.
    In case when interrupt was handled late (due to other interrupts
    or just blocked interrupt for some time) next computed tick time
    was already in the past and system time stopped for a very long time.
    
    Now COMPARE register when set is compared to current COUNT register
    and if it is in the past next tick time is computed until interrupt
    is schedule to be ahead of COUNT register.
    
    Also os_time_advance() takes into account what is the difference of
    COUNT and COMPARE registers and in case of late interrupt, g_os_time
    can advance more then one tick at a time.
---
 kernel/os/src/arch/pic32/os_arch_pic32.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/kernel/os/src/arch/pic32/os_arch_pic32.c b/kernel/os/src/arch/pic32/os_arch_pic32.c
index 3f4b0ea..5f274dc 100644
--- a/kernel/os/src/arch/pic32/os_arch_pic32.c
+++ b/kernel/os/src/arch/pic32/os_arch_pic32.c
@@ -60,15 +60,23 @@ struct os_task *g_fpu_task;
 
 struct os_task_t* g_fpu_user;
 
+static uint32_t last_compare;
+
 static void timer_handler(void);
 
 /* core timer interrupt */
 void __attribute__((interrupt(IPL1AUTO),
 vector(_CORE_TIMER_VECTOR))) isr_core_timer(void)
 {
+    uint32_t compare;
+
     timer_handler();
-    _CP0_SET_COMPARE(_CP0_GET_COMPARE() + OS_TICK_PERIOD);
     IFS0CLR = _IFS0_CTIF_MASK;
+    compare = _CP0_GET_COMPARE();
+    do {
+        compare += OS_TICK_PERIOD;
+        _CP0_SET_COMPARE(compare);
+    } while ((int32_t)(compare - _CP0_GET_COUNT()) <= 0);
 }
 
 /* context switch interrupt, in ctx.S */
@@ -79,7 +87,11 @@ isr_sw0(void);
 static void
 timer_handler(void)
 {
-    os_time_advance(1);
+    uint32_t compare = _CP0_GET_COMPARE();
+    if (last_compare != compare) {
+        os_time_advance((compare - last_compare) / OS_TICK_PERIOD);
+        last_compare = compare;
+    }
 }
 
 void