Skip to content

Commit 733020d

Browse files
1. Fix for anomaly in micros() whwn the counter wrapped just before it was read 2. Specify timer configuration as constants to make micros() considerably faster
1 parent a086f96 commit 733020d

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ cores/arduino/mydebug.cpp
33
libraries/Storage/.development
44
cores/arduino/mydebug.cpp.donotuse
55
.DS_Store
6-
.DS_Store?
6+
.DS_Store?
7+
/.vs
8+
/.gitignore

cores/arduino/time.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#include "IRQManager.h"
33
#include "FspTimer.h"
44

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+
58
volatile unsigned long agt_time_ms = 0;
6-
uint32_t _freq_hz = 0;
79

810
__attribute__((weak)) void delay(uint32_t ms) {
911
R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS);
@@ -17,20 +19,24 @@ __attribute__((weak)) void yield() {
1719
}
1820

1921
static FspTimer main_timer;
20-
21-
static uint32_t _top_counter;
22+
// specifying these details as constants makes micros() faster !
23+
#define _timer_type AGT_TIMER
24+
#define _timer_index 0
25+
#define _timer_underflow_bit R_AGT0->AGTCR_b.TUNDF
26+
#define _timer_clock_divider TIMER_SOURCE_DIV_8 // dividers 1, 2, 4 and 8 work because _timer_period is < 16-bit. bug in R4 1.0.2: divider 4 acts as 1 !?
27+
#define _timer_clock_freq 24000000UL
28+
#define _timer_ticks_per_us (_timer_clock_freq / ((1 << _timer_clock_divider) * 1000000UL))
29+
#define _timer_period (_timer_ticks_per_us * 1000UL)
2230

2331
static void timer_micros_callback(timer_callback_args_t __attribute((unused)) *p_args) {
24-
agt_time_ms += 1; //1ms
32+
agt_time_ms += 1;
2533
}
2634

2735
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());
36+
main_timer.begin(TIMER_MODE_PERIODIC, _timer_type, _timer_index, _timer_period, 1, _timer_clock_divider, timer_micros_callback);;
37+
main_timer.setup_overflow_irq();
3038
main_timer.open();
31-
_top_counter = main_timer.get_counter();
32-
main_timer.start();
33-
_freq_hz = main_timer.get_freq_hz();
39+
main_timer.start(); // bug in R4 1.0.2: calling start() is not necessary: open() starts the counter already !?
3440
}
3541

3642
unsigned long millis()
@@ -43,10 +49,11 @@ unsigned long millis()
4349
}
4450

4551
unsigned long micros() {
46-
47-
// Convert time to us
52+
// Return time in us
4853
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);
54+
uint32_t ms = agt_time_ms;
55+
uint32_t cnt = main_timer.get_counter();
56+
if (_timer_underflow_bit && (cnt > (_timer_period / 2))) ++ms; // the counter wrapped arround just before it was read
5057
NVIC_EnableIRQ(main_timer.get_cfg()->cycle_end_irq);
51-
return time_us;
58+
return ms * 1000 + (((_timer_period - 1) - cnt) / _timer_ticks_per_us);
5259
}

0 commit comments

Comments
 (0)