3
3
#include " FspTimer.h"
4
4
5
5
// 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 ;
9
6
10
7
__attribute__ ((weak)) void delay(uint32_t ms) {
11
8
R_BSP_SoftwareDelay (ms, BSP_DELAY_UNITS_MILLISECONDS);
@@ -18,29 +15,25 @@ void delayMicroseconds(unsigned int us) {
18
15
__attribute__ ((weak)) void yield() {
19
16
}
20
17
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 ;
32
20
33
21
static void timer_micros_callback (timer_callback_args_t __attribute ((unused))* p_args) {
34
22
agt_time_ms += 1 ;
35
23
}
36
24
37
25
void 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 !?
44
37
}
45
38
46
39
unsigned long millis ()
@@ -54,15 +47,17 @@ unsigned long millis()
54
47
55
48
unsigned long micros () {
56
49
// 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 );
58
52
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
63
58
++ms;
64
59
}
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 );
68
63
}
0 commit comments