From 8c25a0fd9d530bfaf3d665ac4649e9e543411928 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 16 Jan 2017 19:52:23 +0800 Subject: [PATCH 1/2] time: workaround for FRC_TIMER_INT_REG write issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases (when RTC register reads are performed from the APP CPU), a write to FRC_TIMER_INT_REG may be lost on the bus. Writing to another DPORT register immediately before or after that works around the issue. We write one dummy value to an address which doesn’t have any register associated with it. Fixes https://github.com/espressif/arduino-esp32/issues/120 --- components/newlib/test/test_time.c | 50 ++++++++++++++++++++++++++++++ components/newlib/time.c | 5 +++ 2 files changed, 55 insertions(+) create mode 100644 components/newlib/test/test_time.c diff --git a/components/newlib/test/test_time.c b/components/newlib/test/test_time.c new file mode 100644 index 0000000000..a230a220bc --- /dev/null +++ b/components/newlib/test/test_time.c @@ -0,0 +1,50 @@ +#include +#include +#include "unity.h" +#include "driver/adc.h" +#include +#include +#include "soc/rtc_cntl_reg.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "sdkconfig.h" + + +// https://github.com/espressif/arduino-esp32/issues/120 +TEST_CASE("Reading RTC registers on APP CPU doesn't affect clock", "[newlib]") +{ + // This runs on APP CPU: + void time_adc_test_task(void* arg) + { + for (int i = 0; i < 200000; ++i) { + // wait for 20us, reading one of RTC registers + uint32_t ccount = xthal_get_ccount(); + while (xthal_get_ccount() - ccount < 20 * CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) { + volatile uint32_t val = REG_READ(RTC_CNTL_STATE0_REG); + (void) val; + } + } + SemaphoreHandle_t * p_done = (SemaphoreHandle_t *) arg; + xSemaphoreGive(*p_done); + vTaskDelay(1); + vTaskDelete(NULL); + } + + SemaphoreHandle_t done = xSemaphoreCreateBinary(); + xTaskCreatePinnedToCore(&time_adc_test_task, "time_adc", 4096, &done, 5, NULL, 1); + + // This runs on PRO CPU: + for (int i = 0; i < 4; ++i) { + struct timeval tv_start; + gettimeofday(&tv_start, NULL); + vTaskDelay(1000/portTICK_PERIOD_MS); + struct timeval tv_stop; + gettimeofday(&tv_stop, NULL); + float time_sec = tv_stop.tv_sec - tv_start.tv_sec + 1e-6f * (tv_stop.tv_usec - tv_start.tv_usec); + printf("(0) time taken: %f sec\n", time_sec); + TEST_ASSERT_TRUE(fabs(time_sec - 1.0f) < 0.1); + } + TEST_ASSERT_TRUE(xSemaphoreTake(done, 5000 / portTICK_RATE_MS)); +} + diff --git a/components/newlib/time.c b/components/newlib/time.c index c9fa72eeee..004b7398c2 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -83,6 +83,11 @@ static volatile uint64_t s_microseconds = 0; static void IRAM_ATTR frc_timer_isr() { + // Write to FRC_TIMER_INT_REG may not take effect in some cases (root cause TBD) + // This extra write works around this issue. + // There is no register at DR_REG_FRC_TIMER_BASE + 0x60 (in fact, any DPORT register address can be used). + WRITE_PERI_REG(DR_REG_FRC_TIMER_BASE + 0x60, 0xabababab); + // Clear interrupt status WRITE_PERI_REG(FRC_TIMER_INT_REG(0), FRC_TIMER_INT_CLR); s_microseconds += FRC1_ISR_PERIOD_US; } From 7776d3e0652090ad491cf23698560b7787c8b781 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 16 Jan 2017 19:53:10 +0800 Subject: [PATCH 2/2] time: only define {get,set}_boot_time if FRC1 or RTC is used as time source Fixes https://github.com/espressif/esp-idf/issues/238 --- components/newlib/time.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/newlib/time.c b/components/newlib/time.c index 004b7398c2..30c7ca7f40 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -94,6 +94,7 @@ static void IRAM_ATTR frc_timer_isr() #endif // WITH_FRC1 +#if defined(WITH_RTC) || defined(WITH_FRC1) static void set_boot_time(uint64_t time_us) { _lock_acquire(&s_boot_time_lock); @@ -118,6 +119,7 @@ static uint64_t get_boot_time() _lock_release(&s_boot_time_lock); return result; } +#endif //defined(WITH_RTC) || defined(WITH_FRC1) void esp_setup_time_syscalls() {