]> git.sur5r.net Git - freertos/blob - Demo/Common/Minimal/crhook.c
Update to V5.0.2
[freertos] / Demo / Common / Minimal / crhook.c
1 /*\r
2         FreeRTOS.org V5.0.2 - Copyright (C) 2003-2008 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
30     * and even write all or part of your application on your behalf.          *\r
31     * See http://www.OpenRTOS.com for details of the services we provide to   *\r
32     * expedite your project.                                                  *\r
33     *                                                                         *\r
34     ***************************************************************************\r
35     ***************************************************************************\r
36 \r
37         Please ensure to read the configuration and relevant port sections of the\r
38         online documentation.\r
39 \r
40         http://www.FreeRTOS.org - Documentation, latest information, license and \r
41         contact details.\r
42 \r
43         http://www.SafeRTOS.com - A version that is certified for use in safety \r
44         critical systems.\r
45 \r
46         http://www.OpenRTOS.com - Commercial support, development, porting, \r
47         licensing and training services.\r
48 */\r
49 \r
50 /*\r
51  * This demo file demonstrates how to send data between an ISR and a \r
52  * co-routine.  A tick hook function is used to periodically pass data between\r
53  * the RTOS tick and a set of 'hook' co-routines.\r
54  *\r
55  * hookNUM_HOOK_CO_ROUTINES co-routines are created.  Each co-routine blocks\r
56  * to wait for a character to be received on a queue from the tick ISR, checks\r
57  * to ensure the character received was that expected, then sends the number\r
58  * back to the tick ISR on a different queue.\r
59  * \r
60  * The tick ISR checks the numbers received back from the 'hook' co-routines \r
61  * matches the number previously sent.\r
62  *\r
63  * If at any time a queue function returns unexpectedly, or an incorrect value\r
64  * is received either by the tick hook or a co-routine then an error is \r
65  * latched.\r
66  *\r
67  * This demo relies on each 'hook' co-routine to execute between each \r
68  * hookTICK_CALLS_BEFORE_POST tick interrupts.  This and the heavy use of \r
69  * queues from within an interrupt may result in an error being detected on \r
70  * slower targets simply due to timing.\r
71  */\r
72 \r
73 /* Scheduler includes. */\r
74 #include "FreeRTOS.h"\r
75 #include "croutine.h"\r
76 #include "queue.h"\r
77 \r
78 /* Demo application includes. */\r
79 #include "crhook.h"\r
80 \r
81 /* The number of 'hook' co-routines that are to be created. */\r
82 #define hookNUM_HOOK_CO_ROUTINES        ( 4 )\r
83 \r
84 /* The number of times the tick hook should be called before a character is \r
85 posted to the 'hook' co-routines. */\r
86 #define hookTICK_CALLS_BEFORE_POST      ( 500 )\r
87 \r
88 /* There should never be more than one item in any queue at any time. */\r
89 #define hookHOOK_QUEUE_LENGTH           ( 1 )\r
90 \r
91 /* Don't block when initially posting to the queue. */\r
92 #define hookNO_BLOCK_TIME               ( 0 )\r
93 \r
94 /* The priority relative to other co-routines (rather than tasks) that the\r
95 'hook' co-routines should take. */\r
96 #define mainHOOK_CR_PRIORITY                    ( 1 )\r
97 /*-----------------------------------------------------------*/\r
98 \r
99 /*\r
100  * The co-routine function itself.\r
101  */\r
102 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex );\r
103 \r
104 \r
105 /*\r
106  * The tick hook function.  This receives a number from each 'hook' co-routine\r
107  * then sends a number to each co-routine.  An error is flagged if a send or \r
108  * receive fails, or an unexpected number is received.\r
109  */\r
110 void vApplicationTickHook( void );\r
111 \r
112 /*-----------------------------------------------------------*/\r
113 \r
114 /* Queues used to send data FROM a co-routine TO the tick hook function.\r
115 The hook functions received (Rx's) on these queues.  One queue per\r
116 'hook' co-routine. */\r
117 static xQueueHandle xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
118 \r
119 /* Queues used to send data FROM the tick hook TO a co-routine function.\r
120 The hood function transmits (Tx's) on these queues.  One queue per\r
121 'hook' co-routine. */\r
122 static xQueueHandle xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
123 \r
124 /* Set to true if an error is detected at any time. */\r
125 static portBASE_TYPE xCoRoutineErrorDetected = pdFALSE;\r
126 \r
127 /*-----------------------------------------------------------*/\r
128 \r
129 void vStartHookCoRoutines( void )\r
130 {\r
131 unsigned portBASE_TYPE uxIndex, uxValueToPost = 0;\r
132 \r
133         for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )\r
134         {\r
135                 /* Create a queue to transmit to and receive from each 'hook' \r
136                 co-routine. */\r
137                 xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) );\r
138                 xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) );\r
139 \r
140                 /* To start things off the tick hook function expects the queue it \r
141                 uses to receive data to contain a value.  */\r
142                 xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );\r
143 \r
144                 /* Create the 'hook' co-routine itself. */\r
145                 xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex );\r
146         }\r
147 }\r
148 /*-----------------------------------------------------------*/\r
149 \r
150 static unsigned portBASE_TYPE uxCallCounter = 0, uxNumberToPost = 0;\r
151 void vApplicationTickHook( void )\r
152 {\r
153 unsigned portBASE_TYPE uxReceivedNumber;\r
154 signed portBASE_TYPE xIndex, xCoRoutineWoken;\r
155 \r
156         /* Is it time to talk to the 'hook' co-routines again? */\r
157         uxCallCounter++;\r
158         if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )\r
159         {\r
160                 uxCallCounter = 0;\r
161 \r
162                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
163                 {\r
164                         xCoRoutineWoken = pdFALSE;\r
165                         if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )\r
166                         {\r
167                                 /* There is no reason why we would not expect the queue to \r
168                                 contain a value. */\r
169                                 xCoRoutineErrorDetected = pdTRUE;\r
170                         }\r
171                         else\r
172                         {\r
173                                 /* Each queue used to receive data from the 'hook' co-routines \r
174                                 should contain the number we last posted to the same co-routine. */\r
175                                 if( uxReceivedNumber != uxNumberToPost )\r
176                                 {\r
177                                         xCoRoutineErrorDetected = pdTRUE;\r
178                                 }\r
179 \r
180                                 /* Nothing should be blocked waiting to post to the queue. */\r
181                                 if( xCoRoutineWoken != pdFALSE )\r
182                                 {\r
183                                         xCoRoutineErrorDetected = pdTRUE;\r
184                                 }\r
185                         }\r
186                 }\r
187 \r
188                 /* Start the next cycle by posting the next number onto each Tx queue. */\r
189                 uxNumberToPost++;\r
190 \r
191                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
192                 {\r
193                         if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )\r
194                         {\r
195                                 /* Posting to the queue should have woken the co-routine that \r
196                                 was blocked on the queue. */\r
197                                 xCoRoutineErrorDetected = pdTRUE;\r
198                         }\r
199                 }\r
200         }\r
201 }\r
202 /*-----------------------------------------------------------*/\r
203 \r
204 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
205 {\r
206 static unsigned portBASE_TYPE uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];\r
207 portBASE_TYPE xResult;\r
208 \r
209         /* Each co-routine MUST start with a call to crSTART(); */\r
210         crSTART( xHandle );\r
211 \r
212         for( ;; )\r
213         {\r
214                 /* Wait to receive a value from the tick hook. */\r
215                 xResult = pdFAIL;\r
216                 crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );\r
217 \r
218                 /* There is no reason why we should not have received something on\r
219                 the queue. */\r
220                 if( xResult != pdPASS )\r
221                 {\r
222                         xCoRoutineErrorDetected = pdTRUE;\r
223                 }\r
224 \r
225                 /* Send the same number back to the idle hook so it can verify it. */\r
226                 xResult = pdFAIL;\r
227                 crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );\r
228                 if( xResult != pdPASS )\r
229                 {\r
230                         /* There is no reason why we should not have been able to post to \r
231                         the queue. */\r
232                         xCoRoutineErrorDetected = pdTRUE;\r
233                 }\r
234         }\r
235 \r
236         /* Each co-routine MUST end with a call to crEND(). */\r
237         crEND();\r
238 }\r
239 /*-----------------------------------------------------------*/\r
240 \r
241 portBASE_TYPE xAreHookCoRoutinesStillRunning( void )\r
242 {\r
243         if( xCoRoutineErrorDetected )\r
244         {\r
245                 return pdFALSE;\r
246         }\r
247         else\r
248         {\r
249                 return pdTRUE;\r
250         }\r
251 }\r
252 \r
253 \r
254 \r