This sample demonstrates the usage of Nut/OS timer functions.
#ifdef __AVR_ATmega128__ /* * Temporary fix for broken routines in GCC. */ #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()); } }