diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index bf4ee06e..7c1e517f 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -38,20 +38,45 @@ void yield() } portMUX_TYPE microsMux = portMUX_INITIALIZER_UNLOCKED; +static pthread_key_t microsStore=NULL; // Thread Local Storage Handle + +void* microsStoreDelete(void * storage) { // release thread local data when task is delete. + if(storage) free(storage); +} unsigned long IRAM_ATTR micros() { - static unsigned long lccount = 0; - static unsigned long overflow = 0; - unsigned long ccount; - portENTER_CRITICAL_ISR(µsMux); - __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) ); - if(ccount < lccount){ - overflow += UINT32_MAX / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; + if (!microsStore) { // first Time Ever thread local not init'd + portENTER_CRITICAL_ISR(µsMux); + pthread_key_create(µsStore,microsStoreDelete); // create initial holder + portEXIT_CRITICAL_ISR(µsMux); } - lccount = ccount; + + uint32_t *ptr;// [0] is lastCount, [1] is overFlow + + ptr = pthread_getspecific(microsStore); // get address of storage + + if(ptr == NULL) { // first time in this thread, allocate mem, init it. + portENTER_CRITICAL_ISR(µsMux); + ptr = (uint32_t*)malloc(sizeof(uint32_t)*2); + pthread_setspecific(microsStore,ptr); // store the pointer to this thread's values + ptr[0] = 0; // lastCount value + ptr[1] = 0; // overFlow + portEXIT_CRITICAL_ISR(µsMux); + } + + unsigned long ccount; + + portENTER_CRITICAL_ISR(µsMux); + __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) ); //get cycle count + if(ccount < ptr[0]) { // overflow occurred + ptr[1] += UINT32_MAX / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; + } + + ptr[0] = ccount; portEXIT_CRITICAL_ISR(µsMux); - return overflow + (ccount / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ); + + return ptr[1] + (ccount / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ); } unsigned long IRAM_ATTR millis()