2
2
#include " IRQManager.h"
3
3
#include " FspTimer.h"
4
4
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
7
6
8
7
__attribute__ ((weak)) void delay(uint32_t ms) {
9
8
R_BSP_SoftwareDelay (ms, BSP_DELAY_UNITS_MILLISECONDS);
@@ -16,21 +15,31 @@ void delayMicroseconds(unsigned int us) {
16
15
__attribute__ ((weak)) void yield() {
17
16
}
18
17
19
- static FspTimer main_timer;
18
+ static FspTimer agt_timer;
19
+ volatile uint32_t agt_time_ms = 0 ;
20
20
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 ;
25
23
}
26
24
27
25
void 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 !?
34
43
}
35
44
36
45
unsigned long millis ()
@@ -43,10 +52,18 @@ unsigned long millis()
43
52
}
44
53
45
54
unsigned 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 );
52
69
}
0 commit comments