Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

timers/timers.c

This sample demonstrates the usage of Nut/OS timer functions.

#ifdef __AVR_ATmega128__

/*
 * Temporary fix for broken routines in GCC.
 */
#include <io.h>

#define wdt_reset() __asm__ __volatile__ ("wdr")

#define wdt_enable(timeout)                \
    __asm__ __volatile__ (                 \
        "in __tmp_reg__, __SREG__"  "\n\t" \
        "cli"                       "\n\t" \
        "wdr"                       "\n\t" \
        "out %1, %0"                "\n\t" \
        "out %1, %0"                "\n\t" \
        "out __SREG__, __tmp_reg__" "\n\t" \
        : /* no outputs */                 \
        : "r" (timeout | BV(WDE) | BV(WDCE)), \
          "I" _SFR_IO_ADDR(WDTCR)        \
        : "r0"                             \
)

#define wdt_disable()                      \
    __asm__ __volatile__ (                 \
        "in __tmp_reg__, __SREG__"  "\n\t" \
        "cli"                       "\n\t" \
        "wdr"                       "\n\t" \
        "out %1, %0"                "\n\t" \
        "out %1, __zero_reg__"      "\n\t" \
        "out __SREG__, __tmp_reg__" "\n\t" \
        : /* no outputs */                 \
        : "r" (BV(WDCE) | BV(WDE)),        \
          "I" _SFR_IO_ADDR(WDTCR)        \
        : "r0"                             \
        )
#else
#include <wdt.h>
#endif

#include <dev/uartavr.h>
#include <sys/thread.h>
#include <sys/timer.h>
#include <sys/event.h>
#include <sys/heap.h>

#include <sys/print.h>
#include <sys/osdebug.h>

/*
 * Timer callback routine.
 *
 * This function is called by the system timer thread.
 * It is executed at a very high priority and must 
 * return as soon as possible and must not call any 
 * potentially blocking function.
 *
 * To keep this example as simple as possible, we
 * break the above rule and call NutPrint functions.
 * However, this is not really a problem, because
 * the UART output queue won't overflow on our few
 * characters und NutPrintFlush returns immediately
 * after starting transmit interrupts, which are
 * running in the background.
 */

void TimerCallback(HANDLE timer, void *arg)
{
    NutEventPostAsync(arg);
}

THREAD(TimerEvent1, arg)
{
    NutPrintString(0, " I1");
    NutThreadSetPriority(4);
    for(;;) {
        if(NutEventWait(arg, 12500))
            NutPrintString(0, " T1");
        else
            NutPrintString(0, " E1");
    }
}

THREAD(TimerEvent2, arg)
{
    NutPrintString(0, " I2");
    NutThreadSetPriority(8);
    for(;;) {
        if(NutEventWait(arg, 12500))
            NutPrintString(0, " T2");
        else
            NutPrintString(0, " E2");
    }
}

THREAD(TimerEvent3, arg)
{
    NutPrintString(0, " I3");
    NutThreadSetPriority(16);
    for(;;) {
        if(NutEventWait(arg, 12500))
            NutPrintString(0, " T3");
        else
            NutPrintString(0, " E3");
    }
}

THREAD(TimerEvent4, arg)
{
    NutPrintString(0, " I4");
    NutThreadSetPriority(32);
    for(;;) {
        if(NutEventWait(arg, 12500))
            NutPrintString(0, " T4");
        else
            NutPrintString(0, " E4");
    }
}

THREAD(Sleeper1, arg)
{
    NutThreadSetPriority(128);
    wdt_reset();
    wdt_enable(3);
    for(;;) {
        if(NutHeapAvailable() > 500) {
            wdt_reset();
            NutPrintFormat(0, "\r\n%u free ", NutHeapAvailable());
        }
        else
            NutPrintString_P(0, PSTR("Memory low\r\n"));
        wdt_disable();
        NutSleep(500);
        wdt_enable(7);
    }
}

THREAD(Sleeper2, arg)
{
    NutThreadSetPriority(129);
    for(;;) {
        NutSleep(500);
        NutPrintString(0, " S2");
    }
}

THREAD(Sleeper3, arg)
{
    NutThreadSetPriority(130);
    for(;;) {
        NutSleep(500);
        NutPrintString(0, " S3");
    }
}

THREAD(Sleeper4, arg)
{
    NutThreadSetPriority(131);
    for(;;) {
        NutSleep(500);
        NutPrintString(0, " S4");
    }
}
/*
 * Main application routine. 
 *
 * Nut/OS automatically calls this entry after initialization.
 */
THREAD(NutMain, arg)
{
    int seq;
    u_long baud = 115200;
    u_long sleep_ms = 2000;
    u_long timer_ms = 125;
    u_long cpu_crystal;
    int one_shot;
    HANDLE timer1, timer2, timer3, timer4;
    HANDLE event1 = 0, event2 = 0, event3 = 0, event4 = 0;

#ifdef NUTDEBUG
    NutKHeapTrace(0);
    NutKOsTrace(1);
#endif

    /*
     * Initialize the UART device.
     */
    NutDeviceIOCtl(0, UART_SETSPEED, &baud);
    outp(BV(RXEN) | BV(TXEN), UCR);

    NutKOsTrace(1);
    NutThreadSetPriority(8);

    /*
     * The timer functions automatically determine the
     * CPU speed during system initialization. Query that
     * value and print it on the console.
     */
    cpu_crystal = NutGetCpuClock();
    NutPrintString_P(0, PSTR("\r\n*******************************************************************************\r\n"));
    NutPrintFormat(0, "\r\nTimer sample running on %u.%04u MHz CPU\r\n",
                   (int)(cpu_crystal / 1000000UL),
                   (int)((cpu_crystal - (cpu_crystal / 1000000UL) * 1000000UL) / 100)
                   );

    NutThreadCreate("tmr1", TimerEvent1, &event1, 384);
    NutThreadCreate("tmr2", TimerEvent2, &event2, 384);
    NutThreadCreate("tmr3", TimerEvent3, &event3, 384);
    NutThreadCreate("tmr4", TimerEvent4, &event4, 384);

    NutThreadCreate("slpr1", Sleeper1, 0, 512);
    NutThreadCreate("slpr2", Sleeper2, 0, 512);
    NutThreadCreate("slpr3", Sleeper3, 0, 512);
    NutThreadCreate("slpr4", Sleeper4, 0, 512);

    /*
     * Endless application loop.
     */
    for(seq = 0;; seq++) {

        /*
         * Predefine the one-shot option flag for the
         * timer started below. Each odd sequence starts
         * a one-shot timer, each even sequence a
         * priodical one.
         */
        if(seq & 1)
            one_shot = TM_ONESHOT;
        else
            one_shot = 0;

        /*
         * Start a timer with 1 second timer intervals.
         * This timer will call TimerCallback exactly one
         * time, if it's a one-shot timer or periodically,
         * if not a one-shot timer.
         *
         * We pass a pointer to the sequence counter,
         * which in turn is passed to the callback
         * function.
         */
        //if((timer_ms += 125) > 500)
        //    timer_ms = 0;
        NutPrintFormat(0, "\r\nStart %s t1 ", one_shot ? "oneshot" : "periodic");
        timer1 = NutTimerStart(timer_ms, TimerCallback, &event1, one_shot);

        NutPrintFormat(0, "\r\nStart %s t2 ", one_shot ? "oneshot" : "periodic");
        timer2 = NutTimerStart(timer_ms, TimerCallback, &event2, one_shot);

        NutPrintFormat(0, "\r\nStart %s t3 ", one_shot ? "oneshot" : "periodic");
        timer3 = NutTimerStart(timer_ms, TimerCallback, &event3, one_shot);

        NutPrintFormat(0, "\r\nStart %s t4 ", one_shot ? "oneshot" : "periodic");
        timer4 = NutTimerStart(timer_ms, TimerCallback, &event4, one_shot);

        /*
         * Sleep for a number of seconds.
         */
        if((sleep_ms += 1000) > 30000)
            sleep_ms = 1000;
        NutPrintFormat(0, "\r\nSleeping %u seconds ", (int)(sleep_ms / 1000UL));
        NutSleep(sleep_ms);

        /*
         * Stop periodical timer. One-shot timers
         * are automatically stopped by Nut/OS.
         */
        if(one_shot == 0) {
            NutPrintString(0, "\r\nStop timers ");
            NutTimerStop(timer1);
            NutTimerStop(timer2);
            NutTimerStop(timer3);
            NutTimerStop(timer4);
        }
        //NutPrintFormat(0, "\r\nSleeping %u seconds ", (int)(sleep_ms / 1000UL));
        //NutSleep(sleep_ms);
        NutPrintFormat(0, "\r\n%u bytes free\r\n", NutHeapAvailable());
    }
}

© 2000-2002 by egnite Software GmbH - visit http://www.ethernut.de/