2 * FreeRTOS Kernel V10.2.1
\r
3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\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
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
31 * This file contains fairly comprehensive checks on the behaviour of event
\r
32 * groups. It is not intended to be a user friendly demonstration of the
\r
35 * NOTE: The tests implemented in this file are informal 'sanity' tests
\r
36 * only and are not part of the module tests that make use of the
\r
37 * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.
\r
41 /* Scheduler include files. */
\r
42 #include "FreeRTOS.h"
\r
44 #include "event_groups.h"
\r
46 /* Demo app includes. */
\r
47 #include "EventGroupsDemo.h"
\r
49 #if( INCLUDE_eTaskGetState != 1 )
\r
50 #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.
\r
53 /* Priorities used by the tasks. */
\r
54 #define ebSET_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
55 #define ebWAIT_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
57 /* Generic bit definitions. */
\r
58 #define ebBIT_0 ( 0x01 )
\r
59 #define ebBIT_1 ( 0x02 )
\r
60 #define ebBIT_2 ( 0x04 )
\r
61 #define ebBIT_3 ( 0x08 )
\r
62 #define ebBIT_4 ( 0x10 )
\r
63 #define ebBIT_5 ( 0x20 )
\r
64 #define ebBIT_6 ( 0x40 )
\r
65 #define ebBIT_7 ( 0x80 )
\r
67 /* Combinations of bits used in the demo. */
\r
68 #define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 )
\r
69 #define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )
\r
71 /* Associate a bit to each task. These bits are used to identify all the tasks
\r
72 that synchronise with the xEventGroupSync() function. */
\r
73 #define ebSET_BIT_TASK_SYNC_BIT ebBIT_0
\r
74 #define ebWAIT_BIT_TASK_SYNC_BIT ebBIT_1
\r
75 #define ebRENDESVOUS_TASK_1_SYNC_BIT ebBIT_2
\r
76 #define ebRENDESVOUS_TASK_2_SYNC_BIT ebBIT_3
\r
77 #define ebALL_SYNC_BITS ( ebSET_BIT_TASK_SYNC_BIT | ebWAIT_BIT_TASK_SYNC_BIT | ebRENDESVOUS_TASK_1_SYNC_BIT | ebRENDESVOUS_TASK_2_SYNC_BIT )
\r
79 /* A block time of zero simply means "don't block". */
\r
80 #define ebDONT_BLOCK ( 0 )
\r
81 #define ebONE_TICK ( ( TickType_t ) 1 )
\r
84 #define ebSHORT_DELAY pdMS_TO_TICKS( ( TickType_t ) 5 )
\r
86 /* Used in the selective bits test which checks no, one or both tasks blocked on
\r
87 event bits in a group are unblocked as appropriate as different bits get set. */
\r
88 #define ebSELECTIVE_BITS_1 0x03
\r
89 #define ebSELECTIVE_BITS_2 0x05
\r
91 #ifndef ebRENDESVOUS_TEST_TASK_STACK_SIZE
\r
92 #define ebRENDESVOUS_TEST_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
\r
95 #ifndef ebEVENT_GROUP_SET_BITS_TEST_TASK_STACK_SIZE
\r
96 #define ebEVENT_GROUP_SET_BITS_TEST_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
\r
99 /*-----------------------------------------------------------*/
\r
102 * NOTE: The tests implemented in this function are informal 'sanity' tests
\r
103 * only and are not part of the module tests that make use of the
\r
104 * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.
\r
106 * The master test task. This task:
\r
108 * 1) Calls prvSelectiveBitsTestMasterFunction() to test the behaviour when two
\r
109 * tasks are blocked on different bits in an event group. The counterpart of
\r
110 * this test is implemented by the prvSelectiveBitsTestSlaveFunction()
\r
111 * function (which is called by the two tasks that block on the event group).
\r
113 * 2) Calls prvBitCombinationTestMasterFunction() to test the behaviour when
\r
114 * just one task is blocked on various combinations of bits within an event
\r
115 * group. The counterpart of this test is implemented within the 'test
\r
118 * 3) Calls prvPerformTaskSyncTests() to test task synchronisation behaviour.
\r
120 static void prvTestMasterTask( void *pvParameters );
\r
123 * A helper task that enables the 'test master' task to perform several
\r
124 * behavioural tests. See the comments above the prvTestMasterTask() prototype
\r
127 static void prvTestSlaveTask( void *pvParameters );
\r
130 * The part of the test that is performed between the 'test master' task and the
\r
131 * 'test slave' task to test the behaviour when the slave blocks on various
\r
132 * event bit combinations.
\r
134 static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );
\r
137 * The part of the test that uses all the tasks to test the task synchronisation
\r
140 static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );
\r
143 * Two instances of prvSyncTask() are created. They start by calling
\r
144 * prvSelectiveBitsTestSlaveFunction() to act as slaves when the test master is
\r
145 * executing the prvSelectiveBitsTestMasterFunction() function. They then loop
\r
146 * to test the task synchronisation (rendezvous) behaviour.
\r
148 static void prvSyncTask( void *pvParameters );
\r
151 * Functions used in a test that blocks two tasks on various different bits
\r
152 * within an event group - then sets each bit in turn and checks that the
\r
153 * correct tasks unblock at the correct times.
\r
155 static BaseType_t prvSelectiveBitsTestMasterFunction( void );
\r
156 static void prvSelectiveBitsTestSlaveFunction( void );
\r
158 /*-----------------------------------------------------------*/
\r
160 /* Variables that are incremented by the tasks on each cycle provided no errors
\r
161 have been found. Used to detect an error or stall in the test cycling. */
\r
162 static volatile uint32_t ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0;
\r
164 /* The event group used by all the task based tests. */
\r
165 static EventGroupHandle_t xEventGroup = NULL;
\r
167 /* The event group used by the interrupt based tests. */
\r
168 static EventGroupHandle_t xISREventGroup = NULL;
\r
170 /* Handles to the tasks that only take part in the synchronisation calls. */
\r
171 static TaskHandle_t xSyncTask1 = NULL, xSyncTask2 = NULL;
\r
173 /*-----------------------------------------------------------*/
\r
175 void vStartEventGroupTasks( void )
\r
177 TaskHandle_t xTestSlaveTaskHandle;
\r
180 * This file contains fairly comprehensive checks on the behaviour of event
\r
181 * groups. It is not intended to be a user friendly demonstration of the
\r
182 * event groups API.
\r
184 * NOTE: The tests implemented in this file are informal 'sanity' tests
\r
185 * only and are not part of the module tests that make use of the
\r
186 * mtCOVERAGE_TEST_MARKER macro within the event groups implementation.
\r
188 * Create the test tasks as described at the top of this file.
\r
190 xTaskCreate( prvTestSlaveTask, "WaitO", ebRENDESVOUS_TEST_TASK_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xTestSlaveTaskHandle );
\r
191 xTaskCreate( prvTestMasterTask, "SetB", ebEVENT_GROUP_SET_BITS_TEST_TASK_STACK_SIZE, ( void * ) xTestSlaveTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL );
\r
192 xTaskCreate( prvSyncTask, "Rndv", ebRENDESVOUS_TEST_TASK_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 );
\r
193 xTaskCreate( prvSyncTask, "Rndv", ebRENDESVOUS_TEST_TASK_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 );
\r
195 /* If the last task was created then the others will have been too. */
\r
196 configASSERT( xSyncTask2 );
\r
198 /* Create the event group used by the ISR tests. The event group used by
\r
199 the tasks is created by the tasks themselves. */
\r
200 xISREventGroup = xEventGroupCreate();
\r
201 configASSERT( xISREventGroup );
\r
203 /*-----------------------------------------------------------*/
\r
205 static void prvTestMasterTask( void *pvParameters )
\r
209 /* The handle to the slave task is passed in as the task parameter. */
\r
210 TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters;
\r
212 /* Avoid compiler warnings. */
\r
213 ( void ) pvParameters;
\r
215 /* Create the event group used by the tasks ready for the initial tests. */
\r
216 xEventGroup = xEventGroupCreate();
\r
217 configASSERT( xEventGroup );
\r
219 /* Perform the tests that block two tasks on different combinations of bits,
\r
220 then set each bit in turn and check the correct tasks unblock at the correct
\r
222 xError = prvSelectiveBitsTestMasterFunction();
\r
226 /* Recreate the event group ready for the next cycle. */
\r
227 xEventGroup = xEventGroupCreate();
\r
228 configASSERT( xEventGroup );
\r
230 /* Perform the tests that check the behaviour when a single task is
\r
231 blocked on various combinations of event bits. */
\r
232 xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle );
\r
234 /* Perform the task synchronisation tests. */
\r
235 xError = prvPerformTaskSyncTests( xError, xTestSlaveTaskHandle );
\r
237 /* Delete the event group. */
\r
238 vEventGroupDelete( xEventGroup );
\r
240 /* Now all the other tasks should have completed and suspended
\r
241 themselves ready for the next go around the loop. */
\r
242 if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
\r
247 if( eTaskGetState( xSyncTask1 ) != eSuspended )
\r
252 if( eTaskGetState( xSyncTask2 ) != eSuspended )
\r
257 /* Only increment the cycle variable if no errors have been detected. */
\r
258 if( xError == pdFALSE )
\r
260 ulTestMasterCycles++;
\r
263 configASSERT( xError == pdFALSE );
\r
266 /*-----------------------------------------------------------*/
\r
268 static void prvSyncTask( void *pvParameters )
\r
270 EventBits_t uxSynchronisationBit, uxReturned;
\r
272 /* A few tests that check the behaviour when two tasks are blocked on
\r
273 various different bits within an event group are performed before this task
\r
274 enters its infinite loop to carry out its main demo function. */
\r
275 prvSelectiveBitsTestSlaveFunction();
\r
277 /* The bit to use to indicate this task is at the synchronisation point is
\r
278 passed in as the task parameter. */
\r
279 uxSynchronisationBit = ( EventBits_t ) pvParameters;
\r
283 /* Now this task takes part in a task synchronisation - sometimes known
\r
284 as a 'rendezvous'. Its execution pattern is controlled by the 'test
\r
285 master' task, which is responsible for taking this task out of the
\r
286 Suspended state when it is time to test the synchronisation behaviour.
\r
287 See: http://www.freertos.org/xEventGroupSync.html. */
\r
288 vTaskSuspend( NULL );
\r
290 /* Set the bit that indicates this task is at the synchronisation
\r
291 point. The first time this is done the 'test master' task has a lower
\r
292 priority than this task so this task will get to the sync point before
\r
293 the set bits task - test this by first calling xEventGroupSync() with
\r
294 a zero block time, and a block time that is too short for the other
\r
295 task, before calling again with a max delay - the first two calls should
\r
296 return before the rendezvous completes, the third only after the
\r
297 rendezvous is complete. */
\r
298 uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
\r
299 uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */
\r
300 ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */
\r
301 ebDONT_BLOCK ); /* The maximum time to wait for the sync condition to be met before giving up. */
\r
303 /* No block time was specified, so as per the comments above, the
\r
304 rendezvous is not expected to have completed yet. */
\r
305 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS );
\r
307 uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
\r
308 uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */
\r
309 ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks taking part in the sync. */
\r
310 ebONE_TICK ); /* The maximum time to wait for the sync condition to be met before giving up. */
\r
312 /* A short block time was specified, so as per the comments above, the
\r
313 rendezvous is not expected to have completed yet. */
\r
314 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS );
\r
316 uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
\r
317 uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */
\r
318 ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */
\r
319 portMAX_DELAY );/* The maximum time to wait for the sync condition to be met before giving up. */
\r
321 /* A max delay was used, so this task should only exit the above
\r
322 function call when the sync condition is met. Check this is the
\r
324 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
\r
326 /* Remove compiler warning if configASSERT() is not defined. */
\r
327 ( void ) uxReturned;
\r
329 /* Wait until the 'test master' task unsuspends this task again. */
\r
330 vTaskSuspend( NULL );
\r
332 /* Set the bit that indicates this task is at the synchronisation
\r
333 point again. This time the 'test master' task has a higher priority
\r
334 than this task so will get to the sync point before this task. */
\r
335 uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );
\r
337 /* Again a max delay was used, so this task should only exit the above
\r
338 function call when the sync condition is met. Check this is the
\r
340 configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
\r
342 /* Block on the event group again. This time the event group is going
\r
343 to be deleted while this task is blocked on it so it is expected that 0
\r
345 uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
\r
346 configASSERT( uxReturned == 0 );
\r
349 /*-----------------------------------------------------------*/
\r
351 static void prvTestSlaveTask( void *pvParameters )
\r
353 EventBits_t uxReturned;
\r
354 BaseType_t xError = pdFALSE;
\r
356 /* Avoid compiler warnings. */
\r
357 ( void ) pvParameters;
\r
361 /**********************************************************************
\r
362 * Part 1: This section is the counterpart to the
\r
363 * prvBitCombinationTestMasterFunction() function which is called by the
\r
364 * test master task.
\r
365 ***********************************************************************
\r
367 This task is controller by the 'test master' task (which is
\r
368 implemented by prvTestMasterTask()). Suspend until resumed by the
\r
369 'test master' task. */
\r
370 vTaskSuspend( NULL );
\r
372 /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get
\r
373 set. Clear the bit on exit. */
\r
374 uxReturned = xEventGroupWaitBits( xEventGroup, /* The event group that contains the event bits being queried. */
\r
375 ebBIT_1, /* The bit to wait for. */
\r
376 pdTRUE, /* Clear the bit on exit. */
\r
377 pdTRUE, /* Wait for all the bits (only one in this case anyway). */
\r
378 portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */
\r
380 /* The 'test master' task set all the bits defined by ebCOMBINED_BITS,
\r
381 only one of which was being waited for by this task. The return value
\r
382 shows the state of the event bits when the task was unblocked, however
\r
383 because the task was waiting for ebBIT_1 and 'clear on exit' was set to
\r
384 the current state of the event bits will have ebBIT_1 clear. */
\r
385 if( uxReturned != ebCOMBINED_BITS )
\r
390 /* Now call xEventGroupWaitBits() again, this time waiting for all the
\r
391 bits in ebCOMBINED_BITS to be set. This call should block until the
\r
392 'test master' task sets ebBIT_1 - which was the bit cleared in the call
\r
393 to xEventGroupWaitBits() above. */
\r
394 uxReturned = xEventGroupWaitBits( xEventGroup,
\r
395 ebCOMBINED_BITS, /* The bits being waited on. */
\r
396 pdFALSE, /* Don't clear the bits on exit. */
\r
397 pdTRUE, /* All the bits must be set to unblock. */
\r
400 /* Were all the bits set? */
\r
401 if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS )
\r
406 /* Suspend again to wait for the 'test master' task. */
\r
407 vTaskSuspend( NULL );
\r
409 /* Now call xEventGroupWaitBits() again, again waiting for all the bits
\r
410 in ebCOMBINED_BITS to be set, but this time clearing the bits when the
\r
411 task is unblocked. */
\r
412 uxReturned = xEventGroupWaitBits( xEventGroup,
\r
413 ebCOMBINED_BITS, /* The bits being waited on. */
\r
414 pdTRUE, /* Clear the bits on exit. */
\r
415 pdTRUE, /* All the bits must be set to unblock. */
\r
418 /* The 'test master' task set all the bits in the event group, so that
\r
419 is the value that should have been returned. The bits defined by
\r
420 ebCOMBINED_BITS will have been clear again in the current value though
\r
421 as 'clear on exit' was set to pdTRUE. */
\r
422 if( uxReturned != ebALL_BITS )
\r
431 /**********************************************************************
\r
432 * Part 2: This section is the counterpart to the
\r
433 * prvPerformTaskSyncTests() function which is called by the
\r
434 * test master task.
\r
435 ***********************************************************************
\r
438 Once again wait for the 'test master' task to unsuspend this task
\r
439 when it is time for the next test. */
\r
440 vTaskSuspend( NULL );
\r
442 /* Now peform a synchronisation with all the other tasks. At this point
\r
443 the 'test master' task has the lowest priority so will get to the sync
\r
444 point after all the other synchronising tasks. */
\r
445 uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the sync. */
\r
446 ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */
\r
447 ebALL_SYNC_BITS, /* The bits to wait for. These bits are set by the other tasks taking part in the sync. */
\r
448 portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */
\r
450 /* A sync with a max delay should only exit when all the synchronisation
\r
452 if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
\r
457 /* ...but now the synchronisation bits should be clear again. Read back
\r
458 the current value of the bits within the event group to check that is
\r
459 the case. Setting the bits to zero will return the bits previous value
\r
460 then leave all the bits clear. */
\r
461 if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )
\r
466 /* Check the bits are indeed 0 now by simply reading then. */
\r
467 if( xEventGroupGetBits( xEventGroup ) != 0 )
\r
472 if( xError == pdFALSE )
\r
474 /* This task is still cycling without finding an error. */
\r
475 ulTestSlaveCycles++;
\r
478 vTaskSuspend( NULL );
\r
480 /* This time sync when the 'test master' task has the highest priority
\r
481 at the point where it sets its sync bit - so this time the 'test master'
\r
482 task will get to the sync point before this task. */
\r
483 uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
\r
485 /* A sync with a max delay should only exit when all the synchronisation
\r
487 if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
\r
492 /* ...but now the sync bits should be clear again. */
\r
493 if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )
\r
498 /* Block on the event group again. This time the event group is going
\r
499 to be deleted while this task is blocked on it, so it is expected that 0
\r
500 will be returned. */
\r
501 uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
\r
503 if( uxReturned != 0 )
\r
508 if( xError == pdFALSE )
\r
510 /* This task is still cycling without finding an error. */
\r
511 ulTestSlaveCycles++;
\r
514 configASSERT( xError == pdFALSE );
\r
517 /*-----------------------------------------------------------*/
\r
519 static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )
\r
521 EventBits_t uxBits;
\r
523 /* The three tasks that take part in the synchronisation (rendezvous) are
\r
524 expected to be in the suspended state at the start of the test. */
\r
525 if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
\r
530 if( eTaskGetState( xSyncTask1 ) != eSuspended )
\r
535 if( eTaskGetState( xSyncTask2 ) != eSuspended )
\r
540 /* Try a synch with no other tasks involved. First set all the bits other
\r
541 than this task's bit. */
\r
542 xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );
\r
544 /* Then wait on just one bit - the bit that is being set. */
\r
545 uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
\r
546 ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */
\r
547 ebSET_BIT_TASK_SYNC_BIT,/* The bits to wait for - in this case it is just waiting for itself. */
\r
548 portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */
\r
550 /* A sync with a max delay should only exit when all the synchronise
\r
551 bits are set...check that is the case. In this case there is only one
\r
552 sync bit anyway. */
\r
553 if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT )
\r
558 /* ...but now the sync bits should be clear again, leaving all the other
\r
559 bits set (as only one bit was being waited for). */
\r
560 if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) )
\r
565 /* Clear all the bits to zero again. */
\r
566 xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );
\r
567 if( xEventGroupGetBits( xEventGroup ) != 0 )
\r
572 /* Unsuspend the other tasks then check they have executed up to the
\r
573 synchronisation point. */
\r
574 vTaskResume( xTestSlaveTaskHandle );
\r
575 vTaskResume( xSyncTask1 );
\r
576 vTaskResume( xSyncTask2 );
\r
578 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
583 if( eTaskGetState( xSyncTask1 ) != eBlocked )
\r
588 if( eTaskGetState( xSyncTask2 ) != eBlocked )
\r
593 /* Set this task's sync bit. */
\r
594 uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
\r
595 ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */
\r
596 ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks that take part in the sync. */
\r
597 portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */
\r
599 /* A sync with a max delay should only exit when all the synchronise
\r
600 bits are set...check that is the case. */
\r
601 if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
\r
606 /* ...but now the sync bits should be clear again. */
\r
607 if( xEventGroupGetBits( xEventGroup ) != 0 )
\r
613 /* The other tasks should now all be suspended again, ready for the next
\r
614 synchronisation. */
\r
615 if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
\r
620 if( eTaskGetState( xSyncTask1 ) != eSuspended )
\r
625 if( eTaskGetState( xSyncTask2 ) != eSuspended )
\r
631 /* Sync again - but this time set the last necessary bit as the
\r
632 highest priority task, rather than the lowest priority task. Unsuspend
\r
633 the other tasks then check they have executed up to the synchronisation
\r
635 vTaskResume( xTestSlaveTaskHandle );
\r
636 vTaskResume( xSyncTask1 );
\r
637 vTaskResume( xSyncTask2 );
\r
639 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
644 if( eTaskGetState( xSyncTask1 ) != eBlocked )
\r
649 if( eTaskGetState( xSyncTask2 ) != eBlocked )
\r
654 /* Raise the priority of this task above that of the other tasks. */
\r
655 vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 );
\r
657 /* Set this task's sync bit. */
\r
658 uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
\r
660 /* A sync with a max delay should only exit when all the synchronisation
\r
662 if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
\r
667 /* ...but now the sync bits should be clear again. */
\r
668 if( xEventGroupGetBits( xEventGroup ) != 0 )
\r
674 /* The other tasks should now all be in the ready state again, but not
\r
675 executed yet as this task still has a higher relative priority. */
\r
676 if( eTaskGetState( xTestSlaveTaskHandle ) != eReady )
\r
681 if( eTaskGetState( xSyncTask1 ) != eReady )
\r
686 if( eTaskGetState( xSyncTask2 ) != eReady )
\r
692 /* Reset the priority of this task back to its original value. */
\r
693 vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );
\r
695 /* Now all the other tasks should have reblocked on the event bits
\r
696 to test the behaviour when the event bits are deleted. */
\r
697 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
702 if( eTaskGetState( xSyncTask1 ) != eBlocked )
\r
707 if( eTaskGetState( xSyncTask2 ) != eBlocked )
\r
714 /*-----------------------------------------------------------*/
\r
716 static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )
\r
718 EventBits_t uxBits;
\r
720 /* Resume the other task. It will block, pending a single bit from
\r
721 within ebCOMBINED_BITS. */
\r
722 vTaskResume( xTestSlaveTaskHandle );
\r
724 /* Ensure the other task is blocked on the task. */
\r
725 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
730 /* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only
\r
731 blocked waiting for one of them. */
\r
732 xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS );
\r
734 /* The 'test slave' task should now have executed, clearing ebBIT_1 (the
\r
735 bit it was blocked on), then re-entered the Blocked state to wait for
\r
736 all the other bits in ebCOMBINED_BITS to be set again. First check
\r
737 ebBIT_1 is clear. */
\r
738 uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
\r
740 if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )
\r
745 /* Ensure the other task is still in the blocked state. */
\r
746 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
751 /* Set all the bits other than ebBIT_1 - which is the bit that must be
\r
752 set before the other task unblocks. */
\r
753 xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 );
\r
755 /* Ensure all the expected bits are still set. */
\r
756 uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
\r
758 if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) )
\r
763 /* Ensure the other task is still in the blocked state. */
\r
764 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
769 /* Now also set ebBIT_1, which should unblock the other task, which will
\r
770 then suspend itself. */
\r
771 xEventGroupSetBits( xEventGroup, ebBIT_1 );
\r
773 /* Ensure the other task is suspended. */
\r
774 if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
\r
779 /* The other task should not have cleared the bits - so all the bits
\r
780 should still be set. */
\r
781 if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS )
\r
786 /* Clear ebBIT_1 again. */
\r
787 if( xEventGroupClearBits( xEventGroup, ebBIT_1 ) != ebALL_BITS )
\r
792 /* Resume the other task - which will wait on all the ebCOMBINED_BITS
\r
793 again - this time clearing the bits when it is unblocked. */
\r
794 vTaskResume( xTestSlaveTaskHandle );
\r
796 /* Ensure the other task is blocked once again. */
\r
797 if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
\r
802 /* Set the bit the other task is waiting for. */
\r
803 xEventGroupSetBits( xEventGroup, ebBIT_1 );
\r
805 /* Ensure the other task is suspended once again. */
\r
806 if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
\r
811 /* The other task should have cleared the bits in ebCOMBINED_BITS.
\r
812 Clear the remaining bits. */
\r
813 uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
\r
815 if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
\r
820 /* Clear all bits ready for the sync with the other three tasks. The
\r
821 value returned is the value prior to the bits being cleared. */
\r
822 if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
\r
827 /* The bits should be clear now. */
\r
828 if( xEventGroupGetBits( xEventGroup ) != 0x00 )
\r
835 /*-----------------------------------------------------------*/
\r
837 static void prvSelectiveBitsTestSlaveFunction( void )
\r
839 EventBits_t uxPendBits, uxReturned;
\r
841 /* Used in a test that blocks two tasks on various different bits within an
\r
842 event group - then sets each bit in turn and checks that the correct tasks
\r
843 unblock at the correct times.
\r
845 This function is called by two different tasks - each of which will use a
\r
846 different bit. Check the task handle to see which task the function was
\r
848 if( xTaskGetCurrentTaskHandle() == xSyncTask1 )
\r
850 uxPendBits = ebSELECTIVE_BITS_1;
\r
854 uxPendBits = ebSELECTIVE_BITS_2;
\r
859 /* Wait until it is time to perform the next cycle of the test. The
\r
860 task is unsuspended by the tests implemented in the
\r
861 prvSelectiveBitsTestMasterFunction() function. */
\r
862 vTaskSuspend( NULL );
\r
863 uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );
\r
865 if( uxReturned == ( EventBits_t ) 0 )
\r
871 /*-----------------------------------------------------------*/
\r
873 static BaseType_t prvSelectiveBitsTestMasterFunction( void )
\r
875 BaseType_t xError = pdFALSE;
\r
878 /* Used in a test that blocks two tasks on various different bits within an
\r
879 event group - then sets each bit in turn and checks that the correct tasks
\r
880 unblock at the correct times. The two other tasks (xSyncTask1 and
\r
881 xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in
\r
884 Both other tasks should start in the suspended state. */
\r
885 if( eTaskGetState( xSyncTask1 ) != eSuspended )
\r
890 if( eTaskGetState( xSyncTask2 ) != eSuspended )
\r
895 /* Test each bit in the byte individually. */
\r
896 for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 )
\r
898 /* Resume both tasks. */
\r
899 vTaskResume( xSyncTask1 );
\r
900 vTaskResume( xSyncTask2 );
\r
902 /* Now both tasks should be blocked on the event group. */
\r
903 if( eTaskGetState( xSyncTask1 ) != eBlocked )
\r
908 if( eTaskGetState( xSyncTask2 ) != eBlocked )
\r
914 xEventGroupSetBits( xEventGroup, uxBit );
\r
916 /* Is the bit set in the first set of selective bits? If so the first
\r
917 sync task should have unblocked and returned to the suspended state. */
\r
918 if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )
\r
920 /* Task should not have unblocked. */
\r
921 if( eTaskGetState( xSyncTask1 ) != eBlocked )
\r
928 /* Task should have unblocked and returned to the suspended state. */
\r
929 if( eTaskGetState( xSyncTask1 ) != eSuspended )
\r
935 /* Same checks for the second sync task. */
\r
936 if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 )
\r
938 /* Task should not have unblocked. */
\r
939 if( eTaskGetState( xSyncTask2 ) != eBlocked )
\r
946 /* Task should have unblocked and returned to the suspended state. */
\r
947 if( eTaskGetState( xSyncTask2 ) != eSuspended )
\r
954 /* Ensure both tasks are blocked on the event group again, then delete the
\r
955 event group so the other tasks leave this portion of the test. */
\r
956 vTaskResume( xSyncTask1 );
\r
957 vTaskResume( xSyncTask2 );
\r
959 /* Deleting the event group is the signal that the two other tasks should
\r
960 leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main
\r
961 part of their functionality. */
\r
962 vEventGroupDelete( xEventGroup );
\r
966 /*-----------------------------------------------------------*/
\r
968 void vPeriodicEventGroupsProcessing( void )
\r
970 static BaseType_t xCallCount = 0, xISRTestError = pdFALSE;
\r
971 const BaseType_t xSetBitCount = 100, xGetBitsCount = 200, xClearBitsCount = 300;
\r
972 const EventBits_t uxBitsToSet = 0x12U;
\r
973 EventBits_t uxReturned;
\r
974 BaseType_t xMessagePosted;
\r
976 /* Called periodically from the tick hook to exercise the "FromISR"
\r
979 /* Check the even group tasks were actually created. */
\r
980 configASSERT( xISREventGroup );
\r
984 if( xCallCount == xSetBitCount )
\r
986 /* All the event bits should start clear. */
\r
987 uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );
\r
988 if( uxReturned != 0x00 )
\r
990 xISRTestError = pdTRUE;
\r
994 /* Set the bits. This is called from the tick hook so it is not
\r
995 necessary to use the last parameter to ensure a context switch
\r
996 occurs immediately. */
\r
997 xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL );
\r
998 if( xMessagePosted != pdPASS )
\r
1000 xISRTestError = pdTRUE;
\r
1004 else if( xCallCount == xGetBitsCount )
\r
1006 /* Check the bits were set as expected. */
\r
1007 uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );
\r
1008 if( uxReturned != uxBitsToSet )
\r
1010 xISRTestError = pdTRUE;
\r
1013 else if( xCallCount == xClearBitsCount )
\r
1015 /* Clear the bits again. */
\r
1016 uxReturned = ( EventBits_t ) xEventGroupClearBitsFromISR( xISREventGroup, uxBitsToSet );
\r
1018 /* Check the message was posted. */
\r
1019 if( uxReturned != pdPASS )
\r
1021 xISRTestError = pdTRUE;
\r
1024 /* Go back to the start. */
\r
1027 /* If no errors have been detected then increment the count of test
\r
1029 if( xISRTestError == pdFALSE )
\r
1036 /* Nothing else to do. */
\r
1040 /*-----------------------------------------------------------*/
\r
1041 /* This is called to check that all the created tasks are still running. */
\r
1042 BaseType_t xAreEventGroupTasksStillRunning( void )
\r
1044 static uint32_t ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0, ulPreviousISRCycles = 0;
\r
1045 BaseType_t xStatus = pdPASS;
\r
1047 /* Check the tasks are still cycling without finding any errors. */
\r
1048 if( ulPreviousSetBitCycles == ulTestMasterCycles )
\r
1052 ulPreviousSetBitCycles = ulTestMasterCycles;
\r
1054 if( ulPreviousWaitBitCycles == ulTestSlaveCycles )
\r
1058 ulPreviousWaitBitCycles = ulTestSlaveCycles;
\r
1060 if( ulPreviousISRCycles == ulISRCycles )
\r
1064 ulPreviousISRCycles = ulISRCycles;
\r