timers/timers.c

Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

For additional information see http://www.ethernut.de/

$Log$ Revision 1.6 2008/01/31 09:38:15 haraldkipp Added return statement in main to avoid warnings with latest GCC.

Revision 1.5 2005/11/22 09:17:31 haraldkipp Replaced specific device names by generalized macros. Thread stack size increased to get it running on ARM CPUs.

Revision 1.4 2005/04/19 08:57:52 haraldkipp Description updated and ARM support added

Revision 1.3 2005/04/05 18:00:29 haraldkipp Make it work on the Gameboy Advance.

Revision 1.2 2004/09/08 10:18:23 haraldkipp For EB40A

Revision 1.1 2003/08/05 18:59:05 haraldkipp Release 3.3 update

Revision 1.14 2003/02/04 18:19:40 harald Version 3 released

Revision 1.13 2003/02/04 16:24:37 harald Adapted to version 3

Revision 1.12 2002/11/02 15:13:18 harald Library dependencies removed

Revision 1.11 2002/10/31 16:27:40 harald Mods by troth for Linux

Revision 1.10 2002/07/03 16:33:21 harald Broken watchdog patch

Revision 1.9 2002/06/26 17:29:07 harald First pre-release with 2.4 stack

Revision 1.8 2002/06/12 10:59:23 harald *** empty log message ***

Revision 1.7 2002/06/04 18:48:50 harald Problems with ATmega128 watchdog

Revision 1.6 2002/05/11 21:01:47 harald Adding more stress to test timer functions

Revision 1.5 2002/05/09 21:49:57 harald Using new default UART. Bufgix: Event queues must be set 0.

Revision 1.4 2002/05/08 16:02:34 harald First Imagecraft compilation

Revision 1.3 2002/05/02 18:48:03 harald *** empty log message ***

Revision 1.2 2002/01/28 19:49:28 harald Testing new timer layout

Revision 1.1 2001/06/28 18:43:13 harald Preview release

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

In addition it demonstrates how to enable system debug output. You need the debug version of the Nut/OS libraries. To create them, you must enable the RTOS Kernel - OS Debug option in the Configurator. Then use the Build Menu in the Configurator to generate the build tree again and build Nut/OS.

Note, that the debug version consumes much more memory than the original version. If in doubt, check the map file.

00001 
00113 #include <cfg/os.h>
00114 #ifdef NUTDEBUG
00115 #include <sys/osdebug.h>
00116 #endif
00117 
00118 #include <stdio.h>
00119 #include <io.h>
00120 
00121 #include <cfg/arch.h>
00122 #include <dev/board.h>
00123 
00124 #include <sys/thread.h>
00125 #include <sys/timer.h>
00126 #include <sys/event.h>
00127 #include <sys/heap.h>
00128 
00129 /*
00130  * Timer callback routine.
00131  *
00132  * This function is called by the system timer thread. It is executed 
00133  * at a very high priority and must return as soon as possible and must 
00134  * not call any potentially blocking function.
00135  *
00136  * To keep this example as simple as possible, we break the above rule 
00137  * and call print functions. However, this is not really a problem, 
00138  * because the UART output queue won't overflow on our few characters 
00139  * and return immediately after starting transmit interrupts, which are
00140  * running in the background.
00141  */
00142 
00143 void TimerCallback(HANDLE timer, void *arg)
00144 {
00145     NutEventPostAsync(arg);
00146 }
00147 
00148 THREAD(TimerEvent1, arg)
00149 {
00150     printf(" I1");
00151     NutThreadSetPriority(4);
00152     for (;;) {
00153         if (NutEventWait(arg, 12500))
00154             printf(" T1");
00155         else
00156             printf(" E1");
00157     }
00158 }
00159 
00160 THREAD(TimerEvent2, arg)
00161 {
00162     printf(" I2");
00163     NutThreadSetPriority(8);
00164     for (;;) {
00165         if (NutEventWait(arg, 12500))
00166             printf(" T2");
00167         else
00168             printf(" E2");
00169     }
00170 }
00171 
00172 THREAD(TimerEvent3, arg)
00173 {
00174     printf(" I3");
00175     NutThreadSetPriority(16);
00176     for (;;) {
00177         if (NutEventWait(arg, 12500))
00178             printf(" T3");
00179         else
00180             printf(" E3");
00181     }
00182 }
00183 
00184 THREAD(TimerEvent4, arg)
00185 {
00186     printf(" I4");
00187     NutThreadSetPriority(32);
00188     for (;;) {
00189         if (NutEventWait(arg, 12500))
00190             printf(" T4");
00191         else
00192             printf(" E4");
00193     }
00194 }
00195 
00196 THREAD(Sleeper1, arg)
00197 {
00198     NutThreadSetPriority(128);
00199     for (;;) {
00200         if (NutHeapAvailable() > 500)
00201             printf("\n%u free ", (u_int)NutHeapAvailable());
00202         else
00203             puts("Memory low");
00204         NutSleep(500);
00205     }
00206 }
00207 
00208 THREAD(Sleeper2, arg)
00209 {
00210     NutThreadSetPriority(129);
00211     for (;;) {
00212         NutSleep(500);
00213         printf(" S2");
00214     }
00215 }
00216 
00217 THREAD(Sleeper3, arg)
00218 {
00219     NutThreadSetPriority(130);
00220     for (;;) {
00221         NutSleep(500);
00222         printf(" S3");
00223     }
00224 }
00225 
00226 THREAD(Sleeper4, arg)
00227 {
00228     NutThreadSetPriority(131);
00229     for (;;) {
00230         NutSleep(500);
00231         printf(" S4");
00232     }
00233 }
00234 
00235 /*
00236  * Main application routine. 
00237  *
00238  */
00239 int main(void)
00240 {
00241     int seq;
00242     u_long baud = 115200;
00243     u_long sleep_ms = 2000;
00244     u_long timer_ms = 125;
00245     u_long cpu_crystal;
00246     int one_shot;
00247     HANDLE timer1, timer2, timer3, timer4;
00248     HANDLE event1 = 0, event2 = 0, event3 = 0, event4 = 0;
00249 
00250     /*
00251      * Register the UART device, open it, assign stdout to it and set 
00252      * the baudrate.
00253      */
00254     NutRegisterDevice(&DEV_DEBUG, 0, 0);
00255     freopen(DEV_DEBUG_NAME, "w", stdout);
00256     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00257 
00258 #ifdef NUTDEBUG
00259     NutTraceHeap(stdout, 1);
00260     NutTraceOs(stdout, 1);
00261 #endif
00262 
00263     NutThreadSetPriority(8);
00264 
00265     /*
00266      * The timer functions automatically determine the
00267      * CPU speed during system initialization. Query that
00268      * value and print it on the console.
00269      */
00270     cpu_crystal = NutGetCpuClock();
00271     puts("\n*******************************************************************************");
00272     printf("Timer sample running on %u.%04u MHz CPU\n",
00273            (int) (cpu_crystal / 1000000UL), (int) ((cpu_crystal - (cpu_crystal / 1000000UL) * 1000000UL) / 100)
00274         );
00275 
00276     NutThreadCreate("tmr1", TimerEvent1, &event1, 512);
00277     NutThreadCreate("tmr2", TimerEvent2, &event2, 512);
00278     NutThreadCreate("tmr3", TimerEvent3, &event3, 512);
00279     NutThreadCreate("tmr4", TimerEvent4, &event4, 512);
00280 
00281     NutThreadCreate("slpr1", Sleeper1, 0, 512);
00282     NutThreadCreate("slpr2", Sleeper2, 0, 512);
00283     NutThreadCreate("slpr3", Sleeper3, 0, 512);
00284     NutThreadCreate("slpr4", Sleeper4, 0, 512);
00285 
00286     /*
00287      * Endless application loop.
00288      */
00289     for (seq = 0;; seq++) {
00290 
00291         /*
00292          * Predefine the one-shot option flag for the
00293          * timer started below. Each odd sequence starts
00294          * a one-shot timer, each even sequence a
00295          * priodical one.
00296          */
00297         if (seq & 1)
00298             one_shot = TM_ONESHOT;
00299         else
00300             one_shot = 0;
00301 
00302         /*
00303          * Start a timer with 1 second timer intervals.
00304          * This timer will call TimerCallback exactly one
00305          * time, if it's a one-shot timer or periodically,
00306          * if not a one-shot timer.
00307          *
00308          * We pass a pointer to the sequence counter,
00309          * which in turn is passed to the callback
00310          * function.
00311          */
00312         //if((timer_ms += 125) > 500)
00313         //    timer_ms = 0;
00314         printf("\nStart %s t1 ", one_shot ? "oneshot" : "periodic");
00315         timer1 = NutTimerStart(timer_ms, TimerCallback, &event1, one_shot);
00316 
00317         printf("\nStart %s t2 ", one_shot ? "oneshot" : "periodic");
00318         timer2 = NutTimerStart(timer_ms, TimerCallback, &event2, one_shot);
00319 
00320         printf("\nStart %s t3 ", one_shot ? "oneshot" : "periodic");
00321         timer3 = NutTimerStart(timer_ms, TimerCallback, &event3, one_shot);
00322 
00323         printf("\nStart %s t4 ", one_shot ? "oneshot" : "periodic");
00324         timer4 = NutTimerStart(timer_ms, TimerCallback, &event4, one_shot);
00325 
00326         /*
00327          * Sleep for a number of seconds.
00328          */
00329         if ((sleep_ms += 1000) > 30000)
00330             sleep_ms = 1000;
00331         printf("\nSleeping %u seconds ", (int) (sleep_ms / 1000UL));
00332         NutSleep(sleep_ms);
00333 
00334         /*
00335          * Stop periodical timer. One-shot timers
00336          * are automatically stopped by Nut/OS.
00337          */
00338         if (one_shot == 0) {
00339             printf("\nStop timers ");
00340             NutTimerStop(timer1);
00341             NutTimerStop(timer2);
00342             NutTimerStop(timer3);
00343             NutTimerStop(timer4);
00344         }
00345         //printf("\nSleeping %u seconds ", (int)(sleep_ms / 1000UL));
00346         //NutSleep(sleep_ms);
00347         printf("\n%u bytes free\n", (u_int)NutHeapAvailable());
00348     }
00349     return 0;
00350 }

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