OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [PC/] [main.c] - Blame information for rev 586

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 586 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
/**
55
 * Creates all the demo application tasks and co-routines, then starts the
56
 * scheduler.
57
 *
58
 * Main. c also creates a task called "Print".  This only executes every
59
 * five seconds but has the highest priority so is guaranteed to get
60
 * processor time.  Its main function is to check that all the other tasks
61
 * are still operational.  Nearly all the tasks in the demo application
62
 * maintain a unique count that is incremented each time the task successfully
63
 * completes its function.  Should any error occur within the task the count is
64
 * permanently halted.  The print task checks the count of each task to ensure
65
 * it has changed since the last time the print task executed.  If any count is
66
 * found not to have changed the print task displays an appropriate message.
67
 * If all the tasks are still incrementing their unique counts the print task
68
 * displays an "OK" message.
69
 *
70
 * The LED flash tasks do not maintain a count as they already provide visual
71
 * feedback of their status.
72
 *
73
 * The print task blocks on the queue into which messages that require
74
 * displaying are posted.  It will therefore only block for the full 5 seconds
75
 * if no messages are posted onto the queue.
76
 *
77
 * Main. c also provides a demonstration of how the trace visualisation utility
78
 * can be used, and how the scheduler can be stopped.
79
 *
80
 * \page MainC main.c
81
 * \ingroup DemoFiles
82
 * <HR>
83
 */
84
 
85
#include <stdlib.h>
86
#include <conio.h>
87
#include "FreeRTOS.h"
88
#include "task.h"
89
#include "croutine.h"
90
#include "partest.h"
91
#include "serial.h"
92
 
93
/* Demo file headers. */
94
#include "BlockQ.h"
95
#include "PollQ.h"
96
#include "death.h"
97
#include "crflash.h"
98
#include "flop.h"
99
#include "print.h"
100
#include "comtest.h"
101
#include "fileio.h"
102
#include "semtest.h"
103
#include "integer.h"
104
#include "dynamic.h"
105
#include "mevents.h"
106
#include "crhook.h"
107
#include "blocktim.h"
108
#include "AltBlock.h"
109
#include "GenQTest.h"
110
#include "QPeek.h"
111
#include "countsem.h"
112
#include "AltQTest.h"
113
#include "AltPollQ.h"
114
#include "AltBlckQ.h"
115
#include "RecMutex.h"
116
 
117
/* Priority definitions for the tasks in the demo application. */
118
#define mainLED_TASK_PRIORITY           ( tskIDLE_PRIORITY + 1 )
119
#define mainCREATOR_TASK_PRIORITY       ( tskIDLE_PRIORITY + 3 )
120
#define mainPRINT_TASK_PRIORITY         ( tskIDLE_PRIORITY + 4 )
121
#define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )
122
#define mainQUEUE_BLOCK_PRIORITY        ( tskIDLE_PRIORITY + 3 )
123
#define mainCOM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 2 )
124
#define mainSEMAPHORE_TASK_PRIORITY     ( tskIDLE_PRIORITY + 1 )
125
#define mainGENERIC_QUEUE_PRIORITY      ( tskIDLE_PRIORITY )
126
 
127
#define mainPRINT_STACK_SIZE            ( ( unsigned short ) 512 )
128
#define mainDEBUG_LOG_BUFFER_SIZE       ( ( unsigned short ) 20480 )
129
 
130
/* The number of flash co-routines to create. */
131
#define mainNUM_FLASH_CO_ROUTINES       ( 8 )
132
 
133
/* Task function for the "Print" task as described at the top of the file. */
134
static void vErrorChecks( void *pvParameters );
135
 
136
/* Function that checks the unique count of all the other tasks as described at
137
the top of the file. */
138
static void prvCheckOtherTasksAreStillRunning( void );
139
 
140
/* Key presses can be used to start/stop the trace visualisation utility or stop
141
the scheduler. */
142
static void     prvCheckForKeyPresses( void );
143
 
144
/* Buffer used by the trace visualisation utility so only needed if the trace
145
being used. */
146
#if configUSE_TRACE_FACILITY == 1
147
        static char pcWriteBuffer[ mainDEBUG_LOG_BUFFER_SIZE ];
148
#endif
149
 
150
/* Constant definition used to turn on/off the pre-emptive scheduler. */
151
static const short sUsingPreemption = configUSE_PREEMPTION;
152
 
153
/* Start the math tasks appropriate to the build.  The Borland port does
154
not yet support floating point so uses the integer equivalent. */
155
static void prvStartMathTasks( void );
156
 
157
/* Check which ever tasks are relevant to this build. */
158
static portBASE_TYPE prvCheckMathTasksAreStillRunning( void );
159
 
160
/* Used to demonstrate the "task switched in" callback function. */
161
static portBASE_TYPE prvExampleTaskHook( void * pvParameter );
162
 
163
/* Just used to count the number of times the example task callback function is
164
called, and the number of times a queue send passes. */
165
static unsigned long long uxCheckTaskHookCallCount = 0;
166
static unsigned long long uxQueueSendPassedCount = 0;
167
 
168
/*-----------------------------------------------------------*/
169
 
170
short main( void )
171
{
172
        /* Initialise hardware and utilities. */
173
        vParTestInitialise();
174
        vPrintInitialise();
175
 
176
        /* CREATE ALL THE DEMO APPLICATION TASKS. */
177
        prvStartMathTasks();
178
        vStartComTestTasks( mainCOM_TEST_PRIORITY, serCOM1, ser115200 );
179
        vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
180
        vStartBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY );
181
        vCreateBlockTimeTasks();
182
        vStartGenericQueueTasks( mainGENERIC_QUEUE_PRIORITY );
183
        vStartSemaphoreTasks( mainSEMAPHORE_TASK_PRIORITY );
184
        vStartDynamicPriorityTasks();
185
        vStartMultiEventTasks();
186
        vStartQueuePeekTasks();
187
        vStartCountingSemaphoreTasks();
188
        vStartAltGenericQueueTasks( mainGENERIC_QUEUE_PRIORITY );
189
        vCreateAltBlockTimeTasks();
190
        vStartAltBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY );
191
        vStartAltPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
192
        vStartRecursiveMutexTasks();
193
 
194
        /* Create the "Print" task as described at the top of the file. */
195
        xTaskCreate( vErrorChecks, "Print", mainPRINT_STACK_SIZE, NULL, mainPRINT_TASK_PRIORITY, NULL );
196
 
197
        /* This task has to be created last as it keeps account of the number of tasks
198
        it expects to see running. */
199
        vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
200
 
201
        /* Create the co-routines that flash the LED's. */
202
        vStartFlashCoRoutines( mainNUM_FLASH_CO_ROUTINES );
203
 
204
        /* Create the co-routines that communicate with the tick hook. */
205
        vStartHookCoRoutines();
206
 
207
        /* Set the scheduler running.  This function will not return unless a task
208
        calls vTaskEndScheduler(). */
209
        vTaskStartScheduler();
210
 
211
        return 1;
212
}
213
/*-----------------------------------------------------------*/
214
 
215
static portBASE_TYPE prvExampleTaskHook( void * pvParameter )
216
{
217
        if( pvParameter != ( void * ) 0xabcd )
218
        {
219
                /* The parameter did not contain the value we expected, so cause an
220
                error to be detected by setting the call count back to zero. */
221
                uxCheckTaskHookCallCount = 0;
222
        }
223
        else
224
        {
225
                /* Simply increment a number so we know the callback has been executed. */
226
                uxCheckTaskHookCallCount++;
227
        }
228
 
229
        return 0;
230
}
231
/*-----------------------------------------------------------*/
232
 
233
void vMainQueueSendPassed( void )
234
{
235
        /* This is just an example implementation of the "queue send" trace hook. */
236
        uxQueueSendPassedCount++;
237
}
238
/*-----------------------------------------------------------*/
239
 
240
static void vErrorChecks( void *pvParameters )
241
{
242
portTickType xExpectedWakeTime;
243
const portTickType xPrintRate = ( portTickType ) 5000 / portTICK_RATE_MS;
244
const long lMaxAllowableTimeDifference = ( long ) 0;
245
portTickType xWakeTime;
246
long lTimeDifference;
247
const char *pcReceivedMessage;
248
const char * const pcTaskBlockedTooLongMsg = "Print task blocked too long!\r\n";
249
const char * const pcUnexpectedHookValueMsg = "Task hook has unexpected value!\r\n";
250
 
251
        ( void ) pvParameters;
252
 
253
        /* Register our callback function. */
254
        vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook );
255
 
256
        /* Just for test purposes. */
257
        if( xTaskGetApplicationTaskTag( NULL ) != prvExampleTaskHook )
258
        {
259
                vPrintDisplayMessage( &pcUnexpectedHookValueMsg );
260
        }
261
 
262
        /* Loop continuously, blocking, then checking all the other tasks are still
263
        running, before blocking once again.  This task blocks on the queue of
264
        messages that require displaying so will wake either by its time out expiring,
265
        or a message becoming available. */
266
        for( ;; )
267
        {
268
                /* Calculate the time we will unblock if no messages are received
269
                on the queue.  This is used to check that we have not blocked for too long. */
270
                xExpectedWakeTime = xTaskGetTickCount();
271
                xExpectedWakeTime += xPrintRate;
272
 
273
                /* Block waiting for either a time out or a message to be posted that
274
                required displaying. */
275
                pcReceivedMessage = pcPrintGetNextMessage( xPrintRate );
276
 
277
                /* Was a message received? */
278
                if( pcReceivedMessage == NULL )
279
                {
280
                        /* A message was not received so we timed out, did we unblock at the
281
                        expected time? */
282
                        xWakeTime = xTaskGetTickCount();
283
 
284
                        /* Calculate the difference between the time we unblocked and the
285
                        time we should have unblocked. */
286
                        if( xWakeTime > xExpectedWakeTime )
287
                        {
288
                                lTimeDifference = ( long ) ( xWakeTime - xExpectedWakeTime );
289
                        }
290
                        else
291
                        {
292
                                lTimeDifference = ( long ) ( xExpectedWakeTime - xWakeTime );
293
                        }
294
 
295
                        if( lTimeDifference > lMaxAllowableTimeDifference )
296
                        {
297
                                /* We blocked too long - create a message that will get
298
                                printed out the next time around.  If we are not using
299
                                preemption then we won't expect the timing to be so
300
                                accurate. */
301
                                if( sUsingPreemption == pdTRUE )
302
                                {
303
                                        vPrintDisplayMessage( &pcTaskBlockedTooLongMsg );
304
                                }
305
                        }
306
 
307
                        /* Check the other tasks are still running, just in case. */
308
                        prvCheckOtherTasksAreStillRunning();
309
                }
310
                else
311
                {
312
                        /* We unblocked due to a message becoming available.  Send the message
313
                        for printing. */
314
                        vDisplayMessage( pcReceivedMessage );
315
                }
316
 
317
                /* Key presses are used to invoke the trace visualisation utility, or end
318
                the program. */
319
                prvCheckForKeyPresses();
320
        }
321
}
322
/*-----------------------------------------------------------*/
323
 
324
static void     prvCheckForKeyPresses( void )
325
{
326
short sIn;
327
 
328
        taskENTER_CRITICAL();
329
                #ifdef DEBUG_BUILD
330
                        /* kbhit can be used in .exe's that are executed from the command
331
                        line, but not if executed through the debugger. */
332
                        sIn = 0;
333
                #else
334
                        sIn = kbhit();
335
                #endif
336
        taskEXIT_CRITICAL();
337
 
338
        if( sIn )
339
        {
340
                /* Key presses can be used to start/stop the trace utility, or end the
341
                program. */
342
                sIn = getch();
343
                switch( sIn )
344
                {
345
                        /* Only define keys for turning on and off the trace if the trace
346
                        is being used. */
347
                        #if configUSE_TRACE_FACILITY == 1
348
                                case 't' :      vTaskList( pcWriteBuffer );
349
                                                        vWriteMessageToDisk( pcWriteBuffer );
350
                                                        break;
351
                                case 's' :      vTaskStartTrace( pcWriteBuffer, mainDEBUG_LOG_BUFFER_SIZE );
352
                                                        break;
353
 
354
                                case 'e' :      {
355
                                                                unsigned long ulBufferLength;
356
                                                                ulBufferLength = ulTaskEndTrace();
357
                                                                vWriteBufferToDisk( pcWriteBuffer, ulBufferLength );
358
                                                        }
359
                                                        break;
360
                        #endif
361
 
362
                        default  :      vTaskEndScheduler();
363
                                                break;
364
                }
365
        }
366
}
367
/*-----------------------------------------------------------*/
368
 
369
static void prvCheckOtherTasksAreStillRunning( void )
370
{
371
static short sErrorHasOccurred = pdFALSE;
372
static unsigned long long uxLastHookCallCount = 0, uxLastQueueSendCount = 0;
373
 
374
        if( prvCheckMathTasksAreStillRunning() != pdTRUE )
375
        {
376
                vDisplayMessage( "Maths task count unchanged!\r\n" );
377
                sErrorHasOccurred = pdTRUE;
378
        }
379
 
380
        if( xAreComTestTasksStillRunning() != pdTRUE )
381
        {
382
                vDisplayMessage( "Com test count unchanged!\r\n" );
383
                sErrorHasOccurred = pdTRUE;
384
        }
385
 
386
        if( xAreBlockingQueuesStillRunning() != pdTRUE )
387
        {
388
                vDisplayMessage( "Blocking queues count unchanged!\r\n" );
389
                sErrorHasOccurred = pdTRUE;
390
        }
391
 
392
        if( xAreAltBlockingQueuesStillRunning() != pdTRUE )
393
        {
394
                vDisplayMessage( "Alt blocking queues count unchanged!\r\n" );
395
                sErrorHasOccurred = pdTRUE;
396
        }
397
 
398
        if( xArePollingQueuesStillRunning() != pdTRUE )
399
        {
400
                vDisplayMessage( "Polling queue count unchanged!\r\n" );
401
                sErrorHasOccurred = pdTRUE;
402
        }
403
 
404
        if( xAreAltPollingQueuesStillRunning() != pdTRUE )
405
        {
406
                vDisplayMessage( "Alt polling queue count unchanged!\r\n" );
407
                sErrorHasOccurred = pdTRUE;
408
        }
409
 
410
        if( xIsCreateTaskStillRunning() != pdTRUE )
411
        {
412
                vDisplayMessage( "Incorrect number of tasks running!\r\n" );
413
                sErrorHasOccurred = pdTRUE;
414
        }
415
 
416
        if( xAreSemaphoreTasksStillRunning() != pdTRUE )
417
        {
418
                vDisplayMessage( "Semaphore take count unchanged!\r\n" );
419
                sErrorHasOccurred = pdTRUE;
420
        }
421
 
422
        if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
423
        {
424
                vDisplayMessage( "Dynamic priority count unchanged!\r\n" );
425
                sErrorHasOccurred = pdTRUE;
426
        }
427
 
428
        if( xAreMultiEventTasksStillRunning() != pdTRUE )
429
        {
430
                vDisplayMessage( "Error in multi events tasks!\r\n" );
431
                sErrorHasOccurred = pdTRUE;
432
        }
433
 
434
        if( xAreFlashCoRoutinesStillRunning() != pdTRUE )
435
        {
436
                vDisplayMessage( "Error in co-routine flash tasks!\r\n" );
437
                sErrorHasOccurred = pdTRUE;
438
        }
439
 
440
        if( xAreHookCoRoutinesStillRunning() != pdTRUE )
441
        {
442
                vDisplayMessage( "Error in tick hook to co-routine communications!\r\n" );
443
                sErrorHasOccurred = pdTRUE;
444
        }
445
 
446
        if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
447
        {
448
                vDisplayMessage( "Error in block time test tasks!\r\n" );
449
                sErrorHasOccurred = pdTRUE;
450
        }
451
 
452
        if( xAreAltBlockTimeTestTasksStillRunning() != pdTRUE )
453
        {
454
                vDisplayMessage( "Error in fast block time test tasks!\r\n" );
455
                sErrorHasOccurred = pdTRUE;
456
        }
457
 
458
        if( xAreGenericQueueTasksStillRunning() != pdTRUE )
459
        {
460
                vDisplayMessage( "Error in generic queue test task!\r\n" );
461
                sErrorHasOccurred = pdTRUE;
462
        }
463
 
464
        if( xAreAltGenericQueueTasksStillRunning() != pdTRUE )
465
        {
466
                vDisplayMessage( "Error in fast generic queue test task!\r\n" );
467
                sErrorHasOccurred = pdTRUE;
468
        }
469
 
470
        if( xAreQueuePeekTasksStillRunning() != pdTRUE )
471
        {
472
                vDisplayMessage( "Error in queue peek test task!\r\n" );
473
                sErrorHasOccurred = pdTRUE;
474
        }
475
 
476
        if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
477
        {
478
                vDisplayMessage( "Error in counting semaphore demo task!\r\n" );
479
                sErrorHasOccurred = pdTRUE;
480
        }
481
 
482
        if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
483
        {
484
                vDisplayMessage( "Error in recursive mutex tasks!\r\n" );
485
                sErrorHasOccurred = pdTRUE;
486
        }
487
 
488
        /* The hook function associated with this task is called each time the task
489
        is switched in.  We therefore expect the number of times the callback
490
        function has been executed to have increrment since the last time this
491
        function executed. */
492
        if( uxCheckTaskHookCallCount <= uxLastHookCallCount )
493
        {
494
                vDisplayMessage( "Error in task hook call count!\r\n" );
495
                sErrorHasOccurred = pdTRUE;
496
        }
497
        else
498
        {
499
                uxLastHookCallCount = uxCheckTaskHookCallCount;
500
        }
501
 
502
        /* We would expect some queue sending to occur between calls of this
503
        function. */
504
        if( uxQueueSendPassedCount <= uxLastQueueSendCount )
505
        {
506
                vDisplayMessage( "Error in queue send hook call count!\r\n" );
507
                sErrorHasOccurred = pdTRUE;
508
        }
509
        else
510
        {
511
                uxLastQueueSendCount = uxQueueSendPassedCount;
512
        }
513
 
514
        if( sErrorHasOccurred == pdFALSE )
515
        {
516
                vDisplayMessage( "OK " );
517
        }
518
}
519
/*-----------------------------------------------------------*/
520
 
521
static void prvStartMathTasks( void )
522
{
523
        #ifdef BCC_INDUSTRIAL_PC_PORT
524
                /* The Borland project does not yet support floating point. */
525
                vStartIntegerMathTasks( tskIDLE_PRIORITY );
526
        #else
527
                vStartMathTasks( tskIDLE_PRIORITY );
528
        #endif
529
}
530
/*-----------------------------------------------------------*/
531
 
532
static portBASE_TYPE prvCheckMathTasksAreStillRunning( void )
533
{
534
        #ifdef BCC_INDUSTRIAL_PC_PORT
535
                /* The Borland project does not yet support floating point. */
536
                return xAreIntegerMathsTaskStillRunning();
537
        #else
538
                return xAreMathsTaskStillRunning();
539
        #endif
540
}
541
/*-----------------------------------------------------------*/
542
 
543
void vApplicationIdleHook( void )
544
{
545
        /* The co-routines are executed in the idle task using the idle task
546
        hook. */
547
        vCoRoutineSchedule();
548
}
549
/*-----------------------------------------------------------*/
550
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.