22#include " IRQManager.h"
33#include " FspTimer.h"
44
5- volatile unsigned long agt_time_ms = 0 ;
6- uint32_t _freq_hz = 0 ;
5+ // this file implements the following public funcions: delay, delayMicroseconds, yield, millis, micros
76
87__attribute__ ((weak)) void delay(uint32_t ms) {
98 R_BSP_SoftwareDelay (ms, BSP_DELAY_UNITS_MILLISECONDS);
@@ -16,21 +15,31 @@ void delayMicroseconds(unsigned int us) {
1615__attribute__ ((weak)) void yield() {
1716}
1817
19- static FspTimer main_timer;
18+ static FspTimer agt_timer;
19+ volatile uint32_t agt_time_ms = 0 ;
2020
21- static uint32_t _top_counter;
22-
23- static void timer_micros_callback (timer_callback_args_t __attribute ((unused)) *p_args) {
24- agt_time_ms += 1 ; // 1ms
21+ static void timer_micros_callback (timer_callback_args_t __attribute ((unused))* p_args) {
22+ agt_time_ms += 1 ;
2523}
2624
2725void startAgt () {
28- main_timer.begin (TIMER_MODE_PERIODIC, AGT_TIMER, 0 , 2000 .0f , 0 .5f , timer_micros_callback);
29- IRQManager::getInstance ().addPeripheral (IRQ_AGT,(void *)main_timer.get_cfg ());
30- main_timer.open ();
31- _top_counter = main_timer.get_counter ();
32- main_timer.start ();
33- _freq_hz = main_timer.get_freq_hz ();
26+ // configure AGT timer 0 to generate an underflow interrupt every 1 ms
27+ // a clock divider 8 works for both the Uno R4 and Portenta C33 because number of clock ticks
28+ // in 1 ms (period) is an integer number and below the 16-bit counter limit
29+ // on the Uno R4 the AGT clock is 24 MHz / 8 -> 3000 ticks per ms
30+ // on the Portenta C33 the AGT clock is 50 Mhz / 8 -> 6250 ticks per ms
31+ const uint32_t clock_freq_Hz = R_FSP_SystemClockHzGet (FSP_PRIV_CLOCK_PCLKB);
32+ const uint32_t period = clock_freq_Hz / ((1 << TIMER_SOURCE_DIV_8) * 1000UL );
33+ agt_timer.begin (/* mode */ TIMER_MODE_PERIODIC,
34+ /* type */ AGT_TIMER,
35+ /* channel */ 0 ,
36+ period,
37+ /* pulse */ 1 ,
38+ TIMER_SOURCE_DIV_8,
39+ timer_micros_callback);;
40+ agt_timer.setup_overflow_irq (8 );
41+ agt_timer.open ();
42+ agt_timer.start (); // bug in R4 1.0.2: calling start() is not necessary: open() starts the counter already !?
3443}
3544
3645unsigned long millis ()
@@ -43,10 +52,18 @@ unsigned long millis()
4352}
4453
4554unsigned long micros () {
46-
47- // Convert time to us
48- NVIC_DisableIRQ (main_timer.get_cfg ()->cycle_end_irq );
49- uint32_t time_us = ((main_timer.get_period_raw () - main_timer.get_counter ()) * 1000 / main_timer.get_period_raw ()) + (agt_time_ms * 1000 );
50- NVIC_EnableIRQ (main_timer.get_cfg ()->cycle_end_irq );
51- return time_us;
55+ // Return time in us
56+ const timer_cfg_t * cfg = agt_timer.get_cfg ();
57+ NVIC_DisableIRQ (cfg->cycle_end_irq );
58+ uint32_t ms = agt_time_ms;
59+ // read from the R_AGT0 registers directly for performance reasons
60+ uint32_t const down_counts = R_AGT0->AGT ; // get the counter value
61+ if (R_AGT0->AGTCR_b .TUNDF && (down_counts > (cfg->period_counts / 2 ))) {
62+ // if the TUNDF (underflow) bit is set, the counter wrapped around
63+ // just before down_counts was read and agt_time_ms was not yet updated
64+ ++ms;
65+ }
66+ NVIC_EnableIRQ (cfg->cycle_end_irq );
67+ uint32_t const up_counts = (cfg->period_counts - 1 ) - down_counts;
68+ return (ms * 1000 ) + ((up_counts * 1000 ) / cfg->period_counts );
5269}
0 commit comments