1 |
/* |
---|
2 |
FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. |
---|
3 |
|
---|
4 |
This file is part of the FreeRTOS distribution. |
---|
5 |
|
---|
6 |
FreeRTOS is free software; you can redistribute it and/or modify it under |
---|
7 |
the terms of the GNU General Public License (version 2) as published by the |
---|
8 |
Free Software Foundation and modified by the FreeRTOS exception. |
---|
9 |
**NOTE** The exception to the GPL is included to allow you to distribute a |
---|
10 |
combined work that includes FreeRTOS without being obliged to provide the |
---|
11 |
source code for proprietary components outside of the FreeRTOS kernel. |
---|
12 |
Alternative commercial license and support terms are also available upon |
---|
13 |
request. See the licensing section of http://www.FreeRTOS.org for full |
---|
14 |
license details. |
---|
15 |
|
---|
16 |
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT |
---|
17 |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
18 |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
19 |
more details. |
---|
20 |
|
---|
21 |
You should have received a copy of the GNU General Public License along |
---|
22 |
with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 |
---|
23 |
Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
---|
24 |
|
---|
25 |
|
---|
26 |
*************************************************************************** |
---|
27 |
* * |
---|
28 |
* Looking for a quick start? Then check out the FreeRTOS eBook! * |
---|
29 |
* See http://www.FreeRTOS.org/Documentation for details * |
---|
30 |
* * |
---|
31 |
*************************************************************************** |
---|
32 |
|
---|
33 |
1 tab == 4 spaces! |
---|
34 |
|
---|
35 |
Please ensure to read the configuration and relevant port sections of the |
---|
36 |
online documentation. |
---|
37 |
|
---|
38 |
http://www.FreeRTOS.org - Documentation, latest information, license and |
---|
39 |
contact details. |
---|
40 |
|
---|
41 |
http://www.SafeRTOS.com - A version that is certified for use in safety |
---|
42 |
critical systems. |
---|
43 |
|
---|
44 |
http://www.OpenRTOS.com - Commercial support, development, porting, |
---|
45 |
licensing and training services. |
---|
46 |
*/ |
---|
47 |
|
---|
48 |
#ifndef INC_FREERTOS_H |
---|
49 |
#error "#include FreeRTOS.h" must appear in source files before "#include croutine.h" |
---|
50 |
#endif |
---|
51 |
|
---|
52 |
|
---|
53 |
|
---|
54 |
|
---|
55 |
#ifndef CO_ROUTINE_H |
---|
56 |
#define CO_ROUTINE_H |
---|
57 |
|
---|
58 |
#include "list.h" |
---|
59 |
|
---|
60 |
#ifdef __cplusplus |
---|
61 |
extern "C" { |
---|
62 |
#endif |
---|
63 |
|
---|
64 |
/* Used to hide the implementation of the co-routine control block. The |
---|
65 |
control block structure however has to be included in the header due to |
---|
66 |
the macro implementation of the co-routine functionality. */ |
---|
67 |
typedef void * xCoRoutineHandle; |
---|
68 |
|
---|
69 |
/* Defines the prototype to which co-routine functions must conform. */ |
---|
70 |
typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); |
---|
71 |
|
---|
72 |
typedef struct corCoRoutineControlBlock |
---|
73 |
{ |
---|
74 |
crCOROUTINE_CODE pxCoRoutineFunction; |
---|
75 |
xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ |
---|
76 |
xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ |
---|
77 |
unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ |
---|
78 |
unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ |
---|
79 |
unsigned portSHORT uxState; /*< Used internally by the co-routine implementation. */ |
---|
80 |
} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ |
---|
81 |
|
---|
82 |
/** |
---|
83 |
* croutine. h |
---|
84 |
*<pre> |
---|
85 |
portBASE_TYPE xCoRoutineCreate( |
---|
86 |
crCOROUTINE_CODE pxCoRoutineCode, |
---|
87 |
unsigned portBASE_TYPE uxPriority, |
---|
88 |
unsigned portBASE_TYPE uxIndex |
---|
89 |
);</pre> |
---|
90 |
* |
---|
91 |
* Create a new co-routine and add it to the list of co-routines that are |
---|
92 |
* ready to run. |
---|
93 |
* |
---|
94 |
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine |
---|
95 |
* functions require special syntax - see the co-routine section of the WEB |
---|
96 |
* documentation for more information. |
---|
97 |
* |
---|
98 |
* @param uxPriority The priority with respect to other co-routines at which |
---|
99 |
* the co-routine will run. |
---|
100 |
* |
---|
101 |
* @param uxIndex Used to distinguish between different co-routines that |
---|
102 |
* execute the same function. See the example below and the co-routine section |
---|
103 |
* of the WEB documentation for further information. |
---|
104 |
* |
---|
105 |
* @return pdPASS if the co-routine was successfully created and added to a ready |
---|
106 |
* list, otherwise an error code defined with ProjDefs.h. |
---|
107 |
* |
---|
108 |
* Example usage: |
---|
109 |
<pre> |
---|
110 |
// Co-routine to be created. |
---|
111 |
void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
112 |
{ |
---|
113 |
// Variables in co-routines must be declared static if they must maintain value across a blocking call. |
---|
114 |
// This may not be necessary for const variables. |
---|
115 |
static const char cLedToFlash[ 2 ] = { 5, 6 }; |
---|
116 |
static const portTickType xTimeToDelay[ 2 ] = { 200, 400 }; |
---|
117 |
|
---|
118 |
// Must start every co-routine with a call to crSTART(); |
---|
119 |
crSTART( xHandle ); |
---|
120 |
|
---|
121 |
for( ;; ) |
---|
122 |
{ |
---|
123 |
// This co-routine just delays for a fixed period, then toggles |
---|
124 |
// an LED. Two co-routines are created using this function, so |
---|
125 |
// the uxIndex parameter is used to tell the co-routine which |
---|
126 |
// LED to flash and how long to delay. This assumes xQueue has |
---|
127 |
// already been created. |
---|
128 |
vParTestToggleLED( cLedToFlash[ uxIndex ] ); |
---|
129 |
crDELAY( xHandle, uxFlashRates[ uxIndex ] ); |
---|
130 |
} |
---|
131 |
|
---|
132 |
// Must end every co-routine with a call to crEND(); |
---|
133 |
crEND(); |
---|
134 |
} |
---|
135 |
|
---|
136 |
// Function that creates two co-routines. |
---|
137 |
void vOtherFunction( void ) |
---|
138 |
{ |
---|
139 |
unsigned char ucParameterToPass; |
---|
140 |
xTaskHandle xHandle; |
---|
141 |
|
---|
142 |
// Create two co-routines at priority 0. The first is given index 0 |
---|
143 |
// so (from the code above) toggles LED 5 every 200 ticks. The second |
---|
144 |
// is given index 1 so toggles LED 6 every 400 ticks. |
---|
145 |
for( uxIndex = 0; uxIndex < 2; uxIndex++ ) |
---|
146 |
{ |
---|
147 |
xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex ); |
---|
148 |
} |
---|
149 |
} |
---|
150 |
</pre> |
---|
151 |
* \defgroup xCoRoutineCreate xCoRoutineCreate |
---|
152 |
* \ingroup Tasks |
---|
153 |
*/ |
---|
154 |
signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); |
---|
155 |
|
---|
156 |
|
---|
157 |
/** |
---|
158 |
* croutine. h |
---|
159 |
*<pre> |
---|
160 |
void vCoRoutineSchedule( void );</pre> |
---|
161 |
* |
---|
162 |
* Run a co-routine. |
---|
163 |
* |
---|
164 |
* vCoRoutineSchedule() executes the highest priority co-routine that is able |
---|
165 |
* to run. The co-routine will execute until it either blocks, yields or is |
---|
166 |
* preempted by a task. Co-routines execute cooperatively so one |
---|
167 |
* co-routine cannot be preempted by another, but can be preempted by a task. |
---|
168 |
* |
---|
169 |
* If an application comprises of both tasks and co-routines then |
---|
170 |
* vCoRoutineSchedule should be called from the idle task (in an idle task |
---|
171 |
* hook). |
---|
172 |
* |
---|
173 |
* Example usage: |
---|
174 |
<pre> |
---|
175 |
// This idle task hook will schedule a co-routine each time it is called. |
---|
176 |
// The rest of the idle task will execute between co-routine calls. |
---|
177 |
void vApplicationIdleHook( void ) |
---|
178 |
{ |
---|
179 |
vCoRoutineSchedule(); |
---|
180 |
} |
---|
181 |
|
---|
182 |
// Alternatively, if you do not require any other part of the idle task to |
---|
183 |
// execute, the idle task hook can call vCoRoutineScheduler() within an |
---|
184 |
// infinite loop. |
---|
185 |
void vApplicationIdleHook( void ) |
---|
186 |
{ |
---|
187 |
for( ;; ) |
---|
188 |
{ |
---|
189 |
vCoRoutineSchedule(); |
---|
190 |
} |
---|
191 |
} |
---|
192 |
</pre> |
---|
193 |
* \defgroup vCoRoutineSchedule vCoRoutineSchedule |
---|
194 |
* \ingroup Tasks |
---|
195 |
*/ |
---|
196 |
void vCoRoutineSchedule( void ); |
---|
197 |
|
---|
198 |
/** |
---|
199 |
* croutine. h |
---|
200 |
* <pre> |
---|
201 |
crSTART( xCoRoutineHandle xHandle );</pre> |
---|
202 |
* |
---|
203 |
* This macro MUST always be called at the start of a co-routine function. |
---|
204 |
* |
---|
205 |
* Example usage: |
---|
206 |
<pre> |
---|
207 |
// Co-routine to be created. |
---|
208 |
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
209 |
{ |
---|
210 |
// Variables in co-routines must be declared static if they must maintain value across a blocking call. |
---|
211 |
static portLONG ulAVariable; |
---|
212 |
|
---|
213 |
// Must start every co-routine with a call to crSTART(); |
---|
214 |
crSTART( xHandle ); |
---|
215 |
|
---|
216 |
for( ;; ) |
---|
217 |
{ |
---|
218 |
// Co-routine functionality goes here. |
---|
219 |
} |
---|
220 |
|
---|
221 |
// Must end every co-routine with a call to crEND(); |
---|
222 |
crEND(); |
---|
223 |
}</pre> |
---|
224 |
* \defgroup crSTART crSTART |
---|
225 |
* \ingroup Tasks |
---|
226 |
*/ |
---|
227 |
#define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0: |
---|
228 |
|
---|
229 |
/** |
---|
230 |
* croutine. h |
---|
231 |
* <pre> |
---|
232 |
crEND();</pre> |
---|
233 |
* |
---|
234 |
* This macro MUST always be called at the end of a co-routine function. |
---|
235 |
* |
---|
236 |
* Example usage: |
---|
237 |
<pre> |
---|
238 |
// Co-routine to be created. |
---|
239 |
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
240 |
{ |
---|
241 |
// Variables in co-routines must be declared static if they must maintain value across a blocking call. |
---|
242 |
static portLONG ulAVariable; |
---|
243 |
|
---|
244 |
// Must start every co-routine with a call to crSTART(); |
---|
245 |
crSTART( xHandle ); |
---|
246 |
|
---|
247 |
for( ;; ) |
---|
248 |
{ |
---|
249 |
// Co-routine functionality goes here. |
---|
250 |
} |
---|
251 |
|
---|
252 |
// Must end every co-routine with a call to crEND(); |
---|
253 |
crEND(); |
---|
254 |
}</pre> |
---|
255 |
* \defgroup crSTART crSTART |
---|
256 |
* \ingroup Tasks |
---|
257 |
*/ |
---|
258 |
#define crEND() } |
---|
259 |
|
---|
260 |
/* |
---|
261 |
* These macros are intended for internal use by the co-routine implementation |
---|
262 |
* only. The macros should not be used directly by application writers. |
---|
263 |
*/ |
---|
264 |
#define crSET_STATE0( xHandle ) ( ( corCRCB * )xHandle)->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): |
---|
265 |
#define crSET_STATE1( xHandle ) ( ( corCRCB * )xHandle)->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): |
---|
266 |
|
---|
267 |
/** |
---|
268 |
* croutine. h |
---|
269 |
*<pre> |
---|
270 |
crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );</pre> |
---|
271 |
* |
---|
272 |
* Delay a co-routine for a fixed period of time. |
---|
273 |
* |
---|
274 |
* crDELAY can only be called from the co-routine function itself - not |
---|
275 |
* from within a function called by the co-routine function. This is because |
---|
276 |
* co-routines do not maintain their own stack. |
---|
277 |
* |
---|
278 |
* @param xHandle The handle of the co-routine to delay. This is the xHandle |
---|
279 |
* parameter of the co-routine function. |
---|
280 |
* |
---|
281 |
* @param xTickToDelay The number of ticks that the co-routine should delay |
---|
282 |
* for. The actual amount of time this equates to is defined by |
---|
283 |
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS |
---|
284 |
* can be used to convert ticks to milliseconds. |
---|
285 |
* |
---|
286 |
* Example usage: |
---|
287 |
<pre> |
---|
288 |
// Co-routine to be created. |
---|
289 |
void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
290 |
{ |
---|
291 |
// Variables in co-routines must be declared static if they must maintain value across a blocking call. |
---|
292 |
// This may not be necessary for const variables. |
---|
293 |
// We are to delay for 200ms. |
---|
294 |
static const xTickType xDelayTime = 200 / portTICK_RATE_MS; |
---|
295 |
|
---|
296 |
// Must start every co-routine with a call to crSTART(); |
---|
297 |
crSTART( xHandle ); |
---|
298 |
|
---|
299 |
for( ;; ) |
---|
300 |
{ |
---|
301 |
// Delay for 200ms. |
---|
302 |
crDELAY( xHandle, xDelayTime ); |
---|
303 |
|
---|
304 |
// Do something here. |
---|
305 |
} |
---|
306 |
|
---|
307 |
// Must end every co-routine with a call to crEND(); |
---|
308 |
crEND(); |
---|
309 |
}</pre> |
---|
310 |
* \defgroup crDELAY crDELAY |
---|
311 |
* \ingroup Tasks |
---|
312 |
*/ |
---|
313 |
#define crDELAY( xHandle, xTicksToDelay ) \ |
---|
314 |
if( xTicksToDelay > 0 ) \ |
---|
315 |
{ \ |
---|
316 |
vCoRoutineAddToDelayedList( xTicksToDelay, NULL ); \ |
---|
317 |
} \ |
---|
318 |
crSET_STATE0( xHandle ); |
---|
319 |
|
---|
320 |
/** |
---|
321 |
* <pre> |
---|
322 |
crQUEUE_SEND( |
---|
323 |
xCoRoutineHandle xHandle, |
---|
324 |
xQueueHandle pxQueue, |
---|
325 |
void *pvItemToQueue, |
---|
326 |
portTickType xTicksToWait, |
---|
327 |
portBASE_TYPE *pxResult |
---|
328 |
)</pre> |
---|
329 |
* |
---|
330 |
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine |
---|
331 |
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. |
---|
332 |
* |
---|
333 |
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas |
---|
334 |
* xQueueSend() and xQueueReceive() can only be used from tasks. |
---|
335 |
* |
---|
336 |
* crQUEUE_SEND can only be called from the co-routine function itself - not |
---|
337 |
* from within a function called by the co-routine function. This is because |
---|
338 |
* co-routines do not maintain their own stack. |
---|
339 |
* |
---|
340 |
* See the co-routine section of the WEB documentation for information on |
---|
341 |
* passing data between tasks and co-routines and between ISR's and |
---|
342 |
* co-routines. |
---|
343 |
* |
---|
344 |
* @param xHandle The handle of the calling co-routine. This is the xHandle |
---|
345 |
* parameter of the co-routine function. |
---|
346 |
* |
---|
347 |
* @param pxQueue The handle of the queue on which the data will be posted. |
---|
348 |
* The handle is obtained as the return value when the queue is created using |
---|
349 |
* the xQueueCreate() API function. |
---|
350 |
* |
---|
351 |
* @param pvItemToQueue A pointer to the data being posted onto the queue. |
---|
352 |
* The number of bytes of each queued item is specified when the queue is |
---|
353 |
* created. This number of bytes is copied from pvItemToQueue into the queue |
---|
354 |
* itself. |
---|
355 |
* |
---|
356 |
* @param xTickToDelay The number of ticks that the co-routine should block |
---|
357 |
* to wait for space to become available on the queue, should space not be |
---|
358 |
* available immediately. The actual amount of time this equates to is defined |
---|
359 |
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant |
---|
360 |
* portTICK_RATE_MS can be used to convert ticks to milliseconds (see example |
---|
361 |
* below). |
---|
362 |
* |
---|
363 |
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if |
---|
364 |
* data was successfully posted onto the queue, otherwise it will be set to an |
---|
365 |
* error defined within ProjDefs.h. |
---|
366 |
* |
---|
367 |
* Example usage: |
---|
368 |
<pre> |
---|
369 |
// Co-routine function that blocks for a fixed period then posts a number onto |
---|
370 |
// a queue. |
---|
371 |
static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
372 |
{ |
---|
373 |
// Variables in co-routines must be declared static if they must maintain value across a blocking call. |
---|
374 |
static portBASE_TYPE xNumberToPost = 0; |
---|
375 |
static portBASE_TYPE xResult; |
---|
376 |
|
---|
377 |
// Co-routines must begin with a call to crSTART(). |
---|
378 |
crSTART( xHandle ); |
---|
379 |
|
---|
380 |
for( ;; ) |
---|
381 |
{ |
---|
382 |
// This assumes the queue has already been created. |
---|
383 |
crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult ); |
---|
384 |
|
---|
385 |
if( xResult != pdPASS ) |
---|
386 |
{ |
---|
387 |
// The message was not posted! |
---|
388 |
} |
---|
389 |
|
---|
390 |
// Increment the number to be posted onto the queue. |
---|
391 |
xNumberToPost++; |
---|
392 |
|
---|
393 |
// Delay for 100 ticks. |
---|
394 |
crDELAY( xHandle, 100 ); |
---|
395 |
} |
---|
396 |
|
---|
397 |
// Co-routines must end with a call to crEND(). |
---|
398 |
crEND(); |
---|
399 |
}</pre> |
---|
400 |
* \defgroup crQUEUE_SEND crQUEUE_SEND |
---|
401 |
* \ingroup Tasks |
---|
402 |
*/ |
---|
403 |
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ |
---|
404 |
{ \ |
---|
405 |
*pxResult = xQueueCRSend( pxQueue, pvItemToQueue, xTicksToWait ); \ |
---|
406 |
if( *pxResult == errQUEUE_BLOCKED ) \ |
---|
407 |
{ \ |
---|
408 |
crSET_STATE0( xHandle ); \ |
---|
409 |
*pxResult = xQueueCRSend( pxQueue, pvItemToQueue, 0 ); \ |
---|
410 |
} \ |
---|
411 |
if( *pxResult == errQUEUE_YIELD ) \ |
---|
412 |
{ \ |
---|
413 |
crSET_STATE1( xHandle ); \ |
---|
414 |
*pxResult = pdPASS; \ |
---|
415 |
} \ |
---|
416 |
} |
---|
417 |
|
---|
418 |
/** |
---|
419 |
* croutine. h |
---|
420 |
* <pre> |
---|
421 |
crQUEUE_RECEIVE( |
---|
422 |
xCoRoutineHandle xHandle, |
---|
423 |
xQueueHandle pxQueue, |
---|
424 |
void *pvBuffer, |
---|
425 |
portTickType xTicksToWait, |
---|
426 |
portBASE_TYPE *pxResult |
---|
427 |
)</pre> |
---|
428 |
* |
---|
429 |
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine |
---|
430 |
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. |
---|
431 |
* |
---|
432 |
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas |
---|
433 |
* xQueueSend() and xQueueReceive() can only be used from tasks. |
---|
434 |
* |
---|
435 |
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not |
---|
436 |
* from within a function called by the co-routine function. This is because |
---|
437 |
* co-routines do not maintain their own stack. |
---|
438 |
* |
---|
439 |
* See the co-routine section of the WEB documentation for information on |
---|
440 |
* passing data between tasks and co-routines and between ISR's and |
---|
441 |
* co-routines. |
---|
442 |
* |
---|
443 |
* @param xHandle The handle of the calling co-routine. This is the xHandle |
---|
444 |
* parameter of the co-routine function. |
---|
445 |
* |
---|
446 |
* @param pxQueue The handle of the queue from which the data will be received. |
---|
447 |
* The handle is obtained as the return value when the queue is created using |
---|
448 |
* the xQueueCreate() API function. |
---|
449 |
* |
---|
450 |
* @param pvBuffer The buffer into which the received item is to be copied. |
---|
451 |
* The number of bytes of each queued item is specified when the queue is |
---|
452 |
* created. This number of bytes is copied into pvBuffer. |
---|
453 |
* |
---|
454 |
* @param xTickToDelay The number of ticks that the co-routine should block |
---|
455 |
* to wait for data to become available from the queue, should data not be |
---|
456 |
* available immediately. The actual amount of time this equates to is defined |
---|
457 |
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant |
---|
458 |
* portTICK_RATE_MS can be used to convert ticks to milliseconds (see the |
---|
459 |
* crQUEUE_SEND example). |
---|
460 |
* |
---|
461 |
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if |
---|
462 |
* data was successfully retrieved from the queue, otherwise it will be set to |
---|
463 |
* an error code as defined within ProjDefs.h. |
---|
464 |
* |
---|
465 |
* Example usage: |
---|
466 |
<pre> |
---|
467 |
// A co-routine receives the number of an LED to flash from a queue. It |
---|
468 |
// blocks on the queue until the number is received. |
---|
469 |
static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
470 |
{ |
---|
471 |
// Variables in co-routines must be declared static if they must maintain value across a blocking call. |
---|
472 |
static portBASE_TYPE xResult; |
---|
473 |
static unsigned portBASE_TYPE uxLEDToFlash; |
---|
474 |
|
---|
475 |
// All co-routines must start with a call to crSTART(). |
---|
476 |
crSTART( xHandle ); |
---|
477 |
|
---|
478 |
for( ;; ) |
---|
479 |
{ |
---|
480 |
// Wait for data to become available on the queue. |
---|
481 |
crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); |
---|
482 |
|
---|
483 |
if( xResult == pdPASS ) |
---|
484 |
{ |
---|
485 |
// We received the LED to flash - flash it! |
---|
486 |
vParTestToggleLED( uxLEDToFlash ); |
---|
487 |
} |
---|
488 |
} |
---|
489 |
|
---|
490 |
crEND(); |
---|
491 |
}</pre> |
---|
492 |
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE |
---|
493 |
* \ingroup Tasks |
---|
494 |
*/ |
---|
495 |
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ |
---|
496 |
{ \ |
---|
497 |
*pxResult = xQueueCRReceive( pxQueue, pvBuffer, xTicksToWait ); \ |
---|
498 |
if( *pxResult == errQUEUE_BLOCKED ) \ |
---|
499 |
{ \ |
---|
500 |
crSET_STATE0( xHandle ); \ |
---|
501 |
*pxResult = xQueueCRReceive( pxQueue, pvBuffer, 0 ); \ |
---|
502 |
} \ |
---|
503 |
if( *pxResult == errQUEUE_YIELD ) \ |
---|
504 |
{ \ |
---|
505 |
crSET_STATE1( xHandle ); \ |
---|
506 |
*pxResult = pdPASS; \ |
---|
507 |
} \ |
---|
508 |
} |
---|
509 |
|
---|
510 |
/** |
---|
511 |
* croutine. h |
---|
512 |
* <pre> |
---|
513 |
crQUEUE_SEND_FROM_ISR( |
---|
514 |
xQueueHandle pxQueue, |
---|
515 |
void *pvItemToQueue, |
---|
516 |
portBASE_TYPE xCoRoutinePreviouslyWoken |
---|
517 |
)</pre> |
---|
518 |
* |
---|
519 |
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the |
---|
520 |
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() |
---|
521 |
* functions used by tasks. |
---|
522 |
* |
---|
523 |
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to |
---|
524 |
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and |
---|
525 |
* xQueueReceiveFromISR() can only be used to pass data between a task and and |
---|
526 |
* ISR. |
---|
527 |
* |
---|
528 |
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue |
---|
529 |
* that is being used from within a co-routine. |
---|
530 |
* |
---|
531 |
* See the co-routine section of the WEB documentation for information on |
---|
532 |
* passing data between tasks and co-routines and between ISR's and |
---|
533 |
* co-routines. |
---|
534 |
* |
---|
535 |
* @param xQueue The handle to the queue on which the item is to be posted. |
---|
536 |
* |
---|
537 |
* @param pvItemToQueue A pointer to the item that is to be placed on the |
---|
538 |
* queue. The size of the items the queue will hold was defined when the |
---|
539 |
* queue was created, so this many bytes will be copied from pvItemToQueue |
---|
540 |
* into the queue storage area. |
---|
541 |
* |
---|
542 |
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto |
---|
543 |
* the same queue multiple times from a single interrupt. The first call |
---|
544 |
* should always pass in pdFALSE. Subsequent calls should pass in |
---|
545 |
* the value returned from the previous call. |
---|
546 |
* |
---|
547 |
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is |
---|
548 |
* used by the ISR to determine if a context switch may be required following |
---|
549 |
* the ISR. |
---|
550 |
* |
---|
551 |
* Example usage: |
---|
552 |
<pre> |
---|
553 |
// A co-routine that blocks on a queue waiting for characters to be received. |
---|
554 |
static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
555 |
{ |
---|
556 |
portCHAR cRxedChar; |
---|
557 |
portBASE_TYPE xResult; |
---|
558 |
|
---|
559 |
// All co-routines must start with a call to crSTART(). |
---|
560 |
crSTART( xHandle ); |
---|
561 |
|
---|
562 |
for( ;; ) |
---|
563 |
{ |
---|
564 |
// Wait for data to become available on the queue. This assumes the |
---|
565 |
// queue xCommsRxQueue has already been created! |
---|
566 |
crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); |
---|
567 |
|
---|
568 |
// Was a character received? |
---|
569 |
if( xResult == pdPASS ) |
---|
570 |
{ |
---|
571 |
// Process the character here. |
---|
572 |
} |
---|
573 |
} |
---|
574 |
|
---|
575 |
// All co-routines must end with a call to crEND(). |
---|
576 |
crEND(); |
---|
577 |
} |
---|
578 |
|
---|
579 |
// An ISR that uses a queue to send characters received on a serial port to |
---|
580 |
// a co-routine. |
---|
581 |
void vUART_ISR( void ) |
---|
582 |
{ |
---|
583 |
portCHAR cRxedChar; |
---|
584 |
portBASE_TYPE xCRWokenByPost = pdFALSE; |
---|
585 |
|
---|
586 |
// We loop around reading characters until there are none left in the UART. |
---|
587 |
while( UART_RX_REG_NOT_EMPTY() ) |
---|
588 |
{ |
---|
589 |
// Obtain the character from the UART. |
---|
590 |
cRxedChar = UART_RX_REG; |
---|
591 |
|
---|
592 |
// Post the character onto a queue. xCRWokenByPost will be pdFALSE |
---|
593 |
// the first time around the loop. If the post causes a co-routine |
---|
594 |
// to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE. |
---|
595 |
// In this manner we can ensure that if more than one co-routine is |
---|
596 |
// blocked on the queue only one is woken by this ISR no matter how |
---|
597 |
// many characters are posted to the queue. |
---|
598 |
xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost ); |
---|
599 |
} |
---|
600 |
}</pre> |
---|
601 |
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR |
---|
602 |
* \ingroup Tasks |
---|
603 |
*/ |
---|
604 |
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) |
---|
605 |
|
---|
606 |
|
---|
607 |
/** |
---|
608 |
* croutine. h |
---|
609 |
* <pre> |
---|
610 |
crQUEUE_SEND_FROM_ISR( |
---|
611 |
xQueueHandle pxQueue, |
---|
612 |
void *pvBuffer, |
---|
613 |
portBASE_TYPE * pxCoRoutineWoken |
---|
614 |
)</pre> |
---|
615 |
* |
---|
616 |
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the |
---|
617 |
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() |
---|
618 |
* functions used by tasks. |
---|
619 |
* |
---|
620 |
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to |
---|
621 |
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and |
---|
622 |
* xQueueReceiveFromISR() can only be used to pass data between a task and and |
---|
623 |
* ISR. |
---|
624 |
* |
---|
625 |
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data |
---|
626 |
* from a queue that is being used from within a co-routine (a co-routine |
---|
627 |
* posted to the queue). |
---|
628 |
* |
---|
629 |
* See the co-routine section of the WEB documentation for information on |
---|
630 |
* passing data between tasks and co-routines and between ISR's and |
---|
631 |
* co-routines. |
---|
632 |
* |
---|
633 |
* @param xQueue The handle to the queue on which the item is to be posted. |
---|
634 |
* |
---|
635 |
* @param pvBuffer A pointer to a buffer into which the received item will be |
---|
636 |
* placed. The size of the items the queue will hold was defined when the |
---|
637 |
* queue was created, so this many bytes will be copied from the queue into |
---|
638 |
* pvBuffer. |
---|
639 |
* |
---|
640 |
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become |
---|
641 |
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a |
---|
642 |
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise |
---|
643 |
* *pxCoRoutineWoken will remain unchanged. |
---|
644 |
* |
---|
645 |
* @return pdTRUE an item was successfully received from the queue, otherwise |
---|
646 |
* pdFALSE. |
---|
647 |
* |
---|
648 |
* Example usage: |
---|
649 |
<pre> |
---|
650 |
// A co-routine that posts a character to a queue then blocks for a fixed |
---|
651 |
// period. The character is incremented each time. |
---|
652 |
static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) |
---|
653 |
{ |
---|
654 |
// cChar holds its value while this co-routine is blocked and must therefore |
---|
655 |
// be declared static. |
---|
656 |
static portCHAR cCharToTx = 'a'; |
---|
657 |
portBASE_TYPE xResult; |
---|
658 |
|
---|
659 |
// All co-routines must start with a call to crSTART(). |
---|
660 |
crSTART( xHandle ); |
---|
661 |
|
---|
662 |
for( ;; ) |
---|
663 |
{ |
---|
664 |
// Send the next character to the queue. |
---|
665 |
crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult ); |
---|
666 |
|
---|
667 |
if( xResult == pdPASS ) |
---|
668 |
{ |
---|
669 |
// The character was successfully posted to the queue. |
---|
670 |
} |
---|
671 |
else |
---|
672 |
{ |
---|
673 |
// Could not post the character to the queue. |
---|
674 |
} |
---|
675 |
|
---|
676 |
// Enable the UART Tx interrupt to cause an interrupt in this |
---|
677 |
// hypothetical UART. The interrupt will obtain the character |
---|
678 |
// from the queue and send it. |
---|
679 |
ENABLE_RX_INTERRUPT(); |
---|
680 |
|
---|
681 |
// Increment to the next character then block for a fixed period. |
---|
682 |
// cCharToTx will maintain its value across the delay as it is |
---|
683 |
// declared static. |
---|
684 |
cCharToTx++; |
---|
685 |
if( cCharToTx > 'x' ) |
---|
686 |
{ |
---|
687 |
cCharToTx = 'a'; |
---|
688 |
} |
---|
689 |
crDELAY( 100 ); |
---|
690 |
} |
---|
691 |
|
---|
692 |
// All co-routines must end with a call to crEND(). |
---|
693 |
crEND(); |
---|
694 |
} |
---|
695 |
|
---|
696 |
// An ISR that uses a queue to receive characters to send on a UART. |
---|
697 |
void vUART_ISR( void ) |
---|
698 |
{ |
---|
699 |
portCHAR cCharToTx; |
---|
700 |
portBASE_TYPE xCRWokenByPost = pdFALSE; |
---|
701 |
|
---|
702 |
while( UART_TX_REG_EMPTY() ) |
---|
703 |
{ |
---|
704 |
// Are there any characters in the queue waiting to be sent? |
---|
705 |
// xCRWokenByPost will automatically be set to pdTRUE if a co-routine |
---|
706 |
// is woken by the post - ensuring that only a single co-routine is |
---|
707 |
// woken no matter how many times we go around this loop. |
---|
708 |
if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) ) |
---|
709 |
{ |
---|
710 |
SEND_CHARACTER( cCharToTx ); |
---|
711 |
} |
---|
712 |
} |
---|
713 |
}</pre> |
---|
714 |
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR |
---|
715 |
* \ingroup Tasks |
---|
716 |
*/ |
---|
717 |
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( pxQueue, pvBuffer, pxCoRoutineWoken ) |
---|
718 |
|
---|
719 |
/* |
---|
720 |
* This function is intended for internal use by the co-routine macros only. |
---|
721 |
* The macro nature of the co-routine implementation requires that the |
---|
722 |
* prototype appears here. The function should not be used by application |
---|
723 |
* writers. |
---|
724 |
* |
---|
725 |
* Removes the current co-routine from its ready list and places it in the |
---|
726 |
* appropriate delayed list. |
---|
727 |
*/ |
---|
728 |
void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ); |
---|
729 |
|
---|
730 |
/* |
---|
731 |
* This function is intended for internal use by the queue implementation only. |
---|
732 |
* The function should not be used by application writers. |
---|
733 |
* |
---|
734 |
* Removes the highest priority co-routine from the event list and places it in |
---|
735 |
* the pending ready list. |
---|
736 |
*/ |
---|
737 |
signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); |
---|
738 |
|
---|
739 |
#ifdef __cplusplus |
---|
740 |
} |
---|
741 |
#endif |
---|
742 |
|
---|
743 |
#endif /* CO_ROUTINE_H */ |
---|