00001 /* 00002 FreeRTOS V6.0.0 - Copyright (C) 2009 Real Time Engineers Ltd. 00003 00004 *************************************************************************** 00005 * * 00006 * If you are: * 00007 * * 00008 * + New to FreeRTOS, * 00009 * + Wanting to learn FreeRTOS or multitasking in general quickly * 00010 * + Looking for basic training, * 00011 * + Wanting to improve your FreeRTOS skills and productivity * 00012 * * 00013 * then take a look at the FreeRTOS eBook * 00014 * * 00015 * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * 00016 * http://www.FreeRTOS.org/Documentation * 00017 * * 00018 * A pdf reference manual is also available. Both are usually delivered * 00019 * to your inbox within 20 minutes to two hours when purchased between 8am * 00020 * and 8pm GMT (although please allow up to 24 hours in case of * 00021 * exceptional circumstances). Thank you for your support! * 00022 * * 00023 *************************************************************************** 00024 00025 This file is part of the FreeRTOS distribution. 00026 00027 FreeRTOS is free software; you can redistribute it and/or modify it under 00028 the terms of the GNU General Public License (version 2) as published by the 00029 Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 00030 ***NOTE*** The exception to the GPL is included to allow you to distribute 00031 a combined work that includes FreeRTOS without being obliged to provide the 00032 source code for proprietary components outside of the FreeRTOS kernel. 00033 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT 00034 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00035 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00036 more details. You should have received a copy of the GNU General Public 00037 License and the FreeRTOS license exception along with FreeRTOS; if not it 00038 can be viewed here: http://www.freertos.org/a00114.html and also obtained 00039 by writing to Richard Barry, contact details for whom are available on the 00040 FreeRTOS WEB site. 00041 00042 1 tab == 4 spaces! 00043 00044 http://www.FreeRTOS.org - Documentation, latest information, license and 00045 contact details. 00046 00047 http://www.SafeRTOS.com - A version that is certified for use in safety 00048 critical systems. 00049 00050 http://www.OpenRTOS.com - Commercial support, development, porting, 00051 licensing and training services. 00052 */ 00053 00054 /* 00055 * This demo file demonstrates how to send data between an ISR and a 00056 * co-routine. A tick hook function is used to periodically pass data between 00057 * the RTOS tick and a set of 'hook' co-routines. 00058 * 00059 * hookNUM_HOOK_CO_ROUTINES co-routines are created. Each co-routine blocks 00060 * to wait for a character to be received on a queue from the tick ISR, checks 00061 * to ensure the character received was that expected, then sends the number 00062 * back to the tick ISR on a different queue. 00063 * 00064 * The tick ISR checks the numbers received back from the 'hook' co-routines 00065 * matches the number previously sent. 00066 * 00067 * If at any time a queue function returns unexpectedly, or an incorrect value 00068 * is received either by the tick hook or a co-routine then an error is 00069 * latched. 00070 * 00071 * This demo relies on each 'hook' co-routine to execute between each 00072 * hookTICK_CALLS_BEFORE_POST tick interrupts. This and the heavy use of 00073 * queues from within an interrupt may result in an error being detected on 00074 * slower targets simply due to timing. 00075 */ 00076 00077 /* Scheduler includes. */ 00078 #include "FreeRTOS.h" 00079 #include "croutine.h" 00080 #include "queue.h" 00081 00082 /* Demo application includes. */ 00083 #include "crhook.h" 00084 00085 /* The number of 'hook' co-routines that are to be created. */ 00086 #define hookNUM_HOOK_CO_ROUTINES ( 4 ) 00087 00088 /* The number of times the tick hook should be called before a character is 00089 posted to the 'hook' co-routines. */ 00090 #define hookTICK_CALLS_BEFORE_POST ( 500 ) 00091 00092 /* There should never be more than one item in any queue at any time. */ 00093 #define hookHOOK_QUEUE_LENGTH ( 1 ) 00094 00095 /* Don't block when initially posting to the queue. */ 00096 #define hookNO_BLOCK_TIME ( 0 ) 00097 00098 /* The priority relative to other co-routines (rather than tasks) that the 00099 'hook' co-routines should take. */ 00100 #define mainHOOK_CR_PRIORITY ( 1 ) 00101 /*-----------------------------------------------------------*/ 00102 00103 /* 00104 * The co-routine function itself. 00105 */ 00106 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ); 00107 00108 00109 /* 00110 * The tick hook function. This receives a number from each 'hook' co-routine 00111 * then sends a number to each co-routine. An error is flagged if a send or 00112 * receive fails, or an unexpected number is received. 00113 */ 00114 void vApplicationTickHook( void ); 00115 00116 /*-----------------------------------------------------------*/ 00117 00118 /* Queues used to send data FROM a co-routine TO the tick hook function. 00119 The hook functions received (Rx's) on these queues. One queue per 00120 'hook' co-routine. */ 00121 static xQueueHandle xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ]; 00122 00123 /* Queues used to send data FROM the tick hook TO a co-routine function. 00124 The hood function transmits (Tx's) on these queues. One queue per 00125 'hook' co-routine. */ 00126 static xQueueHandle xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ]; 00127 00128 /* Set to true if an error is detected at any time. */ 00129 static portBASE_TYPE xCoRoutineErrorDetected = pdFALSE; 00130 00131 /*-----------------------------------------------------------*/ 00132 00133 void vStartHookCoRoutines( void ) 00134 { 00135 unsigned portBASE_TYPE uxIndex, uxValueToPost = 0; 00136 00137 for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ ) 00138 { 00139 /* Create a queue to transmit to and receive from each 'hook' 00140 co-routine. */ 00141 xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) ); 00142 xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) ); 00143 00144 /* To start things off the tick hook function expects the queue it 00145 uses to receive data to contain a value. */ 00146 xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME ); 00147 00148 /* Create the 'hook' co-routine itself. */ 00149 xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex ); 00150 } 00151 } 00152 /*-----------------------------------------------------------*/ 00153 00154 static unsigned portBASE_TYPE uxCallCounter = 0, uxNumberToPost = 0; 00155 void vApplicationTickHook( void ) 00156 { 00157 unsigned portBASE_TYPE uxReceivedNumber; 00158 signed portBASE_TYPE xIndex, xCoRoutineWoken; 00159 00160 /* Is it time to talk to the 'hook' co-routines again? */ 00161 uxCallCounter++; 00162 if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST ) 00163 { 00164 uxCallCounter = 0; 00165 00166 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) 00167 { 00168 xCoRoutineWoken = pdFALSE; 00169 if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS ) 00170 { 00171 /* There is no reason why we would not expect the queue to 00172 contain a value. */ 00173 xCoRoutineErrorDetected = pdTRUE; 00174 } 00175 else 00176 { 00177 /* Each queue used to receive data from the 'hook' co-routines 00178 should contain the number we last posted to the same co-routine. */ 00179 if( uxReceivedNumber != uxNumberToPost ) 00180 { 00181 xCoRoutineErrorDetected = pdTRUE; 00182 } 00183 00184 /* Nothing should be blocked waiting to post to the queue. */ 00185 if( xCoRoutineWoken != pdFALSE ) 00186 { 00187 xCoRoutineErrorDetected = pdTRUE; 00188 } 00189 } 00190 } 00191 00192 /* Start the next cycle by posting the next number onto each Tx queue. */ 00193 uxNumberToPost++; 00194 00195 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) 00196 { 00197 if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE ) 00198 { 00199 /* Posting to the queue should have woken the co-routine that 00200 was blocked on the queue. */ 00201 xCoRoutineErrorDetected = pdTRUE; 00202 } 00203 } 00204 } 00205 } 00206 /*-----------------------------------------------------------*/ 00207 00208 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) 00209 { 00210 static unsigned portBASE_TYPE uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ]; 00211 portBASE_TYPE xResult; 00212 00213 /* Each co-routine MUST start with a call to crSTART(); */ 00214 crSTART( xHandle ); 00215 00216 for( ;; ) 00217 { 00218 /* Wait to receive a value from the tick hook. */ 00219 xResult = pdFAIL; 00220 crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult ); 00221 00222 /* There is no reason why we should not have received something on 00223 the queue. */ 00224 if( xResult != pdPASS ) 00225 { 00226 xCoRoutineErrorDetected = pdTRUE; 00227 } 00228 00229 /* Send the same number back to the idle hook so it can verify it. */ 00230 xResult = pdFAIL; 00231 crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult ); 00232 if( xResult != pdPASS ) 00233 { 00234 /* There is no reason why we should not have been able to post to 00235 the queue. */ 00236 xCoRoutineErrorDetected = pdTRUE; 00237 } 00238 } 00239 00240 /* Each co-routine MUST end with a call to crEND(). */ 00241 crEND(); 00242 } 00243 /*-----------------------------------------------------------*/ 00244 00245 portBASE_TYPE xAreHookCoRoutinesStillRunning( void ) 00246 { 00247 if( xCoRoutineErrorDetected ) 00248 { 00249 return pdFALSE; 00250 } 00251 else 00252 { 00253 return pdTRUE; 00254 } 00255 } 00256 00257 00258