avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] avr-libc delay functions


From: kuebelr
Subject: [avr-libc-dev] avr-libc delay functions
Date: Sun, 12 Jan 2003 01:42:28 -0500
User-agent: Mutt/1.4i

All,

I have written a pair of delay functions for an AVR project of mine and
noticed they would take care an item on your TODO list (I did see any
new delay stuff in CVS).

The us_spin() and ms_spin() functions take the number of
milliseconds/microseconds to stall. The user must define AVR_CLK as the
frequency of the CPU. The inner loop of each function takes 1 us/ms to
complete and the outer loop executes it the proper number of times. The
functions work correctly for any value of us/ms (0-65535). The functions
are also small (9 instructions each with the -Os flag).

The problem with including these in a library is that the loop counts
(for the inner loops) have to be available at compile time. You could
convert these to '#define ms_spin()' things I guess. I'll come up with
something if you need.

I also noticed that the current delay functions will not perform
correctly if the __count argument is 0 (the brne instruction will see a
0xff(ff) after the dec). They are corrected below.

You can consider this work public domain, I just would like credit in
the distribution if you use them. Also, I'll be happy to change anything
if needed.

Let me know what you think.

Thanks.
Rob Kuebel.

#define AVR_CLK (4000000)
#define LOOPS_PER_US (AVR_CLK/4)
#define LOOPS_PER_MS (AVR_CLK/1000/4)

/* spin for us microseconds */
void us_spin(unsigned short us)
{
        if (!us)
                return;

        /* the inner loop takes 4 cycles per iteration */
        __asm__ __volatile__ (
                "1:                     \n"
                "       ldi r26, %3     \n"
                "       ldi r27, %2     \n"
                "2:     sbiw r26, 1     \n"
                "       brne 2b         \n"
                "       sbiw %0, 1      \n"
                "       brne 1b         \n"
                : "=w" (us)
                : "w" (us), "i" (LOOPS_PER_MS >> 8), "i" (0xff & LOOPS_PER_MS)
                );
}

/* spin for ms milliseconds */
void ms_spin(unsigned short ms)
{
        if (!ms)
                return;

        /* the inner loop takes 4 cycles per iteration */
        __asm__ __volatile__ (
                "1:                     \n"
                "       ldi r26, %3     \n"
                "       ldi r27, %2     \n"
                "2:     sbiw r26, 1     \n"
                "       brne 2b         \n"
                "       sbiw %0, 1      \n"
                "       brne 1b         \n"
                : "=w" (ms)
                : "w" (ms), "i" (LOOPS_PER_MS >> 8), "i" (0xff & LOOPS_PER_MS)
                );
}

/* 8-bit count, 3 cycles/loop */
static inline void
_delay_loop_1(unsigned char __count)
{
        if (!__count)
                return;

        asm volatile (
                "1: dec %0" "\n\t"
                "brne 1b"
                : "=r" (__count)
                : "0" (__count)
        );
}

/* 16-bit count, 4 cycles/loop */
static inline void
_delay_loop_2(unsigned int __count)
{
        if (!__count)
                return;

        asm volatile (
                "1: sbiw %0,1" "\n\t"
                "brne 1b"
                : "=w" (__count)
                : "0" (__count)
        );
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]