Skip to content

drift (and issues) in esp_timer_get_time and xTaskGetTickCount (GIT8266O-646) #1068

@dsptech

Description

@dsptech

Environment

  • Development Kit : nodemcu
  • IDF version : 89a3f25
  • Development Env: Eclipse
  • Operating System: Windows
  • Power Supply: USB

Problem Description

Drift in esp_timer_get_time and xTaskGetTickCount. Not protected access to the timer handle variables in esp_timer_get_time

Expected Behavior

no time drift.

Actual Behavior

see problem description

Steps to reproduce

The snipped below compare the elapsed time by esp_timer_get_time() and xTaskGetTickCount() against the hardware timer WDEVTSF0_TIME_LO. As visible in the attached log, after one minute (with no concurrent task, no wifi etc) esp_timer_get_time() has a drift of 42ms. Also xTaskGetTickCount() show a drift of 68ms (@250Hz Freertos freq.).

After an investigation I seen the below issues in xPortSysTickHandle (port.c):

  • 1st drift: ccount timer is read at each handler call and after that it is set to 0. There is no way to take in account the cpu cycles (ticks of ccount timer) lost in the operations. Moreover, a concurrent nmi shot (pwm) might further degrade the operation.
  • 2nd drift: us variable is evaluated and the remainder is discarded.
  • 3rd drift: ticks variable is evaluated from us variable and the remainder is discarded again.

Furthermore, esp_timer_get_time() read the 64bit g_esp_os_us handler variabile and ccount timer without disabling the interrupts. An invalid "not monotonic" value might be returned.

I need an immediate solution so I've already written a new working handler with 0 drift.
I will send out a pull request today in case my solution is deemed useful for the community.

Regards.

Code to reproduce this issue

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdbool.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_timer.h>
#include <esp_system.h>

void app_main()
{
    uint32_t wdev_us,wdevBase_us,elapsedWdev_us;
    uint32_t esp_us, espBase_us, elapsedEsp_us ;
    int32_t wdevVsEsp_us, wdevVsOs_us;
    uint32_t os_tks,osBase_tks,elapsedOs_us;
    bool init=false;
    for (;;) {
        wdev_us = REG_READ(WDEVTSF0_TIME_LO); //first 32 bit only
        esp_us = esp_timer_get_time();        //first 32 bit only
        os_tks = xTaskGetTickCount();
        if (!init){
            init = true;
            wdevBase_us = wdev_us;
            espBase_us = esp_us;
            osBase_tks = os_tks;
        }
        elapsedWdev_us  = wdev_us - wdevBase_us;
        elapsedEsp_us = esp_us - espBase_us;
        elapsedOs_us = 1000000/(configTICK_RATE_HZ) * (os_tks - osBase_tks);
        wdevVsEsp_us = elapsedWdev_us - elapsedEsp_us;
        wdevVsOs_us  = elapsedWdev_us - elapsedOs_us;
        printf("Elapsed Time ms - WDEV: %6" PRIu32 ", ESP : %6" PRIu32 ", OS (freertos) : %6"  PRIu32 "\n",
        	elapsedWdev_us/1000,elapsedEsp_us/1000,elapsedOs_us/1000);
        printf("                     WDEV vs ESP ms : %6" PRIi32", WDEV vs OS ms : %6" PRIi32 "\n\n",
        	wdevVsEsp_us/1000,wdevVsOs_us/1000);
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

Debug Logs

Elapsed Time ms - WDEV:      0, ESP :      0, OS (freertos) :      0
                     WDEV vs ESP ms :      0, WDEV vs OS ms :      0

Elapsed Time ms - WDEV:   5010, ESP :   5006, OS (freertos) :   5008
                     WDEV vs ESP ms :      3, WDEV vs OS ms :      2

Elapsed Time ms - WDEV:  10016, ESP :  10009, OS (freertos) :  10008
                     WDEV vs ESP ms :      7, WDEV vs OS ms :      8

Elapsed Time ms - WDEV:  15022, ESP :  15011, OS (freertos) :  15008
                     WDEV vs ESP ms :     10, WDEV vs OS ms :     14

Elapsed Time ms - WDEV:  20028, ESP :  20014, OS (freertos) :  20008
                     WDEV vs ESP ms :     14, WDEV vs OS ms :     20

Elapsed Time ms - WDEV:  25034, ESP :  25016, OS (freertos) :  25008
                     WDEV vs ESP ms :     17, WDEV vs OS ms :     26

Elapsed Time ms - WDEV:  30040, ESP :  30019, OS (freertos) :  30008
                     WDEV vs ESP ms :     21, WDEV vs OS ms :     32

Elapsed Time ms - WDEV:  35046, ESP :  35021, OS (freertos) :  35008
                     WDEV vs ESP ms :     24, WDEV vs OS ms :     38

Elapsed Time ms - WDEV:  40052, ESP :  40024, OS (freertos) :  40008
                     WDEV vs ESP ms :     28, WDEV vs OS ms :     44

Elapsed Time ms - WDEV:  45058, ESP :  45026, OS (freertos) :  45008
                     WDEV vs ESP ms :     31, WDEV vs OS ms :     50

Elapsed Time ms - WDEV:  50064, ESP :  50029, OS (freertos) :  50008
                     WDEV vs ESP ms :     35, WDEV vs OS ms :     56

Elapsed Time ms - WDEV:  55070, ESP :  55031, OS (freertos) :  55008
                     WDEV vs ESP ms :     38, WDEV vs OS ms :     62

Elapsed Time ms - WDEV:  60076, ESP :  60034, OS (freertos) :  60008
                     WDEV vs ESP ms :     42, WDEV vs OS ms :     68

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions