[En-Nut-Discussion] Low level timer functions

Harald Kipp harald.kipp at egnite.de
Fri Jun 10 09:31:03 CEST 2005


Hi Ole,

How do we say in Germany? "Offer him a little finger and he will
pull off your arm." :-)

My problem with additional timer/counter functions is, that
it seems to be no easy solution for a hardware independent
layer. But I'd agree that even some AVR specific functions
will be helpful.

In the meantime I think I have a nice solution for the
crystal frequency detection, which no longer depends on
wait states of external RAM. 'counter' is an u_long and
just needs to be multiplied by 128 the get the frequency
in Hz.

Harald

     /* Disable timer 0 interrupts. */
     cbi(TIMSK, TOIE0);
     cbi(TIMSK, OCIE0);

     /* Select oscillator 1 (32.768 kHz). */
     sbi(ASSR, AS0);

     /* Reset counter register. */
     outb(TCNT0, 0);

     /* Set prescaler to 8. Overflow will occur every 62.5 ms. */
     outb(TCCR0, _BV(CS01));

     /* Wait for asynchronous busy clear. */
     while ((inb(ASSR) & (_BV(TCN0UB) | _BV(OCR0UB) | _BV(TCR0UB))) != 0);

     /* Clear interrupt flags. */
     outb(TIFR, _BV(OCF0) | _BV(TOV0));

     counter = 1;
     NutEnterCritical();
     __asm__ __volatile__("firstovf:              \n\t"
                          "in %D0,%1              \n\t"
                          "andi %D0,1             \n\t"
                          "breq firstovf          \n\t"
                          "out %1,%D0             \n\n"
                          /* This loop has 8 cycles. */
                          "nextovf:               \n\t"
                          "sec                    \n\t"
                          "adc %A0,__zero_reg__   \n\t"
                          "adc %B0,__zero_reg__   \n\t"
                          "adc %C0,__zero_reg__   \n\t"
                          "in %D0,%1              \n\t"
                          "andi %D0,1             \n\t"
                          "breq nextovf           \n\t"
                          "clr %D0                    "
                          :"=d"(counter) /* Output */
                          :"I"(_SFR_IO_ADDR(TIFR)), "0"(counter) /* Input */
         );
     NutExitCritical();




More information about the En-Nut-Discussion mailing list