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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [Minimal/] [AltBlckQ.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
 * This is a version of BlockQ.c that uses the alternative (Alt) API.
56
 *
57
 * Creates six tasks that operate on three queues as follows:
58
 *
59
 * The first two tasks send and receive an incrementing number to/from a queue.
60
 * One task acts as a producer and the other as the consumer.  The consumer is a
61
 * higher priority than the producer and is set to block on queue reads.  The queue
62
 * only has space for one item - as soon as the producer posts a message on the
63
 * queue the consumer will unblock, pre-empt the producer, and remove the item.
64
 *
65
 * The second two tasks work the other way around.  Again the queue used only has
66
 * enough space for one item.  This time the consumer has a lower priority than the
67
 * producer.  The producer will try to post on the queue blocking when the queue is
68
 * full.  When the consumer wakes it will remove the item from the queue, causing
69
 * the producer to unblock, pre-empt the consumer, and immediately re-fill the
70
 * queue.
71
 *
72
 * The last two tasks use the same queue producer and consumer functions.  This time the queue has
73
 * enough space for lots of items and the tasks operate at the same priority.  The
74
 * producer will execute, placing items into the queue.  The consumer will start
75
 * executing when either the queue becomes full (causing the producer to block) or
76
 * a context switch occurs (tasks of the same priority will time slice).
77
 *
78
 */
79
 
80
 
81
#include <stdlib.h>
82
 
83
/* Scheduler include files. */
84
#include "FreeRTOS.h"
85
#include "task.h"
86
#include "queue.h"
87
 
88
/* Demo program include files. */
89
#include "AltBlckQ.h"
90
 
91
#define blckqSTACK_SIZE         configMINIMAL_STACK_SIZE
92
#define blckqNUM_TASK_SETS      ( 3 )
93
 
94
/* Structure used to pass parameters to the blocking queue tasks. */
95
typedef struct BLOCKING_QUEUE_PARAMETERS
96
{
97
        xQueueHandle xQueue;                                    /*< The queue to be used by the task. */
98
        portTickType xBlockTime;                                /*< The block time to use on queue reads/writes. */
99
        volatile portSHORT *psCheckVariable;    /*< Incremented on each successful cycle to check the task is still running. */
100
} xBlockingQueueParameters;
101
 
102
/* Task function that creates an incrementing number and posts it on a queue. */
103
static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters );
104
 
105
/* Task function that removes the incrementing number from a queue and checks that
106
it is the expected number. */
107
static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters );
108
 
109
/* Variables which are incremented each time an item is removed from a queue, and
110
found to be the expected value.
111
These are used to check that the tasks are still running. */
112
static volatile portSHORT sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 };
113
 
114
/* Variable which are incremented each time an item is posted on a queue.   These
115
are used to check that the tasks are still running. */
116
static volatile portSHORT sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 };
117
 
118
/*-----------------------------------------------------------*/
119
 
120
void vStartAltBlockingQueueTasks( unsigned portBASE_TYPE uxPriority )
121
{
122
xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2;
123
xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4;
124
xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6;
125
const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5;
126
const portTickType xBlockTime = ( portTickType ) 1000 / portTICK_RATE_MS;
127
const portTickType xDontBlock = ( portTickType ) 0;
128
 
129
        /* Create the first two tasks as described at the top of the file. */
130
 
131
        /* First create the structure used to pass parameters to the consumer tasks. */
132
        pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
133
 
134
        /* Create the queue used by the first two tasks to pass the incrementing number.
135
        Pass a pointer to the queue in the parameter structure. */
136
        pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) );
137
 
138
        /* The consumer is created first so gets a block time as described above. */
139
        pxQueueParameters1->xBlockTime = xBlockTime;
140
 
141
        /* Pass in the variable that this task is going to increment so we can check it
142
        is still running. */
143
        pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );
144
 
145
        /* Create the structure used to pass parameters to the producer task. */
146
        pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
147
 
148
        /* Pass the queue to this task also, using the parameter structure. */
149
        pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
150
 
151
        /* The producer is not going to block - as soon as it posts the consumer will
152
        wake and remove the item so the producer should always have room to post. */
153
        pxQueueParameters2->xBlockTime = xDontBlock;
154
 
155
        /* Pass in the variable that this task is going to increment so we can check
156
        it is still running. */
157
        pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );
158
 
159
 
160
        /* Note the producer has a lower priority than the consumer when the tasks are
161
        spawned. */
162
        xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );
163
        xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );
164
 
165
 
166
 
167
        /* Create the second two tasks as described at the top of the file.   This uses
168
        the same mechanism but reverses the task priorities. */
169
 
170
        pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
171
        pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) );
172
        pxQueueParameters3->xBlockTime = xDontBlock;
173
        pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] );
174
 
175
        pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
176
        pxQueueParameters4->xQueue = pxQueueParameters3->xQueue;
177
        pxQueueParameters4->xBlockTime = xBlockTime;
178
        pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] );
179
 
180
        xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL );
181
        xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL );
182
 
183
 
184
 
185
        /* Create the last two tasks as described above.  The mechanism is again just
186
        the same.  This time both parameter structures are given a block time. */
187
        pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
188
        pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) );
189
        pxQueueParameters5->xBlockTime = xBlockTime;
190
        pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] );
191
 
192
        pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
193
        pxQueueParameters6->xQueue = pxQueueParameters5->xQueue;
194
        pxQueueParameters6->xBlockTime = xBlockTime;
195
        pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] );
196
 
197
        xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL );
198
        xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL );
199
}
200
/*-----------------------------------------------------------*/
201
 
202
static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters )
203
{
204
unsigned portSHORT usValue = 0;
205
xBlockingQueueParameters *pxQueueParameters;
206
portSHORT sErrorEverOccurred = pdFALSE;
207
 
208
        #ifdef USE_STDIO
209
        void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
210
 
211
                const portCHAR * const pcTaskStartMsg = "Alt blocking queue producer task started.\r\n";
212
 
213
                /* Queue a message for printing to say the task has started. */
214
                vPrintDisplayMessage( &pcTaskStartMsg );
215
        #endif
216
 
217
        pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
218
 
219
        for( ;; )
220
        {
221
                if( xQueueAltSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS )
222
                {
223
                        sErrorEverOccurred = pdTRUE;
224
                }
225
                else
226
                {
227
                        /* We have successfully posted a message, so increment the variable
228
                        used to check we are still running. */
229
                        if( sErrorEverOccurred == pdFALSE )
230
                        {
231
                                ( *pxQueueParameters->psCheckVariable )++;
232
                        }
233
 
234
                        /* Increment the variable we are going to post next time round.  The
235
                        consumer will expect the numbers to     follow in numerical order. */
236
                        ++usValue;
237
                }
238
        }
239
}
240
/*-----------------------------------------------------------*/
241
 
242
static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters )
243
{
244
unsigned portSHORT usData, usExpectedValue = 0;
245
xBlockingQueueParameters *pxQueueParameters;
246
portSHORT sErrorEverOccurred = pdFALSE;
247
 
248
        #ifdef USE_STDIO
249
        void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
250
 
251
                const portCHAR * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n";
252
 
253
                /* Queue a message for printing to say the task has started. */
254
                vPrintDisplayMessage( &pcTaskStartMsg );
255
        #endif
256
 
257
        pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
258
 
259
        for( ;; )
260
        {
261
                if( xQueueAltReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS )
262
                {
263
                        if( usData != usExpectedValue )
264
                        {
265
                                /* Catch-up. */
266
                                usExpectedValue = usData;
267
 
268
                                sErrorEverOccurred = pdTRUE;
269
                        }
270
                        else
271
                        {
272
                                /* We have successfully received a message, so increment the
273
                                variable used to check we are still running. */
274
                                if( sErrorEverOccurred == pdFALSE )
275
                                {
276
                                        ( *pxQueueParameters->psCheckVariable )++;
277
                                }
278
 
279
                                /* Increment the value we expect to remove from the queue next time
280
                                round. */
281
                                ++usExpectedValue;
282
                        }
283
                }
284
        }
285
}
286
/*-----------------------------------------------------------*/
287
 
288
/* This is called to check that all the created tasks are still running. */
289
portBASE_TYPE xAreAltBlockingQueuesStillRunning( void )
290
{
291
static portSHORT sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 };
292
static portSHORT sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 };
293
portBASE_TYPE xReturn = pdPASS, xTasks;
294
 
295
        /* Not too worried about mutual exclusion on these variables as they are 16
296
        bits and we are only reading them. We also only care to see if they have
297
        changed or not.
298
 
299
        Loop through each check variable to and return pdFALSE if any are found not
300
        to have changed since the last call. */
301
 
302
        for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )
303
        {
304
                if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ]  )
305
                {
306
                        xReturn = pdFALSE;
307
                }
308
                sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
309
 
310
 
311
                if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ]  )
312
                {
313
                        xReturn = pdFALSE;
314
                }
315
                sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
316
        }
317
 
318
        return xReturn;
319
}
320
 

powered by: WebSVN 2.1.0

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