1
|
/*
|
2
|
FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
|
3
|
|
4
|
This file is part of the FreeRTOS.org distribution.
|
5
|
|
6
|
FreeRTOS.org is free software; you can redistribute it and/or modify
|
7
|
it under the terms of the GNU General Public License as published by
|
8
|
the Free Software Foundation; either version 2 of the License, or
|
9
|
(at your option) any later version.
|
10
|
|
11
|
FreeRTOS.org is distributed in the hope that it will be useful,
|
12
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
GNU General Public License for more details.
|
15
|
|
16
|
You should have received a copy of the GNU General Public License
|
17
|
along with FreeRTOS.org; if not, write to the Free Software
|
18
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
|
20
|
A special exception to the GPL can be applied should you wish to distribute
|
21
|
a combined work that includes FreeRTOS.org, without being obliged to provide
|
22
|
the source code for any proprietary components. See the licensing section
|
23
|
of http://www.FreeRTOS.org for full details of how and when the exception
|
24
|
can be applied.
|
25
|
|
26
|
***************************************************************************
|
27
|
See http://www.FreeRTOS.org for documentation, latest information, license
|
28
|
and contact details. Please ensure to read the configuration and relevant
|
29
|
port sections of the online documentation.
|
30
|
|
31
|
Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
|
32
|
with commercial development and support options.
|
33
|
***************************************************************************
|
34
|
*/
|
35
|
|
36
|
#ifndef QUEUE_H
|
37
|
#define QUEUE_H
|
38
|
|
39
|
typedef void *xQueueHandle;
|
40
|
|
41
|
/**
|
42
|
* queue. h
|
43
|
* <pre>
|
44
|
xQueueHandle xQueueCreate(
|
45
|
unsigned portBASE_TYPE uxQueueLength,
|
46
|
unsigned portBASE_TYPE uxItemSize
|
47
|
);
|
48
|
* </pre>
|
49
|
*
|
50
|
* Creates a new queue instance. This allocates the storage required by the
|
51
|
* new queue and returns a handle for the queue.
|
52
|
*
|
53
|
* @param uxQueueLength The maximum number of items that the queue can contain.
|
54
|
*
|
55
|
* @param uxItemSize The number of bytes each item in the queue will require.
|
56
|
* Items are queued by copy, not by reference, so this is the number of bytes
|
57
|
* that will be copied for each posted item. Each item on the queue must be
|
58
|
* the same size.
|
59
|
*
|
60
|
* @return If the queue is successfully create then a handle to the newly
|
61
|
* created queue is returned. If the queue cannot be created then 0 is
|
62
|
* returned.
|
63
|
*
|
64
|
* Example usage:
|
65
|
<pre>
|
66
|
struct AMessage
|
67
|
{
|
68
|
portCHAR ucMessageID;
|
69
|
portCHAR ucData[ 20 ];
|
70
|
};
|
71
|
|
72
|
void vATask( void *pvParameters )
|
73
|
{
|
74
|
xQueueHandle xQueue1, xQueue2;
|
75
|
|
76
|
// Create a queue capable of containing 10 unsigned long values.
|
77
|
xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
|
78
|
if( xQueue1 == 0 )
|
79
|
{
|
80
|
// Queue was not created and must not be used.
|
81
|
}
|
82
|
|
83
|
// Create a queue capable of containing 10 pointers to AMessage structures.
|
84
|
// These should be passed by pointer as they contain a lot of data.
|
85
|
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
|
86
|
if( xQueue2 == 0 )
|
87
|
{
|
88
|
// Queue was not created and must not be used.
|
89
|
}
|
90
|
|
91
|
// ... Rest of task code.
|
92
|
}
|
93
|
</pre>
|
94
|
* \defgroup xQueueCreate xQueueCreate
|
95
|
* \ingroup QueueManagement
|
96
|
*/
|
97
|
xQueueHandle xQueueCreate (unsigned portBASE_TYPE uxQueueLength,
|
98
|
unsigned portBASE_TYPE uxItemSize);
|
99
|
|
100
|
/**
|
101
|
* queue. h
|
102
|
* <pre>
|
103
|
portBASE_TYPE xQueueSend(
|
104
|
xQueueHandle xQueue,
|
105
|
const void * pvItemToQueue,
|
106
|
portTickType xTicksToWait
|
107
|
);
|
108
|
* </pre>
|
109
|
*
|
110
|
* Post an item on a queue. The item is queued by copy, not by reference.
|
111
|
* This function must not be called from an interrupt service routine.
|
112
|
* See xQueueSendFromISR () for an alternative which may be used in an ISR.
|
113
|
*
|
114
|
* @param xQueue The handle to the queue on which the item is to be posted.
|
115
|
*
|
116
|
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
117
|
* queue. The size of the items the queue will hold was defined when the
|
118
|
* queue was created, so this many bytes will be copied from pvItemToQueue
|
119
|
* into the queue storage area.
|
120
|
*
|
121
|
* @param xTicksToWait The maximum amount of time the task should block
|
122
|
* waiting for space to become available on the queue, should it already
|
123
|
* be full. The call will return immediately if this is set to 0. The
|
124
|
* time is defined in tick periods so the constant portTICK_RATE_MS
|
125
|
* should be used to convert to real time if this is required.
|
126
|
*
|
127
|
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
|
128
|
*
|
129
|
* Example usage:
|
130
|
<pre>
|
131
|
struct AMessage
|
132
|
{
|
133
|
portCHAR ucMessageID;
|
134
|
portCHAR ucData[ 20 ];
|
135
|
} xMessage;
|
136
|
|
137
|
unsigned portLONG ulVar = 10UL;
|
138
|
|
139
|
void vATask( void *pvParameters )
|
140
|
{
|
141
|
xQueueHandle xQueue1, xQueue2;
|
142
|
struct AMessage *pxMessage;
|
143
|
|
144
|
// Create a queue capable of containing 10 unsigned long values.
|
145
|
xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
|
146
|
|
147
|
// Create a queue capable of containing 10 pointers to AMessage structures.
|
148
|
// These should be passed by pointer as they contain a lot of data.
|
149
|
xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
|
150
|
|
151
|
// ...
|
152
|
|
153
|
if( xQueue1 != 0 )
|
154
|
{
|
155
|
// Send an unsigned long. Wait for 10 ticks for space to become
|
156
|
// available if necessary.
|
157
|
if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
|
158
|
{
|
159
|
// Failed to post the message, even after 10 ticks.
|
160
|
}
|
161
|
}
|
162
|
|
163
|
if( xQueue2 != 0 )
|
164
|
{
|
165
|
// Send a pointer to a struct AMessage object. Don't block if the
|
166
|
// queue is already full.
|
167
|
pxMessage = & xMessage;
|
168
|
xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
|
169
|
}
|
170
|
|
171
|
// ... Rest of task code.
|
172
|
}
|
173
|
</pre>
|
174
|
* \defgroup xQueueSend xQueueSend
|
175
|
* \ingroup QueueManagement
|
176
|
*/
|
177
|
signed portBASE_TYPE xQueueSend (xQueueHandle xQueue,
|
178
|
const void *pvItemToQueue,
|
179
|
portTickType xTicksToWait);
|
180
|
|
181
|
/**
|
182
|
* queue. h
|
183
|
* <pre>
|
184
|
portBASE_TYPE xQueueReceive(
|
185
|
xQueueHandle xQueue,
|
186
|
void *pvBuffer,
|
187
|
portTickType xTicksToWait
|
188
|
);</pre>
|
189
|
*
|
190
|
* Receive an item from a queue. The item is received by copy so a buffer of
|
191
|
* adequate size must be provided. The number of bytes copied into the buffer
|
192
|
* was defined when the queue was created.
|
193
|
*
|
194
|
* This function must not be used in an interrupt service routine. See
|
195
|
* xQueueReceiveFromISR for an alternative that can.
|
196
|
*
|
197
|
* @param pxQueue The handle to the queue from which the item is to be
|
198
|
* received.
|
199
|
*
|
200
|
* @param pvBuffer Pointer to the buffer into which the received item will
|
201
|
* be copied.
|
202
|
*
|
203
|
* @param xTicksToWait The maximum amount of time the task should block
|
204
|
* waiting for an item to receive should the queue be empty at the time
|
205
|
* of the call. The time is defined in tick periods so the constant
|
206
|
* portTICK_RATE_MS should be used to convert to real time if this is required.
|
207
|
*
|
208
|
* @return pdTRUE if an item was successfully received from the queue,
|
209
|
* otherwise pdFALSE.
|
210
|
*
|
211
|
* Example usage:
|
212
|
<pre>
|
213
|
struct AMessage
|
214
|
{
|
215
|
portCHAR ucMessageID;
|
216
|
portCHAR ucData[ 20 ];
|
217
|
} xMessage;
|
218
|
|
219
|
xQueueHandle xQueue;
|
220
|
|
221
|
// Task to create a queue and post a value.
|
222
|
void vATask( void *pvParameters )
|
223
|
{
|
224
|
struct AMessage *pxMessage;
|
225
|
|
226
|
// Create a queue capable of containing 10 pointers to AMessage structures.
|
227
|
// These should be passed by pointer as they contain a lot of data.
|
228
|
xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
|
229
|
if( xQueue == 0 )
|
230
|
{
|
231
|
// Failed to create the queue.
|
232
|
}
|
233
|
|
234
|
// ...
|
235
|
|
236
|
// Send a pointer to a struct AMessage object. Don't block if the
|
237
|
// queue is already full.
|
238
|
pxMessage = & xMessage;
|
239
|
xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
|
240
|
|
241
|
// ... Rest of task code.
|
242
|
}
|
243
|
|
244
|
// Task to receive from the queue.
|
245
|
void vADifferentTask( void *pvParameters )
|
246
|
{
|
247
|
struct AMessage *pxRxedMessage;
|
248
|
|
249
|
if( xQueue != 0 )
|
250
|
{
|
251
|
// Receive a message on the created queue. Block for 10 ticks if a
|
252
|
// message is not immediately available.
|
253
|
if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
|
254
|
{
|
255
|
// pcRxedMessage now points to the struct AMessage variable posted
|
256
|
// by vATask.
|
257
|
}
|
258
|
}
|
259
|
|
260
|
// ... Rest of task code.
|
261
|
}
|
262
|
</pre>
|
263
|
* \defgroup xQueueReceive xQueueReceive
|
264
|
* \ingroup QueueManagement
|
265
|
*/
|
266
|
signed portBASE_TYPE xQueueReceive (xQueueHandle xQueue, void *pvBuffer,
|
267
|
portTickType xTicksToWait);
|
268
|
|
269
|
/**
|
270
|
* queue. h
|
271
|
* <pre>unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle xQueue );</pre>
|
272
|
*
|
273
|
* Return the number of messages stored in a queue.
|
274
|
*
|
275
|
* @param xQueue A handle to the queue being queried.
|
276
|
*
|
277
|
* @return The number of messages available in the queue.
|
278
|
*
|
279
|
* \page uxQueueMessagesWaiting uxQueueMessagesWaiting
|
280
|
* \ingroup QueueManagement
|
281
|
*/
|
282
|
unsigned portBASE_TYPE uxQueueMessagesWaiting (xQueueHandle xQueue);
|
283
|
|
284
|
/**
|
285
|
* queue. h
|
286
|
* <pre>void vQueueDelete( xQueueHandle xQueue );</pre>
|
287
|
*
|
288
|
* Delete a queue - freeing all the memory allocated for storing of items
|
289
|
* placed on the queue.
|
290
|
*
|
291
|
* @param xQueue A handle to the queue to be deleted.
|
292
|
*
|
293
|
* \page vQueueDelete vQueueDelete
|
294
|
* \ingroup QueueManagement
|
295
|
*/
|
296
|
void vQueueDelete (xQueueHandle xQueue);
|
297
|
|
298
|
/**
|
299
|
* queue. h
|
300
|
* <pre>
|
301
|
portBASE_TYPE xQueueSendFromISR(
|
302
|
xQueueHandle pxQueue,
|
303
|
const void *pvItemToQueue,
|
304
|
portBASE_TYPE xTaskPreviouslyWoken
|
305
|
);
|
306
|
</pre>
|
307
|
*
|
308
|
* Post an item on a queue. It is safe to use this function from within an
|
309
|
* interrupt service routine.
|
310
|
*
|
311
|
* Items are queued by copy not reference so it is preferable to only
|
312
|
* queue small items, especially when called from an ISR. In most cases
|
313
|
* it would be preferable to store a pointer to the item being queued.
|
314
|
*
|
315
|
* @param xQueue The handle to the queue on which the item is to be posted.
|
316
|
*
|
317
|
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
318
|
* queue. The size of the items the queue will hold was defined when the
|
319
|
* queue was created, so this many bytes will be copied from pvItemToQueue
|
320
|
* into the queue storage area.
|
321
|
*
|
322
|
* @param cTaskPreviouslyWoken This is included so an ISR can post onto
|
323
|
* the same queue multiple times from a single interrupt. The first call
|
324
|
* should always pass in pdFALSE. Subsequent calls should pass in
|
325
|
* the value returned from the previous call. See the file serial .c in the
|
326
|
* PC port for a good example of this mechanism.
|
327
|
*
|
328
|
* @return pdTRUE if a task was woken by posting onto the queue. This is
|
329
|
* used by the ISR to determine if a context switch may be required following
|
330
|
* the ISR.
|
331
|
*
|
332
|
* Example usage for buffered IO (where the ISR can obtain more than one value
|
333
|
* per call):
|
334
|
<pre>
|
335
|
void vBufferISR( void )
|
336
|
{
|
337
|
portCHAR cIn;
|
338
|
portBASE_TYPE xTaskWokenByPost;
|
339
|
|
340
|
// We have not woken a task at the start of the ISR.
|
341
|
cTaskWokenByPost = pdFALSE;
|
342
|
|
343
|
// Loop until the buffer is empty.
|
344
|
do
|
345
|
{
|
346
|
// Obtain a byte from the buffer.
|
347
|
cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
|
348
|
|
349
|
// Post the byte. The first time round the loop cTaskWokenByPost
|
350
|
// will be pdFALSE. If the queue send causes a task to wake we do
|
351
|
// not want the task to run until we have finished the ISR, so
|
352
|
// xQueueSendFromISR does not cause a context switch. Also we
|
353
|
// don't want subsequent posts to wake any other tasks, so we store
|
354
|
// the return value back into cTaskWokenByPost so xQueueSendFromISR
|
355
|
// knows not to wake any task the next iteration of the loop.
|
356
|
xTaskWokenByPost = xQueueSendFromISR( xRxQueue, &cIn, cTaskWokenByPost );
|
357
|
|
358
|
} while( portINPUT_BYTE( BUFFER_COUNT ) );
|
359
|
|
360
|
// Now the buffer is empty we can switch context if necessary.
|
361
|
if( cTaskWokenByPost )
|
362
|
{
|
363
|
taskYIELD ();
|
364
|
}
|
365
|
}
|
366
|
</pre>
|
367
|
*
|
368
|
* \defgroup xQueueSendFromISR xQueueSendFromISR
|
369
|
* \ingroup QueueManagement
|
370
|
*/
|
371
|
signed portBASE_TYPE xQueueSendFromISR (xQueueHandle pxQueue,
|
372
|
const void *pvItemToQueue,
|
373
|
signed portBASE_TYPE
|
374
|
xTaskPreviouslyWoken);
|
375
|
|
376
|
/**
|
377
|
* queue. h
|
378
|
* <pre>
|
379
|
portBASE_TYPE xQueueReceiveFromISR(
|
380
|
xQueueHandle pxQueue,
|
381
|
void *pvBuffer,
|
382
|
portBASE_TYPE *pxTaskWoken
|
383
|
);
|
384
|
* </pre>
|
385
|
*
|
386
|
* Receive an item from a queue. It is safe to use this function from within an
|
387
|
* interrupt service routine.
|
388
|
*
|
389
|
* @param pxQueue The handle to the queue from which the item is to be
|
390
|
* received.
|
391
|
*
|
392
|
* @param pvBuffer Pointer to the buffer into which the received item will
|
393
|
* be copied.
|
394
|
*
|
395
|
* @param pxTaskWoken A task may be blocked waiting for space to become
|
396
|
* available on the queue. If xQueueReceiveFromISR causes such a task to
|
397
|
* unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
|
398
|
* remain unchanged.
|
399
|
*
|
400
|
* @return pdTRUE if an item was successfully received from the queue,
|
401
|
* otherwise pdFALSE.
|
402
|
*
|
403
|
* Example usage:
|
404
|
<pre>
|
405
|
|
406
|
xQueueHandle xQueue;
|
407
|
|
408
|
// Function to create a queue and post some values.
|
409
|
void vAFunction( void *pvParameters )
|
410
|
{
|
411
|
portCHAR cValueToPost;
|
412
|
const portTickType xBlockTime = ( portTickType )0xff;
|
413
|
|
414
|
// Create a queue capable of containing 10 characters.
|
415
|
xQueue = xQueueCreate( 10, sizeof( portCHAR ) );
|
416
|
if( xQueue == 0 )
|
417
|
{
|
418
|
// Failed to create the queue.
|
419
|
}
|
420
|
|
421
|
// ...
|
422
|
|
423
|
// Post some characters that will be used within an ISR. If the queue
|
424
|
// is full then this task will block for xBlockTime ticks.
|
425
|
cValueToPost = 'a';
|
426
|
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
|
427
|
cValueToPost = 'b';
|
428
|
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
|
429
|
|
430
|
// ... keep posting characters ... this task may block when the queue
|
431
|
// becomes full.
|
432
|
|
433
|
cValueToPost = 'c';
|
434
|
xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
|
435
|
}
|
436
|
|
437
|
// ISR that outputs all the characters received on the queue.
|
438
|
void vISR_Routine( void )
|
439
|
{
|
440
|
portBASE_TYPE xTaskWokenByReceive = pdFALSE;
|
441
|
portCHAR cRxedChar;
|
442
|
|
443
|
while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
|
444
|
{
|
445
|
// A character was received. Output the character now.
|
446
|
vOutputCharacter( cRxedChar );
|
447
|
|
448
|
// If removing the character from the queue woke the task that was
|
449
|
// posting onto the queue cTaskWokenByReceive will have been set to
|
450
|
// pdTRUE. No matter how many times this loop iterates only one
|
451
|
// task will be woken.
|
452
|
}
|
453
|
|
454
|
if( cTaskWokenByPost != ( portCHAR ) pdFALSE;
|
455
|
{
|
456
|
taskYIELD ();
|
457
|
}
|
458
|
}
|
459
|
</pre>
|
460
|
* \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
|
461
|
* \ingroup QueueManagement
|
462
|
*/
|
463
|
signed portBASE_TYPE xQueueReceiveFromISR (xQueueHandle pxQueue,
|
464
|
void *pvBuffer,
|
465
|
signed portBASE_TYPE *
|
466
|
pxTaskWoken);
|
467
|
|
468
|
|
469
|
/*
|
470
|
* The functions defined above are for passing data to and from tasks. The
|
471
|
* functions below are the equivalents for passing data to and from
|
472
|
* co-rtoutines.
|
473
|
*
|
474
|
* These functions are called from the co-routine macro implementation and
|
475
|
* should not be called directly from application code. Instead use the macro
|
476
|
* wrappers defined within croutine.h.
|
477
|
*/
|
478
|
signed portBASE_TYPE xQueueCRSendFromISR (xQueueHandle pxQueue,
|
479
|
const void *pvItemToQueue,
|
480
|
signed portBASE_TYPE
|
481
|
xCoRoutinePreviouslyWoken);
|
482
|
signed portBASE_TYPE xQueueCRReceiveFromISR (xQueueHandle pxQueue,
|
483
|
void *pvBuffer,
|
484
|
signed portBASE_TYPE *
|
485
|
pxTaskWoken);
|
486
|
signed portBASE_TYPE xQueueCRSend (xQueueHandle pxQueue,
|
487
|
const void *pvItemToQueue,
|
488
|
portTickType xTicksToWait);
|
489
|
signed portBASE_TYPE xQueueCRReceive (xQueueHandle pxQueue, void *pvBuffer,
|
490
|
portTickType xTicksToWait);
|
491
|
|
492
|
#endif
|