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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [Minimal/] [dynamic.c] - Blame information for rev 615

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 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
 * The first test creates three tasks - two counter tasks (one continuous count
56
 * and one limited count) and one controller.  A "count" variable is shared
57
 * between all three tasks.  The two counter tasks should never be in a "ready"
58
 * state at the same time.  The controller task runs at the same priority as
59
 * the continuous count task, and at a lower priority than the limited count
60
 * task.
61
 *
62
 * One counter task loops indefinitely, incrementing the shared count variable
63
 * on each iteration.  To ensure it has exclusive access to the variable it
64
 * raises it's priority above that of the controller task before each
65
 * increment, lowering it again to it's original priority before starting the
66
 * next iteration.
67
 *
68
 * The other counter task increments the shared count variable on each
69
 * iteration of it's loop until the count has reached a limit of 0xff - at
70
 * which point it suspends itself.  It will not start a new loop until the
71
 * controller task has made it "ready" again by calling vTaskResume ().
72
 * This second counter task operates at a higher priority than controller
73
 * task so does not need to worry about mutual exclusion of the counter
74
 * variable.
75
 *
76
 * The controller task is in two sections.  The first section controls and
77
 * monitors the continuous count task.  When this section is operational the
78
 * limited count task is suspended.  Likewise, the second section controls
79
 * and monitors the limited count task.  When this section is operational the
80
 * continuous count task is suspended.
81
 *
82
 * In the first section the controller task first takes a copy of the shared
83
 * count variable.  To ensure mutual exclusion on the count variable it
84
 * suspends the continuous count task, resuming it again when the copy has been
85
 * taken.  The controller task then sleeps for a fixed period - during which
86
 * the continuous count task will execute and increment the shared variable.
87
 * When the controller task wakes it checks that the continuous count task
88
 * has executed by comparing the copy of the shared variable with its current
89
 * value.  This time, to ensure mutual exclusion, the scheduler itself is
90
 * suspended with a call to vTaskSuspendAll ().  This is for demonstration
91
 * purposes only and is not a recommended technique due to its inefficiency.
92
 *
93
 * After a fixed number of iterations the controller task suspends the
94
 * continuous count task, and moves on to its second section.
95
 *
96
 * At the start of the second section the shared variable is cleared to zero.
97
 * The limited count task is then woken from it's suspension by a call to
98
 * vTaskResume ().  As this counter task operates at a higher priority than
99
 * the controller task the controller task should not run again until the
100
 * shared variable has been counted up to the limited value causing the counter
101
 * task to suspend itself.  The next line after vTaskResume () is therefore
102
 * a check on the shared variable to ensure everything is as expected.
103
 *
104
 *
105
 * The second test consists of a couple of very simple tasks that post onto a
106
 * queue while the scheduler is suspended.  This test was added to test parts
107
 * of the scheduler not exercised by the first test.
108
 *
109
 */
110
 
111
#include <stdlib.h>
112
 
113
/* Scheduler include files. */
114
#include "FreeRTOS.h"
115
#include "task.h"
116
#include "semphr.h"
117
 
118
/* Demo app include files. */
119
#include "dynamic.h"
120
 
121
/* Function that implements the "limited count" task as described above. */
122
static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters );
123
 
124
/* Function that implements the "continuous count" task as described above. */
125
static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters );
126
 
127
/* Function that implements the controller task as described above. */
128
static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters );
129
 
130
static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters );
131
static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters );
132
 
133
/* Demo task specific constants. */
134
#define priSTACK_SIZE                           ( configMINIMAL_STACK_SIZE )
135
#define priSLEEP_TIME                           ( ( portTickType ) 128 / portTICK_RATE_MS )
136
#define priLOOPS                                        ( 5 )
137
#define priMAX_COUNT                            ( ( unsigned long ) 0xff )
138
#define priNO_BLOCK                                     ( ( portTickType ) 0 )
139
#define priSUSPENDED_QUEUE_LENGTH       ( 1 )
140
 
141
/*-----------------------------------------------------------*/
142
 
143
/* Handles to the two counter tasks.  These could be passed in as parameters
144
to the controller task to prevent them having to be file scope. */
145
static xTaskHandle xContinousIncrementHandle, xLimitedIncrementHandle;
146
 
147
/* The shared counter variable.  This is passed in as a parameter to the two
148
counter variables for demonstration purposes. */
149
static unsigned long ulCounter;
150
 
151
/* Variables used to check that the tasks are still operating without error.
152
Each complete iteration of the controller task increments this variable
153
provided no errors have been found.  The variable maintaining the same value
154
is therefore indication of an error. */
155
static volatile unsigned short usCheckVariable = ( unsigned short ) 0;
156
static volatile portBASE_TYPE xSuspendedQueueSendError = pdFALSE;
157
static volatile portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE;
158
 
159
/* Queue used by the second test. */
160
xQueueHandle xSuspendedTestQueue;
161
 
162
/*-----------------------------------------------------------*/
163
/*
164
 * Start the three tasks as described at the top of the file.
165
 * Note that the limited count task is given a higher priority.
166
 */
167
void vStartDynamicPriorityTasks( void )
168
{
169
        xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned long ) );
170
 
171
        /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
172
        in use.  The queue registry is provided as a means for kernel aware
173
        debuggers to locate queues and has no purpose if a kernel aware debugger
174
        is not being used.  The call to vQueueAddToRegistry() will be removed
175
        by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
176
        defined to be less than 1. */
177
        vQueueAddToRegistry( xSuspendedTestQueue, ( signed char * ) "Suspended_Test_Queue" );
178
 
179
        xTaskCreate( vContinuousIncrementTask, ( signed char * ) "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinousIncrementHandle );
180
        xTaskCreate( vLimitedIncrementTask, ( signed char * ) "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle );
181
        xTaskCreate( vCounterControlTask, ( signed char * ) "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
182
        xTaskCreate( vQueueSendWhenSuspendedTask, ( signed char * ) "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
183
        xTaskCreate( vQueueReceiveWhenSuspendedTask, ( signed char * ) "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
184
}
185
/*-----------------------------------------------------------*/
186
 
187
/*
188
 * Just loops around incrementing the shared variable until the limit has been
189
 * reached.  Once the limit has been reached it suspends itself.
190
 */
191
static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters )
192
{
193
unsigned long *pulCounter;
194
 
195
        /* Take a pointer to the shared variable from the parameters passed into
196
        the task. */
197
        pulCounter = ( unsigned long * ) pvParameters;
198
 
199
        /* This will run before the control task, so the first thing it does is
200
        suspend - the control task will resume it when ready. */
201
        vTaskSuspend( NULL );
202
 
203
        for( ;; )
204
        {
205
                /* Just count up to a value then suspend. */
206
                ( *pulCounter )++;
207
 
208
                if( *pulCounter >= priMAX_COUNT )
209
                {
210
                        vTaskSuspend( NULL );
211
                }
212
        }
213
}
214
/*-----------------------------------------------------------*/
215
 
216
/*
217
 * Just keep counting the shared variable up.  The control task will suspend
218
 * this task when it wants.
219
 */
220
static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters )
221
{
222
unsigned long *pulCounter;
223
unsigned portBASE_TYPE uxOurPriority;
224
 
225
        /* Take a pointer to the shared variable from the parameters passed into
226
        the task. */
227
        pulCounter = ( unsigned long * ) pvParameters;
228
 
229
        /* Query our priority so we can raise it when exclusive access to the
230
        shared variable is required. */
231
        uxOurPriority = uxTaskPriorityGet( NULL );
232
 
233
        for( ;; )
234
        {
235
                /* Raise our priority above the controller task to ensure a context
236
                switch does not occur while we are accessing this variable. */
237
                vTaskPrioritySet( NULL, uxOurPriority + 1 );
238
                        ( *pulCounter )++;
239
                vTaskPrioritySet( NULL, uxOurPriority );
240
        }
241
}
242
/*-----------------------------------------------------------*/
243
 
244
/*
245
 * Controller task as described above.
246
 */
247
static portTASK_FUNCTION( vCounterControlTask, pvParameters )
248
{
249
unsigned long ulLastCounter;
250
short sLoops;
251
short sError = pdFALSE;
252
 
253
        /* Just to stop warning messages. */
254
        ( void ) pvParameters;
255
 
256
        for( ;; )
257
        {
258
                /* Start with the counter at zero. */
259
                ulCounter = ( unsigned long ) 0;
260
 
261
                /* First section : */
262
 
263
                /* Check the continuous count task is running. */
264
                for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
265
                {
266
                        /* Suspend the continuous count task so we can take a mirror of the
267
                        shared variable without risk of corruption. */
268
                        vTaskSuspend( xContinousIncrementHandle );
269
                                ulLastCounter = ulCounter;
270
                        vTaskResume( xContinousIncrementHandle );
271
 
272
                        /* Now delay to ensure the other task has processor time. */
273
                        vTaskDelay( priSLEEP_TIME );
274
 
275
                        /* Check the shared variable again.  This time to ensure mutual
276
                        exclusion the whole scheduler will be locked.  This is just for
277
                        demo purposes! */
278
                        vTaskSuspendAll();
279
                        {
280
                                if( ulLastCounter == ulCounter )
281
                                {
282
                                        /* The shared variable has not changed.  There is a problem
283
                                        with the continuous count task so flag an error. */
284
                                        sError = pdTRUE;
285
                                }
286
                        }
287
                        xTaskResumeAll();
288
                }
289
 
290
 
291
                /* Second section: */
292
 
293
                /* Suspend the continuous counter task so it stops accessing the shared variable. */
294
                vTaskSuspend( xContinousIncrementHandle );
295
 
296
                /* Reset the variable. */
297
                ulCounter = ( unsigned long ) 0;
298
 
299
                /* Resume the limited count task which has a higher priority than us.
300
                We should therefore not return from this call until the limited count
301
                task has suspended itself with a known value in the counter variable. */
302
                vTaskResume( xLimitedIncrementHandle );
303
 
304
                /* Does the counter variable have the expected value? */
305
                if( ulCounter != priMAX_COUNT )
306
                {
307
                        sError = pdTRUE;
308
                }
309
 
310
                if( sError == pdFALSE )
311
                {
312
                        /* If no errors have occurred then increment the check variable. */
313
                        portENTER_CRITICAL();
314
                                usCheckVariable++;
315
                        portEXIT_CRITICAL();
316
                }
317
 
318
                /* Resume the continuous count task and do it all again. */
319
                vTaskResume( xContinousIncrementHandle );
320
        }
321
}
322
/*-----------------------------------------------------------*/
323
 
324
static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters )
325
{
326
static unsigned long ulValueToSend = ( unsigned long ) 0;
327
 
328
        /* Just to stop warning messages. */
329
        ( void ) pvParameters;
330
 
331
        for( ;; )
332
        {
333
                vTaskSuspendAll();
334
                {
335
                        /* We must not block while the scheduler is suspended! */
336
                        if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE )
337
                        {
338
                                xSuspendedQueueSendError = pdTRUE;
339
                        }
340
                }
341
                xTaskResumeAll();
342
 
343
                vTaskDelay( priSLEEP_TIME );
344
 
345
                ++ulValueToSend;
346
        }
347
}
348
/*-----------------------------------------------------------*/
349
 
350
static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters )
351
{
352
static unsigned long ulExpectedValue = ( unsigned long ) 0, ulReceivedValue;
353
portBASE_TYPE xGotValue;
354
 
355
        /* Just to stop warning messages. */
356
        ( void ) pvParameters;
357
 
358
        for( ;; )
359
        {
360
                do
361
                {
362
                        /* Suspending the scheduler here is fairly pointless and
363
                        undesirable for a normal application.  It is done here purely
364
                        to test the scheduler.  The inner xTaskResumeAll() should
365
                        never return pdTRUE as the scheduler is still locked by the
366
                        outer call. */
367
                        vTaskSuspendAll();
368
                        {
369
                                vTaskSuspendAll();
370
                                {
371
                                        xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
372
                                }
373
                                if( xTaskResumeAll() )
374
                                {
375
                                        xSuspendedQueueReceiveError = pdTRUE;
376
                                }
377
                        }
378
                        xTaskResumeAll();
379
 
380
                        #if configUSE_PREEMPTION == 0
381
                        {
382
                                taskYIELD();
383
                        }
384
                        #endif
385
 
386
                } while( xGotValue == pdFALSE );
387
 
388
                if( ulReceivedValue != ulExpectedValue )
389
                {
390
                        xSuspendedQueueReceiveError = pdTRUE;
391
                }
392
 
393
                ++ulExpectedValue;
394
        }
395
}
396
/*-----------------------------------------------------------*/
397
 
398
/* Called to check that all the created tasks are still running without error. */
399
portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )
400
{
401
/* Keep a history of the check variables so we know if it has been incremented
402
since the last call. */
403
static unsigned short usLastTaskCheck = ( unsigned short ) 0;
404
portBASE_TYPE xReturn = pdTRUE;
405
 
406
        /* Check the tasks are still running by ensuring the check variable
407
        is still incrementing. */
408
 
409
        if( usCheckVariable == usLastTaskCheck )
410
        {
411
                /* The check has not incremented so an error exists. */
412
                xReturn = pdFALSE;
413
        }
414
 
415
        if( xSuspendedQueueSendError == pdTRUE )
416
        {
417
                xReturn = pdFALSE;
418
        }
419
 
420
        if( xSuspendedQueueReceiveError == pdTRUE )
421
        {
422
                xReturn = pdFALSE;
423
        }
424
 
425
        usLastTaskCheck = usCheckVariable;
426
        return xReturn;
427
}

powered by: WebSVN 2.1.0

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