mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
time: workaround for FRC_TIMER_INT_REG write issue
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
This commit is contained in:
parent
48ae7ab500
commit
8c25a0fd9d
50
components/newlib/test/test_time.c
Normal file
50
components/newlib/test/test_time.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "unity.h"
|
||||
#include "driver/adc.h"
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user