]> git.sur5r.net Git - freertos/commitdiff
Add volatile qualifier to loop counters used to detect stalled tasks.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 20 May 2008 05:22:35 +0000 (05:22 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 20 May 2008 05:22:35 +0000 (05:22 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@365 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/Common/Minimal/QPeek.c
Demo/Common/Minimal/blocktim.c
Demo/Common/Minimal/countsem.c
Demo/Common/Minimal/dynamic.c
Demo/Common/Minimal/recmutex.c

index f957d39f8c80411fcee8d186f74388e4152c1ab0..46e28e7dc2a61855397965b72055cbdcf95be5f2 100644 (file)
-/*\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
-/* \r
- * Tests the behaviour when data is peeked from a queue when there are\r
- * multiple tasks blocked on the queue.\r
- */\r
-\r
-\r
-#include <stdlib.h>\r
-\r
-/* Scheduler include files. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "queue.h"\r
-#include "semphr.h"\r
-\r
-/* Demo program include files. */\r
-#include "QPeek.h"\r
-\r
-#define qpeekQUEUE_LENGTH              ( 5 )\r
-#define qpeekNO_BLOCK                  ( 0 )\r
-#define qpeekSHORT_DELAY               ( 10 )\r
-\r
-#define qpeekLOW_PRIORITY                      ( tskIDLE_PRIORITY + 0 )\r
-#define qpeekMEDIUM_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
-#define qpeekHIGH_PRIORITY                     ( tskIDLE_PRIORITY + 2 )\r
-#define qpeekHIGHEST_PRIORITY          ( tskIDLE_PRIORITY + 3 )\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * The following three tasks are used to demonstrate the peeking behaviour.\r
- * Each task is given a different priority to demonstrate the order in which\r
- * tasks are woken as data is peeked from a queue.\r
- */\r
-static void prvLowPriorityPeekTask( void *pvParameters );\r
-static void prvMediumPriorityPeekTask( void *pvParameters );\r
-static void prvHighPriorityPeekTask( void *pvParameters );\r
-static void prvHighestPriorityPeekTask( void *pvParameters );\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
-detected in any of the tasks. */\r
-static portBASE_TYPE xErrorDetected = pdFALSE;\r
-\r
-/* Counter that is incremented on each cycle of a test.  This is used to\r
-detect a stalled task - a test that is no longer running. */\r
-static volatile unsigned portLONG ulLoopCounter = 0;\r
-\r
-/* Handles to the test tasks. */\r
-xTaskHandle xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;\r
-/*-----------------------------------------------------------*/\r
-\r
-void vStartQueuePeekTasks( void )\r
-{\r
-xQueueHandle xQueue;\r
-\r
-       /* Create the queue that we are going to use for the test/demo. */\r
-       xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( unsigned portLONG ) );\r
-\r
-       /* Create the demo tasks and pass it the queue just created.  We are\r
-       passing the queue handle by value so it does not matter that it is declared\r
-       on the stack here. */\r
-       xTaskCreate( prvLowPriorityPeekTask, ( signed portCHAR * )"PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );\r
-       xTaskCreate( prvMediumPriorityPeekTask, ( signed portCHAR * )"PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );\r
-       xTaskCreate( prvHighPriorityPeekTask, ( signed portCHAR * )"PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );\r
-       xTaskCreate( prvHighestPriorityPeekTask, ( signed portCHAR * )"PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvHighestPriorityPeekTask( void *pvParameters )\r
-{\r
-xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
-unsigned portLONG ulValue;\r
-\r
-       #ifdef USE_STDIO\r
-       {\r
-               void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
-       \r
-               const portCHAR * const pcTaskStartMsg = "Queue peek test started.\r\n";\r
-\r
-               /* Queue a message for printing to say the task has started. */\r
-               vPrintDisplayMessage( &pcTaskStartMsg );\r
-       }\r
-       #endif\r
-\r
-       for( ;; )\r
-       {\r
-               /* Try peeking from the queue.  The queue should be empty so we will\r
-               block, allowing the high priority task to execute. */\r
-               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )\r
-               {\r
-                       /* We expected to have received something by the time we unblock. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* When we reach here the high and medium priority tasks should still\r
-               be blocked on the queue.  We unblocked because the low priority task\r
-               wrote a value to the queue, which we should have peeked.  Peeking the\r
-               data (rather than receiving it) will leave the data on the queue, so\r
-               the high priority task should then have also been unblocked, but not\r
-               yet executed. */\r
-               if( ulValue != 0x11223344 )\r
-               {\r
-                       /* We did not receive the expected value. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
-               {\r
-                       /* The message should have been left on the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* Now we are going to actually receive the data, so when the high\r
-               priority task runs it will find the queue empty and return to the\r
-               blocked state. */\r
-               ulValue = 0;\r
-               if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )\r
-               {\r
-                       /* We expected to receive the value. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( ulValue != 0x11223344 )\r
-               {\r
-                       /* We did not receive the expected value - which should have been\r
-                       the same value as was peeked. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* Now we will block again as the queue is once more empty.  The low \r
-               priority task can then execute again. */\r
-               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )\r
-               {\r
-                       /* We expected to have received something by the time we unblock. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* When we get here the low priority task should have again written to the\r
-               queue. */\r
-               if( ulValue != 0x01234567 )\r
-               {\r
-                       /* We did not receive the expected value. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
-               {\r
-                       /* The message should have been left on the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* We only peeked the data, so suspending ourselves now should enable\r
-               the high priority task to also peek the data.  The high priority task\r
-               will have been unblocked when we peeked the data as we left the data\r
-               in the queue. */\r
-               vTaskSuspend( NULL );\r
-\r
-\r
-\r
-               /* This time we are going to do the same as the above test, but the\r
-               high priority task is going to receive the data, rather than peek it.\r
-               This means that the medium priority task should never peek the value. */\r
-               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( ulValue != 0xaabbaabb )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               vTaskSuspend( NULL );           \r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvHighPriorityPeekTask( void *pvParameters )\r
-{\r
-xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
-unsigned portLONG ulValue;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Try peeking from the queue.  The queue should be empty so we will\r
-               block, allowing the medium priority task to execute.  Both the high\r
-               and highest priority tasks will then be blocked on the queue. */\r
-               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )\r
-               {\r
-                       /* We expected to have received something by the time we unblock. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* When we get here the highest priority task should have peeked the data\r
-               (unblocking this task) then suspended (allowing this task to also peek\r
-               the data). */\r
-               if( ulValue != 0x01234567 )\r
-               {\r
-                       /* We did not receive the expected value. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
-               {\r
-                       /* The message should have been left on the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* We only peeked the data, so suspending ourselves now should enable\r
-               the medium priority task to also peek the data.  The medium priority task\r
-               will have been unblocked when we peeked the data as we left the data\r
-               in the queue. */\r
-               vTaskSuspend( NULL );\r
-\r
-\r
-               /* This time we are going actually receive the value, so the medium\r
-               priority task will never peek the data - we removed it from the queue. */\r
-               if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( ulValue != 0xaabbaabb )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               vTaskSuspend( NULL );                           \r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvMediumPriorityPeekTask( void *pvParameters )\r
-{\r
-xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
-unsigned portLONG ulValue;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Try peeking from the queue.  The queue should be empty so we will\r
-               block, allowing the low priority task to execute.  The highest, high\r
-               and medium priority tasks will then all be blocked on the queue. */\r
-               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )\r
-               {\r
-                       /* We expected to have received something by the time we unblock. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* When we get here the high priority task should have peeked the data\r
-               (unblocking this task) then suspended (allowing this task to also peek\r
-               the data). */\r
-               if( ulValue != 0x01234567 )\r
-               {\r
-                       /* We did not receive the expected value. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
-               {\r
-                       /* The message should have been left on the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* Just so we know the test is still running. */\r
-               ulLoopCounter++;\r
-\r
-               /* Now we can suspend ourselves so the low priority task can execute\r
-               again. */\r
-               vTaskSuspend( NULL );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvLowPriorityPeekTask( void *pvParameters )\r
-{\r
-xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
-unsigned portLONG ulValue;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Write some data to the queue.  This should unblock the highest \r
-               priority task that is waiting to peek data from the queue. */\r
-               ulValue = 0x11223344;\r
-               if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )\r
-               {\r
-                       /* We were expecting the queue to be empty so we should not of\r
-                       had a problem writing to the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* By the time we get here the data should have been removed from\r
-               the queue. */\r
-               if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* Write another value to the queue, again waking the highest priority\r
-               task that is blocked on the queue. */\r
-               ulValue = 0x01234567;\r
-               if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )\r
-               {\r
-                       /* We were expecting the queue to be empty so we should not of\r
-                       had a problem writing to the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* All the other tasks should now have successfully peeked the data.\r
-               The data is still in the queue so we should be able to receive it. */\r
-               ulValue = 0;\r
-               if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )\r
-               {\r
-                       /* We expected to receive the data. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               if( ulValue != 0x01234567 )\r
-               {\r
-                       /* We did not receive the expected value. */\r
-               }\r
-               \r
-               /* Lets just delay a while as this is an intensive test as we don't\r
-               want to starve other tests of processing time. */\r
-               vTaskDelay( qpeekSHORT_DELAY );\r
-\r
-               /* Unsuspend the other tasks so we can repeat the test - this time\r
-               however not all the other tasks will peek the data as the high\r
-               priority task is actually going to remove it from the queue.  Send\r
-               to front is used just to be different.  As the queue is empty it\r
-               makes no difference to the result. */\r
-               vTaskResume( xMediumPriorityTask );\r
-               vTaskResume( xHighPriorityTask );\r
-               vTaskResume( xHighestPriorityTask );\r
-\r
-               ulValue = 0xaabbaabb;\r
-               if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )\r
-               {\r
-                       /* We were expecting the queue to be empty so we should not of\r
-                       had a problem writing to the queue. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* This time we should find that the queue is empty.  The high priority\r
-               task actually removed the data rather than just peeking it. */\r
-               if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )\r
-               {\r
-                       /* We expected to receive the data. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* Unsuspend the highest and high priority tasks so we can go back\r
-               and repeat the whole thing.  The medium priority task should not be\r
-               suspended as it was not able to peek the data in this last case. */\r
-               vTaskResume( xHighPriorityTask );\r
-               vTaskResume( xHighestPriorityTask );            \r
-\r
-               /* Lets just delay a while as this is an intensive test as we don't\r
-               want to starve other tests of processing time. */\r
-               vTaskDelay( qpeekSHORT_DELAY );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* This is called to check that all the created tasks are still running. */\r
-portBASE_TYPE xAreQueuePeekTasksStillRunning( void )\r
-{\r
-static unsigned portLONG ulLastLoopCounter = 0;\r
-\r
-       /* If the demo task is still running then we expect the loopcounter to\r
-       have incremented since this function was last called. */\r
-       if( ulLastLoopCounter == ulLoopCounter )\r
-       {\r
-               xErrorDetected = pdTRUE;\r
-       }\r
-\r
-       ulLastLoopCounter = ulLoopCounter;\r
-\r
-       /* Errors detected in the task itself will have latched xErrorDetected\r
-       to true. */\r
-\r
-       return !xErrorDetected;\r
-}\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.
+*/
+
+
+/* 
+ * Tests the behaviour when data is peeked from a queue when there are
+ * multiple tasks blocked on the queue.
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "QPeek.h"
+
+#define qpeekQUEUE_LENGTH              ( 5 )
+#define qpeekNO_BLOCK                  ( 0 )
+#define qpeekSHORT_DELAY               ( 10 )
+
+#define qpeekLOW_PRIORITY                      ( tskIDLE_PRIORITY + 0 )
+#define qpeekMEDIUM_PRIORITY           ( tskIDLE_PRIORITY + 1 )
+#define qpeekHIGH_PRIORITY                     ( tskIDLE_PRIORITY + 2 )
+#define qpeekHIGHEST_PRIORITY          ( tskIDLE_PRIORITY + 3 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The following three tasks are used to demonstrate the peeking behaviour.
+ * Each task is given a different priority to demonstrate the order in which
+ * tasks are woken as data is peeked from a queue.
+ */
+static void prvLowPriorityPeekTask( void *pvParameters );
+static void prvMediumPriorityPeekTask( void *pvParameters );
+static void prvHighPriorityPeekTask( void *pvParameters );
+static void prvHighestPriorityPeekTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static volatile portBASE_TYPE xErrorDetected = pdFALSE;
+
+/* Counter that is incremented on each cycle of a test.  This is used to
+detect a stalled task - a test that is no longer running. */
+static volatile unsigned portLONG ulLoopCounter = 0;
+
+/* Handles to the test tasks. */
+xTaskHandle xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;
+/*-----------------------------------------------------------*/
+
+void vStartQueuePeekTasks( void )
+{
+xQueueHandle xQueue;
+
+       /* Create the queue that we are going to use for the test/demo. */
+       xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( unsigned portLONG ) );
+
+       /* Create the demo tasks and pass it the queue just created.  We are
+       passing the queue handle by value so it does not matter that it is declared
+       on the stack here. */
+       xTaskCreate( prvLowPriorityPeekTask, ( signed portCHAR * )"PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
+       xTaskCreate( prvMediumPriorityPeekTask, ( signed portCHAR * )"PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
+       xTaskCreate( prvHighPriorityPeekTask, ( signed portCHAR * )"PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
+       xTaskCreate( prvHighestPriorityPeekTask, ( signed portCHAR * )"PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask );
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighestPriorityPeekTask( void *pvParameters )
+{
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
+unsigned portLONG ulValue;
+
+       #ifdef USE_STDIO
+       {
+               void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
+       
+               const portCHAR * const pcTaskStartMsg = "Queue peek test started.\r\n";
+
+               /* Queue a message for printing to say the task has started. */
+               vPrintDisplayMessage( &pcTaskStartMsg );
+       }
+       #endif
+
+       for( ;; )
+       {
+               /* Try peeking from the queue.  The queue should be empty so we will
+               block, allowing the high priority task to execute. */
+               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+               {
+                       /* We expected to have received something by the time we unblock. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* When we reach here the high and medium priority tasks should still
+               be blocked on the queue.  We unblocked because the low priority task
+               wrote a value to the queue, which we should have peeked.  Peeking the
+               data (rather than receiving it) will leave the data on the queue, so
+               the high priority task should then have also been unblocked, but not
+               yet executed. */
+               if( ulValue != 0x11223344 )
+               {
+                       /* We did not receive the expected value. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( uxQueueMessagesWaiting( xQueue ) != 1 )
+               {
+                       /* The message should have been left on the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* Now we are going to actually receive the data, so when the high
+               priority task runs it will find the queue empty and return to the
+               blocked state. */
+               ulValue = 0;
+               if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+               {
+                       /* We expected to receive the value. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( ulValue != 0x11223344 )
+               {
+                       /* We did not receive the expected value - which should have been
+                       the same value as was peeked. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* Now we will block again as the queue is once more empty.  The low 
+               priority task can then execute again. */
+               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+               {
+                       /* We expected to have received something by the time we unblock. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* When we get here the low priority task should have again written to the
+               queue. */
+               if( ulValue != 0x01234567 )
+               {
+                       /* We did not receive the expected value. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( uxQueueMessagesWaiting( xQueue ) != 1 )
+               {
+                       /* The message should have been left on the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* We only peeked the data, so suspending ourselves now should enable
+               the high priority task to also peek the data.  The high priority task
+               will have been unblocked when we peeked the data as we left the data
+               in the queue. */
+               vTaskSuspend( NULL );
+
+
+
+               /* This time we are going to do the same as the above test, but the
+               high priority task is going to receive the data, rather than peek it.
+               This means that the medium priority task should never peek the value. */
+               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+               {
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( ulValue != 0xaabbaabb )
+               {
+                       xErrorDetected = pdTRUE;
+               }
+
+               vTaskSuspend( NULL );           
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighPriorityPeekTask( void *pvParameters )
+{
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
+unsigned portLONG ulValue;
+
+       for( ;; )
+       {
+               /* Try peeking from the queue.  The queue should be empty so we will
+               block, allowing the medium priority task to execute.  Both the high
+               and highest priority tasks will then be blocked on the queue. */
+               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+               {
+                       /* We expected to have received something by the time we unblock. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* When we get here the highest priority task should have peeked the data
+               (unblocking this task) then suspended (allowing this task to also peek
+               the data). */
+               if( ulValue != 0x01234567 )
+               {
+                       /* We did not receive the expected value. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( uxQueueMessagesWaiting( xQueue ) != 1 )
+               {
+                       /* The message should have been left on the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* We only peeked the data, so suspending ourselves now should enable
+               the medium priority task to also peek the data.  The medium priority task
+               will have been unblocked when we peeked the data as we left the data
+               in the queue. */
+               vTaskSuspend( NULL );
+
+
+               /* This time we are going actually receive the value, so the medium
+               priority task will never peek the data - we removed it from the queue. */
+               if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+               {
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( ulValue != 0xaabbaabb )
+               {
+                       xErrorDetected = pdTRUE;
+               }
+
+               vTaskSuspend( NULL );                           
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvMediumPriorityPeekTask( void *pvParameters )
+{
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
+unsigned portLONG ulValue;
+
+       for( ;; )
+       {
+               /* Try peeking from the queue.  The queue should be empty so we will
+               block, allowing the low priority task to execute.  The highest, high
+               and medium priority tasks will then all be blocked on the queue. */
+               if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
+               {
+                       /* We expected to have received something by the time we unblock. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* When we get here the high priority task should have peeked the data
+               (unblocking this task) then suspended (allowing this task to also peek
+               the data). */
+               if( ulValue != 0x01234567 )
+               {
+                       /* We did not receive the expected value. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( uxQueueMessagesWaiting( xQueue ) != 1 )
+               {
+                       /* The message should have been left on the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* Just so we know the test is still running. */
+               ulLoopCounter++;
+
+               /* Now we can suspend ourselves so the low priority task can execute
+               again. */
+               vTaskSuspend( NULL );
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvLowPriorityPeekTask( void *pvParameters )
+{
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
+unsigned portLONG ulValue;
+
+       for( ;; )
+       {
+               /* Write some data to the queue.  This should unblock the highest 
+               priority task that is waiting to peek data from the queue. */
+               ulValue = 0x11223344;
+               if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+               {
+                       /* We were expecting the queue to be empty so we should not of
+                       had a problem writing to the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* By the time we get here the data should have been removed from
+               the queue. */
+               if( uxQueueMessagesWaiting( xQueue ) != 0 )
+               {
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* Write another value to the queue, again waking the highest priority
+               task that is blocked on the queue. */
+               ulValue = 0x01234567;
+               if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+               {
+                       /* We were expecting the queue to be empty so we should not of
+                       had a problem writing to the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* All the other tasks should now have successfully peeked the data.
+               The data is still in the queue so we should be able to receive it. */
+               ulValue = 0;
+               if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+               {
+                       /* We expected to receive the data. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               if( ulValue != 0x01234567 )
+               {
+                       /* We did not receive the expected value. */
+               }
+               
+               /* Lets just delay a while as this is an intensive test as we don't
+               want to starve other tests of processing time. */
+               vTaskDelay( qpeekSHORT_DELAY );
+
+               /* Unsuspend the other tasks so we can repeat the test - this time
+               however not all the other tasks will peek the data as the high
+               priority task is actually going to remove it from the queue.  Send
+               to front is used just to be different.  As the queue is empty it
+               makes no difference to the result. */
+               vTaskResume( xMediumPriorityTask );
+               vTaskResume( xHighPriorityTask );
+               vTaskResume( xHighestPriorityTask );
+
+               ulValue = 0xaabbaabb;
+               if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
+               {
+                       /* We were expecting the queue to be empty so we should not of
+                       had a problem writing to the queue. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* This time we should find that the queue is empty.  The high priority
+               task actually removed the data rather than just peeking it. */
+               if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
+               {
+                       /* We expected to receive the data. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               /* Unsuspend the highest and high priority tasks so we can go back
+               and repeat the whole thing.  The medium priority task should not be
+               suspended as it was not able to peek the data in this last case. */
+               vTaskResume( xHighPriorityTask );
+               vTaskResume( xHighestPriorityTask );            
+
+               /* Lets just delay a while as this is an intensive test as we don't
+               want to starve other tests of processing time. */
+               vTaskDelay( qpeekSHORT_DELAY );
+       }
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreQueuePeekTasksStillRunning( void )
+{
+static unsigned portLONG ulLastLoopCounter = 0;
+
+       /* If the demo task is still running then we expect the loopcounter to
+       have incremented since this function was last called. */
+       if( ulLastLoopCounter == ulLoopCounter )
+       {
+               xErrorDetected = pdTRUE;
+       }
+
+       ulLastLoopCounter = ulLoopCounter;
+
+       /* Errors detected in the task itself will have latched xErrorDetected
+       to true. */
+
+       return !xErrorDetected;
+}
+
index 9d28d1376453ee3f730303d8a1ecb87a2f9feee5..f79bfc722d71c1e7853f351729e52fd0b52fe9fb 100644 (file)
-/*\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;
+}
index f35c47621e68fb503edd7db76349b6be393f4a22..4f8f58ccdf2fb0e6db9104a3ab9fcc4981daa97a 100644 (file)
-/*\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
-/* \r
- * Simple demonstration of the usage of counting semaphore.\r
- */\r
-\r
-/* Scheduler include files. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "semphr.h"\r
-\r
-/* Demo program include files. */\r
-#include "countsem.h"\r
-\r
-/* The maximum count value that the semaphore used for the demo can hold. */\r
-#define countMAX_COUNT_VALUE   ( 200 )\r
-\r
-/* Constants used to indicate whether or not the semaphore should have been\r
-created with its maximum count value, or its minimum count value.  These \r
-numbers are used to ensure that the pointers passed in as the task parameters\r
-are valid. */\r
-#define countSTART_AT_MAX_COUNT        ( 0xaa )\r
-#define countSTART_AT_ZERO             ( 0x55 )\r
-\r
-/* Two tasks are created for the test.  One uses a semaphore created with its\r
-count value set to the maximum, and one with the count value set to zero. */\r
-#define countNUM_TEST_TASKS            ( 2 )\r
-#define countDONT_BLOCK                        ( 0 )\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
-detected in any of the tasks. */\r
-static portBASE_TYPE xErrorDetected = pdFALSE;\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * The demo task.  This simply counts the semaphore up to its maximum value,\r
- * the counts it back down again.  The result of each semaphore 'give' and\r
- * 'take' is inspected, with an error being flagged if it is found not to be\r
- * the expected result.\r
- */\r
-static void prvCountingSemaphoreTask( void *pvParameters );\r
-\r
-/*\r
- * Utility function to increment the semaphore count value up from zero to\r
- * countMAX_COUNT_VALUE.\r
- */\r
-static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter );\r
-\r
-/*\r
- * Utility function to decrement the semaphore count value up from \r
- * countMAX_COUNT_VALUE to zero.\r
- */\r
-static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter );\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* The structure that is passed into the task as the task parameter. */\r
-typedef struct COUNT_SEM_STRUCT\r
-{\r
-       /* The semaphore to be used for the demo. */\r
-       xSemaphoreHandle xSemaphore;\r
-\r
-       /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with\r
-       its count value set to its max count value, or countSTART_AT_ZERO if it\r
-       should have been created with its count value set to 0. */\r
-       unsigned portBASE_TYPE uxExpectedStartCount;    \r
-\r
-       /* Incremented on each cycle of the demo task.  Used to detect a stalled\r
-       task. */\r
-       unsigned portBASE_TYPE uxLoopCounter;                   \r
-} xCountSemStruct;\r
-\r
-/* Two structures are defined, one is passed to each test task. */\r
-static xCountSemStruct xParameters[ countNUM_TEST_TASKS ];\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-void vStartCountingSemaphoreTasks( void )\r
-{\r
-       /* Create the semaphores that we are going to use for the test/demo.  The\r
-       first should be created such that it starts at its maximum count value,\r
-       the second should be created such that it starts with a count value of zero. */\r
-       xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE );\r
-       xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT;\r
-       xParameters[ 0 ].uxLoopCounter = 0;\r
-\r
-       xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 );\r
-       xParameters[ 1 ].uxExpectedStartCount = 0;\r
-       xParameters[ 1 ].uxLoopCounter = 0;\r
-\r
-       /* Were the semaphores created? */\r
-       if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) )\r
-       {\r
-               /* Create the demo tasks, passing in the semaphore to use as the parameter. */\r
-               xTaskCreate( prvCountingSemaphoreTask, ( signed portCHAR * ) "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL );\r
-               xTaskCreate( prvCountingSemaphoreTask, ( signed portCHAR * ) "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL );              \r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter )\r
-{\r
-unsigned portBASE_TYPE ux;\r
-\r
-       /* If the semaphore count is at its maximum then we should not be able to\r
-       'give' the semaphore. */\r
-       if( xSemaphoreGive( xSemaphore ) == pdPASS )\r
-       {\r
-               xErrorDetected = pdTRUE;\r
-       }\r
-\r
-       /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */\r
-       for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )\r
-       {\r
-               if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS )\r
-               {\r
-                       /* We expected to be able to take the semaphore. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               ( *puxLoopCounter )++;\r
-       }\r
-\r
-       #if configUSE_PREEMPTION == 0\r
-               taskYIELD();\r
-       #endif\r
-\r
-       /* If the semaphore count is zero then we should not be able to 'take' \r
-       the semaphore. */\r
-       if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )\r
-       {\r
-               xErrorDetected = pdTRUE;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter )\r
-{\r
-unsigned portBASE_TYPE ux;\r
-\r
-       /* If the semaphore count is zero then we should not be able to 'take' \r
-       the semaphore. */\r
-       if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )\r
-       {\r
-               xErrorDetected = pdTRUE;\r
-       }\r
-\r
-       /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */\r
-       for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )\r
-       {\r
-               if( xSemaphoreGive( xSemaphore ) != pdPASS )\r
-               {\r
-                       /* We expected to be able to take the semaphore. */\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               ( *puxLoopCounter )++;\r
-       }\r
-\r
-       #if configUSE_PREEMPTION == 0\r
-               taskYIELD();\r
-       #endif\r
-\r
-       /* If the semaphore count is at its maximum then we should not be able to\r
-       'give' the semaphore. */\r
-       if( xSemaphoreGive( xSemaphore ) == pdPASS )\r
-       {\r
-               xErrorDetected = pdTRUE;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvCountingSemaphoreTask( void *pvParameters )\r
-{\r
-xCountSemStruct *pxParameter;\r
-\r
-       #ifdef USE_STDIO\r
-       void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
-       \r
-               const portCHAR * const pcTaskStartMsg = "Counting semaphore demo started.\r\n";\r
-\r
-               /* Queue a message for printing to say the task has started. */\r
-               vPrintDisplayMessage( &pcTaskStartMsg );\r
-       #endif\r
-\r
-       /* The semaphore to be used was passed as the parameter. */\r
-       pxParameter = ( xCountSemStruct * ) pvParameters;\r
-\r
-       /* Did we expect to find the semaphore already at its max count value, or\r
-       at zero? */\r
-       if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT )\r
-       {\r
-               prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );\r
-       }\r
-\r
-       /* Now we expect the semaphore count to be 0, so this time there is an\r
-       error if we can take the semaphore. */\r
-       if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS )\r
-       {\r
-               xErrorDetected = pdTRUE;\r
-       }\r
-\r
-       for( ;; )\r
-       {\r
-               prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );\r
-               prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-portBASE_TYPE xAreCountingSemaphoreTasksStillRunning( void )\r
-{\r
-static unsigned portBASE_TYPE uxLastCount0 = 0, uxLastCount1 = 0;\r
-portBASE_TYPE xReturn = pdPASS;\r
-\r
-       /* Return fail if any 'give' or 'take' did not result in the expected\r
-       behaviour. */\r
-       if( xErrorDetected != pdFALSE )\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
-\r
-       /* Return fail if either task is not still incrementing its loop counter. */\r
-       if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter )\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
-       else\r
-       {\r
-               uxLastCount0 = xParameters[ 0 ].uxLoopCounter;\r
-       }\r
-\r
-       if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter )\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
-       else\r
-       {\r
-               uxLastCount1 = xParameters[ 1 ].uxLoopCounter;\r
-       }\r
-\r
-       return xReturn;\r
-}\r
-\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.
+*/
+
+
+/* 
+ * Simple demonstration of the usage of counting semaphore.
+ */
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "countsem.h"
+
+/* The maximum count value that the semaphore used for the demo can hold. */
+#define countMAX_COUNT_VALUE   ( 200 )
+
+/* Constants used to indicate whether or not the semaphore should have been
+created with its maximum count value, or its minimum count value.  These 
+numbers are used to ensure that the pointers passed in as the task parameters
+are valid. */
+#define countSTART_AT_MAX_COUNT        ( 0xaa )
+#define countSTART_AT_ZERO             ( 0x55 )
+
+/* Two tasks are created for the test.  One uses a semaphore created with its
+count value set to the maximum, and one with the count value set to zero. */
+#define countNUM_TEST_TASKS            ( 2 )
+#define countDONT_BLOCK                        ( 0 )
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static volatile portBASE_TYPE xErrorDetected = pdFALSE;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The demo task.  This simply counts the semaphore up to its maximum value,
+ * the counts it back down again.  The result of each semaphore 'give' and
+ * 'take' is inspected, with an error being flagged if it is found not to be
+ * the expected result.
+ */
+static void prvCountingSemaphoreTask( void *pvParameters );
+
+/*
+ * Utility function to increment the semaphore count value up from zero to
+ * countMAX_COUNT_VALUE.
+ */
+static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter );
+
+/*
+ * Utility function to decrement the semaphore count value up from 
+ * countMAX_COUNT_VALUE to zero.
+ */
+static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter );
+
+/*-----------------------------------------------------------*/
+
+/* The structure that is passed into the task as the task parameter. */
+typedef struct COUNT_SEM_STRUCT
+{
+       /* The semaphore to be used for the demo. */
+       xSemaphoreHandle xSemaphore;
+
+       /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with
+       its count value set to its max count value, or countSTART_AT_ZERO if it
+       should have been created with its count value set to 0. */
+       unsigned portBASE_TYPE uxExpectedStartCount;    
+
+       /* Incremented on each cycle of the demo task.  Used to detect a stalled
+       task. */
+       unsigned portBASE_TYPE uxLoopCounter;                   
+} xCountSemStruct;
+
+/* Two structures are defined, one is passed to each test task. */
+static volatile xCountSemStruct xParameters[ countNUM_TEST_TASKS ];
+
+/*-----------------------------------------------------------*/
+
+void vStartCountingSemaphoreTasks( void )
+{
+       /* Create the semaphores that we are going to use for the test/demo.  The
+       first should be created such that it starts at its maximum count value,
+       the second should be created such that it starts with a count value of zero. */
+       xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE );
+       xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT;
+       xParameters[ 0 ].uxLoopCounter = 0;
+
+       xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 );
+       xParameters[ 1 ].uxExpectedStartCount = 0;
+       xParameters[ 1 ].uxLoopCounter = 0;
+
+       /* Were the semaphores created? */
+       if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) )
+       {
+               /* Create the demo tasks, passing in the semaphore to use as the parameter. */
+               xTaskCreate( prvCountingSemaphoreTask, ( signed portCHAR * ) "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL );
+               xTaskCreate( prvCountingSemaphoreTask, ( signed portCHAR * ) "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL );              
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter )
+{
+unsigned portBASE_TYPE ux;
+
+       /* If the semaphore count is at its maximum then we should not be able to
+       'give' the semaphore. */
+       if( xSemaphoreGive( xSemaphore ) == pdPASS )
+       {
+               xErrorDetected = pdTRUE;
+       }
+
+       /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */
+       for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )
+       {
+               if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS )
+               {
+                       /* We expected to be able to take the semaphore. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               ( *puxLoopCounter )++;
+       }
+
+       #if configUSE_PREEMPTION == 0
+               taskYIELD();
+       #endif
+
+       /* If the semaphore count is zero then we should not be able to 'take' 
+       the semaphore. */
+       if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
+       {
+               xErrorDetected = pdTRUE;
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter )
+{
+unsigned portBASE_TYPE ux;
+
+       /* If the semaphore count is zero then we should not be able to 'take' 
+       the semaphore. */
+       if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
+       {
+               xErrorDetected = pdTRUE;
+       }
+
+       /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */
+       for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )
+       {
+               if( xSemaphoreGive( xSemaphore ) != pdPASS )
+               {
+                       /* We expected to be able to take the semaphore. */
+                       xErrorDetected = pdTRUE;
+               }
+
+               ( *puxLoopCounter )++;
+       }
+
+       #if configUSE_PREEMPTION == 0
+               taskYIELD();
+       #endif
+
+       /* If the semaphore count is at its maximum then we should not be able to
+       'give' the semaphore. */
+       if( xSemaphoreGive( xSemaphore ) == pdPASS )
+       {
+               xErrorDetected = pdTRUE;
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvCountingSemaphoreTask( void *pvParameters )
+{
+xCountSemStruct *pxParameter;
+
+       #ifdef USE_STDIO
+       void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
+       
+               const portCHAR * const pcTaskStartMsg = "Counting semaphore demo started.\r\n";
+
+               /* Queue a message for printing to say the task has started. */
+               vPrintDisplayMessage( &pcTaskStartMsg );
+       #endif
+
+       /* The semaphore to be used was passed as the parameter. */
+       pxParameter = ( xCountSemStruct * ) pvParameters;
+
+       /* Did we expect to find the semaphore already at its max count value, or
+       at zero? */
+       if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT )
+       {
+               prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
+       }
+
+       /* Now we expect the semaphore count to be 0, so this time there is an
+       error if we can take the semaphore. */
+       if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS )
+       {
+               xErrorDetected = pdTRUE;
+       }
+
+       for( ;; )
+       {
+               prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
+               prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
+       }
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xAreCountingSemaphoreTasksStillRunning( void )
+{
+static unsigned portBASE_TYPE uxLastCount0 = 0, uxLastCount1 = 0;
+portBASE_TYPE xReturn = pdPASS;
+
+       /* Return fail if any 'give' or 'take' did not result in the expected
+       behaviour. */
+       if( xErrorDetected != pdFALSE )
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Return fail if either task is not still incrementing its loop counter. */
+       if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter )
+       {
+               xReturn = pdFAIL;
+       }
+       else
+       {
+               uxLastCount0 = xParameters[ 0 ].uxLoopCounter;
+       }
+
+       if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter )
+       {
+               xReturn = pdFAIL;
+       }
+       else
+       {
+               uxLastCount1 = xParameters[ 1 ].uxLoopCounter;
+       }
+
+       return xReturn;
+}
+
+
index 08c65b64d74df83c2efa63cf8a255f38f5dec4c1..a0a97b9d103926167265bb414e2295d15690fd85 100644 (file)
-/*\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
- * The first test creates three tasks - two counter tasks (one continuous count \r
- * and one limited count) and one controller.  A "count" variable is shared \r
- * between all three tasks.  The two counter tasks should never be in a "ready" \r
- * state at the same time.  The controller task runs at the same priority as \r
- * the continuous count task, and at a lower priority than the limited count \r
- * task.\r
- *\r
- * One counter task loops indefinitely, incrementing the shared count variable\r
- * on each iteration.  To ensure it has exclusive access to the variable it\r
- * raises it's priority above that of the controller task before each \r
- * increment, lowering it again to it's original priority before starting the\r
- * next iteration.\r
- *\r
- * The other counter task increments the shared count variable on each\r
- * iteration of it's loop until the count has reached a limit of 0xff - at\r
- * which point it suspends itself.  It will not start a new loop until the \r
- * controller task has made it "ready" again by calling vTaskResume ().  \r
- * This second counter task operates at a higher priority than controller \r
- * task so does not need to worry about mutual exclusion of the counter \r
- * variable.\r
- *\r
- * The controller task is in two sections.  The first section controls and\r
- * monitors the continuous count task.  When this section is operational the \r
- * limited count task is suspended.  Likewise, the second section controls \r
- * and monitors the limited count task.  When this section is operational the \r
- * continuous count task is suspended.\r
- *\r
- * In the first section the controller task first takes a copy of the shared\r
- * count variable.  To ensure mutual exclusion on the count variable it\r
- * suspends the continuous count task, resuming it again when the copy has been\r
- * taken.  The controller task then sleeps for a fixed period - during which\r
- * the continuous count task will execute and increment the shared variable.\r
- * When the controller task wakes it checks that the continuous count task\r
- * has executed by comparing the copy of the shared variable with its current\r
- * value.  This time, to ensure mutual exclusion, the scheduler itself is \r
- * suspended with a call to vTaskSuspendAll ().  This is for demonstration \r
- * purposes only and is not a recommended technique due to its inefficiency.\r
- *\r
- * After a fixed number of iterations the controller task suspends the \r
- * continuous count task, and moves on to its second section.\r
- *\r
- * At the start of the second section the shared variable is cleared to zero.\r
- * The limited count task is then woken from it's suspension by a call to\r
- * vTaskResume ().  As this counter task operates at a higher priority than\r
- * the controller task the controller task should not run again until the\r
- * shared variable has been counted up to the limited value causing the counter\r
- * task to suspend itself.  The next line after vTaskResume () is therefore\r
- * a check on the shared variable to ensure everything is as expected.\r
- *\r
- *\r
- * The second test consists of a couple of very simple tasks that post onto a \r
- * queue while the scheduler is suspended.  This test was added to test parts\r
- * of the scheduler not exercised by the first test.\r
- *\r
- */\r
-\r
-#include <stdlib.h>\r
-\r
-/* Scheduler include files. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "semphr.h"\r
-\r
-/* Demo app include files. */\r
-#include "dynamic.h"\r
-\r
-/* Function that implements the "limited count" task as described above. */\r
-static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters );\r
-\r
-/* Function that implements the "continuous count" task as described above. */\r
-static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters );\r
-\r
-/* Function that implements the controller task as described above. */\r
-static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters );\r
-\r
-static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters );\r
-static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters );\r
-\r
-/* Demo task specific constants. */\r
-#define priSTACK_SIZE                          ( configMINIMAL_STACK_SIZE )\r
-#define priSLEEP_TIME                          ( ( portTickType ) 128 / portTICK_RATE_MS )\r
-#define priLOOPS                                       ( 5 )\r
-#define priMAX_COUNT                           ( ( unsigned portLONG ) 0xff )\r
-#define priNO_BLOCK                                    ( ( portTickType ) 0 )\r
-#define priSUSPENDED_QUEUE_LENGTH      ( 1 )\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Handles to the two counter tasks.  These could be passed in as parameters\r
-to the controller task to prevent them having to be file scope. */\r
-static xTaskHandle xContinousIncrementHandle, xLimitedIncrementHandle;\r
-\r
-/* The shared counter variable.  This is passed in as a parameter to the two \r
-counter variables for demonstration purposes. */\r
-static unsigned portLONG ulCounter;\r
-\r
-/* Variables used to check that the tasks are still operating without error.\r
-Each complete iteration of the controller task increments this variable\r
-provided no errors have been found.  The variable maintaining the same value\r
-is therefore indication of an error. */\r
-static unsigned portSHORT usCheckVariable = ( unsigned portSHORT ) 0;\r
-static portBASE_TYPE xSuspendedQueueSendError = pdFALSE;\r
-static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE;\r
-\r
-/* Queue used by the second test. */\r
-xQueueHandle xSuspendedTestQueue;\r
-\r
-/*-----------------------------------------------------------*/\r
-/*\r
- * Start the three tasks as described at the top of the file.\r
- * Note that the limited count task is given a higher priority.\r
- */\r
-void vStartDynamicPriorityTasks( void )\r
-{\r
-       xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned portLONG ) );\r
-       xTaskCreate( vContinuousIncrementTask, ( signed portCHAR * ) "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinousIncrementHandle );\r
-       xTaskCreate( vLimitedIncrementTask, ( signed portCHAR * ) "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle );\r
-       xTaskCreate( vCounterControlTask, ( signed portCHAR * ) "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
-       xTaskCreate( vQueueSendWhenSuspendedTask, ( signed portCHAR * ) "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
-       xTaskCreate( vQueueReceiveWhenSuspendedTask, ( signed portCHAR * ) "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * Just loops around incrementing the shared variable until the limit has been\r
- * reached.  Once the limit has been reached it suspends itself. \r
- */\r
-static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters )\r
-{\r
-unsigned portLONG *pulCounter;\r
-\r
-       /* Take a pointer to the shared variable from the parameters passed into\r
-       the task. */\r
-       pulCounter = ( unsigned portLONG * ) pvParameters;\r
-\r
-       /* This will run before the control task, so the first thing it does is\r
-       suspend - the control task will resume it when ready. */\r
-       vTaskSuspend( NULL );\r
-\r
-       for( ;; )\r
-       {\r
-               /* Just count up to a value then suspend. */\r
-               ( *pulCounter )++;      \r
-               \r
-               if( *pulCounter >= priMAX_COUNT )\r
-               {\r
-                       vTaskSuspend( NULL );\r
-               }       \r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * Just keep counting the shared variable up.  The control task will suspend\r
- * this task when it wants.\r
- */\r
-static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters )\r
-{\r
-unsigned portLONG *pulCounter;\r
-unsigned portBASE_TYPE uxOurPriority;\r
-\r
-       /* Take a pointer to the shared variable from the parameters passed into\r
-       the task. */\r
-       pulCounter = ( unsigned portLONG * ) pvParameters;\r
-\r
-       /* Query our priority so we can raise it when exclusive access to the \r
-       shared variable is required. */\r
-       uxOurPriority = uxTaskPriorityGet( NULL );\r
-\r
-       for( ;; )\r
-       {\r
-               /* Raise our priority above the controller task to ensure a context\r
-               switch does not occur while we are accessing this variable. */\r
-               vTaskPrioritySet( NULL, uxOurPriority + 1 );\r
-                       ( *pulCounter )++;              \r
-               vTaskPrioritySet( NULL, uxOurPriority );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * Controller task as described above.\r
- */\r
-static portTASK_FUNCTION( vCounterControlTask, pvParameters )\r
-{\r
-unsigned portLONG ulLastCounter;\r
-portSHORT sLoops;\r
-portSHORT sError = pdFALSE;\r
-\r
-       /* Just to stop warning messages. */\r
-       ( void ) pvParameters;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Start with the counter at zero. */\r
-               ulCounter = ( unsigned portLONG ) 0;\r
-\r
-               /* First section : */\r
-\r
-               /* Check the continuous count task is running. */\r
-               for( sLoops = 0; sLoops < priLOOPS; sLoops++ )\r
-               {\r
-                       /* Suspend the continuous count task so we can take a mirror of the\r
-                       shared variable without risk of corruption. */\r
-                       vTaskSuspend( xContinousIncrementHandle );\r
-                               ulLastCounter = ulCounter;\r
-                       vTaskResume( xContinousIncrementHandle );\r
-                       \r
-                       /* Now delay to ensure the other task has processor time. */\r
-                       vTaskDelay( priSLEEP_TIME );\r
-\r
-                       /* Check the shared variable again.  This time to ensure mutual \r
-                       exclusion the whole scheduler will be locked.  This is just for\r
-                       demo purposes! */\r
-                       vTaskSuspendAll();\r
-                       {\r
-                               if( ulLastCounter == ulCounter )\r
-                               {\r
-                                       /* The shared variable has not changed.  There is a problem\r
-                                       with the continuous count task so flag an error. */\r
-                                       sError = pdTRUE;\r
-                               }\r
-                       }\r
-                       xTaskResumeAll();\r
-               }\r
-\r
-\r
-               /* Second section: */\r
-\r
-               /* Suspend the continuous counter task so it stops accessing the shared variable. */\r
-               vTaskSuspend( xContinousIncrementHandle );\r
-\r
-               /* Reset the variable. */\r
-               ulCounter = ( unsigned portLONG ) 0;\r
-\r
-               /* Resume the limited count task which has a higher priority than us.\r
-               We should therefore not return from this call until the limited count\r
-               task has suspended itself with a known value in the counter variable. */\r
-               vTaskResume( xLimitedIncrementHandle );\r
-\r
-               /* Does the counter variable have the expected value? */\r
-               if( ulCounter != priMAX_COUNT )\r
-               {\r
-                       sError = pdTRUE;\r
-               }\r
-\r
-               if( sError == pdFALSE )\r
-               {\r
-                       /* If no errors have occurred then increment the check variable. */\r
-                       portENTER_CRITICAL();\r
-                               usCheckVariable++;\r
-                       portEXIT_CRITICAL();\r
-               }\r
-\r
-               /* Resume the continuous count task and do it all again. */\r
-               vTaskResume( xContinousIncrementHandle );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters )\r
-{\r
-static unsigned portLONG ulValueToSend = ( unsigned portLONG ) 0;\r
-\r
-       /* Just to stop warning messages. */\r
-       ( void ) pvParameters;\r
-\r
-       for( ;; )\r
-       {\r
-               vTaskSuspendAll();\r
-               {\r
-                       /* We must not block while the scheduler is suspended! */\r
-                       if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE )\r
-                       {\r
-                               xSuspendedQueueSendError = pdTRUE;\r
-                       }\r
-               }\r
-               xTaskResumeAll();\r
-\r
-               vTaskDelay( priSLEEP_TIME );\r
-\r
-               ++ulValueToSend;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters )\r
-{\r
-static unsigned portLONG ulExpectedValue = ( unsigned portLONG ) 0, ulReceivedValue;\r
-portBASE_TYPE xGotValue;\r
-\r
-       /* Just to stop warning messages. */\r
-       ( void ) pvParameters;\r
-\r
-       for( ;; )\r
-       {\r
-               do\r
-               {\r
-                       /* Suspending the scheduler here is fairly pointless and \r
-                       undesirable for a normal application.  It is done here purely\r
-                       to test the scheduler.  The inner xTaskResumeAll() should\r
-                       never return pdTRUE as the scheduler is still locked by the\r
-                       outer call. */\r
-                       vTaskSuspendAll();\r
-                       {\r
-                               vTaskSuspendAll();\r
-                               {\r
-                                       xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );\r
-                               }\r
-                               if( xTaskResumeAll() )\r
-                               {\r
-                                       xSuspendedQueueReceiveError = pdTRUE;\r
-                               }\r
-                       }\r
-                       xTaskResumeAll();\r
-\r
-                       #if configUSE_PREEMPTION == 0\r
-                       {\r
-                               taskYIELD();\r
-                       }\r
-                       #endif\r
-\r
-               } while( xGotValue == pdFALSE );\r
-\r
-               if( ulReceivedValue != ulExpectedValue )\r
-               {\r
-                       xSuspendedQueueReceiveError = pdTRUE;\r
-               }\r
-\r
-               ++ulExpectedValue;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Called to check that all the created tasks are still running without error. */\r
-portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )\r
-{\r
-/* Keep a history of the check variables so we know if it has been incremented \r
-since the last call. */\r
-static unsigned portSHORT usLastTaskCheck = ( unsigned portSHORT ) 0;\r
-portBASE_TYPE xReturn = pdTRUE;\r
-\r
-       /* Check the tasks are still running by ensuring the check variable\r
-       is still incrementing. */\r
-\r
-       if( usCheckVariable == usLastTaskCheck )\r
-       {\r
-               /* The check has not incremented so an error exists. */\r
-               xReturn = pdFALSE;\r
-       }\r
-\r
-       if( xSuspendedQueueSendError == pdTRUE )\r
-       {\r
-               xReturn = pdFALSE;\r
-       }\r
-\r
-       if( xSuspendedQueueReceiveError == pdTRUE )\r
-       {\r
-               xReturn = pdFALSE;\r
-       }\r
-\r
-       usLastTaskCheck = usCheckVariable;\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.
+*/
+
+/*
+ * The first test creates three tasks - two counter tasks (one continuous count 
+ * and one limited count) and one controller.  A "count" variable is shared 
+ * between all three tasks.  The two counter tasks should never be in a "ready" 
+ * state at the same time.  The controller task runs at the same priority as 
+ * the continuous count task, and at a lower priority than the limited count 
+ * task.
+ *
+ * One counter task loops indefinitely, incrementing the shared count variable
+ * on each iteration.  To ensure it has exclusive access to the variable it
+ * raises it's priority above that of the controller task before each 
+ * increment, lowering it again to it's original priority before starting the
+ * next iteration.
+ *
+ * The other counter task increments the shared count variable on each
+ * iteration of it's loop until the count has reached a limit of 0xff - at
+ * which point it suspends itself.  It will not start a new loop until the 
+ * controller task has made it "ready" again by calling vTaskResume ().  
+ * This second counter task operates at a higher priority than controller 
+ * task so does not need to worry about mutual exclusion of the counter 
+ * variable.
+ *
+ * The controller task is in two sections.  The first section controls and
+ * monitors the continuous count task.  When this section is operational the 
+ * limited count task is suspended.  Likewise, the second section controls 
+ * and monitors the limited count task.  When this section is operational the 
+ * continuous count task is suspended.
+ *
+ * In the first section the controller task first takes a copy of the shared
+ * count variable.  To ensure mutual exclusion on the count variable it
+ * suspends the continuous count task, resuming it again when the copy has been
+ * taken.  The controller task then sleeps for a fixed period - during which
+ * the continuous count task will execute and increment the shared variable.
+ * When the controller task wakes it checks that the continuous count task
+ * has executed by comparing the copy of the shared variable with its current
+ * value.  This time, to ensure mutual exclusion, the scheduler itself is 
+ * suspended with a call to vTaskSuspendAll ().  This is for demonstration 
+ * purposes only and is not a recommended technique due to its inefficiency.
+ *
+ * After a fixed number of iterations the controller task suspends the 
+ * continuous count task, and moves on to its second section.
+ *
+ * At the start of the second section the shared variable is cleared to zero.
+ * The limited count task is then woken from it's suspension by a call to
+ * vTaskResume ().  As this counter task operates at a higher priority than
+ * the controller task the controller task should not run again until the
+ * shared variable has been counted up to the limited value causing the counter
+ * task to suspend itself.  The next line after vTaskResume () is therefore
+ * a check on the shared variable to ensure everything is as expected.
+ *
+ *
+ * The second test consists of a couple of very simple tasks that post onto a 
+ * queue while the scheduler is suspended.  This test was added to test parts
+ * of the scheduler not exercised by the first test.
+ *
+ */
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo app include files. */
+#include "dynamic.h"
+
+/* Function that implements the "limited count" task as described above. */
+static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters );
+
+/* Function that implements the "continuous count" task as described above. */
+static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters );
+
+/* Function that implements the controller task as described above. */
+static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters );
+
+static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters );
+static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters );
+
+/* Demo task specific constants. */
+#define priSTACK_SIZE                          ( configMINIMAL_STACK_SIZE )
+#define priSLEEP_TIME                          ( ( portTickType ) 128 / portTICK_RATE_MS )
+#define priLOOPS                                       ( 5 )
+#define priMAX_COUNT                           ( ( unsigned portLONG ) 0xff )
+#define priNO_BLOCK                                    ( ( portTickType ) 0 )
+#define priSUSPENDED_QUEUE_LENGTH      ( 1 )
+
+/*-----------------------------------------------------------*/
+
+/* Handles to the two counter tasks.  These could be passed in as parameters
+to the controller task to prevent them having to be file scope. */
+static xTaskHandle xContinousIncrementHandle, xLimitedIncrementHandle;
+
+/* The shared counter variable.  This is passed in as a parameter to the two 
+counter variables for demonstration purposes. */
+static unsigned portLONG ulCounter;
+
+/* Variables used to check that the tasks are still operating without error.
+Each complete iteration of the controller task increments this variable
+provided no errors have been found.  The variable maintaining the same value
+is therefore indication of an error. */
+static volatile unsigned portSHORT usCheckVariable = ( unsigned portSHORT ) 0;
+static volatile portBASE_TYPE xSuspendedQueueSendError = pdFALSE;
+static volatile portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE;
+
+/* Queue used by the second test. */
+xQueueHandle xSuspendedTestQueue;
+
+/*-----------------------------------------------------------*/
+/*
+ * Start the three tasks as described at the top of the file.
+ * Note that the limited count task is given a higher priority.
+ */
+void vStartDynamicPriorityTasks( void )
+{
+       xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned portLONG ) );
+       xTaskCreate( vContinuousIncrementTask, ( signed portCHAR * ) "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinousIncrementHandle );
+       xTaskCreate( vLimitedIncrementTask, ( signed portCHAR * ) "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle );
+       xTaskCreate( vCounterControlTask, ( signed portCHAR * ) "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+       xTaskCreate( vQueueSendWhenSuspendedTask, ( signed portCHAR * ) "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+       xTaskCreate( vQueueReceiveWhenSuspendedTask, ( signed portCHAR * ) "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Just loops around incrementing the shared variable until the limit has been
+ * reached.  Once the limit has been reached it suspends itself. 
+ */
+static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters )
+{
+unsigned portLONG *pulCounter;
+
+       /* Take a pointer to the shared variable from the parameters passed into
+       the task. */
+       pulCounter = ( unsigned portLONG * ) pvParameters;
+
+       /* This will run before the control task, so the first thing it does is
+       suspend - the control task will resume it when ready. */
+       vTaskSuspend( NULL );
+
+       for( ;; )
+       {
+               /* Just count up to a value then suspend. */
+               ( *pulCounter )++;      
+               
+               if( *pulCounter >= priMAX_COUNT )
+               {
+                       vTaskSuspend( NULL );
+               }       
+       }
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Just keep counting the shared variable up.  The control task will suspend
+ * this task when it wants.
+ */
+static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters )
+{
+unsigned portLONG *pulCounter;
+unsigned portBASE_TYPE uxOurPriority;
+
+       /* Take a pointer to the shared variable from the parameters passed into
+       the task. */
+       pulCounter = ( unsigned portLONG * ) pvParameters;
+
+       /* Query our priority so we can raise it when exclusive access to the 
+       shared variable is required. */
+       uxOurPriority = uxTaskPriorityGet( NULL );
+
+       for( ;; )
+       {
+               /* Raise our priority above the controller task to ensure a context
+               switch does not occur while we are accessing this variable. */
+               vTaskPrioritySet( NULL, uxOurPriority + 1 );
+                       ( *pulCounter )++;              
+               vTaskPrioritySet( NULL, uxOurPriority );
+       }
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Controller task as described above.
+ */
+static portTASK_FUNCTION( vCounterControlTask, pvParameters )
+{
+unsigned portLONG ulLastCounter;
+portSHORT sLoops;
+portSHORT sError = pdFALSE;
+
+       /* Just to stop warning messages. */
+       ( void ) pvParameters;
+
+       for( ;; )
+       {
+               /* Start with the counter at zero. */
+               ulCounter = ( unsigned portLONG ) 0;
+
+               /* First section : */
+
+               /* Check the continuous count task is running. */
+               for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
+               {
+                       /* Suspend the continuous count task so we can take a mirror of the
+                       shared variable without risk of corruption. */
+                       vTaskSuspend( xContinousIncrementHandle );
+                               ulLastCounter = ulCounter;
+                       vTaskResume( xContinousIncrementHandle );
+                       
+                       /* Now delay to ensure the other task has processor time. */
+                       vTaskDelay( priSLEEP_TIME );
+
+                       /* Check the shared variable again.  This time to ensure mutual 
+                       exclusion the whole scheduler will be locked.  This is just for
+                       demo purposes! */
+                       vTaskSuspendAll();
+                       {
+                               if( ulLastCounter == ulCounter )
+                               {
+                                       /* The shared variable has not changed.  There is a problem
+                                       with the continuous count task so flag an error. */
+                                       sError = pdTRUE;
+                               }
+                       }
+                       xTaskResumeAll();
+               }
+
+
+               /* Second section: */
+
+               /* Suspend the continuous counter task so it stops accessing the shared variable. */
+               vTaskSuspend( xContinousIncrementHandle );
+
+               /* Reset the variable. */
+               ulCounter = ( unsigned portLONG ) 0;
+
+               /* Resume the limited count task which has a higher priority than us.
+               We should therefore not return from this call until the limited count
+               task has suspended itself with a known value in the counter variable. */
+               vTaskResume( xLimitedIncrementHandle );
+
+               /* Does the counter variable have the expected value? */
+               if( ulCounter != priMAX_COUNT )
+               {
+                       sError = pdTRUE;
+               }
+
+               if( sError == pdFALSE )
+               {
+                       /* If no errors have occurred then increment the check variable. */
+                       portENTER_CRITICAL();
+                               usCheckVariable++;
+                       portEXIT_CRITICAL();
+               }
+
+               /* Resume the continuous count task and do it all again. */
+               vTaskResume( xContinousIncrementHandle );
+       }
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters )
+{
+static unsigned portLONG ulValueToSend = ( unsigned portLONG ) 0;
+
+       /* Just to stop warning messages. */
+       ( void ) pvParameters;
+
+       for( ;; )
+       {
+               vTaskSuspendAll();
+               {
+                       /* We must not block while the scheduler is suspended! */
+                       if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE )
+                       {
+                               xSuspendedQueueSendError = pdTRUE;
+                       }
+               }
+               xTaskResumeAll();
+
+               vTaskDelay( priSLEEP_TIME );
+
+               ++ulValueToSend;
+       }
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters )
+{
+static unsigned portLONG ulExpectedValue = ( unsigned portLONG ) 0, ulReceivedValue;
+portBASE_TYPE xGotValue;
+
+       /* Just to stop warning messages. */
+       ( void ) pvParameters;
+
+       for( ;; )
+       {
+               do
+               {
+                       /* Suspending the scheduler here is fairly pointless and 
+                       undesirable for a normal application.  It is done here purely
+                       to test the scheduler.  The inner xTaskResumeAll() should
+                       never return pdTRUE as the scheduler is still locked by the
+                       outer call. */
+                       vTaskSuspendAll();
+                       {
+                               vTaskSuspendAll();
+                               {
+                                       xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
+                               }
+                               if( xTaskResumeAll() )
+                               {
+                                       xSuspendedQueueReceiveError = pdTRUE;
+                               }
+                       }
+                       xTaskResumeAll();
+
+                       #if configUSE_PREEMPTION == 0
+                       {
+                               taskYIELD();
+                       }
+                       #endif
+
+               } while( xGotValue == pdFALSE );
+
+               if( ulReceivedValue != ulExpectedValue )
+               {
+                       xSuspendedQueueReceiveError = pdTRUE;
+               }
+
+               ++ulExpectedValue;
+       }
+}
+/*-----------------------------------------------------------*/
+
+/* Called to check that all the created tasks are still running without error. */
+portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )
+{
+/* Keep a history of the check variables so we know if it has been incremented 
+since the last call. */
+static unsigned portSHORT usLastTaskCheck = ( unsigned portSHORT ) 0;
+portBASE_TYPE xReturn = pdTRUE;
+
+       /* Check the tasks are still running by ensuring the check variable
+       is still incrementing. */
+
+       if( usCheckVariable == usLastTaskCheck )
+       {
+               /* The check has not incremented so an error exists. */
+               xReturn = pdFALSE;
+       }
+
+       if( xSuspendedQueueSendError == pdTRUE )
+       {
+               xReturn = pdFALSE;
+       }
+
+       if( xSuspendedQueueReceiveError == pdTRUE )
+       {
+               xReturn = pdFALSE;
+       }
+
+       usLastTaskCheck = usCheckVariable;
+       return xReturn;
+}
index 0074ad5b3cd00592d692b0dd95ee52c45606bec2..e7de988c0ca9930a77f94db3e638acd1553cf6af 100644 (file)
-/*\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
-       The tasks defined on this page demonstrate the use of recursive mutexes.\r
-\r
-       For recursive mutex functionality the created mutex should be created using\r
-       xSemaphoreCreateRecursiveMutex(), then be manipulated\r
-       using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API\r
-       functions.\r
-\r
-       This demo creates three tasks all of which access the same recursive mutex:\r
-\r
-       prvRecursiveMutexControllingTask() has the highest priority so executes \r
-       first and grabs the mutex.  It then performs some recursive accesses - \r
-       between each of which it sleeps for a short period to let the lower \r
-       priority tasks execute.  When it has completed its demo functionality\r
-       it gives the mutex back before suspending itself.\r
-\r
-       prvRecursiveMutexBlockingTask() attempts to access the mutex by performing\r
-       a blocking 'take'.  The blocking task has a lower priority than the \r
-       controlling     task so by the time it executes the mutex has already been\r
-       taken by the controlling task,  causing the blocking task to block.  It \r
-       does not unblock until the controlling task has given the mutex back, \r
-       and it does not actually run until the controlling task has suspended \r
-       itself (due to the relative priorities).  When it eventually does obtain\r
-       the mutex all it does is give the mutex back prior to also suspending \r
-       itself.  At this point both the controlling task and the blocking task are \r
-       suspended.\r
-\r
-       prvRecursiveMutexPollingTask() runs at the idle priority.  It spins round\r
-       a tight loop attempting to obtain the mutex with a non-blocking call.  As\r
-       the lowest priority task it will not successfully obtain the mutex until\r
-       both the controlling and blocking tasks are suspended.  Once it eventually \r
-       does obtain the mutex it first unsuspends both the controlling task and\r
-       blocking task prior to giving the mutex back - resulting in the polling\r
-       task temporarily inheriting the controlling tasks priority.\r
-*/\r
-\r
-/* Scheduler include files. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "semphr.h"\r
-\r
-/* Demo app include files. */\r
-#include "recmutex.h"\r
-\r
-/* Priorities assigned to the three tasks. */\r
-#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
-#define recmuBLOCKING_TASK_PRIORITY            ( tskIDLE_PRIORITY + 1 )\r
-#define recmuPOLLING_TASK_PRIORITY             ( tskIDLE_PRIORITY + 0 )\r
-\r
-/* The recursive call depth. */\r
-#define recmuMAX_COUNT                                 ( 10 )\r
-\r
-/* Misc. */\r
-#define recmuSHORT_DELAY                               ( 20 / portTICK_RATE_MS )\r
-#define recmuNO_DELAY                                  ( ( portTickType ) 0 )\r
-#define recmuTWO_TICK_DELAY                            ( ( portTickType ) 2 )\r
-\r
-/* The three tasks as described at the top of this file. */\r
-static void prvRecursiveMutexControllingTask( void *pvParameters );\r
-static void prvRecursiveMutexBlockingTask( void *pvParameters );\r
-static void prvRecursiveMutexPollingTask( void *pvParameters );\r
-\r
-/* The mutex used by the demo. */\r
-static xSemaphoreHandle xMutex;\r
-\r
-/* Variables used to detect and latch errors. */\r
-static portBASE_TYPE xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE;\r
-static unsigned portBASE_TYPE uxControllingCycles = 0, uxBlockingCycles, uxPollingCycles = 0;\r
-\r
-/* Handles of the two higher priority tasks, required so they can be resumed \r
-(unsuspended). */\r
-static xTaskHandle xControllingTaskHandle, xBlockingTaskHandle;\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-void vStartRecursiveMutexTasks( void )\r
-{\r
-       /* Just creates the mutex and the three tasks. */\r
-\r
-       xMutex = xSemaphoreCreateRecursiveMutex();\r
-\r
-       if( xMutex != NULL )\r
-       {\r
-               xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );\r
-        xTaskCreate( prvRecursiveMutexBlockingTask, "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle );\r
-        xTaskCreate( prvRecursiveMutexPollingTask, "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvRecursiveMutexControllingTask( void *pvParameters )\r
-{\r
-unsigned portBASE_TYPE ux;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Should not be able to 'give' the mutex, as we have not yet 'taken'\r
-               it. */\r
-               if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )\r
-               {\r
-                       xErrorOccurred = pdTRUE;\r
-               }\r
-\r
-               for( ux = 0; ux < recmuMAX_COUNT; ux++ )\r
-               {\r
-                       /* We should now be able to take the mutex as many times as\r
-                       we like.  A one tick delay is used so the polling task will\r
-                       inherit our priority on all but the first cycle of this task. \r
-                       If we did not block attempting to receive the mutex then no\r
-                       priority inheritance would occur. */\r
-                       if( xSemaphoreTakeRecursive( xMutex, recmuTWO_TICK_DELAY ) != pdPASS )\r
-                       {\r
-                               xErrorOccurred = pdTRUE;\r
-                       }\r
-\r
-                       /* Ensure the other task attempting to access the mutex (and the\r
-                       other demo tasks) are able to execute. */\r
-                       vTaskDelay( recmuSHORT_DELAY );\r
-               }\r
-\r
-               /* For each time we took the mutex, give it back. */\r
-               for( ux = 0; ux < recmuMAX_COUNT; ux++ )\r
-               {\r
-                       /* Ensure the other task attempting to access the mutex (and the\r
-                       other demo tasks) are able to execute. */\r
-                       vTaskDelay( recmuSHORT_DELAY );\r
-\r
-                       /* We should now be able to give the mutex as many times as we\r
-                       took it. */\r
-                       if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )\r
-                       {\r
-                               xErrorOccurred = pdTRUE;\r
-                       }\r
-               }\r
-\r
-               /* Having given it back the same number of times as it was taken, we\r
-               should no longer be the mutex owner, so the next give sh ould fail. */\r
-               if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )\r
-               {\r
-                       xErrorOccurred = pdTRUE;\r
-               }\r
-\r
-               /* Keep count of the number of cycles this task has performed so a \r
-               stall can be detected. */\r
-               uxControllingCycles++;\r
-\r
-               /* Suspend ourselves to the blocking task can execute. */\r
-               xControllingIsSuspended = pdTRUE;\r
-               vTaskSuspend( NULL );\r
-               xControllingIsSuspended = pdFALSE;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvRecursiveMutexBlockingTask( void *pvParameters )\r
-{\r
-       for( ;; )\r
-       {\r
-               /* Attempt to obtain the mutex.  We should block until the \r
-               controlling task has given up the mutex, and not actually execute\r
-               past this call until the controlling task is suspended. */\r
-               if( xSemaphoreTakeRecursive( xMutex, portMAX_DELAY ) == pdPASS )\r
-               {\r
-                       if( xControllingIsSuspended != pdTRUE )\r
-                       {\r
-                               /* Did not expect to execute until the controlling task was\r
-                               suspended. */\r
-                               xErrorOccurred = pdTRUE;\r
-                       }\r
-                       else\r
-                       {\r
-                               /* Give the mutex back before suspending ourselves to allow\r
-                               the polling task to obtain the mutex. */\r
-                               if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )\r
-                               {\r
-                                       xErrorOccurred = pdTRUE;\r
-                               }\r
-\r
-                               xBlockingIsSuspended = pdTRUE;\r
-                               vTaskSuspend( NULL );\r
-                               xBlockingIsSuspended = pdFALSE;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       /* We should not leave the xSemaphoreTakeRecursive() function\r
-                       until the mutex was obtained. */\r
-                       xErrorOccurred = pdTRUE;\r
-               }\r
-\r
-               /* The controlling and blocking tasks should be in lock step. */\r
-               if( uxControllingCycles != ( uxBlockingCycles + 1 ) )\r
-               {\r
-                       xErrorOccurred = pdTRUE;\r
-               }\r
-\r
-               /* Keep count of the number of cycles this task has performed so a \r
-               stall can be detected. */\r
-               uxBlockingCycles++;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvRecursiveMutexPollingTask( void *pvParameters )\r
-{\r
-       for( ;; )\r
-       {\r
-               /* Keep attempting to obtain the mutex.  We should only obtain it when\r
-               the blocking task has suspended itself. */\r
-               if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )\r
-               {\r
-                       /* Is the blocking task suspended? */\r
-                       if( xBlockingIsSuspended != pdTRUE )\r
-                       {\r
-                               xErrorOccurred = pdTRUE;\r
-                       }\r
-                       else\r
-                       {\r
-                               /* Keep count of the number of cycles this task has performed so \r
-                               a stall can be detected. */\r
-                               uxPollingCycles++;\r
-\r
-                               /* We can resume the other tasks here even though they have a\r
-                               higher priority than the polling task.  When they execute they\r
-                               will attempt to obtain the mutex but fail because the polling\r
-                               task is still the mutex holder.  The polling task (this task)\r
-                               will then inherit the higher priority. */                               \r
-                               vTaskResume( xBlockingTaskHandle );\r
-                vTaskResume( xControllingTaskHandle );\r
-                       \r
-                               /* Release the mutex, disinheriting the higher priority again. */\r
-                               if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )\r
-                               {\r
-                                       xErrorOccurred = pdTRUE;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               #if configUSE_PREEMPTION == 0\r
-               {\r
-                       taskYIELD();\r
-               }\r
-               #endif\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* This is called to check that all the created tasks are still running. */\r
-portBASE_TYPE xAreRecursiveMutexTasksStillRunning( void )\r
-{\r
-portBASE_TYPE xReturn;\r
-static unsigned portBASE_TYPE uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0;\r
-\r
-       /* Is the controlling task still cycling? */\r
-       if( uxLastControllingCycles == uxControllingCycles )\r
-       {\r
-               xErrorOccurred = pdTRUE;\r
-       }\r
-       else\r
-       {\r
-               uxLastControllingCycles = uxControllingCycles;\r
-       }\r
-\r
-       /* Is the blocking task still cycling? */\r
-       if( uxLastBlockingCycles == uxBlockingCycles )\r
-       {\r
-               xErrorOccurred = pdTRUE;\r
-       }\r
-       else\r
-       {\r
-               uxLastBlockingCycles = uxBlockingCycles;\r
-       }\r
-\r
-       /* Is the polling task still cycling? */\r
-       if( uxLastPollingCycles == uxPollingCycles )\r
-       {\r
-               xErrorOccurred = pdTRUE;\r
-       }\r
-       else\r
-       {\r
-               uxLastPollingCycles = uxPollingCycles;\r
-       }\r
-\r
-       if( xErrorOccurred == pdTRUE )\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
-       else\r
-       {\r
-               xReturn = pdTRUE;\r
-       }\r
-\r
-       return xReturn;\r
-}\r
-\r
-\r
-\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.
+*/
+
+/*
+       The tasks defined on this page demonstrate the use of recursive mutexes.
+
+       For recursive mutex functionality the created mutex should be created using
+       xSemaphoreCreateRecursiveMutex(), then be manipulated
+       using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API
+       functions.
+
+       This demo creates three tasks all of which access the same recursive mutex:
+
+       prvRecursiveMutexControllingTask() has the highest priority so executes 
+       first and grabs the mutex.  It then performs some recursive accesses - 
+       between each of which it sleeps for a short period to let the lower 
+       priority tasks execute.  When it has completed its demo functionality
+       it gives the mutex back before suspending itself.
+
+       prvRecursiveMutexBlockingTask() attempts to access the mutex by performing
+       a blocking 'take'.  The blocking task has a lower priority than the 
+       controlling     task so by the time it executes the mutex has already been
+       taken by the controlling task,  causing the blocking task to block.  It 
+       does not unblock until the controlling task has given the mutex back, 
+       and it does not actually run until the controlling task has suspended 
+       itself (due to the relative priorities).  When it eventually does obtain
+       the mutex all it does is give the mutex back prior to also suspending 
+       itself.  At this point both the controlling task and the blocking task are 
+       suspended.
+
+       prvRecursiveMutexPollingTask() runs at the idle priority.  It spins round
+       a tight loop attempting to obtain the mutex with a non-blocking call.  As
+       the lowest priority task it will not successfully obtain the mutex until
+       both the controlling and blocking tasks are suspended.  Once it eventually 
+       does obtain the mutex it first unsuspends both the controlling task and
+       blocking task prior to giving the mutex back - resulting in the polling
+       task temporarily inheriting the controlling tasks priority.
+*/
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo app include files. */
+#include "recmutex.h"
+
+/* Priorities assigned to the three tasks. */
+#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define recmuBLOCKING_TASK_PRIORITY            ( tskIDLE_PRIORITY + 1 )
+#define recmuPOLLING_TASK_PRIORITY             ( tskIDLE_PRIORITY + 0 )
+
+/* The recursive call depth. */
+#define recmuMAX_COUNT                                 ( 10 )
+
+/* Misc. */
+#define recmuSHORT_DELAY                               ( 20 / portTICK_RATE_MS )
+#define recmuNO_DELAY                                  ( ( portTickType ) 0 )
+#define recmuTWO_TICK_DELAY                            ( ( portTickType ) 2 )
+
+/* The three tasks as described at the top of this file. */
+static void prvRecursiveMutexControllingTask( void *pvParameters );
+static void prvRecursiveMutexBlockingTask( void *pvParameters );
+static void prvRecursiveMutexPollingTask( void *pvParameters );
+
+/* The mutex used by the demo. */
+static xSemaphoreHandle xMutex;
+
+/* Variables used to detect and latch errors. */
+static volatile portBASE_TYPE xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE;
+static volatile unsigned portBASE_TYPE uxControllingCycles = 0, uxBlockingCycles, uxPollingCycles = 0;
+
+/* Handles of the two higher priority tasks, required so they can be resumed 
+(unsuspended). */
+static xTaskHandle xControllingTaskHandle, xBlockingTaskHandle;
+
+/*-----------------------------------------------------------*/
+
+void vStartRecursiveMutexTasks( void )
+{
+       /* Just creates the mutex and the three tasks. */
+
+       xMutex = xSemaphoreCreateRecursiveMutex();
+
+       if( xMutex != NULL )
+       {
+               xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );
+        xTaskCreate( prvRecursiveMutexBlockingTask, "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle );
+        xTaskCreate( prvRecursiveMutexPollingTask, "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL );
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexControllingTask( void *pvParameters )
+{
+unsigned portBASE_TYPE ux;
+
+       for( ;; )
+       {
+               /* Should not be able to 'give' the mutex, as we have not yet 'taken'
+               it. */
+               if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
+               {
+                       xErrorOccurred = pdTRUE;
+               }
+
+               for( ux = 0; ux < recmuMAX_COUNT; ux++ )
+               {
+                       /* We should now be able to take the mutex as many times as
+                       we like.  A one tick delay is used so the polling task will
+                       inherit our priority on all but the first cycle of this task. 
+                       If we did not block attempting to receive the mutex then no
+                       priority inheritance would occur. */
+                       if( xSemaphoreTakeRecursive( xMutex, recmuTWO_TICK_DELAY ) != pdPASS )
+                       {
+                               xErrorOccurred = pdTRUE;
+                       }
+
+                       /* Ensure the other task attempting to access the mutex (and the
+                       other demo tasks) are able to execute. */
+                       vTaskDelay( recmuSHORT_DELAY );
+               }
+
+               /* For each time we took the mutex, give it back. */
+               for( ux = 0; ux < recmuMAX_COUNT; ux++ )
+               {
+                       /* Ensure the other task attempting to access the mutex (and the
+                       other demo tasks) are able to execute. */
+                       vTaskDelay( recmuSHORT_DELAY );
+
+                       /* We should now be able to give the mutex as many times as we
+                       took it. */
+                       if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
+                       {
+                               xErrorOccurred = pdTRUE;
+                       }
+               }
+
+               /* Having given it back the same number of times as it was taken, we
+               should no longer be the mutex owner, so the next give sh ould fail. */
+               if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
+               {
+                       xErrorOccurred = pdTRUE;
+               }
+
+               /* Keep count of the number of cycles this task has performed so a 
+               stall can be detected. */
+               uxControllingCycles++;
+
+               /* Suspend ourselves to the blocking task can execute. */
+               xControllingIsSuspended = pdTRUE;
+               vTaskSuspend( NULL );
+               xControllingIsSuspended = pdFALSE;
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexBlockingTask( void *pvParameters )
+{
+       for( ;; )
+       {
+               /* Attempt to obtain the mutex.  We should block until the 
+               controlling task has given up the mutex, and not actually execute
+               past this call until the controlling task is suspended. */
+               if( xSemaphoreTakeRecursive( xMutex, portMAX_DELAY ) == pdPASS )
+               {
+                       if( xControllingIsSuspended != pdTRUE )
+                       {
+                               /* Did not expect to execute until the controlling task was
+                               suspended. */
+                               xErrorOccurred = pdTRUE;
+                       }
+                       else
+                       {
+                               /* Give the mutex back before suspending ourselves to allow
+                               the polling task to obtain the mutex. */
+                               if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
+                               {
+                                       xErrorOccurred = pdTRUE;
+                               }
+
+                               xBlockingIsSuspended = pdTRUE;
+                               vTaskSuspend( NULL );
+                               xBlockingIsSuspended = pdFALSE;
+                       }
+               }
+               else
+               {
+                       /* We should not leave the xSemaphoreTakeRecursive() function
+                       until the mutex was obtained. */
+                       xErrorOccurred = pdTRUE;
+               }
+
+               /* The controlling and blocking tasks should be in lock step. */
+               if( uxControllingCycles != ( uxBlockingCycles + 1 ) )
+               {
+                       xErrorOccurred = pdTRUE;
+               }
+
+               /* Keep count of the number of cycles this task has performed so a 
+               stall can be detected. */
+               uxBlockingCycles++;
+       }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexPollingTask( void *pvParameters )
+{
+       for( ;; )
+       {
+               /* Keep attempting to obtain the mutex.  We should only obtain it when
+               the blocking task has suspended itself. */
+               if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )
+               {
+                       /* Is the blocking task suspended? */
+                       if( xBlockingIsSuspended != pdTRUE )
+                       {
+                               xErrorOccurred = pdTRUE;
+                       }
+                       else
+                       {
+                               /* Keep count of the number of cycles this task has performed so 
+                               a stall can be detected. */
+                               uxPollingCycles++;
+
+                               /* We can resume the other tasks here even though they have a
+                               higher priority than the polling task.  When they execute they
+                               will attempt to obtain the mutex but fail because the polling
+                               task is still the mutex holder.  The polling task (this task)
+                               will then inherit the higher priority. */                               
+                               vTaskResume( xBlockingTaskHandle );
+                vTaskResume( xControllingTaskHandle );
+                       
+                               /* Release the mutex, disinheriting the higher priority again. */
+                               if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
+                               {
+                                       xErrorOccurred = pdTRUE;
+                               }
+                       }
+               }
+
+               #if configUSE_PREEMPTION == 0
+               {
+                       taskYIELD();
+               }
+               #endif
+       }
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreRecursiveMutexTasksStillRunning( void )
+{
+portBASE_TYPE xReturn;
+static unsigned portBASE_TYPE uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0;
+
+       /* Is the controlling task still cycling? */
+       if( uxLastControllingCycles == uxControllingCycles )
+       {
+               xErrorOccurred = pdTRUE;
+       }
+       else
+       {
+               uxLastControllingCycles = uxControllingCycles;
+       }
+
+       /* Is the blocking task still cycling? */
+       if( uxLastBlockingCycles == uxBlockingCycles )
+       {
+               xErrorOccurred = pdTRUE;
+       }
+       else
+       {
+               uxLastBlockingCycles = uxBlockingCycles;
+       }
+
+       /* Is the polling task still cycling? */
+       if( uxLastPollingCycles == uxPollingCycles )
+       {
+               xErrorOccurred = pdTRUE;
+       }
+       else
+       {
+               uxLastPollingCycles = uxPollingCycles;
+       }
+
+       if( xErrorOccurred == pdTRUE )
+       {
+               xReturn = pdFAIL;
+       }
+       else
+       {
+               xReturn = pdTRUE;
+       }
+
+       return xReturn;
+}
+
+
+
+