33#include " FspTimer.h"
44
55// this file implements the following public funcions: delay, delayMicroseconds, yield, millis, micros
6- // The millis and micros implementation uses timer AGT0 (24 HMz, 16-bits, count-down mode, 1 ms period)
7-
8- volatile unsigned long agt_time_ms = 0 ;
96
107__attribute__ ((weak)) void delay(uint32_t ms) {
118 R_BSP_SoftwareDelay (ms, BSP_DELAY_UNITS_MILLISECONDS);
@@ -18,29 +15,25 @@ void delayMicroseconds(unsigned int us) {
1815__attribute__ ((weak)) void yield() {
1916}
2017
21- static FspTimer main_timer;
22- const uint8_t _timer_type = AGT_TIMER;
23- const uint8_t _timer_index = 0 ;
24- inline uint8_t _timer_get_underflow_bit () { return R_AGT0->AGTCR_b .TUNDF ; }
25- inline uint16_t _timer_get_counter () { return R_AGT0->AGT ; }
26- // clock divider 8 works for the Uno R4 and Portenta C33 both because _timer_period is < 16-bit.
27- // on the Uno R4 the AGT clock is 24 MHz / 8 -> 3000 ticks per ms
28- // on the Portenta C33 the AGT clock is 50 Mhz / 8 -> 6250 ticks per ms
29- const timer_source_div_t _timer_clock_divider = TIMER_SOURCE_DIV_8;
30- uint32_t _timer_period;
31- const uint8_t TIMER_PRIORITY = 8 ;
18+ static FspTimer agt_timer;
19+ volatile uint32_t agt_time_ms = 0 ;
3220
3321static void timer_micros_callback (timer_callback_args_t __attribute ((unused))* p_args) {
3422 agt_time_ms += 1 ;
3523}
3624
3725void startAgt () {
38- const uint32_t _timer_clock_freq = R_FSP_SystemClockHzGet (_timer_type == AGT_TIMER ? FSP_PRIV_CLOCK_PCLKB : FSP_PRIV_CLOCK_PCLKD);
39- _timer_period = _timer_clock_freq / ((1 << _timer_clock_divider) * 1000UL );
40- main_timer.begin (TIMER_MODE_PERIODIC, _timer_type, _timer_index, _timer_period, 1 , _timer_clock_divider, timer_micros_callback);;
41- main_timer.setup_overflow_irq (TIMER_PRIORITY);
42- main_timer.open ();
43- main_timer.start (); // bug in R4 1.0.2: calling start() is not necessary: open() starts the counter already !?
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 = R_FSP_SystemClockHzGet (FSP_PRIV_CLOCK_PCLKB);
32+ const uint32_t period = clock_freq / ((1 << TIMER_SOURCE_DIV_8) * 1000UL );
33+ agt_timer.begin (TIMER_MODE_PERIODIC, AGT_TIMER, 0 , period, 1 , TIMER_SOURCE_DIV_8, timer_micros_callback);;
34+ agt_timer.setup_overflow_irq (8 );
35+ agt_timer.open ();
36+ agt_timer.start (); // bug in R4 1.0.2: calling start() is not necessary: open() starts the counter already !?
4437}
4538
4639unsigned long millis ()
@@ -54,15 +47,17 @@ unsigned long millis()
5447
5548unsigned long micros () {
5649 // Return time in us
57- NVIC_DisableIRQ (main_timer.get_cfg ()->cycle_end_irq );
50+ const timer_cfg_t * cfg = agt_timer.get_cfg ();
51+ NVIC_DisableIRQ (cfg->cycle_end_irq );
5852 uint32_t ms = agt_time_ms;
59- uint32_t const down_counts = _timer_get_counter ();
60- if (_timer_get_underflow_bit () && (down_counts > (_timer_period / 2 )))
61- {
62- // the counter wrapped around just before it was read
53+ // read from the R_AGT0 registers directly for performance reasons
54+ uint32_t const down_counts = R_AGT0->AGT ; // get the counter value
55+ if (R_AGT0->AGTCR_b .TUNDF && (down_counts > (cfg->period_counts / 2 ))) {
56+ // if the TUNDF (underflow) bit is set, the counter wrapped around
57+ // just before down_counts was read and agt_time_ms was not yet updated
6358 ++ms;
6459 }
65- NVIC_EnableIRQ (main_timer. get_cfg () ->cycle_end_irq );
66- uint32_t const up_counts = (_timer_period - 1 ) - down_counts;
67- return (ms * 1000 ) + ((up_counts * 1000 ) / _timer_period );
60+ NVIC_EnableIRQ (cfg ->cycle_end_irq );
61+ uint32_t const up_counts = (cfg-> period_counts - 1 ) - down_counts;
62+ return (ms * 1000 ) + ((up_counts * 1000 ) / cfg-> period_counts );
6863}
0 commit comments