Making my own micros()...problem


I'm currently trying trying to generate a 25KHz PWM for a PC style fan on the timer 2 (Ok) and also using the timer 2 for my own timing functions.
I have a problem on the 2nd part of the project, the following sketch is simplified to have a more readable code and problem.

This only uses the TIMER2 with normal mode, with an ISR at overflow that increments a variable that is supposed to help in timing measure. Each overflow happened after 128 micros seconds.

Here is the code :

long Timer2_Big_Cpt;

void setup() {

Timer2_Big_Cpt = 0;

TCCR2A = 0b00000000; // TIMER2 normal mode
TCCR2B = 0b00000010; // TIMER2 prescaler /8
TIMSK2 |= 1; // TIMER2 OVF interrupt enabled
TCNT2 = 0;

sei(); //OK for interrupt

ISR(TIMER2_OVF_vect) {


// very approximative but it's not our problem now...
long My_Micros()
// each ++ means 128 microsec
return Timer2_Big_Cpt*128;

void loop() {

long old, new_tm;

old = My_Micros();
//sei(); ///////////////////

new_tm = My_Micros();

If I leave the //sei() commented, the print "says" 0.
Otyherwise, it is OK, the number printed is around 500_000 that is OK

Why is it necessary to reactivate the interrupts ? Another function (delay ?) disables it ?
Anything "escapes" me...

Thanks in advance !

I see at least 3 problems:

  1. Don't mess with disabling / enabling interrupts in the ISR. That's all taken care of for you.

  2. You didn't declare Timer2_Big_Cpt as volatile.

  3. Accesses to Timer2_Big_Cpt are not atomic. You must protect them with critical sections in non-ISR code.

Make that 4 problems:

  1. Timer2_Big_Cpt should be 'unsigned long' (uint32_t), not 'long' (int32_t).

Make that 5 problems:

  1. My_Micros() should return uint32_t, not int32_t.

The volative keyword of my variable was missing and explains a big part of my problem.

I was totally unaware that the code may prevent my variable from expected changes without this.

I'll also add the critical section for the 4 bytes reading.

Thanks !