]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/crhook.c
576e247e08a6461ae4896d3a65cf117711f9bd84
[freertos] / FreeRTOS / Demo / Common / Minimal / crhook.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*\r
29  * This demo file demonstrates how to send data between an ISR and a\r
30  * co-routine.  A tick hook function is used to periodically pass data between\r
31  * the RTOS tick and a set of 'hook' co-routines.\r
32  *\r
33  * hookNUM_HOOK_CO_ROUTINES co-routines are created.  Each co-routine blocks\r
34  * to wait for a character to be received on a queue from the tick ISR, checks\r
35  * to ensure the character received was that expected, then sends the number\r
36  * back to the tick ISR on a different queue.\r
37  *\r
38  * The tick ISR checks the numbers received back from the 'hook' co-routines\r
39  * matches the number previously sent.\r
40  *\r
41  * If at any time a queue function returns unexpectedly, or an incorrect value\r
42  * is received either by the tick hook or a co-routine then an error is\r
43  * latched.\r
44  *\r
45  * This demo relies on each 'hook' co-routine to execute between each\r
46  * hookTICK_CALLS_BEFORE_POST tick interrupts.  This and the heavy use of\r
47  * queues from within an interrupt may result in an error being detected on\r
48  * slower targets simply due to timing.\r
49  */\r
50 \r
51 /* Scheduler includes. */\r
52 #include "FreeRTOS.h"\r
53 #include "croutine.h"\r
54 #include "queue.h"\r
55 \r
56 /* Demo application includes. */\r
57 #include "crhook.h"\r
58 \r
59 /* The number of 'hook' co-routines that are to be created. */\r
60 #define hookNUM_HOOK_CO_ROUTINES        ( 4 )\r
61 \r
62 /* The number of times the tick hook should be called before a character is\r
63 posted to the 'hook' co-routines. */\r
64 #define hookTICK_CALLS_BEFORE_POST      ( 500 )\r
65 \r
66 /* There should never be more than one item in any queue at any time. */\r
67 #define hookHOOK_QUEUE_LENGTH           ( 1 )\r
68 \r
69 /* Don't block when initially posting to the queue. */\r
70 #define hookNO_BLOCK_TIME               ( 0 )\r
71 \r
72 /* The priority relative to other co-routines (rather than tasks) that the\r
73 'hook' co-routines should take. */\r
74 #define mainHOOK_CR_PRIORITY                    ( 1 )\r
75 /*-----------------------------------------------------------*/\r
76 \r
77 /*\r
78  * The co-routine function itself.\r
79  */\r
80 static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );\r
81 \r
82 \r
83 /*\r
84  * The tick hook function.  This receives a number from each 'hook' co-routine\r
85  * then sends a number to each co-routine.  An error is flagged if a send or\r
86  * receive fails, or an unexpected number is received.\r
87  */\r
88 void vApplicationTickHook( void );\r
89 \r
90 /*-----------------------------------------------------------*/\r
91 \r
92 /* Queues used to send data FROM a co-routine TO the tick hook function.\r
93 The hook functions received (Rx's) on these queues.  One queue per\r
94 'hook' co-routine. */\r
95 static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
96 \r
97 /* Queues used to send data FROM the tick hook TO a co-routine function.\r
98 The hood function transmits (Tx's) on these queues.  One queue per\r
99 'hook' co-routine. */\r
100 static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];\r
101 \r
102 /* Set to true if an error is detected at any time. */\r
103 static BaseType_t xCoRoutineErrorDetected = pdFALSE;\r
104 \r
105 /*-----------------------------------------------------------*/\r
106 \r
107 void vStartHookCoRoutines( void )\r
108 {\r
109 UBaseType_t uxIndex, uxValueToPost = 0;\r
110 \r
111         for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )\r
112         {\r
113                 /* Create a queue to transmit to and receive from each 'hook'\r
114                 co-routine. */\r
115                 xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );\r
116                 xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );\r
117 \r
118                 /* To start things off the tick hook function expects the queue it\r
119                 uses to receive data to contain a value.  */\r
120                 xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );\r
121 \r
122                 /* Create the 'hook' co-routine itself. */\r
123                 xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex );\r
124         }\r
125 }\r
126 /*-----------------------------------------------------------*/\r
127 \r
128 static UBaseType_t uxCallCounter = 0, uxNumberToPost = 0;\r
129 void vApplicationTickHook( void )\r
130 {\r
131 UBaseType_t uxReceivedNumber;\r
132 BaseType_t xIndex, xCoRoutineWoken;\r
133 \r
134         /* Is it time to talk to the 'hook' co-routines again? */\r
135         uxCallCounter++;\r
136         if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )\r
137         {\r
138                 uxCallCounter = 0;\r
139 \r
140                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
141                 {\r
142                         xCoRoutineWoken = pdFALSE;\r
143                         if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )\r
144                         {\r
145                                 /* There is no reason why we would not expect the queue to\r
146                                 contain a value. */\r
147                                 xCoRoutineErrorDetected = pdTRUE;\r
148                         }\r
149                         else\r
150                         {\r
151                                 /* Each queue used to receive data from the 'hook' co-routines\r
152                                 should contain the number we last posted to the same co-routine. */\r
153                                 if( uxReceivedNumber != uxNumberToPost )\r
154                                 {\r
155                                         xCoRoutineErrorDetected = pdTRUE;\r
156                                 }\r
157 \r
158                                 /* Nothing should be blocked waiting to post to the queue. */\r
159                                 if( xCoRoutineWoken != pdFALSE )\r
160                                 {\r
161                                         xCoRoutineErrorDetected = pdTRUE;\r
162                                 }\r
163                         }\r
164                 }\r
165 \r
166                 /* Start the next cycle by posting the next number onto each Tx queue. */\r
167                 uxNumberToPost++;\r
168 \r
169                 for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )\r
170                 {\r
171                         if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )\r
172                         {\r
173                                 /* Posting to the queue should have woken the co-routine that\r
174                                 was blocked on the queue. */\r
175                                 xCoRoutineErrorDetected = pdTRUE;\r
176                         }\r
177                 }\r
178         }\r
179 }\r
180 /*-----------------------------------------------------------*/\r
181 \r
182 static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )\r
183 {\r
184 static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];\r
185 BaseType_t xResult;\r
186 \r
187         /* Each co-routine MUST start with a call to crSTART(); */\r
188         crSTART( xHandle );\r
189 \r
190         for( ;; )\r
191         {\r
192                 /* Wait to receive a value from the tick hook. */\r
193                 xResult = pdFAIL;\r
194                 crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );\r
195 \r
196                 /* There is no reason why we should not have received something on\r
197                 the queue. */\r
198                 if( xResult != pdPASS )\r
199                 {\r
200                         xCoRoutineErrorDetected = pdTRUE;\r
201                 }\r
202 \r
203                 /* Send the same number back to the idle hook so it can verify it. */\r
204                 xResult = pdFAIL;\r
205                 crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );\r
206                 if( xResult != pdPASS )\r
207                 {\r
208                         /* There is no reason why we should not have been able to post to\r
209                         the queue. */\r
210                         xCoRoutineErrorDetected = pdTRUE;\r
211                 }\r
212         }\r
213 \r
214         /* Each co-routine MUST end with a call to crEND(). */\r
215         crEND();\r
216 }\r
217 /*-----------------------------------------------------------*/\r
218 \r
219 BaseType_t xAreHookCoRoutinesStillRunning( void )\r
220 {\r
221         if( xCoRoutineErrorDetected )\r
222         {\r
223                 return pdFALSE;\r
224         }\r
225         else\r
226         {\r
227                 return pdTRUE;\r
228         }\r
229 }\r
230 \r
231 \r
232 \r