-/*\r
- FreeRTOS.org V5.0.0 - Copyright (C) 2003-2008 Richard Barry.\r
-\r
- This file is part of the FreeRTOS.org distribution.\r
-\r
- FreeRTOS.org is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- FreeRTOS.org is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with FreeRTOS.org; if not, write to the Free Software\r
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
-\r
- A special exception to the GPL can be applied should you wish to distribute\r
- a combined work that includes FreeRTOS.org, without being obliged to provide\r
- the source code for any proprietary components. See the licensing section\r
- of http://www.FreeRTOS.org for full details of how and when the exception\r
- can be applied.\r
-\r
- ***************************************************************************\r
- ***************************************************************************\r
- * *\r
- * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, *\r
- * and even write all or part of your application on your behalf. *\r
- * See http://www.OpenRTOS.com for details of the services we provide to *\r
- * expedite your project. *\r
- * *\r
- ***************************************************************************\r
- ***************************************************************************\r
-\r
- Please ensure to read the configuration and relevant port sections of the\r
- online documentation.\r
-\r
- http://www.FreeRTOS.org - Documentation, latest information, license and \r
- contact details.\r
-\r
- http://www.SafeRTOS.com - A version that is certified for use in safety \r
- critical systems.\r
-\r
- http://www.OpenRTOS.com - Commercial support, development, porting, \r
- licensing and training services.\r
-*/\r
-\r
-/*\r
- * This file contains some test scenarios that ensure tasks do not exit queue\r
- * send or receive functions prematurely. A description of the tests is\r
- * included within the code.\r
- */\r
-\r
-/* Kernel includes. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "queue.h"\r
-\r
-/* Demo includes. */\r
-#include "blocktim.h"\r
-\r
-/* Task priorities. */\r
-#define bktPRIMARY_PRIORITY ( 3 )\r
-#define bktSECONDARY_PRIORITY ( 2 )\r
-\r
-/* Task behaviour. */\r
-#define bktQUEUE_LENGTH ( 5 )\r
-#define bktSHORT_WAIT ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )\r
-#define bktPRIMARY_BLOCK_TIME ( 10 )\r
-#define bktALLOWABLE_MARGIN ( 15 )\r
-#define bktTIME_TO_BLOCK ( 175 )\r
-#define bktDONT_BLOCK ( ( portTickType ) 0 )\r
-#define bktRUN_INDICATOR ( ( unsigned portBASE_TYPE ) 0x55 )\r
-\r
-/* The queue on which the tasks block. */\r
-static xQueueHandle xTestQueue;\r
-\r
-/* Handle to the secondary task is required by the primary task for calls\r
-to vTaskSuspend/Resume(). */\r
-static xTaskHandle xSecondary;\r
-\r
-/* Used to ensure that tasks are still executing without error. */\r
-static portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;\r
-static portBASE_TYPE xErrorOccurred = pdFALSE;\r
-\r
-/* Provides a simple mechanism for the primary task to know when the\r
-secondary task has executed. */\r
-static volatile unsigned portBASE_TYPE xRunIndicator;\r
-\r
-/* The two test tasks. Their behaviour is commented within the files. */\r
-static void vPrimaryBlockTimeTestTask( void *pvParameters );\r
-static void vSecondaryBlockTimeTestTask( void *pvParameters );\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-void vCreateBlockTimeTasks( void )\r
-{\r
- /* Create the queue on which the two tasks block. */\r
- xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );\r
-\r
- /* Create the two test tasks. */\r
- xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
- xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void vPrimaryBlockTimeTestTask( void *pvParameters )\r
-{\r
-portBASE_TYPE xItem, xData;\r
-portTickType xTimeWhenBlocking;\r
-portTickType xTimeToBlock, xBlockedTime;\r
-\r
- ( void ) pvParameters;\r
-\r
- for( ;; )\r
- {\r
- /*********************************************************************\r
- Test 1\r
-\r
- Simple block time wakeup test on queue receives. */\r
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
- {\r
- /* The queue is empty. Attempt to read from the queue using a block\r
- time. When we wake, ensure the delta in time is as expected. */\r
- xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
-\r
- xTimeWhenBlocking = xTaskGetTickCount();\r
- \r
- /* We should unblock after xTimeToBlock having not received\r
- anything on the queue. */\r
- if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* How long were we blocked for? */\r
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
-\r
- if( xBlockedTime < xTimeToBlock )\r
- {\r
- /* Should not have blocked for less than we requested. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
- {\r
- /* Should not have blocked for longer than we requested,\r
- although we would not necessarily run as soon as we were\r
- unblocked so a margin is allowed. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-\r
- /*********************************************************************\r
- Test 2\r
-\r
- Simple block time wakeup test on queue sends.\r
-\r
- First fill the queue. It should be empty so all sends should pass. */\r
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
- {\r
- if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- #if configUSE_PREEMPTION == 0\r
- taskYIELD();\r
- #endif\r
- }\r
-\r
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
- {\r
- /* The queue is full. Attempt to write to the queue using a block\r
- time. When we wake, ensure the delta in time is as expected. */\r
- xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;\r
-\r
- xTimeWhenBlocking = xTaskGetTickCount();\r
- \r
- /* We should unblock after xTimeToBlock having not received\r
- anything on the queue. */\r
- if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* How long were we blocked for? */\r
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
-\r
- if( xBlockedTime < xTimeToBlock )\r
- {\r
- /* Should not have blocked for less than we requested. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )\r
- {\r
- /* Should not have blocked for longer than we requested,\r
- although we would not necessarily run as soon as we were\r
- unblocked so a margin is allowed. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-\r
- /*********************************************************************\r
- Test 3\r
-\r
- Wake the other task, it will block attempting to post to the queue.\r
- When we read from the queue the other task will wake, but before it\r
- can run we will post to the queue again. When the other task runs it\r
- will find the queue still full, even though it was woken. It should\r
- recognise that its block time has not expired and return to block for\r
- the remains of its block time.\r
-\r
- Wake the other task so it blocks attempting to post to the already\r
- full queue. */\r
- xRunIndicator = 0;\r
- vTaskResume( xSecondary );\r
-\r
- /* We need to wait a little to ensure the other task executes. */\r
- while( xRunIndicator != bktRUN_INDICATOR )\r
- {\r
- /* The other task has not yet executed. */\r
- vTaskDelay( bktSHORT_WAIT );\r
- }\r
- /* Make sure the other task is blocked on the queue. */\r
- vTaskDelay( bktSHORT_WAIT );\r
- xRunIndicator = 0;\r
-\r
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
- {\r
- /* Now when we make space on the queue the other task should wake\r
- but not execute as this task has higher priority. */ \r
- if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Now fill the queue again before the other task gets a chance to\r
- execute. If the other task had executed we would find the queue\r
- full ourselves, and the other task have set xRunIndicator. */\r
- if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( xRunIndicator == bktRUN_INDICATOR )\r
- {\r
- /* The other task should not have executed. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Raise the priority of the other task so it executes and blocks\r
- on the queue again. */\r
- vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
-\r
- /* The other task should now have re-blocked without exiting the\r
- queue function. */\r
- if( xRunIndicator == bktRUN_INDICATOR )\r
- {\r
- /* The other task should not have executed outside of the\r
- queue function. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Set the priority back down. */\r
- vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); \r
- }\r
-\r
- /* Let the other task timeout. When it unblockes it will check that it\r
- unblocked at the correct time, then suspend itself. */\r
- while( xRunIndicator != bktRUN_INDICATOR )\r
- {\r
- vTaskDelay( bktSHORT_WAIT );\r
- }\r
- vTaskDelay( bktSHORT_WAIT );\r
- xRunIndicator = 0;\r
-\r
-\r
- /*********************************************************************\r
- Test 4\r
-\r
- As per test 3 - but with the send and receive the other way around.\r
- The other task blocks attempting to read from the queue.\r
-\r
- Empty the queue. We should find that it is full. */\r
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
- {\r
- if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
- \r
- /* Wake the other task so it blocks attempting to read from the\r
- already empty queue. */\r
- vTaskResume( xSecondary );\r
-\r
- /* We need to wait a little to ensure the other task executes. */\r
- while( xRunIndicator != bktRUN_INDICATOR )\r
- {\r
- vTaskDelay( bktSHORT_WAIT );\r
- }\r
- vTaskDelay( bktSHORT_WAIT );\r
- xRunIndicator = 0;\r
-\r
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )\r
- {\r
- /* Now when we place an item on the queue the other task should\r
- wake but not execute as this task has higher priority. */ \r
- if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Now empty the queue again before the other task gets a chance to\r
- execute. If the other task had executed we would find the queue\r
- empty ourselves, and the other task would be suspended. */\r
- if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( xRunIndicator == bktRUN_INDICATOR )\r
- {\r
- /* The other task should not have executed. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Raise the priority of the other task so it executes and blocks\r
- on the queue again. */\r
- vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );\r
-\r
- /* The other task should now have re-blocked without exiting the\r
- queue function. */\r
- if( xRunIndicator == bktRUN_INDICATOR )\r
- {\r
- /* The other task should not have executed outside of the\r
- queue function. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
- vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); \r
- }\r
-\r
- /* Let the other task timeout. When it unblockes it will check that it\r
- unblocked at the correct time, then suspend itself. */\r
- while( xRunIndicator != bktRUN_INDICATOR )\r
- {\r
- vTaskDelay( bktSHORT_WAIT );\r
- }\r
- vTaskDelay( bktSHORT_WAIT );\r
-\r
- xPrimaryCycles++;\r
- }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void vSecondaryBlockTimeTestTask( void *pvParameters )\r
-{\r
-portTickType xTimeWhenBlocking, xBlockedTime;\r
-portBASE_TYPE xData;\r
-\r
- ( void ) pvParameters;\r
-\r
- for( ;; )\r
- {\r
- /*********************************************************************\r
- Test 1 and 2\r
-\r
- This task does does not participate in these tests. */\r
- vTaskSuspend( NULL );\r
-\r
- /*********************************************************************\r
- Test 3\r
-\r
- The first thing we do is attempt to read from the queue. It should be\r
- full so we block. Note the time before we block so we can check the\r
- wake time is as per that expected. */\r
- xTimeWhenBlocking = xTaskGetTickCount();\r
- \r
- /* We should unblock after bktTIME_TO_BLOCK having not received\r
- anything on the queue. */\r
- xData = 0;\r
- xRunIndicator = bktRUN_INDICATOR;\r
- if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* How long were we inside the send function? */\r
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
-\r
- /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
- if( xBlockedTime < bktTIME_TO_BLOCK )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
- either. A margin is permitted as we would not necessarily run as\r
- soon as we unblocked. */\r
- if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Suspend ready for test 3. */\r
- xRunIndicator = bktRUN_INDICATOR;\r
- vTaskSuspend( NULL );\r
-\r
- /*********************************************************************\r
- Test 4\r
-\r
- As per test three, but with the send and receive reversed. */\r
- xTimeWhenBlocking = xTaskGetTickCount();\r
- \r
- /* We should unblock after bktTIME_TO_BLOCK having not received\r
- anything on the queue. */\r
- xRunIndicator = bktRUN_INDICATOR;\r
- if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
-\r
- /* We should not have blocked for less time than bktTIME_TO_BLOCK. */\r
- if( xBlockedTime < bktTIME_TO_BLOCK )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* We should of not blocked for much longer than bktALLOWABLE_MARGIN\r
- either. A margin is permitted as we would not necessarily run as soon\r
- as we unblocked. */\r
- if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- xRunIndicator = bktRUN_INDICATOR;\r
-\r
- xSecondaryCycles++;\r
- }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void )\r
-{\r
-static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;\r
-portBASE_TYPE xReturn = pdPASS;\r
-\r
- /* Have both tasks performed at least one cycle since this function was\r
- last called? */\r
- if( xPrimaryCycles == xLastPrimaryCycleCount )\r
- {\r
- xReturn = pdFAIL;\r
- }\r
-\r
- if( xSecondaryCycles == xLastSecondaryCycleCount )\r
- {\r
- xReturn = pdFAIL;\r
- }\r
-\r
- if( xErrorOccurred == pdTRUE )\r
- {\r
- xReturn = pdFAIL;\r
- }\r
-\r
- xLastSecondaryCycleCount = xSecondaryCycles;\r
- xLastPrimaryCycleCount = xPrimaryCycles;\r
-\r
- return xReturn;\r
-}\r
+/*
+ FreeRTOS.org V5.0.0 - Copyright (C) 2003-2008 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ ***************************************************************************
+ * *
+ * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, *
+ * and even write all or part of your application on your behalf. *
+ * See http://www.OpenRTOS.com for details of the services we provide to *
+ * expedite your project. *
+ * *
+ ***************************************************************************
+ ***************************************************************************
+
+ Please ensure to read the configuration and relevant port sections of the
+ online documentation.
+
+ http://www.FreeRTOS.org - Documentation, latest information, license and
+ contact details.
+
+ http://www.SafeRTOS.com - A version that is certified for use in safety
+ critical systems.
+
+ http://www.OpenRTOS.com - Commercial support, development, porting,
+ licensing and training services.
+*/
+
+/*
+ * This file contains some test scenarios that ensure tasks do not exit queue
+ * send or receive functions prematurely. A description of the tests is
+ * included within the code.
+ */
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Demo includes. */
+#include "blocktim.h"
+
+/* Task priorities. */
+#define bktPRIMARY_PRIORITY ( 3 )
+#define bktSECONDARY_PRIORITY ( 2 )
+
+/* Task behaviour. */
+#define bktQUEUE_LENGTH ( 5 )
+#define bktSHORT_WAIT ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )
+#define bktPRIMARY_BLOCK_TIME ( 10 )
+#define bktALLOWABLE_MARGIN ( 15 )
+#define bktTIME_TO_BLOCK ( 175 )
+#define bktDONT_BLOCK ( ( portTickType ) 0 )
+#define bktRUN_INDICATOR ( ( unsigned portBASE_TYPE ) 0x55 )
+
+/* The queue on which the tasks block. */
+static xQueueHandle xTestQueue;
+
+/* Handle to the secondary task is required by the primary task for calls
+to vTaskSuspend/Resume(). */
+static xTaskHandle xSecondary;
+
+/* Used to ensure that tasks are still executing without error. */
+static volatile portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;
+static volatile portBASE_TYPE xErrorOccurred = pdFALSE;
+
+/* Provides a simple mechanism for the primary task to know when the
+secondary task has executed. */
+static volatile unsigned portBASE_TYPE xRunIndicator;
+
+/* The two test tasks. Their behaviour is commented within the files. */
+static void vPrimaryBlockTimeTestTask( void *pvParameters );
+static void vSecondaryBlockTimeTestTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+void vCreateBlockTimeTasks( void )
+{
+ /* Create the queue on which the two tasks block. */
+ xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );
+
+ /* Create the two test tasks. */
+ xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
+ xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
+}
+/*-----------------------------------------------------------*/
+
+static void vPrimaryBlockTimeTestTask( void *pvParameters )
+{
+portBASE_TYPE xItem, xData;
+portTickType xTimeWhenBlocking;
+portTickType xTimeToBlock, xBlockedTime;
+
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /*********************************************************************
+ Test 1
+
+ Simple block time wakeup test on queue receives. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* The queue is empty. Attempt to read from the queue using a block
+ time. When we wake, ensure the delta in time is as expected. */
+ xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
+
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after xTimeToBlock having not received
+ anything on the queue. */
+ if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we blocked for? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ if( xBlockedTime < xTimeToBlock )
+ {
+ /* Should not have blocked for less than we requested. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
+ {
+ /* Should not have blocked for longer than we requested,
+ although we would not necessarily run as soon as we were
+ unblocked so a margin is allowed. */
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /*********************************************************************
+ Test 2
+
+ Simple block time wakeup test on queue sends.
+
+ First fill the queue. It should be empty so all sends should pass. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+ }
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* The queue is full. Attempt to write to the queue using a block
+ time. When we wake, ensure the delta in time is as expected. */
+ xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
+
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after xTimeToBlock having not received
+ anything on the queue. */
+ if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we blocked for? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ if( xBlockedTime < xTimeToBlock )
+ {
+ /* Should not have blocked for less than we requested. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
+ {
+ /* Should not have blocked for longer than we requested,
+ although we would not necessarily run as soon as we were
+ unblocked so a margin is allowed. */
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /*********************************************************************
+ Test 3
+
+ Wake the other task, it will block attempting to post to the queue.
+ When we read from the queue the other task will wake, but before it
+ can run we will post to the queue again. When the other task runs it
+ will find the queue still full, even though it was woken. It should
+ recognise that its block time has not expired and return to block for
+ the remains of its block time.
+
+ Wake the other task so it blocks attempting to post to the already
+ full queue. */
+ xRunIndicator = 0;
+ vTaskResume( xSecondary );
+
+ /* We need to wait a little to ensure the other task executes. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ /* The other task has not yet executed. */
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ /* Make sure the other task is blocked on the queue. */
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* Now when we make space on the queue the other task should wake
+ but not execute as this task has higher priority. */
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now fill the queue again before the other task gets a chance to
+ execute. If the other task had executed we would find the queue
+ full ourselves, and the other task have set xRunIndicator. */
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Raise the priority of the other task so it executes and blocks
+ on the queue again. */
+ vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
+
+ /* The other task should now have re-blocked without exiting the
+ queue function. */
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed outside of the
+ queue function. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Set the priority back down. */
+ vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
+ }
+
+ /* Let the other task timeout. When it unblockes it will check that it
+ unblocked at the correct time, then suspend itself. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+
+ /*********************************************************************
+ Test 4
+
+ As per test 3 - but with the send and receive the other way around.
+ The other task blocks attempting to read from the queue.
+
+ Empty the queue. We should find that it is full. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /* Wake the other task so it blocks attempting to read from the
+ already empty queue. */
+ vTaskResume( xSecondary );
+
+ /* We need to wait a little to ensure the other task executes. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* Now when we place an item on the queue the other task should
+ wake but not execute as this task has higher priority. */
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now empty the queue again before the other task gets a chance to
+ execute. If the other task had executed we would find the queue
+ empty ourselves, and the other task would be suspended. */
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Raise the priority of the other task so it executes and blocks
+ on the queue again. */
+ vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
+
+ /* The other task should now have re-blocked without exiting the
+ queue function. */
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed outside of the
+ queue function. */
+ xErrorOccurred = pdTRUE;
+ }
+ vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
+ }
+
+ /* Let the other task timeout. When it unblockes it will check that it
+ unblocked at the correct time, then suspend itself. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+ vTaskDelay( bktSHORT_WAIT );
+
+ xPrimaryCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vSecondaryBlockTimeTestTask( void *pvParameters )
+{
+portTickType xTimeWhenBlocking, xBlockedTime;
+portBASE_TYPE xData;
+
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /*********************************************************************
+ Test 1 and 2
+
+ This task does does not participate in these tests. */
+ vTaskSuspend( NULL );
+
+ /*********************************************************************
+ Test 3
+
+ The first thing we do is attempt to read from the queue. It should be
+ full so we block. Note the time before we block so we can check the
+ wake time is as per that expected. */
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after bktTIME_TO_BLOCK having not received
+ anything on the queue. */
+ xData = 0;
+ xRunIndicator = bktRUN_INDICATOR;
+ if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we inside the send function? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+ if( xBlockedTime < bktTIME_TO_BLOCK )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+ either. A margin is permitted as we would not necessarily run as
+ soon as we unblocked. */
+ if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Suspend ready for test 3. */
+ xRunIndicator = bktRUN_INDICATOR;
+ vTaskSuspend( NULL );
+
+ /*********************************************************************
+ Test 4
+
+ As per test three, but with the send and receive reversed. */
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after bktTIME_TO_BLOCK having not received
+ anything on the queue. */
+ xRunIndicator = bktRUN_INDICATOR;
+ if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+ if( xBlockedTime < bktTIME_TO_BLOCK )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+ either. A margin is permitted as we would not necessarily run as soon
+ as we unblocked. */
+ if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xRunIndicator = bktRUN_INDICATOR;
+
+ xSecondaryCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void )
+{
+static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
+portBASE_TYPE xReturn = pdPASS;
+
+ /* Have both tasks performed at least one cycle since this function was
+ last called? */
+ if( xPrimaryCycles == xLastPrimaryCycleCount )
+ {
+ xReturn = pdFAIL;
+ }
+
+ if( xSecondaryCycles == xLastSecondaryCycleCount )
+ {
+ xReturn = pdFAIL;
+ }
+
+ if( xErrorOccurred == pdTRUE )
+ {
+ xReturn = pdFAIL;
+ }
+
+ xLastSecondaryCycleCount = xSecondaryCycles;
+ xLastPrimaryCycleCount = xPrimaryCycles;
+
+ return xReturn;
+}