]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/crhook.c
Update version number.
[freertos] / FreeRTOS / Demo / Common / Minimal / crhook.c
1 /*\r
2     FreeRTOS V7.5.1 - Copyright (C) 2013 Real Time Engineers Ltd.\r
3 \r
4     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
5 \r
6     ***************************************************************************\r
7      *                                                                       *\r
8      *    FreeRTOS provides completely free yet professionally developed,    *\r
9      *    robust, strictly quality controlled, supported, and cross          *\r
10      *    platform software that has become a de facto standard.             *\r
11      *                                                                       *\r
12      *    Help yourself get started quickly and support the FreeRTOS         *\r
13      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
14      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
15      *                                                                       *\r
16      *    Thank you!                                                         *\r
17      *                                                                       *\r
18     ***************************************************************************\r
19 \r
20     This file is part of the FreeRTOS distribution.\r
21 \r
22     FreeRTOS is free software; you can redistribute it and/or modify it under\r
23     the terms of the GNU General Public License (version 2) as published by the\r
24     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
25 \r
26     >>! NOTE: The modification to the GPL is included to allow you to distribute\r
27     >>! a combined work that includes FreeRTOS without being obliged to provide\r
28     >>! the source code for proprietary components outside of the FreeRTOS\r
29     >>! kernel.\r
30 \r
31     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
32     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
33     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
34     link: http://www.freertos.org/a00114.html\r
35 \r
36     1 tab == 4 spaces!\r
37 \r
38     ***************************************************************************\r
39      *                                                                       *\r
40      *    Having a problem?  Start by reading the FAQ "My application does   *\r
41      *    not run, what could be wrong?"                                     *\r
42      *                                                                       *\r
43      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
44      *                                                                       *\r
45     ***************************************************************************\r
46 \r
47     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
48     license and Real Time Engineers Ltd. contact details.\r
49 \r
50     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
51     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
52     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
53 \r
54     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
55     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
56     licenses offer ticketed support, indemnification and middleware.\r
57 \r
58     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
59     engineered and independently SIL3 certified version for use in safety and\r
60     mission critical applications that require provable dependability.\r
61 \r
62     1 tab == 4 spaces!\r
63 */\r
64 \r
65 /*\r
66  * This demo file demonstrates how to send data between an ISR and a \r
67  * co-routine.  A tick hook function is used to periodically pass data between\r
68  * the RTOS tick and a set of 'hook' co-routines.\r
69  *\r
70  * hookNUM_HOOK_CO_ROUTINES co-routines are created.  Each co-routine blocks\r
71  * to wait for a character to be received on a queue from the tick ISR, checks\r
72  * to ensure the character received was that expected, then sends the number\r
73  * back to the tick ISR on a different queue.\r
74  * \r
75  * The tick ISR checks the numbers received back from the 'hook' co-routines \r
76  * matches the number previously sent.\r
77  *\r
78  * If at any time a queue function returns unexpectedly, or an incorrect value\r
79  * is received either by the tick hook or a co-routine then an error is \r
80  * latched.\r
81  *\r
82  * This demo relies on each 'hook' co-routine to execute between each \r
83  * hookTICK_CALLS_BEFORE_POST tick interrupts.  This and the heavy use of \r
84  * queues from within an interrupt may result in an error being detected on \r
85  * slower targets simply due to timing.\r
86  */\r
87 \r
88 /* Scheduler includes. */\r
89 #include "FreeRTOS.h"\r
90 #include "croutine.h"\r
91 #include "queue.h"\r
92 \r
93 /* Demo application includes. */\r
94 #include "crhook.h"\r
95 \r
96 /* The number of 'hook' co-routines that are to be created. */\r
97 #define hookNUM_HOOK_CO_ROUTINES        ( 4 )\r
98 \r
99 /* The number of times the tick hook should be called before a character is \r
100 posted to the 'hook' co-routines. */\r
101 #define hookTICK_CALLS_BEFORE_POST      ( 500 )\r
102 \r
103 /* There should never be more than one item in any queue at any time. */\r
104 #define hookHOOK_QUEUE_LENGTH           ( 1 )\r
105 \r
106 /* Don't block when initially posting to the queue. */\r
107 #define hookNO_BLOCK_TIME               ( 0 )\r
108 \r
109 /* The priority relative to other co-routines (rather than tasks) that the\r
110 'hook' co-routines should take. */\r
111 #define mainHOOK_CR_PRIORITY                    ( 1 )\r
112 /*-----------------------------------------------------------*/\r
113 \r
114 /*\r
115  * The co-routine function itself.\r
116  */\r
117 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex );\r
118 \r
119 \r
120 /*\r
121  * The tick hook function.  This receives a number from each 'hook' co-routine\r
122  * then sends a number to each co-routine.  An error is flagged if a send or \r
123  * receive fails, or an unexpected number is received.\r
124  */\r
125 void vApplicationTickHook( void );\r
126 \r
127 /*-----------------------------------------------------------*/\r
128 \r
129 /* Queues used to send data FROM a co-routine TO the tick hook function.\r
130 The hook functions received (Rx's) on these queues.  One queue per\r
131 'hook' co-routine. */\r
132 static xQueueHandle xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
133 \r
134 /* Queues used to send data FROM the tick hook TO a co-routine function.\r
135 The hood function transmits (Tx's) on these queues.  One queue per\r
136 'hook' co-routine. */\r
137 static xQueueHandle xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
138 \r
139 /* Set to true if an error is detected at any time. */\r
140 static portBASE_TYPE xCoRoutineErrorDetected = pdFALSE;\r
141 \r
142 /*-----------------------------------------------------------*/\r
143 \r
144 void vStartHookCoRoutines( void )\r
145 {\r
146 unsigned portBASE_TYPE uxIndex, uxValueToPost = 0;\r
147 \r
148         for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )\r
149         {\r
150                 /* Create a queue to transmit to and receive from each 'hook' \r
151                 co-routine. */\r
152                 xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) );\r
153                 xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) );\r
154 \r
155                 /* To start things off the tick hook function expects the queue it \r
156                 uses to receive data to contain a value.  */\r
157                 xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );\r
158 \r
159                 /* Create the 'hook' co-routine itself. */\r
160                 xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex );\r
161         }\r
162 }\r
163 /*-----------------------------------------------------------*/\r
164 \r
165 static unsigned portBASE_TYPE uxCallCounter = 0, uxNumberToPost = 0;\r
166 void vApplicationTickHook( void )\r
167 {\r
168 unsigned portBASE_TYPE uxReceivedNumber;\r
169 signed portBASE_TYPE xIndex, xCoRoutineWoken;\r
170 \r
171         /* Is it time to talk to the 'hook' co-routines again? */\r
172         uxCallCounter++;\r
173         if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )\r
174         {\r
175                 uxCallCounter = 0;\r
176 \r
177                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
178                 {\r
179                         xCoRoutineWoken = pdFALSE;\r
180                         if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )\r
181                         {\r
182                                 /* There is no reason why we would not expect the queue to \r
183                                 contain a value. */\r
184                                 xCoRoutineErrorDetected = pdTRUE;\r
185                         }\r
186                         else\r
187                         {\r
188                                 /* Each queue used to receive data from the 'hook' co-routines \r
189                                 should contain the number we last posted to the same co-routine. */\r
190                                 if( uxReceivedNumber != uxNumberToPost )\r
191                                 {\r
192                                         xCoRoutineErrorDetected = pdTRUE;\r
193                                 }\r
194 \r
195                                 /* Nothing should be blocked waiting to post to the queue. */\r
196                                 if( xCoRoutineWoken != pdFALSE )\r
197                                 {\r
198                                         xCoRoutineErrorDetected = pdTRUE;\r
199                                 }\r
200                         }\r
201                 }\r
202 \r
203                 /* Start the next cycle by posting the next number onto each Tx queue. */\r
204                 uxNumberToPost++;\r
205 \r
206                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
207                 {\r
208                         if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )\r
209                         {\r
210                                 /* Posting to the queue should have woken the co-routine that \r
211                                 was blocked on the queue. */\r
212                                 xCoRoutineErrorDetected = pdTRUE;\r
213                         }\r
214                 }\r
215         }\r
216 }\r
217 /*-----------------------------------------------------------*/\r
218 \r
219 static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )\r
220 {\r
221 static unsigned portBASE_TYPE uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];\r
222 portBASE_TYPE xResult;\r
223 \r
224         /* Each co-routine MUST start with a call to crSTART(); */\r
225         crSTART( xHandle );\r
226 \r
227         for( ;; )\r
228         {\r
229                 /* Wait to receive a value from the tick hook. */\r
230                 xResult = pdFAIL;\r
231                 crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );\r
232 \r
233                 /* There is no reason why we should not have received something on\r
234                 the queue. */\r
235                 if( xResult != pdPASS )\r
236                 {\r
237                         xCoRoutineErrorDetected = pdTRUE;\r
238                 }\r
239 \r
240                 /* Send the same number back to the idle hook so it can verify it. */\r
241                 xResult = pdFAIL;\r
242                 crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );\r
243                 if( xResult != pdPASS )\r
244                 {\r
245                         /* There is no reason why we should not have been able to post to \r
246                         the queue. */\r
247                         xCoRoutineErrorDetected = pdTRUE;\r
248                 }\r
249         }\r
250 \r
251         /* Each co-routine MUST end with a call to crEND(). */\r
252         crEND();\r
253 }\r
254 /*-----------------------------------------------------------*/\r
255 \r
256 portBASE_TYPE xAreHookCoRoutinesStillRunning( void )\r
257 {\r
258         if( xCoRoutineErrorDetected )\r
259         {\r
260                 return pdFALSE;\r
261         }\r
262         else\r
263         {\r
264                 return pdTRUE;\r
265         }\r
266 }\r
267 \r
268 \r
269 \r