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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [Full/] [events.c] - Blame information for rev 609

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
 * This file exercises the event mechanism whereby more than one task is
56
 * blocked waiting for the same event.
57
 *
58
 * The demo creates five tasks - four 'event' tasks, and a controlling task.
59
 * The event tasks have various different priorities and all block on reading
60
 * the same queue.  The controlling task writes data to the queue, then checks
61
 * to see which of the event tasks read the data from the queue.  The
62
 * controlling task has the lowest priority of all the tasks so is guaranteed
63
 * to always get preempted immediately upon writing to the queue.
64
 *
65
 * By selectively suspending and resuming the event tasks the controlling task
66
 * can check that the highest priority task that is blocked on the queue is the
67
 * task that reads the posted data from the queue.
68
 *
69
 * Two of the event tasks share the same priority.  When neither of these tasks
70
 * are suspended they should alternate - one reading one message from the queue,
71
 * the other the next message, etc.
72
 */
73
 
74
/* Standard includes. */
75
#include <stdlib.h>
76
#include <stdio.h>
77
#include <string.h>
78
 
79
/* Scheduler include files. */
80
#include "FreeRTOS.h"
81
#include "task.h"
82
#include "queue.h"
83
 
84
/* Demo program include files. */
85
#include "mevents.h"
86
#include "print.h"
87
 
88
/* Demo specific constants. */
89
#define evtSTACK_SIZE           ( ( unsigned portBASE_TYPE ) configMINIMAL_STACK_SIZE )
90
#define evtNUM_TASKS            ( 4 )
91
#define evtQUEUE_LENGTH         ( ( unsigned portBASE_TYPE ) 3 )
92
#define evtNO_DELAY                                             0
93
 
94
/* Just indexes used to uniquely identify the tasks.  Note that two tasks are
95
'highest' priority. */
96
#define evtHIGHEST_PRIORITY_INDEX_2             3
97
#define evtHIGHEST_PRIORITY_INDEX_1             2
98
#define evtMEDIUM_PRIORITY_INDEX                1
99
#define evtLOWEST_PRIORITY_INDEX                0
100
 
101
/* Each event task increments one of these counters each time it reads data
102
from the queue. */
103
static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
104
 
105
/* Each time the controlling task posts onto the queue it increments the
106
expected count of the task that it expected to read the data from the queue
107
(i.e. the task with the highest priority that should be blocked on the queue).
108
 
109
xExpectedTaskCounters are incremented from the controlling task, and
110
xTaskCounters are incremented from the individual event tasks - therefore
111
comparing xTaskCounters to xExpectedTaskCounters shows whether or not the
112
correct task was unblocked by the post. */
113
static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
114
 
115
/* Handles to the four event tasks.  These are required to suspend and resume
116
the tasks. */
117
static xTaskHandle xCreatedTasks[ evtNUM_TASKS ];
118
 
119
/* The single queue onto which the controlling task posts, and the four event
120
tasks block. */
121
static xQueueHandle xQueue;
122
 
123
/* Flag used to indicate whether or not an error has occurred at any time.
124
An error is either the queue being full when not expected, or an unexpected
125
task reading data from the queue. */
126
static portBASE_TYPE xHealthStatus = pdPASS;
127
 
128
/*-----------------------------------------------------------*/
129
 
130
/* Function that implements the event task.  This is created four times. */
131
static void prvMultiEventTask( void *pvParameters );
132
 
133
/* Function that implements the controlling task. */
134
static void prvEventControllerTask( void *pvParameters );
135
 
136
/* This is a utility function that posts data to the queue, then compares
137
xExpectedTaskCounters with xTaskCounters to ensure everything worked as
138
expected.
139
 
140
The event tasks all have higher priorities the controlling task.  Therefore
141
the controlling task will always get preempted between writhing to the queue
142
and checking the task counters.
143
 
144
@param xExpectedTask  The index to the task that the controlling task thinks
145
                      should be the highest priority task waiting for data, and
146
                                          therefore the task that will unblock.
147
 
148
@param  xIncrement    The number of items that should be written to the queue.
149
*/
150
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement );
151
 
152
/* This is just incremented each cycle of the controlling tasks function so
153
the main application can ensure the test is still running. */
154
static portBASE_TYPE xCheckVariable = 0;
155
 
156
/*-----------------------------------------------------------*/
157
 
158
void vStartMultiEventTasks( void )
159
{
160
        /* Create the queue to be used for all the communications. */
161
        xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
162
 
163
        /* Start the controlling task.  This has the idle priority to ensure it is
164
        always preempted by the event tasks. */
165
        xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
166
 
167
        /* Start the four event tasks.  Note that two have priority 3, one
168
        priority 2 and the other priority 1. */
169
        xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) );
170
        xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) );
171
        xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) );
172
        xTaskCreate( prvMultiEventTask, "Event3", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 3 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ) );
173
}
174
/*-----------------------------------------------------------*/
175
 
176
static void prvMultiEventTask( void *pvParameters )
177
{
178
portBASE_TYPE *pxCounter;
179
unsigned portBASE_TYPE uxDummy;
180
const char * const pcTaskStartMsg = "Multi event task started.\r\n";
181
 
182
        /* The variable this task will increment is passed in as a parameter. */
183
        pxCounter = ( portBASE_TYPE * ) pvParameters;
184
 
185
        vPrintDisplayMessage( &pcTaskStartMsg );
186
 
187
        for( ;; )
188
        {
189
                /* Block on the queue. */
190
                if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) )
191
                {
192
                        /* We unblocked by reading the queue - so simply increment
193
                        the counter specific to this task instance. */
194
                        ( *pxCounter )++;
195
                }
196
                else
197
                {
198
                        xHealthStatus = pdFAIL;
199
                }
200
        }
201
}
202
/*-----------------------------------------------------------*/
203
 
204
static void prvEventControllerTask( void *pvParameters )
205
{
206
const char * const pcTaskStartMsg = "Multi event controller task started.\r\n";
207
portBASE_TYPE xDummy = 0;
208
 
209
        /* Just to stop warnings. */
210
        ( void ) pvParameters;
211
 
212
        vPrintDisplayMessage( &pcTaskStartMsg );
213
 
214
        for( ;; )
215
        {
216
                /* All tasks are blocked on the queue.  When a message is posted one of
217
                the two tasks that share the highest priority should unblock to read
218
                the queue.  The next message written should unblock the other task with
219
                the same high priority, and so on in order.   No other task should
220
                unblock to read data as they have lower priorities. */
221
 
222
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
223
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 );
224
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
225
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 );
226
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
227
 
228
                /* For the rest of these tests we don't need the second 'highest'
229
                priority task - so it is suspended. */
230
                vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
231
 
232
 
233
 
234
                /* Now suspend the other highest priority task.  The medium priority
235
                task will then be the task with the highest priority that remains
236
                blocked on the queue. */
237
                vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
238
 
239
                /* This time, when we post onto the queue we will expect the medium
240
                priority task to unblock and preempt us. */
241
                prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 );
242
 
243
                /* Now try resuming the highest priority task while the scheduler is
244
                suspended.  The task should start executing as soon as the scheduler
245
                is resumed - therefore when we post to the queue again, the highest
246
                priority task should again preempt us. */
247
                vTaskSuspendAll();
248
                        vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
249
                xTaskResumeAll();
250
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
251
 
252
                /* Now we are going to suspend the high and medium priority tasks.  The
253
                low priority task should then preempt us.  Again the task suspension is
254
                done with the whole scheduler suspended just for test purposes. */
255
                vTaskSuspendAll();
256
                        vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
257
                        vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
258
                xTaskResumeAll();
259
                prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 );
260
 
261
                /* Do the same basic test another few times - selectively suspending
262
                and resuming tasks and each time calling prvCheckTaskCounters() passing
263
                to the function the number of the task we expected to be unblocked by
264
                the     post. */
265
 
266
                vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
267
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
268
 
269
                vTaskSuspendAll(); /* Just for test. */
270
                        vTaskSuspendAll(); /* Just for test. */
271
                                vTaskSuspendAll(); /* Just for even more test. */
272
                                        vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
273
                                xTaskResumeAll();
274
                        xTaskResumeAll();
275
                xTaskResumeAll();
276
                prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 );
277
 
278
                vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
279
                prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 );
280
 
281
                vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
282
                prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
283
 
284
                /* Now a slight change, first suspend all tasks. */
285
                vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
286
                vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
287
                vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
288
 
289
                /* Now when we resume the low priority task and write to the queue 3
290
                times.  We expect the low priority task to service the queue three
291
                times. */
292
                vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
293
                prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH );
294
 
295
                /* Again suspend all tasks (only the low priority task is not suspended
296
                already). */
297
                vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
298
 
299
                /* This time we are going to suspend the scheduler, resume the low
300
                priority task, then resume the high priority task.  In this state we
301
                will write to the queue three times.  When the scheduler is resumed
302
                we expect the high priority task to service all three messages. */
303
                vTaskSuspendAll();
304
                {
305
                        vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
306
                        vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
307
 
308
                        for( xDummy = 0; xDummy < evtQUEUE_LENGTH; xDummy++ )
309
                        {
310
                                if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE )
311
                                {
312
                                        xHealthStatus = pdFAIL;
313
                                }
314
                        }
315
 
316
                        /* The queue should not have been serviced yet!.  The scheduler
317
                        is still suspended. */
318
                        if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
319
                        {
320
                                xHealthStatus = pdFAIL;
321
                        }
322
                }
323
                xTaskResumeAll();
324
 
325
                /* We should have been preempted by resuming the scheduler - so by the
326
                time we are running again we expect the high priority task to have
327
                removed three items from the queue. */
328
                xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH;
329
                if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
330
                {
331
                        xHealthStatus = pdFAIL;
332
                }
333
 
334
                /* The medium priority and second high priority tasks are still
335
                suspended.  Make sure to resume them before starting again. */
336
                vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
337
                vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
338
 
339
                /* Just keep incrementing to show the task is still executing. */
340
                xCheckVariable++;
341
        }
342
}
343
/*-----------------------------------------------------------*/
344
 
345
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement )
346
{
347
portBASE_TYPE xDummy = 0;
348
 
349
        /* Write to the queue the requested number of times.  The data written is
350
        not important. */
351
        for( xDummy = 0; xDummy < xIncrement; xDummy++ )
352
        {
353
                if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE )
354
                {
355
                        /* Did not expect to ever find the queue full. */
356
                        xHealthStatus = pdFAIL;
357
                }
358
        }
359
 
360
        /* All the tasks blocked on the queue have a priority higher than the
361
        controlling task.  Writing to the queue will therefore have caused this
362
        task to be preempted.  By the time this line executes the event task will
363
        have executed and incremented its counter.  Increment the expected counter
364
        to the same value. */
365
        ( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement;
366
 
367
        /* Check the actual counts and expected counts really are the same. */
368
        if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
369
        {
370
                /* The counters were not the same.  This means a task we did not expect
371
                to unblock actually did unblock. */
372
                xHealthStatus = pdFAIL;
373
        }
374
}
375
/*-----------------------------------------------------------*/
376
 
377
portBASE_TYPE xAreMultiEventTasksStillRunning( void )
378
{
379
static portBASE_TYPE xPreviousCheckVariable = 0;
380
 
381
        /* Called externally to periodically check that this test is still
382
        operational. */
383
 
384
        if( xPreviousCheckVariable == xCheckVariable )
385
        {
386
                xHealthStatus = pdFAIL;
387
        }
388
 
389
        xPreviousCheckVariable = xCheckVariable;
390
 
391
        return xHealthStatus;
392
}
393
 
394
 

powered by: WebSVN 2.1.0

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