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/
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 }