]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RL78_E2Studio_GCC/src/Common-Demo-Tasks/blocktim.c
Fix spelling issues.
[freertos] / FreeRTOS / Demo / RL78_E2Studio_GCC / src / Common-Demo-Tasks / blocktim.c
1 /*\r
2  * FreeRTOS Kernel V10.1.0\r
3  * Copyright (C) 2018 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 file contains some test scenarios that ensure tasks do not exit queue\r
30  * send or receive functions prematurely.  A description of the tests is\r
31  * included within the code.\r
32  */\r
33 \r
34 /* Kernel includes. */\r
35 #include "FreeRTOS.h"\r
36 #include "task.h"\r
37 #include "queue.h"\r
38 \r
39 /* Demo includes. */\r
40 #include "blocktim.h"\r
41 \r
42 /* Task priorities.  Allow these to be overridden. */\r
43 #ifndef bktPRIMARY_PRIORITY\r
44         #define bktPRIMARY_PRIORITY             ( configMAX_PRIORITIES - 3 )\r
45 #endif\r
46 \r
47 #ifndef bktSECONDARY_PRIORITY\r
48         #define bktSECONDARY_PRIORITY   ( configMAX_PRIORITIES - 4 )\r
49 #endif\r
50 \r
51 /* Task behaviour. */\r
52 #define bktQUEUE_LENGTH                         ( 5 )\r
53 #define bktSHORT_WAIT                           ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS )\r
54 #define bktPRIMARY_BLOCK_TIME           ( 10 )\r
55 #define bktALLOWABLE_MARGIN                     ( 15 )\r
56 #define bktTIME_TO_BLOCK                        ( 175 )\r
57 #define bktDONT_BLOCK                           ( ( TickType_t ) 0 )\r
58 #define bktRUN_INDICATOR                        ( ( unsigned portBASE_TYPE ) 0x55 )\r
59 \r
60 /* The queue on which the tasks block. */\r
61 static QueueHandle_t xTestQueue;\r
62 \r
63 /* Handle to the secondary task is required by the primary task for calls\r
64 to vTaskSuspend/Resume(). */\r
65 static TaskHandle_t xSecondary;\r
66 \r
67 /* Used to ensure that tasks are still executing without error. */\r
68 static volatile portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;\r
69 static volatile portBASE_TYPE xErrorOccurred = pdFALSE;\r
70 \r
71 /* Provides a simple mechanism for the primary task to know when the\r
72 secondary task has executed. */\r
73 static volatile unsigned portBASE_TYPE xRunIndicator;\r
74 \r
75 /* The two test tasks.  Their behaviour is commented within the files. */\r
76 static void vPrimaryBlockTimeTestTask( void *pvParameters );\r
77 static void vSecondaryBlockTimeTestTask( void *pvParameters );\r
78 \r
79 /*-----------------------------------------------------------*/\r
80 \r
81 void vCreateBlockTimeTasks( void )\r
82 {\r
83         /* Create the queue on which the two tasks block. */\r
84     xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );\r
85 \r
86         /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
87         in use.  The queue registry is provided as a means for kernel aware\r
88         debuggers to locate queues and has no purpose if a kernel aware debugger\r
89         is not being used.  The call to vQueueAddToRegistry() will be removed\r
90         by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is\r
91         defined to be less than 1. */\r
92         vQueueAddToRegistry( xTestQueue, ( signed char * ) "Block_Time_Queue" );\r
93 \r
94         /* Create the two test tasks. */\r
95         xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
96         xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );\r
97 }\r
98 /*-----------------------------------------------------------*/\r
99 \r
100 static void vPrimaryBlockTimeTestTask( void *pvParameters )\r
101 {\r
102 portBASE_TYPE xItem, xData;\r
103 TickType_t xTimeWhenBlocking;\r
104 TickType_t xTimeToBlock, xBlockedTime;\r
105 \r
106         ( void ) pvParameters;\r
107 \r
108         for( ;; )\r
109         {\r
110                 /*********************************************************************\r
111         Test 1\r
112 \r
113         Simple block time wakeup test on queue receives. */\r
114                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
115                 {\r
116                         /* The queue is empty. Attempt to read from the queue using a block\r
117                         time.  When we wake, ensure the delta in time is as expected. */\r
118                         xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
119 \r
120                         xTimeWhenBlocking = xTaskGetTickCount();\r
121 \r
122                         /* We should unblock after xTimeToBlock having not received\r
123                         anything on the queue. */\r
124                         if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )\r
125                         {\r
126                                 xErrorOccurred = pdTRUE;\r
127                         }\r
128 \r
129                         /* How long were we blocked for? */\r
130                         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
131 \r
132                         if( xBlockedTime < xTimeToBlock )\r
133                         {\r
134                                 /* Should not have blocked for less than we requested. */\r
135                                 xErrorOccurred = pdTRUE;\r
136                         }\r
137 \r
138                         if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
139                         {\r
140                                 /* Should not have blocked for longer than we requested,\r
141                                 although we would not necessarily run as soon as we were\r
142                                 unblocked so a margin is allowed. */\r
143                                 xErrorOccurred = pdTRUE;\r
144                         }\r
145                 }\r
146 \r
147                 /*********************************************************************\r
148         Test 2\r
149 \r
150         Simple block time wakeup test on queue sends.\r
151 \r
152                 First fill the queue.  It should be empty so all sends should pass. */\r
153                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
154                 {\r
155                         if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
156                         {\r
157                                 xErrorOccurred = pdTRUE;\r
158                         }\r
159 \r
160                         #if configUSE_PREEMPTION == 0\r
161                                 taskYIELD();\r
162                         #endif\r
163                 }\r
164 \r
165                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
166                 {\r
167                         /* The queue is full. Attempt to write to the queue using a block\r
168                         time.  When we wake, ensure the delta in time is as expected. */\r
169                         xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
170 \r
171                         xTimeWhenBlocking = xTaskGetTickCount();\r
172 \r
173                         /* We should unblock after xTimeToBlock having not received\r
174                         anything on the queue. */\r
175                         if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )\r
176                         {\r
177                                 xErrorOccurred = pdTRUE;\r
178                         }\r
179 \r
180                         /* How long were we blocked for? */\r
181                         xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
182 \r
183                         if( xBlockedTime < xTimeToBlock )\r
184                         {\r
185                                 /* Should not have blocked for less than we requested. */\r
186                                 xErrorOccurred = pdTRUE;\r
187                         }\r
188 \r
189                         if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
190                         {\r
191                                 /* Should not have blocked for longer than we requested,\r
192                                 although we would not necessarily run as soon as we were\r
193                                 unblocked so a margin is allowed. */\r
194                                 xErrorOccurred = pdTRUE;\r
195                         }\r
196                 }\r
197 \r
198                 /*********************************************************************\r
199         Test 3\r
200 \r
201                 Wake the other task, it will block attempting to post to the queue.\r
202                 When we read from the queue the other task will wake, but before it\r
203                 can run we will post to the queue again.  When the other task runs it\r
204                 will find the queue still full, even though it was woken.  It should\r
205                 recognise that its block time has not expired and return to block for\r
206                 the remains of its block time.\r
207 \r
208                 Wake the other task so it blocks attempting to post to the already\r
209                 full queue. */\r
210                 xRunIndicator = 0;\r
211                 vTaskResume( xSecondary );\r
212 \r
213                 /* We need to wait a little to ensure the other task executes. */\r
214                 while( xRunIndicator != bktRUN_INDICATOR )\r
215                 {\r
216                         /* The other task has not yet executed. */\r
217                         vTaskDelay( bktSHORT_WAIT );\r
218                 }\r
219                 /* Make sure the other task is blocked on the queue. */\r
220                 vTaskDelay( bktSHORT_WAIT );\r
221                 xRunIndicator = 0;\r
222 \r
223                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
224                 {\r
225                         /* Now when we make space on the queue the other task should wake\r
226                         but not execute as this task has higher priority. */\r
227                         if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
228                         {\r
229                                 xErrorOccurred = pdTRUE;\r
230                         }\r
231 \r
232                         /* Now fill the queue again before the other task gets a chance to\r
233                         execute.  If the other task had executed we would find the queue\r
234                         full ourselves, and the other task have set xRunIndicator. */\r
235                         if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
236                         {\r
237                                 xErrorOccurred = pdTRUE;\r
238                         }\r
239 \r
240                         if( xRunIndicator == bktRUN_INDICATOR )\r
241                         {\r
242                                 /* The other task should not have executed. */\r
243                                 xErrorOccurred = pdTRUE;\r
244                         }\r
245 \r
246                         /* Raise the priority of the other task so it executes and blocks\r
247                         on the queue again. */\r
248                         vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
249 \r
250                         /* The other task should now have re-blocked without exiting the\r
251                         queue function. */\r
252                         if( xRunIndicator == bktRUN_INDICATOR )\r
253                         {\r
254                                 /* The other task should not have executed outside of the\r
255                                 queue function. */\r
256                                 xErrorOccurred = pdTRUE;\r
257                         }\r
258 \r
259                         /* Set the priority back down. */\r
260                         vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );\r
261                 }\r
262 \r
263                 /* Let the other task timeout.  When it unblockes it will check that it\r
264                 unblocked at the correct time, then suspend itself. */\r
265                 while( xRunIndicator != bktRUN_INDICATOR )\r
266                 {\r
267                         vTaskDelay( bktSHORT_WAIT );\r
268                 }\r
269                 vTaskDelay( bktSHORT_WAIT );\r
270                 xRunIndicator = 0;\r
271 \r
272 \r
273                 /*********************************************************************\r
274         Test 4\r
275 \r
276                 As per test 3 - but with the send and receive the other way around.\r
277                 The other task blocks attempting to read from the queue.\r
278 \r
279                 Empty the queue.  We should find that it is full. */\r
280                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
281                 {\r
282                         if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
283                         {\r
284                                 xErrorOccurred = pdTRUE;\r
285                         }\r
286                 }\r
287 \r
288                 /* Wake the other task so it blocks attempting to read from  the\r
289                 already empty queue. */\r
290                 vTaskResume( xSecondary );\r
291 \r
292                 /* We need to wait a little to ensure the other task executes. */\r
293                 while( xRunIndicator != bktRUN_INDICATOR )\r
294                 {\r
295                         vTaskDelay( bktSHORT_WAIT );\r
296                 }\r
297                 vTaskDelay( bktSHORT_WAIT );\r
298                 xRunIndicator = 0;\r
299 \r
300                 for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
301                 {\r
302                         /* Now when we place an item on the queue the other task should\r
303                         wake but not execute as this task has higher priority. */\r
304                         if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
305                         {\r
306                                 xErrorOccurred = pdTRUE;\r
307                         }\r
308 \r
309                         /* Now empty the queue again before the other task gets a chance to\r
310                         execute.  If the other task had executed we would find the queue\r
311                         empty ourselves, and the other task would be suspended. */\r
312                         if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
313                         {\r
314                                 xErrorOccurred = pdTRUE;\r
315                         }\r
316 \r
317                         if( xRunIndicator == bktRUN_INDICATOR )\r
318                         {\r
319                                 /* The other task should not have executed. */\r
320                                 xErrorOccurred = pdTRUE;\r
321                         }\r
322 \r
323                         /* Raise the priority of the other task so it executes and blocks\r
324                         on the queue again. */\r
325                         vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
326 \r
327                         /* The other task should now have re-blocked without exiting the\r
328                         queue function. */\r
329                         if( xRunIndicator == bktRUN_INDICATOR )\r
330                         {\r
331                                 /* The other task should not have executed outside of the\r
332                                 queue function. */\r
333                                 xErrorOccurred = pdTRUE;\r
334                         }\r
335                         vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );\r
336                 }\r
337 \r
338                 /* Let the other task timeout.  When it unblockes it will check that it\r
339                 unblocked at the correct time, then suspend itself. */\r
340                 while( xRunIndicator != bktRUN_INDICATOR )\r
341                 {\r
342                         vTaskDelay( bktSHORT_WAIT );\r
343                 }\r
344                 vTaskDelay( bktSHORT_WAIT );\r
345 \r
346                 xPrimaryCycles++;\r
347         }\r
348 }\r
349 /*-----------------------------------------------------------*/\r
350 \r
351 static void vSecondaryBlockTimeTestTask( void *pvParameters )\r
352 {\r
353 TickType_t xTimeWhenBlocking, xBlockedTime;\r
354 portBASE_TYPE xData;\r
355 \r
356         ( void ) pvParameters;\r
357 \r
358         for( ;; )\r
359         {\r
360                 /*********************************************************************\r
361         Test 1 and 2\r
362 \r
363                 This task does does not participate in these tests. */\r
364                 vTaskSuspend( NULL );\r
365 \r
366                 /*********************************************************************\r
367         Test 3\r
368 \r
369                 The first thing we do is attempt to read from the queue.  It should be\r
370                 full so we block.  Note the time before we block so we can check the\r
371                 wake time is as per that expected. */\r
372                 xTimeWhenBlocking = xTaskGetTickCount();\r
373 \r
374                 /* We should unblock after bktTIME_TO_BLOCK having not sent\r
375                 anything to the queue. */\r
376                 xData = 0;\r
377                 xRunIndicator = bktRUN_INDICATOR;\r
378                 if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )\r
379                 {\r
380                         xErrorOccurred = pdTRUE;\r
381                 }\r
382 \r
383                 /* How long were we inside the send function? */\r
384                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
385 \r
386                 /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
387                 if( xBlockedTime < bktTIME_TO_BLOCK )\r
388                 {\r
389                         xErrorOccurred = pdTRUE;\r
390                 }\r
391 \r
392                 /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
393                 either.  A margin is permitted as we would not necessarily run as\r
394                 soon as we unblocked. */\r
395                 if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
396                 {\r
397                         xErrorOccurred = pdTRUE;\r
398                 }\r
399 \r
400                 /* Suspend ready for test 3. */\r
401                 xRunIndicator = bktRUN_INDICATOR;\r
402                 vTaskSuspend( NULL );\r
403 \r
404                 /*********************************************************************\r
405         Test 4\r
406 \r
407                 As per test three, but with the send and receive reversed. */\r
408                 xTimeWhenBlocking = xTaskGetTickCount();\r
409 \r
410                 /* We should unblock after bktTIME_TO_BLOCK having not received\r
411                 anything on the queue. */\r
412                 xRunIndicator = bktRUN_INDICATOR;\r
413                 if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )\r
414                 {\r
415                         xErrorOccurred = pdTRUE;\r
416                 }\r
417 \r
418                 xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
419 \r
420                 /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
421                 if( xBlockedTime < bktTIME_TO_BLOCK )\r
422                 {\r
423                         xErrorOccurred = pdTRUE;\r
424                 }\r
425 \r
426                 /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
427                 either.  A margin is permitted as we would not necessarily run as soon\r
428                 as we unblocked. */\r
429                 if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
430                 {\r
431                         xErrorOccurred = pdTRUE;\r
432                 }\r
433 \r
434                 xRunIndicator = bktRUN_INDICATOR;\r
435 \r
436                 xSecondaryCycles++;\r
437         }\r
438 }\r
439 /*-----------------------------------------------------------*/\r
440 \r
441 portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void )\r
442 {\r
443 static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;\r
444 portBASE_TYPE xReturn = pdPASS;\r
445 \r
446         /* Have both tasks performed at least one cycle since this function was\r
447         last called? */\r
448         if( xPrimaryCycles == xLastPrimaryCycleCount )\r
449         {\r
450                 xReturn = pdFAIL;\r
451         }\r
452 \r
453         if( xSecondaryCycles == xLastSecondaryCycleCount )\r
454         {\r
455                 xReturn = pdFAIL;\r
456         }\r
457 \r
458         if( xErrorOccurred == pdTRUE )\r
459         {\r
460                 xReturn = pdFAIL;\r
461         }\r
462 \r
463         xLastSecondaryCycleCount = xSecondaryCycles;\r
464         xLastPrimaryCycleCount = xPrimaryCycles;\r
465 \r
466         return xReturn;\r
467 }\r