]> begriffs open source - freertos/blob - Demo/Common/Minimal/crhook.c
Update to V4.6.1 - including PIC32MX port.
[freertos] / Demo / Common / Minimal / crhook.c
1 /*\r
2         FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 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         See http://www.FreeRTOS.org for documentation, latest information, license \r
28         and contact details.  Please ensure to read the configuration and relevant \r
29         port sections of the online documentation.\r
30 \r
31         Also see http://www.SafeRTOS.com a version that has been certified for use\r
32         in safety critical systems, plus commercial licensing, development and\r
33         support options.\r
34         ***************************************************************************\r
35 */\r
36 \r
37 /*\r
38  * This demo file demonstrates how to send data between an ISR and a \r
39  * co-routine.  A tick hook function is used to periodically pass data between\r
40  * the RTOS tick and a set of 'hook' co-routines.\r
41  *\r
42  * hookNUM_HOOK_CO_ROUTINES co-routines are created.  Each co-routine blocks\r
43  * to wait for a character to be received on a queue from the tick ISR, checks\r
44  * to ensure the character received was that expected, then sends the number\r
45  * back to the tick ISR on a different queue.\r
46  * \r
47  * The tick ISR checks the numbers received back from the 'hook' co-routines \r
48  * matches the number previously sent.\r
49  *\r
50  * If at any time a queue function returns unexpectedly, or an incorrect value\r
51  * is received either by the tick hook or a co-routine then an error is \r
52  * latched.\r
53  *\r
54  * This demo relies on each 'hook' co-routine to execute between each \r
55  * hookTICK_CALLS_BEFORE_POST tick interrupts.  This and the heavy use of \r
56  * queues from within an interrupt may result in an error being detected on \r
57  * slower targets simply due to timing.\r
58  */\r
59 \r
60 /* Scheduler includes. */\r
61 #include "FreeRTOS.h"\r
62 #include "croutine.h"\r
63 #include "queue.h"\r
64 \r
65 /* Demo application includes. */\r
66 #include "crhook.h"\r
67 \r
68 /* The number of 'hook' co-routines that are to be created. */\r
69 #define hookNUM_HOOK_CO_ROUTINES        ( 4 )\r
70 \r
71 /* The number of times the tick hook should be called before a character is \r
72 posted to the 'hook' co-routines. */\r
73 #define hookTICK_CALLS_BEFORE_POST      ( 250 )\r
74 \r
75 /* There should never be more than one item in any queue at any time. */\r
76 #define hookHOOK_QUEUE_LENGTH           ( 1 )\r
77 \r
78 /* Don't block when initially posting to the queue. */\r
79 #define hookNO_BLOCK_TIME               ( 0 )\r
80 \r
81 /* The priority relative to other co-routines (rather than tasks) that the\r
82 'hook' co-routines should take. */\r
83 #define mainHOOK_CR_PRIORITY                    ( 1 )\r
84 /*-----------------------------------------------------------*/\r
85 \r
86 /*\r
87  * The co-routine function itself.\r
88  */\r
89 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex );\r
90 \r
91 \r
92 /*\r
93  * The tick hook function.  This receives a number from each 'hook' co-routine\r
94  * then sends a number to each co-routine.  An error is flagged if a send or \r
95  * receive fails, or an unexpected number is received.\r
96  */\r
97 void vApplicationTickHook( void );\r
98 \r
99 /*-----------------------------------------------------------*/\r
100 \r
101 /* Queues used to send data FROM a co-routine TO the tick hook function.\r
102 The hook functions received (Rx's) on these queues.  One queue per\r
103 'hook' co-routine. */\r
104 static xQueueHandle xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
105 \r
106 /* Queues used to send data FROM the tick hook TO a co-routine function.\r
107 The hood function transmits (Tx's) on these queues.  One queue per\r
108 'hook' co-routine. */\r
109 static xQueueHandle xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
110 \r
111 /* Set to true if an error is detected at any time. */\r
112 static portBASE_TYPE xCoRoutineErrorDetected = pdFALSE;\r
113 \r
114 /*-----------------------------------------------------------*/\r
115 \r
116 void vStartHookCoRoutines( void )\r
117 {\r
118 unsigned portBASE_TYPE uxIndex, uxValueToPost = 0;\r
119 \r
120         for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )\r
121         {\r
122                 /* Create a queue to transmit to and receive from each 'hook' \r
123                 co-routine. */\r
124                 xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) );\r
125                 xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) );\r
126 \r
127                 /* To start things off the tick hook function expects the queue it \r
128                 uses to receive data to contain a value.  */\r
129                 xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );\r
130 \r
131                 /* Create the 'hook' co-routine itself. */\r
132                 xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex );\r
133         }\r
134 }\r
135 /*-----------------------------------------------------------*/\r
136 \r
137 static unsigned portBASE_TYPE uxCallCounter = 0, uxNumberToPost = 0;\r
138 void vApplicationTickHook( void )\r
139 {\r
140 unsigned portBASE_TYPE uxReceivedNumber;\r
141 signed portBASE_TYPE xIndex, xCoRoutineWoken;\r
142 \r
143         /* Is it time to talk to the 'hook' co-routines again? */\r
144         uxCallCounter++;\r
145         if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )\r
146         {\r
147                 uxCallCounter = 0;\r
148 \r
149                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
150                 {\r
151                         xCoRoutineWoken = pdFALSE;\r
152                         if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )\r
153                         {\r
154                                 /* There is no reason why we would not expect the queue to \r
155                                 contain a value. */\r
156                                 xCoRoutineErrorDetected = pdTRUE;\r
157                         }\r
158                         else\r
159                         {\r
160                                 /* Each queue used to receive data from the 'hook' co-routines \r
161                                 should contain the number we last posted to the same co-routine. */\r
162                                 if( uxReceivedNumber != uxNumberToPost )\r
163                                 {\r
164                                         xCoRoutineErrorDetected = pdTRUE;\r
165                                 }\r
166 \r
167                                 /* Nothing should be blocked waiting to post to the queue. */\r
168                                 if( xCoRoutineWoken != pdFALSE )\r
169                                 {\r
170                                         xCoRoutineErrorDetected = pdTRUE;\r
171                                 }\r
172                         }\r
173                 }\r
174 \r
175                 /* Start the next cycle by posting the next number onto each Tx queue. */\r
176                 uxNumberToPost++;\r
177 \r
178                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
179                 {\r
180                         if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )\r
181                         {\r
182                                 /* Posting to the queue should have woken the co-routine that \r
183                                 was blocked on the queue. */\r
184                                 xCoRoutineErrorDetected = pdTRUE;\r
185                         }\r
186                 }\r
187         }\r
188 }\r
189 /*-----------------------------------------------------------*/\r
190 \r
191 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
192 {\r
193 static unsigned portBASE_TYPE uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];\r
194 portBASE_TYPE xResult;\r
195 \r
196         /* Each co-routine MUST start with a call to crSTART(); */\r
197         crSTART( xHandle );\r
198 \r
199         for( ;; )\r
200         {\r
201                 /* Wait to receive a value from the tick hook. */\r
202                 xResult = pdFAIL;\r
203                 crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );\r
204 \r
205                 /* There is no reason why we should not have received something on\r
206                 the queue. */\r
207                 if( xResult != pdPASS )\r
208                 {\r
209                         xCoRoutineErrorDetected = pdTRUE;\r
210                 }\r
211 \r
212                 /* Send the same number back to the idle hook so it can verify it. */\r
213                 xResult = pdFAIL;\r
214                 crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );\r
215                 if( xResult != pdPASS )\r
216                 {\r
217                         /* There is no reason why we should not have been able to post to \r
218                         the queue. */\r
219                         xCoRoutineErrorDetected = pdTRUE;\r
220                 }\r
221         }\r
222 \r
223         /* Each co-routine MUST end with a call to crEND(). */\r
224         crEND();\r
225 }\r
226 /*-----------------------------------------------------------*/\r
227 \r
228 portBASE_TYPE xAreHookCoRoutinesStillRunning( void )\r
229 {\r
230         if( xCoRoutineErrorDetected )\r
231         {\r
232                 return pdFALSE;\r
233         }\r
234         else\r
235         {\r
236                 return pdTRUE;\r
237         }\r
238 }\r
239 \r
240 \r
241 \r