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