www.freertos.org

Dependents:   mbed_freeRTOS_send

Fork of FreeRTOS by Rohit Grover

Committer:
rgrover1
Date:
Fri Jan 24 14:56:04 2014 +0000
Revision:
0:8e57f3e9cc89
Making FreeRTOS available as a library

Who changed what in which revision?

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