Skip to content

Commit e0197ca

Browse files
committed
Make millis() timer configurable by compile define
1 parent 325a6cc commit e0197ca

File tree

2 files changed

+54
-33
lines changed

2 files changed

+54
-33
lines changed

boards.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ uno2018.build.f_cpu=16000000L
1818
uno2018.build.board=AVR_UNO_WIFI_REV2
1919
uno2018.build.core=arduino
2020
uno2018.build.variant=uno2018
21+
uno2018.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3
2122
#uno2018.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu}
2223

2324
uno2018.bootloader.tool=avrdude
@@ -26,6 +27,7 @@ uno2018.fuses.file=fuses_4809.bin
2627

2728
menu.mode=Registers emulation
2829
uno2018.menu.mode.on=ATMEGA328
29-
uno2018.menu.mode.on.build.extra_flags=-DUNO_WIFI_REV2_328MODE
30+
uno2018.menu.mode.on.build.328emulation=-DUNO_WIFI_REV2_328MODE
3031
uno2018.menu.mode.off=None (ATMEGA4809)
32+
uno2018.menu.mode.off.build.328emulation=
3133
##############################################################

cores/arduino/wiring.c

+51-32
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,25 @@
2222

2323
#include "wiring_private.h"
2424

25-
// the prescaler is set so that timerb0 ticks every 64 clock cycles, and the
25+
// the prescaler is set so that timer ticks every 64 clock cycles, and the
2626
// the overflow handler is called every 256 ticks.
27-
volatile uint16_t microseconds_per_timerb0_overflow;
28-
volatile uint16_t microseconds_per_timerb0_tick;
27+
volatile uint16_t microseconds_per_timer_overflow;
28+
volatile uint16_t microseconds_per_timer_tick;
2929

3030
uint32_t F_CPU_CORRECTED = F_CPU;
3131

32-
// the whole number of milliseconds per timerb0 overflow
32+
// the whole number of milliseconds per timer overflow
3333
uint16_t millis_inc;
3434

35-
// the fractional number of milliseconds per timerb0 overflow
35+
// the fractional number of milliseconds per timer overflow
3636
uint16_t fract_inc;
3737
#define FRACT_MAX (1000)
3838

39-
// whole number of microseconds per timerb0 tick
39+
// whole number of microseconds per timer tick
4040

41-
volatile uint32_t timerb0_overflow_count = 0;
42-
volatile uint32_t timerb0_millis = 0;
43-
static uint16_t timerb0_fract = 0;
41+
volatile uint32_t timer_overflow_count = 0;
42+
volatile uint32_t timer_millis = 0;
43+
static uint16_t timer_fract = 0;
4444

4545
inline uint16_t clockCyclesPerMicrosecondComp(uint32_t clk){
4646
return ( (clk) / 1000000L );
@@ -58,12 +58,31 @@ inline unsigned long microsecondsToClockCycles(unsigned long microseconds){
5858
return ( microseconds * clockCyclesPerMicrosecond() );
5959
}
6060

61+
static volatile TCB_t* _timer =
62+
#if defined(MILLIS_USE_TIMERB0)
63+
&TCB0;
64+
#elif defined(MILLIS_USE_TIMERB1)
65+
&TCB1;
66+
#elif defined(MILLIS_USE_TIMERB2)
67+
&TCB2;
68+
#else
69+
&TCB3;
70+
#endif
71+
72+
#if defined(MILLIS_USE_TIMERB0)
6173
ISR(TCB0_INT_vect)
74+
#elif defined(MILLIS_USE_TIMERB1)
75+
ISR(TCB1_INT_vect)
76+
#elif defined(MILLIS_USE_TIMERB2)
77+
ISR(TCB2_INT_vect)
78+
#else
79+
ISR(TCB3_INT_vect)
80+
#endif
6281
{
6382
// copy these to local variables so they can be stored in registers
6483
// (volatile variables must be read from memory on every access)
65-
uint32_t m = timerb0_millis;
66-
uint16_t f = timerb0_fract;
84+
uint32_t m = timer_millis;
85+
uint16_t f = timer_fract;
6786

6887
m += millis_inc;
6988
f += fract_inc;
@@ -73,12 +92,12 @@ ISR(TCB0_INT_vect)
7392
m += 1;
7493
}
7594

76-
timerb0_fract = f;
77-
timerb0_millis = m;
78-
timerb0_overflow_count++;
95+
timer_fract = f;
96+
timer_millis = m;
97+
timer_overflow_count++;
7998

8099
/* Clear flag */
81-
TCB0.INTFLAGS = TCB_CAPT_bm;
100+
_timer->INTFLAGS = TCB_CAPT_bm;
82101
}
83102

84103
unsigned long millis()
@@ -89,7 +108,7 @@ unsigned long millis()
89108
// inconsistent value (e.g. in the middle of a write to timer0_millis)
90109
uint8_t status = SREG;
91110
cli();
92-
m = timerb0_millis;
111+
m = timer_millis;
93112

94113
SREG = status;
95114

@@ -105,22 +124,22 @@ unsigned long micros() {
105124
cli();
106125

107126
/* Get current number of overflows and timer count */
108-
overflows = timerb0_overflow_count;
109-
ticks = TCB0.CNTL;
127+
overflows = timer_overflow_count;
128+
ticks = _timer->CNTL;
110129

111130
/* If the timer overflow flag is raised, we just missed it,
112131
increment to account for it, & read new ticks */
113-
if(TCB0.INTFLAGS & TCB_CAPT_bm){
132+
if(_timer->INTFLAGS & TCB_CAPT_bm){
114133
overflows++;
115-
ticks = TCB0.CNTL;
134+
ticks = _timer->CNTL;
116135
}
117136

118137
/* Restore state */
119138
SREG = status;
120139

121140
/* Return microseconds of up time (resets every ~70mins) */
122-
microseconds = ((overflows * microseconds_per_timerb0_overflow)
123-
+ (ticks * microseconds_per_timerb0_tick));
141+
microseconds = ((overflows * microseconds_per_timer_overflow)
142+
+ (ticks * microseconds_per_timer_tick));
124143
return microseconds;
125144
}
126145

@@ -355,27 +374,27 @@ void init()
355374

356375
setup_timers();
357376

358-
/********************* TCB0 for system time tracking **************************/
377+
/********************* TIMER for system time tracking **************************/
359378

360379
/* Calculate relevant time tracking values */
361-
microseconds_per_timerb0_overflow = clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF);
362-
microseconds_per_timerb0_tick = microseconds_per_timerb0_overflow/TIME_TRACKING_TIMER_PERIOD;
380+
microseconds_per_timer_overflow = clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF);
381+
microseconds_per_timer_tick = microseconds_per_timer_overflow/TIME_TRACKING_TIMER_PERIOD;
363382

364-
millis_inc = microseconds_per_timerb0_overflow / 1000;
365-
fract_inc = ((microseconds_per_timerb0_overflow % 1000));
383+
millis_inc = microseconds_per_timer_overflow / 1000;
384+
fract_inc = ((microseconds_per_timer_overflow % 1000));
366385

367386
/* Default Periodic Interrupt Mode */
368387
/* TOP value for overflow every 1024 clock cycles */
369-
TCB0.CCMP = TIME_TRACKING_TIMER_PERIOD;
388+
_timer->CCMP = TIME_TRACKING_TIMER_PERIOD;
370389

371-
/* Enable TCB0 interrupt */
372-
TCB0.INTCTRL |= TCB_CAPT_bm;
390+
/* Enable timer interrupt */
391+
_timer->INTCTRL |= TCB_CAPT_bm;
373392

374393
/* Clock selection -> same as TCA (F_CPU/64 -- 250kHz) */
375-
TCB0.CTRLA = TCB_CLKSEL_CLKTCA_gc;
394+
_timer->CTRLA = TCB_CLKSEL_CLKTCA_gc;
376395

377396
/* Enable & start */
378-
TCB0.CTRLA |= TCB_ENABLE_bm; /* Keep this last before enabling interrupts to ensure tracking as accurate as possible */
397+
_timer->CTRLA |= TCB_ENABLE_bm; /* Keep this last before enabling interrupts to ensure tracking as accurate as possible */
379398

380399
/*************************** ENABLE GLOBAL INTERRUPTS *************************/
381400

0 commit comments

Comments
 (0)