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