itmr rollover in delay loop

Frank Rowand frowand@cup.hp.com
Wed, 24 Nov 1999 11:36:25 PST


>> Look at the loop.  What we do is basically
>> 
>>       cr16 = mfctl(16);
>>       while(((cr16+loops)-mfctl(16))>0);
>
>You definitely don't want to do the above!
>
>Even ignoring the possibility of an interrupt that takes us away
>for awhile, there's the simple possibility that cr16 might
>roll over during your loop.

Careful use of unsigned variables fixes the problem.  The easiest way to
explain this is by a small sample program:


main() {

unsigned long a;
unsigned long b;
int k;

a = 0xfffffffd;
b = 0xfffffffa;

printf("a       b        b - a         0 < (int)(b - a)\n\n");

for (k = 0; k < 10; k++) {
        printf("0x%x  0x%x  0x%x  %s\n", a, b, (b-a), (0 < (int)(b-a)) ? "y" : "n");
        b++;
}

printf("\n\n");

b += 0x7ffffff4;

for (k = 0; k < 10; k++) {
        printf("0x%x  0x%x  0x%x  %s\n", a, b, (b-a), (0 < (int)(b-a)) ? "y" : "n");
        b++;
}

}




The output from this program is:


a       b        b - a         0 < (int)(b - a)

0xfffffffd  0xfffffffa  0xfffffffd  n
0xfffffffd  0xfffffffb  0xfffffffe  n
0xfffffffd  0xfffffffc  0xffffffff  n
0xfffffffd  0xfffffffd  0x0  n
0xfffffffd  0xfffffffe  0x1  y
0xfffffffd  0xffffffff  0x2  y
0xfffffffd  0x0  0x3  y
0xfffffffd  0x1  0x4  y
0xfffffffd  0x2  0x5  y
0xfffffffd  0x3  0x6  y


0xfffffffd  0x7ffffff8  0x7ffffffb  y
0xfffffffd  0x7ffffff9  0x7ffffffc  y
0xfffffffd  0x7ffffffa  0x7ffffffd  y
0xfffffffd  0x7ffffffb  0x7ffffffe  y
0xfffffffd  0x7ffffffc  0x7fffffff  y
0xfffffffd  0x7ffffffd  0x80000000  n
0xfffffffd  0x7ffffffe  0x80000001  n
0xfffffffd  0x7fffffff  0x80000002  n
0xfffffffd  0x80000000  0x80000003  n
0xfffffffd  0x80000001  0x80000004  n



Note that the calculation to decide whether rollover occurred is only
good for half the maximum magnitude of the counter (2^31 in our case).



-Frank