diff --git a/.gitignore b/.gitignore index f065235b3..216b0ba99 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ cores/arduino/mydebug.cpp libraries/Storage/.development cores/arduino/mydebug.cpp.donotuse .DS_Store -.DS_Store? \ No newline at end of file +.DS_Store? +/.vs +/.gitignore diff --git a/cores/arduino/time.cpp b/cores/arduino/time.cpp index 39f56f41b..8fc9a2e08 100644 --- a/cores/arduino/time.cpp +++ b/cores/arduino/time.cpp @@ -2,8 +2,7 @@ #include "IRQManager.h" #include "FspTimer.h" -volatile unsigned long agt_time_ms = 0; -uint32_t _freq_hz = 0; +// this file implements the following public funcions: delay, delayMicroseconds, yield, millis, micros __attribute__((weak)) void delay(uint32_t ms) { R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS); @@ -16,21 +15,31 @@ void delayMicroseconds(unsigned int us) { __attribute__((weak)) void yield() { } -static FspTimer main_timer; +static FspTimer agt_timer; +volatile uint32_t agt_time_ms = 0; -static uint32_t _top_counter; - -static void timer_micros_callback(timer_callback_args_t __attribute((unused)) *p_args) { - agt_time_ms += 1; //1ms +static void timer_micros_callback(timer_callback_args_t __attribute((unused))* p_args) { + agt_time_ms += 1; } void startAgt() { - main_timer.begin(TIMER_MODE_PERIODIC, AGT_TIMER, 0, 2000.0f, 0.5f, timer_micros_callback); - IRQManager::getInstance().addPeripheral(IRQ_AGT,(void*)main_timer.get_cfg()); - main_timer.open(); - _top_counter = main_timer.get_counter(); - main_timer.start(); - _freq_hz = main_timer.get_freq_hz(); + // configure AGT timer 0 to generate an underflow interrupt every 1 ms + // a clock divider 8 works for both the Uno R4 and Portenta C33 because number of clock ticks + // in 1 ms (period) is an integer number and below the 16-bit counter limit + // on the Uno R4 the AGT clock is 24 MHz / 8 -> 3000 ticks per ms + // on the Portenta C33 the AGT clock is 50 Mhz / 8 -> 6250 ticks per ms + const uint32_t clock_freq_Hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKB); + const uint32_t period = clock_freq_Hz / ((1 << TIMER_SOURCE_DIV_8) * 1000UL); + agt_timer.begin(/* mode */ TIMER_MODE_PERIODIC, + /* type */ AGT_TIMER, + /* channel */ 0, + period, + /* pulse */ 1, + TIMER_SOURCE_DIV_8, + timer_micros_callback);; + agt_timer.setup_overflow_irq(8); + agt_timer.open(); + agt_timer.start(); // bug in R4 1.0.2: calling start() is not necessary: open() starts the counter already !? } unsigned long millis() @@ -43,10 +52,18 @@ unsigned long millis() } unsigned long micros() { - - // Convert time to us - NVIC_DisableIRQ(main_timer.get_cfg()->cycle_end_irq); - uint32_t time_us = ((main_timer.get_period_raw() - main_timer.get_counter()) * 1000 / main_timer.get_period_raw()) + (agt_time_ms * 1000); - NVIC_EnableIRQ(main_timer.get_cfg()->cycle_end_irq); - return time_us; + // Return time in us + const timer_cfg_t* cfg = agt_timer.get_cfg(); + NVIC_DisableIRQ(cfg->cycle_end_irq); + uint32_t ms = agt_time_ms; + // read from the R_AGT0 registers directly for performance reasons + uint32_t const down_counts = R_AGT0->AGT; // get the counter value + if (R_AGT0->AGTCR_b.TUNDF && (down_counts > (cfg->period_counts / 2))) { + // if the TUNDF (underflow) bit is set, the counter wrapped around + // just before down_counts was read and agt_time_ms was not yet updated + ++ms; + } + NVIC_EnableIRQ(cfg->cycle_end_irq); + uint32_t const up_counts = (cfg->period_counts - 1) - down_counts; + return (ms * 1000) + ((up_counts * 1000) / cfg->period_counts); }