--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+ * Creates six tasks that operate on three queues as follows:\r
+ *\r
+ * The first two tasks send and receive an incrementing number to/from a queue.\r
+ * One task acts as a producer and the other as the consumer. The consumer is a\r
+ * higher priority than the producer and is set to block on queue reads. The queue\r
+ * only has space for one item - as soon as the producer posts a message on the\r
+ * queue the consumer will unblock, pre-empt the producer, and remove the item.\r
+ *\r
+ * The second two tasks work the other way around. Again the queue used only has\r
+ * enough space for one item. This time the consumer has a lower priority than the\r
+ * producer. The producer will try to post on the queue blocking when the queue is\r
+ * full. When the consumer wakes it will remove the item from the queue, causing\r
+ * the producer to unblock, pre-empt the consumer, and immediately re-fill the\r
+ * queue.\r
+ *\r
+ * The last two tasks use the same queue producer and consumer functions. This time the queue has\r
+ * enough space for lots of items and the tasks operate at the same priority. The\r
+ * producer will execute, placing items into the queue. The consumer will start\r
+ * executing when either the queue becomes full (causing the producer to block) or\r
+ * a context switch occurs (tasks of the same priority will time slice).\r
+ *\r
+ */\r
+\r
+/*\r
+\r
+Changes from V4.1.1\r
+\r
+ + The second set of tasks were created the wrong way around. This has been\r
+ corrected.\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
+\r
+/* Demo program include files. */\r
+#include "BlockQ.h"\r
+\r
+#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE\r
+#define blckqNUM_TASK_SETS ( 3 )\r
+\r
+/* Structure used to pass parameters to the blocking queue tasks. */\r
+typedef struct BLOCKING_QUEUE_PARAMETERS\r
+{\r
+ xQueueHandle xQueue; /*< The queue to be used by the task. */\r
+ portTickType xBlockTime; /*< The block time to use on queue reads/writes. */\r
+ volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */\r
+} xBlockingQueueParameters;\r
+\r
+/* Task function that creates an incrementing number and posts it on a queue. */\r
+static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters );\r
+\r
+/* Task function that removes the incrementing number from a queue and checks that\r
+it is the expected number. */\r
+static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters );\r
+\r
+/* Variables which are incremented each time an item is removed from a queue, and\r
+found to be the expected value.\r
+These are used to check that the tasks are still running. */\r
+static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned short ) 0, ( unsigned short ) 0, ( unsigned short ) 0 };\r
+\r
+/* Variable which are incremented each time an item is posted on a queue. These\r
+are used to check that the tasks are still running. */\r
+static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned short ) 0, ( unsigned short ) 0, ( unsigned short ) 0 };\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2;\r
+xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4;\r
+xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6;\r
+const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5;\r
+const portTickType xBlockTime = ( portTickType ) 1000 / portTICK_RATE_MS;\r
+const portTickType xDontBlock = ( portTickType ) 0;\r
+\r
+ /* Create the first two tasks as described at the top of the file. */\r
+ \r
+ /* First create the structure used to pass parameters to the consumer tasks. */\r
+ pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );\r
+\r
+ /* Create the queue used by the first two tasks to pass the incrementing number.\r
+ Pass a pointer to the queue in the parameter structure. */\r
+ pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );\r
+\r
+ /* The consumer is created first so gets a block time as described above. */\r
+ pxQueueParameters1->xBlockTime = xBlockTime;\r
+\r
+ /* Pass in the variable that this task is going to increment so we can check it\r
+ is still running. */\r
+ pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );\r
+ \r
+ /* Create the structure used to pass parameters to the producer task. */\r
+ pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );\r
+\r
+ /* Pass the queue to this task also, using the parameter structure. */\r
+ pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;\r
+\r
+ /* The producer is not going to block - as soon as it posts the consumer will\r
+ wake and remove the item so the producer should always have room to post. */\r
+ pxQueueParameters2->xBlockTime = xDontBlock;\r
+\r
+ /* Pass in the variable that this task is going to increment so we can check\r
+ it is still running. */\r
+ pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );\r
+\r
+\r
+ /* Note the producer has a lower priority than the consumer when the tasks are\r
+ spawned. */\r
+ xTaskCreate( vBlockingQueueConsumer, ( signed char * ) "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );\r
+ xTaskCreate( vBlockingQueueProducer, ( signed char * ) "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );\r
+\r
+ \r
+\r
+ /* Create the second two tasks as described at the top of the file. This uses\r
+ the same mechanism but reverses the task priorities. */\r
+\r
+ pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );\r
+ pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );\r
+ pxQueueParameters3->xBlockTime = xDontBlock;\r
+ pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] );\r
+\r
+ pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );\r
+ pxQueueParameters4->xQueue = pxQueueParameters3->xQueue;\r
+ pxQueueParameters4->xBlockTime = xBlockTime;\r
+ pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] );\r
+\r
+ xTaskCreate( vBlockingQueueConsumer, ( signed char * ) "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( vBlockingQueueProducer, ( signed char * ) "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL );\r
+\r
+\r
+\r
+ /* Create the last two tasks as described above. The mechanism is again just\r
+ the same. This time both parameter structures are given a block time. */\r
+ pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );\r
+ pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );\r
+ pxQueueParameters5->xBlockTime = xBlockTime;\r
+ pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] );\r
+\r
+ pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );\r
+ pxQueueParameters6->xQueue = pxQueueParameters5->xQueue;\r
+ pxQueueParameters6->xBlockTime = xBlockTime;\r
+ pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); \r
+\r
+ xTaskCreate( vBlockingQueueProducer, ( signed char * ) "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( vBlockingQueueConsumer, ( signed char * ) "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters )\r
+{\r
+unsigned short usValue = 0;\r
+xBlockingQueueParameters *pxQueueParameters;\r
+short sErrorEverOccurred = pdFALSE;\r
+\r
+ pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;\r
+\r
+ for( ;; )\r
+ { \r
+ if( xQueueSend( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS )\r
+ {\r
+ sErrorEverOccurred = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ /* We have successfully posted a message, so increment the variable\r
+ used to check we are still running. */\r
+ if( sErrorEverOccurred == pdFALSE )\r
+ {\r
+ ( *pxQueueParameters->psCheckVariable )++;\r
+ }\r
+\r
+ /* Increment the variable we are going to post next time round. The\r
+ consumer will expect the numbers to follow in numerical order. */\r
+ ++usValue;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters )\r
+{\r
+unsigned short usData, usExpectedValue = 0;\r
+xBlockingQueueParameters *pxQueueParameters;\r
+short sErrorEverOccurred = pdFALSE;\r
+\r
+ pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;\r
+\r
+ for( ;; )\r
+ { \r
+ if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS )\r
+ {\r
+ if( usData != usExpectedValue )\r
+ {\r
+ /* Catch-up. */\r
+ usExpectedValue = usData;\r
+\r
+ sErrorEverOccurred = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ /* We have successfully received a message, so increment the\r
+ variable used to check we are still running. */ \r
+ if( sErrorEverOccurred == pdFALSE )\r
+ {\r
+ ( *pxQueueParameters->psCheckVariable )++;\r
+ }\r
+ \r
+ /* Increment the value we expect to remove from the queue next time\r
+ round. */\r
+ ++usExpectedValue;\r
+ } \r
+ } \r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+portBASE_TYPE xAreBlockingQueuesStillRunning( void )\r
+{\r
+static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned short ) 0, ( unsigned short ) 0, ( unsigned short ) 0 };\r
+static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned short ) 0, ( unsigned short ) 0, ( unsigned short ) 0 };\r
+portBASE_TYPE xReturn = pdPASS, xTasks;\r
+\r
+ /* Not too worried about mutual exclusion on these variables as they are 16\r
+ bits and we are only reading them. We also only care to see if they have\r
+ changed or not.\r
+ \r
+ Loop through each check variable to and return pdFALSE if any are found not\r
+ to have changed since the last call. */\r
+\r
+ for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )\r
+ {\r
+ if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];\r
+\r
+\r
+ if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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 extra queue functionality introduced in FreeRTOS.org V4.5.0 - \r
+ * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and \r
+ * mutex behaviour. \r
+ *\r
+ * See the comments above the prvSendFrontAndBackTest() and \r
+ * prvLowPriorityMutexTask() prototypes below for more information.\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 "GenQTest.h"\r
+\r
+#define genqQUEUE_LENGTH ( 5 )\r
+#define genqNO_BLOCK ( 0 )\r
+\r
+#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY )\r
+#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
+#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
+#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack()\r
+ * macros by using both to fill a queue, then reading from the queue to\r
+ * check the resultant queue order is as expected. Queue data is also\r
+ * peeked.\r
+ */\r
+static void prvSendFrontAndBackTest( void *pvParameters );\r
+\r
+/*\r
+ * The following three tasks are used to demonstrate the mutex behaviour.\r
+ * Each task is given a different priority to demonstrate the priority\r
+ * inheritance mechanism.\r
+ *\r
+ * The low priority task obtains a mutex. After this a high priority task\r
+ * attempts to obtain the same mutex, causing its priority to be inherited\r
+ * by the low priority task. The task with the inherited high priority then\r
+ * resumes a medium priority task to ensure it is not blocked by the medium\r
+ * priority task while it holds the inherited high priority. Once the mutex\r
+ * is returned the task with the inherited priority returns to its original\r
+ * low priority, and is therefore immediately preempted by first the high\r
+ * priority task and then the medium prioroity task before it can continue.\r
+ */\r
+static void prvLowPriorityMutexTask( void *pvParameters );\r
+static void prvMediumPriorityMutexTask( void *pvParameters );\r
+static void prvHighPriorityMutexTask( 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
+/* Counters that are 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
+static volatile unsigned portLONG ulLoopCounter2 = 0;\r
+\r
+/* The variable that is guarded by the mutex in the mutex demo tasks. */\r
+static volatile unsigned portLONG ulGuardedVariable = 0;\r
+\r
+/* Handles used in the mutext test to suspend and resume the high and medium\r
+priority mutex test tasks. */\r
+static xTaskHandle xHighPriorityMutexTask, xMediumPriorityMutexTask;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+xQueueHandle xQueue;\r
+xSemaphoreHandle xMutex;\r
+\r
+ /* Create the queue that we are going to use for the\r
+ prvSendFrontAndBackTest demo. */\r
+ xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( unsigned portLONG ) );\r
+\r
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
+ in use. The queue registry is provided as a means for kernel aware \r
+ debuggers to locate queues and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "Gen_Queue_Test" );\r
+\r
+ /* Create the demo task and pass it the queue just created. We are\r
+ passing the queue handle by value so it does not matter that it is\r
+ declared on the stack here. */\r
+ xTaskCreate( prvSendFrontAndBackTest, ( signed portCHAR * )"GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );\r
+\r
+ /* Create the mutex used by the prvMutexTest task. */\r
+ xMutex = xSemaphoreCreateMutex();\r
+\r
+ /* vQueueAddToRegistry() adds the mutex to the registry, if one is\r
+ in use. The registry is provided as a means for kernel aware \r
+ debuggers to locate mutexes and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Gen_Queue_Mutex" );\r
+\r
+ /* Create the mutex demo tasks and pass it the mutex just created. We are\r
+ passing the mutex handle by value so it does not matter that it is declared\r
+ on the stack here. */\r
+ xTaskCreate( prvLowPriorityMutexTask, ( signed portCHAR * )"MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
+ xTaskCreate( prvMediumPriorityMutexTask, ( signed portCHAR * )"MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
+ xTaskCreate( prvHighPriorityMutexTask, ( signed portCHAR * )"MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendFrontAndBackTest( void *pvParameters )\r
+{\r
+unsigned portLONG ulData, ulData2;\r
+xQueueHandle xQueue;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\r
+\r
+ xQueue = ( xQueueHandle ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* The queue is empty, so sending an item to the back of the queue\r
+ should have the same efect as sending it to the front of the queue.\r
+\r
+ First send to the front and check everything is as expected. */\r
+ xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* The data we sent to the queue should equal the data we just received\r
+ from the queue. */\r
+ if( ulLoopCounter != ulData )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Then do the same, sending the data to the back, checking everything\r
+ is as expected. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* The data we sent to the queue should equal the data we just received\r
+ from the queue. */\r
+ if( ulLoopCounter != ulData )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+\r
+\r
+ /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */\r
+ for( ulData = 2; ulData < 5; ulData++ )\r
+ {\r
+ xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+ }\r
+\r
+ /* Now the order in the queue should be 2, 3, 4, with 2 being the first\r
+ thing to be read out. Now add 1 then 0 to the front of the queue. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 3 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ ulData = 1;\r
+ xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+ ulData = 0;\r
+ xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+\r
+ /* Now the queue should be full, and when we read the data out we\r
+ should receive 0, 1, 2, 3, 4. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 5 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ /* Check the data we read out is in the expected order. */\r
+ for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )\r
+ {\r
+ /* Try peeking the data first. */\r
+ if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulData != ulData2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ \r
+\r
+ /* Now try receiving the data for real. The value should be the\r
+ same. Clobber the value first so we know we really received it. */\r
+ ulData2 = ~ulData2;\r
+ if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulData != ulData2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* The queue should now be empty again. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+\r
+ /* Our queue is empty once more, add 10, 11 to the back. */\r
+ ulData = 10;\r
+ if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ ulData = 11;\r
+ if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the\r
+ front. */\r
+ for( ulData = 9; ulData >= 7; ulData-- )\r
+ {\r
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Now check that the queue is full, and that receiving data provides\r
+ the expected sequence of 7, 8, 9, 10, 11. */\r
+ if( uxQueueMessagesWaiting( xQueue ) != 5 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ /* Check the data we read out is in the expected order. */\r
+ for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )\r
+ {\r
+ if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulData != ulData2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ }\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ ulLoopCounter++;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLowPriorityMutexTask( void *pvParameters )\r
+{\r
+xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\r
+\r
+ for( ;; )\r
+ {\r
+ /* Take the mutex. It should be available now. */\r
+ if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Set our guarded variable to a known start value. */\r
+ ulGuardedVariable = 0;\r
+\r
+ /* Our priority should be as per that assigned when the task was\r
+ created. */\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Now unsuspend the high priority task. This will attempt to take the\r
+ mutex, and block when it finds it cannot obtain it. */\r
+ vTaskResume( xHighPriorityMutexTask );\r
+\r
+ /* We should now have inherited the prioritoy of the high priority task,\r
+ as by now it will have attempted to get the mutex. */\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* We can attempt to set our priority to the test priority - between the\r
+ idle priority and the medium/high test priorities, but our actual\r
+ prioroity should remain at the high priority. */\r
+ vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Now unsuspend the medium priority task. This should not run as our\r
+ inherited priority is above that of the medium priority task. */\r
+ vTaskResume( xMediumPriorityMutexTask );\r
+\r
+ /* If the did run then it will have incremented our guarded variable. */\r
+ if( ulGuardedVariable != 0 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* When we give back the semaphore our priority should be disinherited\r
+ back to the priority to which we attempted to set ourselves. This means\r
+ that when the high priority task next blocks, the medium priority task\r
+ should execute and increment the guarded variable. When we next run\r
+ both the high and medium priority tasks will have been suspended again. */\r
+ if( xSemaphoreGive( xMutex ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Check that the guarded variable did indeed increment... */\r
+ if( ulGuardedVariable != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* ... and that our priority has been disinherited to\r
+ genqMUTEX_TEST_PRIORITY. */\r
+ if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* Set our priority back to our original priority ready for the next\r
+ loop around this test. */\r
+ vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );\r
+\r
+ /* Just to show we are still running. */\r
+ ulLoopCounter2++;\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif \r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMediumPriorityMutexTask( void *pvParameters )\r
+{\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* The medium priority task starts by suspending itself. The low\r
+ priority task will unsuspend this task when required. */\r
+ vTaskSuspend( NULL );\r
+\r
+ /* When this task unsuspends all it does is increment the guarded\r
+ variable, this is so the low priority task knows that it has\r
+ executed. */\r
+ ulGuardedVariable++;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvHighPriorityMutexTask( void *pvParameters )\r
+{\r
+xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* The high priority task starts by suspending itself. The low\r
+ priority task will unsuspend this task when required. */\r
+ vTaskSuspend( NULL );\r
+\r
+ /* When this task unsuspends all it does is attempt to obtain\r
+ the mutex. It should find the mutex is not available so a\r
+ block time is specified. */\r
+ if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ /* When we eventually obtain the mutex we just give it back then\r
+ return to suspend ready for the next test. */\r
+ if( xSemaphoreGive( xMutex ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ } \r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+portBASE_TYPE xAreGenericQueueTasksStillRunning( void )\r
+{\r
+static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;\r
+\r
+ /* If the demo task is still running then we expect the loopcounters to\r
+ have incremented since this function was last called. */\r
+ if( ulLastLoopCounter == ulLoopCounter )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( ulLastLoopCounter2 == ulLoopCounter2 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ ulLastLoopCounter = ulLoopCounter;\r
+ ulLastLoopCounter2 = ulLoopCounter2; \r
+\r
+ /* Errors detected in the task itself will have latched xErrorDetected\r
+ to true. */\r
+\r
+ return !xErrorDetected;\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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 version of PollQ. c is for use on systems that have limited stack\r
+ * space and no display facilities. The complete version can be found in\r
+ * the Demo/Common/Full directory.\r
+ *\r
+ * Creates two tasks that communicate over a single queue. One task acts as a\r
+ * producer, the other a consumer.\r
+ *\r
+ * The producer loops for three iteration, posting an incrementing number onto the\r
+ * queue each cycle. It then delays for a fixed period before doing exactly the\r
+ * same again.\r
+ *\r
+ * The consumer loops emptying the queue. Each item removed from the queue is\r
+ * checked to ensure it contains the expected value. When the queue is empty it\r
+ * blocks for a fixed period, then does the same again.\r
+ *\r
+ * All queue access is performed without blocking. The consumer completely empties\r
+ * the queue each time it runs so the producer should never find the queue full.\r
+ *\r
+ * An error is flagged if the consumer obtains an unexpected value or the producer\r
+ * find the queue is full.\r
+ */\r
+\r
+/*\r
+Changes from V2.0.0\r
+\r
+ + Delay periods are now specified using variables and constants of\r
+ portTickType rather than unsigned long.\r
+*/\r
+\r
+#include <stdlib.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+/* Demo program include files. */\r
+#include "PollQ.h"\r
+\r
+#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE\r
+#define pollqQUEUE_SIZE ( 10 )\r
+#define pollqPRODUCER_DELAY ( ( portTickType ) 200 / portTICK_RATE_MS )\r
+#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( portTickType ) ( 20 / portTICK_RATE_MS ) )\r
+#define pollqNO_DELAY ( ( portTickType ) 0 )\r
+#define pollqVALUES_TO_PRODUCE ( ( signed portBASE_TYPE ) 3 )\r
+#define pollqINITIAL_VALUE ( ( signed portBASE_TYPE ) 0 )\r
+\r
+/* The task that posts the incrementing number onto the queue. */\r
+static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters );\r
+\r
+/* The task that empties the queue. */\r
+static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters );\r
+\r
+/* Variables that are used to check that the tasks are still running with no\r
+errors. */\r
+static volatile signed portBASE_TYPE xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+static xQueueHandle xPolledQueue;\r
+\r
+ /* Create the queue used by the producer and consumer. */\r
+ xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );\r
+\r
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
+ in use. The queue registry is provided as a means for kernel aware \r
+ debuggers to locate queues and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( xPolledQueue, ( signed char * ) "Poll_Test_Queue" );\r
+\r
+ /* Spawn the producer and consumer. */\r
+ xTaskCreate( vPolledQueueConsumer, ( signed char * ) "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL );\r
+ xTaskCreate( vPolledQueueProducer, ( signed char * ) "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vPolledQueueProducer, pvParameters )\r
+{\r
+unsigned short usValue = ( unsigned short ) 0;\r
+signed portBASE_TYPE xError = pdFALSE, xLoop;\r
+\r
+ for( ;; )\r
+ { \r
+ for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ )\r
+ {\r
+ /* Send an incrementing number on the queue without blocking. */\r
+ if( xQueueSend( *( ( xQueueHandle * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS )\r
+ {\r
+ /* We should never find the queue full so if we get here there\r
+ has been an error. */\r
+ xError = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ if( xError == pdFALSE )\r
+ {\r
+ /* If an error has ever been recorded we stop incrementing the\r
+ check variable. */\r
+ portENTER_CRITICAL();\r
+ xPollingProducerCount++;\r
+ portEXIT_CRITICAL();\r
+ }\r
+\r
+ /* Update the value we are going to post next time around. */\r
+ usValue++;\r
+ }\r
+ }\r
+\r
+ /* Wait before we start posting again to ensure the consumer runs and\r
+ empties the queue. */\r
+ vTaskDelay( pollqPRODUCER_DELAY );\r
+ }\r
+} /*lint !e818 Function prototype must conform to API. */\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters )\r
+{\r
+unsigned short usData, usExpectedValue = ( unsigned short ) 0;\r
+signed portBASE_TYPE xError = pdFALSE;\r
+\r
+ for( ;; )\r
+ { \r
+ /* Loop until the queue is empty. */\r
+ while( uxQueueMessagesWaiting( *( ( xQueueHandle * ) pvParameters ) ) )\r
+ {\r
+ if( xQueueReceive( *( ( xQueueHandle * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS )\r
+ {\r
+ if( usData != usExpectedValue )\r
+ {\r
+ /* This is not what we expected to receive so an error has\r
+ occurred. */\r
+ xError = pdTRUE;\r
+\r
+ /* Catch-up to the value we received so our next expected\r
+ value should again be correct. */\r
+ usExpectedValue = usData;\r
+ }\r
+ else\r
+ {\r
+ if( xError == pdFALSE )\r
+ {\r
+ /* Only increment the check variable if no errors have\r
+ occurred. */\r
+ portENTER_CRITICAL();\r
+ xPollingConsumerCount++;\r
+ portEXIT_CRITICAL();\r
+ }\r
+ }\r
+\r
+ /* Next time round we would expect the number to be one higher. */\r
+ usExpectedValue++;\r
+ }\r
+ }\r
+\r
+ /* Now the queue is empty we block, allowing the producer to place more\r
+ items in the queue. */\r
+ vTaskDelay( pollqCONSUMER_DELAY );\r
+ }\r
+} /*lint !e818 Function prototype must conform to API. */\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running with no errors. */\r
+portBASE_TYPE xArePollingQueuesStillRunning( void )\r
+{\r
+portBASE_TYPE xReturn;\r
+\r
+ /* Check both the consumer and producer poll count to check they have both\r
+ been changed since out last trip round. We do not need a critical section\r
+ around the check variables as this is called from a higher priority than\r
+ the other tasks that access the same variables. */\r
+ if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) ||\r
+ ( xPollingProducerCount == pollqINITIAL_VALUE )\r
+ )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
+\r
+ /* Set the check variables back down so we know if they have been\r
+ incremented the next time around. */\r
+ xPollingConsumerCount = pollqINITIAL_VALUE;\r
+ xPollingProducerCount = pollqINITIAL_VALUE;\r
+\r
+ return xReturn;\r
+}\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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 volatile 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
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
+ in use. The queue registry is provided as a means for kernel aware \r
+ debuggers to locate queues and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "QPeek_Test_Queue" );\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
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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. Allow these to be overridden. */\r
+#ifndef bktPRIMARY_PRIORITY\r
+ #define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )\r
+#endif\r
+\r
+#ifndef bktSECONDARY_PRIORITY\r
+ #define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 )\r
+#endif\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 volatile portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;\r
+static volatile 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
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
+ in use. The queue registry is provided as a means for kernel aware\r
+ debuggers to locate queues and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is\r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( xTestQueue, ( signed char * ) "Block_Time_Queue" );\r
+\r
+ /* Create the two test tasks. */\r
+ xTaskCreate( vPrimaryBlockTimeTestTask, ( signed char * )"BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
+ xTaskCreate( vSecondaryBlockTimeTestTask, ( signed char * )"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 sent\r
+ anything to 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
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+ * Create a single persistent task which periodically dynamically creates another\r
+ * two tasks. The original task is called the creator task, the two tasks it\r
+ * creates are called suicidal tasks.\r
+ *\r
+ * One of the created suicidal tasks kill one other suicidal task before killing\r
+ * itself - leaving just the original task remaining.\r
+ *\r
+ * The creator task must be spawned after all of the other demo application tasks\r
+ * as it keeps a check on the number of tasks under the scheduler control. The\r
+ * number of tasks it expects to see running should never be greater than the\r
+ * number of tasks that were in existence when the creator task was spawned, plus\r
+ * one set of four suicidal tasks. If this number is exceeded an error is flagged.\r
+ *\r
+ * \page DeathC death.c\r
+ * \ingroup DemoFiles\r
+ * <HR>\r
+ */\r
+\r
+/*\r
+Changes from V3.0.0\r
+ + CreationCount sizes changed from unsigned portBASE_TYPE to\r
+ unsigned short to minimize the risk of overflowing.\r
+ \r
+ + Reset of usLastCreationCount added\r
+ \r
+Changes from V3.1.0\r
+ + Changed the dummy calculation to use variables of type long, rather than\r
+ float. This allows the file to be used with ports that do not support\r
+ floating point.\r
+\r
+*/\r
+\r
+#include <stdlib.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* Demo program include files. */\r
+#include "death.h"\r
+\r
+#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 )\r
+\r
+/* The task originally created which is responsible for periodically dynamically\r
+creating another four tasks. */\r
+static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters );\r
+\r
+/* The task function of the dynamically created tasks. */\r
+static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters );\r
+\r
+/* A variable which is incremented every time the dynamic tasks are created. This\r
+is used to check that the task is still running. */\r
+static volatile unsigned short usCreationCount = 0;\r
+\r
+/* Used to store the number of tasks that were originally running so the creator\r
+task can tell if any of the suicidal tasks have failed to die.\r
+*/\r
+static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0;\r
+\r
+/* Tasks are deleted by the idle task. Under heavy load the idle task might\r
+not get much processing time, so it would be legitimate for several tasks to\r
+remain undeleted for a short period. */\r
+static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 2;\r
+\r
+/* Used to store a handle to the task that should be killed by a suicidal task,\r
+before it kills itself. */\r
+xTaskHandle xCreatedTask;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+unsigned portBASE_TYPE *puxPriority;\r
+\r
+ /* Create the Creator tasks - passing in as a parameter the priority at which\r
+ the suicidal tasks should be created. */\r
+ puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );\r
+ *puxPriority = uxPriority;\r
+\r
+ xTaskCreate( vCreateTasks, ( signed char * ) "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );\r
+\r
+ /* Record the number of tasks that are running now so we know if any of the\r
+ suicidal tasks have failed to be killed. */\r
+ uxTasksRunningAtStart = ( unsigned portBASE_TYPE ) uxTaskGetNumberOfTasks();\r
+ \r
+ /* FreeRTOS.org versions before V3.0 started the idle-task as the very\r
+ first task. The idle task was then already included in uxTasksRunningAtStart.\r
+ From FreeRTOS V3.0 on, the idle task is started when the scheduler is\r
+ started. Therefore the idle task is not yet accounted for. We correct\r
+ this by increasing uxTasksRunningAtStart by 1. */\r
+ uxTasksRunningAtStart++;\r
+ \r
+ /* From FreeRTOS version 7.0.0 can optionally create a timer service task. \r
+ If this is done, then uxTasksRunningAtStart needs incrementing again as that\r
+ too is created when the scheduler is started. */\r
+ #if configUSE_TIMERS == 1\r
+ uxTasksRunningAtStart++;\r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+ \r
+static portTASK_FUNCTION( vSuicidalTask, pvParameters )\r
+{\r
+volatile long l1, l2;\r
+xTaskHandle xTaskToKill;\r
+const portTickType xDelay = ( portTickType ) 200 / portTICK_RATE_MS;\r
+\r
+ if( pvParameters != NULL )\r
+ {\r
+ /* This task is periodically created four times. Two created tasks are\r
+ passed a handle to the other task so it can kill it before killing itself.\r
+ The other task is passed in null. */\r
+ xTaskToKill = *( xTaskHandle* )pvParameters;\r
+ }\r
+ else\r
+ {\r
+ xTaskToKill = NULL;\r
+ }\r
+\r
+ for( ;; )\r
+ {\r
+ /* Do something random just to use some stack and registers. */\r
+ l1 = 2;\r
+ l2 = 89;\r
+ l2 *= l1;\r
+ vTaskDelay( xDelay );\r
+\r
+ if( xTaskToKill != NULL )\r
+ {\r
+ /* Make sure the other task has a go before we delete it. */\r
+ vTaskDelay( ( portTickType ) 0 );\r
+\r
+ /* Kill the other task that was created by vCreateTasks(). */\r
+ vTaskDelete( xTaskToKill );\r
+\r
+ /* Kill ourselves. */\r
+ vTaskDelete( NULL );\r
+ }\r
+ }\r
+}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vCreateTasks, pvParameters )\r
+{\r
+const portTickType xDelay = ( portTickType ) 1000 / portTICK_RATE_MS;\r
+unsigned portBASE_TYPE uxPriority;\r
+\r
+ uxPriority = *( unsigned portBASE_TYPE * ) pvParameters;\r
+ vPortFree( pvParameters );\r
+\r
+ for( ;; )\r
+ {\r
+ /* Just loop round, delaying then creating the four suicidal tasks. */\r
+ vTaskDelay( xDelay );\r
+\r
+ xCreatedTask = NULL;\r
+\r
+ xTaskCreate( vSuicidalTask, ( signed char * ) "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask );\r
+ xTaskCreate( vSuicidalTask, ( signed char * ) "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL );\r
+\r
+ ++usCreationCount;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that the creator task is still running and that there\r
+are not any more than four extra tasks. */\r
+portBASE_TYPE xIsCreateTaskStillRunning( void )\r
+{\r
+static unsigned short usLastCreationCount = 0xfff;\r
+portBASE_TYPE xReturn = pdTRUE;\r
+static unsigned portBASE_TYPE uxTasksRunningNow;\r
+\r
+ if( usLastCreationCount == usCreationCount )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ usLastCreationCount = usCreationCount;\r
+ }\r
+ \r
+ uxTasksRunningNow = ( unsigned portBASE_TYPE ) uxTaskGetNumberOfTasks();\r
+\r
+ if( uxTasksRunningNow < uxTasksRunningAtStart )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ /* Everything is okay. */\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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 long ) 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 long 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 volatile unsigned short usCheckVariable = ( unsigned short ) 0;\r
+static volatile portBASE_TYPE xSuspendedQueueSendError = pdFALSE;\r
+static volatile 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 long ) );\r
+\r
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
+ in use. The queue registry is provided as a means for kernel aware \r
+ debuggers to locate queues and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( xSuspendedTestQueue, ( signed char * ) "Suspended_Test_Queue" );\r
+\r
+ xTaskCreate( vContinuousIncrementTask, ( signed char * ) "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinousIncrementHandle );\r
+ xTaskCreate( vLimitedIncrementTask, ( signed char * ) "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle );\r
+ xTaskCreate( vCounterControlTask, ( signed char * ) "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( vQueueSendWhenSuspendedTask, ( signed char * ) "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( vQueueReceiveWhenSuspendedTask, ( signed char * ) "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 long *pulCounter;\r
+\r
+ /* Take a pointer to the shared variable from the parameters passed into\r
+ the task. */\r
+ pulCounter = ( unsigned long * ) 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 long *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 long * ) 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 long ulLastCounter;\r
+short sLoops;\r
+short 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 long ) 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 long ) 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 long ulValueToSend = ( unsigned long ) 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 long ulExpectedValue = ( unsigned long ) 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 short usLastTaskCheck = ( unsigned short ) 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
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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 version of flash .c is for use on systems that have limited stack space\r
+ * and no display facilities. The complete version can be found in the \r
+ * Demo/Common/Full directory.\r
+ * \r
+ * Three tasks are created, each of which flash an LED at a different rate. The first \r
+ * LED flashes every 200ms, the second every 400ms, the third every 600ms.\r
+ *\r
+ * The LED flash tasks provide instant visual feedback. They show that the scheduler \r
+ * is still operational.\r
+ *\r
+ */\r
+\r
+\r
+#include <stdlib.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* Demo program include files. */\r
+#include "partest.h"\r
+#include "flash.h"\r
+\r
+#define ledSTACK_SIZE configMINIMAL_STACK_SIZE\r
+#define ledNUMBER_OF_LEDS ( 3 )\r
+#define ledFLASH_RATE_BASE ( ( portTickType ) 333 )\r
+\r
+/* Variable used by the created tasks to calculate the LED number to use, and\r
+the rate at which they should flash the LED. */\r
+static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0;\r
+\r
+/* The task that is created three times. */\r
+static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+signed portBASE_TYPE xLEDTask;\r
+\r
+ /* Create the three tasks. */\r
+ for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )\r
+ {\r
+ /* Spawn the task. */\r
+ xTaskCreate( vLEDFlashTask, ( signed char * ) "LEDx", ledSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vLEDFlashTask, pvParameters )\r
+{\r
+portTickType xFlashRate, xLastFlashTime;\r
+unsigned portBASE_TYPE uxLED;\r
+\r
+ /* The parameters are not used. */\r
+ ( void ) pvParameters;\r
+\r
+ /* Calculate the LED and flash rate. */\r
+ portENTER_CRITICAL();\r
+ {\r
+ /* See which of the eight LED's we should use. */\r
+ uxLED = uxFlashTaskNumber;\r
+\r
+ /* Update so the next task uses the next LED. */\r
+ uxFlashTaskNumber++;\r
+ }\r
+ portEXIT_CRITICAL();\r
+\r
+ xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) uxLED );\r
+ xFlashRate /= portTICK_RATE_MS;\r
+\r
+ /* We will turn the LED on and off again in the delay period, so each\r
+ delay is only half the total period. */\r
+ xFlashRate /= ( portTickType ) 2;\r
+\r
+ /* We need to initialise xLastFlashTime prior to the first call to \r
+ vTaskDelayUntil(). */\r
+ xLastFlashTime = xTaskGetTickCount();\r
+\r
+ for(;;)\r
+ {\r
+ /* Delay for half the flash period then turn the LED on. */\r
+ vTaskDelayUntil( &xLastFlashTime, xFlashRate );\r
+ vParTestToggleLED( uxLED );\r
+\r
+ /* Delay for half the flash period then turn the LED off. */\r
+ vTaskDelayUntil( &xLastFlashTime, xFlashRate );\r
+ vParTestToggleLED( uxLED );\r
+ }\r
+} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef BLOCK_Q_H\r
+#define BLOCK_Q_H\r
+\r
+void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreBlockingQueuesStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef GEN_Q_TEST_H\r
+#define GEN_Q_TEST_H\r
+\r
+void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreGenericQueueTasksStillRunning( void );\r
+\r
+#endif /* GEN_Q_TEST_H */\r
+\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef POLLED_Q_H\r
+#define POLLED_Q_H\r
+\r
+void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xArePollingQueuesStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef Q_PEEK_TEST_H\r
+#define Q_PEEK_TEST_H\r
+\r
+void vStartQueuePeekTasks( void );\r
+portBASE_TYPE xAreQueuePeekTasksStillRunning( void );\r
+\r
+#endif /* Q_PEEK_TEST_H */\r
+\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef BLOCK_TIME_TEST_H\r
+#define BLOCK_TIME_TEST_H\r
+\r
+void vCreateBlockTimeTasks( void );\r
+portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef SUICIDE_TASK_H\r
+#define SUICIDE_TASK_H\r
+\r
+void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xIsCreateTaskStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef DYNAMIC_MANIPULATION_H\r
+#define DYNAMIC_MANIPULATION_H\r
+\r
+void vStartDynamicPriorityTasks( void );\r
+portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef FLASH_LED_H\r
+#define FLASH_LED_H\r
+\r
+void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority );\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef FLOP_TASKS_H\r
+#define FLOP_TASKS_H\r
+\r
+void vStartMathTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreMathsTaskStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef PARTEST_H\r
+#define PARTEST_H\r
+\r
+#define partstDEFAULT_PORT_ADDRESS ( ( unsigned short ) 0x378 )\r
+\r
+void vParTestInitialise( void );\r
+void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue );\r
+void vParTestToggleLED( unsigned portBASE_TYPE uxLED );\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef RECURSIVE_MUTEX_TEST_H\r
+#define RECURSIVE_MUTEX_TEST_H\r
+\r
+void vStartRecursiveMutexTasks( void );\r
+portBASE_TYPE xAreRecursiveMutexTasksStillRunning( void );\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+#ifndef SEMAPHORE_TEST_H\r
+#define SEMAPHORE_TEST_H\r
+\r
+void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreSemaphoreTasksStillRunning( void );\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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 volatile portBASE_TYPE xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE;\r
+static volatile unsigned portBASE_TYPE uxControllingCycles = 0, uxBlockingCycles = 0, 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
+ /* vQueueAddToRegistry() adds the mutex to the registry, if one is\r
+ in use. The registry is provided as a means for kernel aware \r
+ debuggers to locate mutex and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Recursive_Mutex" );\r
+\r
+\r
+ if( xMutex != NULL )\r
+ {\r
+ xTaskCreate( prvRecursiveMutexControllingTask, ( signed portCHAR * ) "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );\r
+ xTaskCreate( prvRecursiveMutexBlockingTask, ( signed portCHAR * ) "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle );\r
+ xTaskCreate( prvRecursiveMutexPollingTask, ( signed portCHAR * ) "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
+ /* Just to remove compiler warning. */\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* Should not be able to 'give' the mutex, as we have not yet 'taken'\r
+ it. The first time through, the mutex will not have been used yet,\r
+ subsequent times through, at this point the mutex will be held by the\r
+ polling task. */\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.\r
+ \r
+ The first time through the mutex will be immediately available, on\r
+ subsequent times through the mutex will be held by the polling task\r
+ at this point and this Take will cause the polling task to inherit\r
+ the priority of this task. In this case the block time must be\r
+ long enough to ensure the polling task will execute again before the\r
+ block time expires. If the block time does expire then the error\r
+ flag will be set here. */\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 to ensure they either block\r
+ (where a block time is specified) or return an error (where no \r
+ block time is specified) as the mutex is held by this task. */\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. When the mutex is available again the Blocking task\r
+ should be unblocked but not run because it has a lower priority\r
+ than this task. The polling task should also not run at this point\r
+ as it too has a lower priority than this task. */\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
+ /* Just to remove compiler warning. */\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* This task will run while the controlling task is blocked, and the\r
+ controlling task will block only once it has the mutex - therefore\r
+ this call should block until the controlling task has given up the \r
+ mutex, and not actually execute past this call until the controlling \r
+ 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
+ /* Just to remove compiler warning. */\r
+ ( 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, which in turn should only\r
+ happen when the controlling task is also suspended. */\r
+ if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )\r
+ {\r
+ /* Is the blocking task suspended? */\r
+ if( ( xBlockingIsSuspended != pdTRUE ) || ( xControllingIsSuspended != pdTRUE ) )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ /* Keep count of the number of cycles this task has performed \r
+ so 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. The Blocking task will\r
+ block indefinitely when it attempts to obtain the mutex, the\r
+ Controlling task will only block for a fixed period and an\r
+ error will be latched if the polling task has not returned the\r
+ mutex by the time this fixed period has expired. */\r
+ vTaskResume( xBlockingTaskHandle );\r
+ vTaskResume( xControllingTaskHandle );\r
+ \r
+ /* The other two tasks should now have executed and no longer\r
+ be suspended. */\r
+ if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ } \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
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+ * Creates two sets of two tasks. The tasks within a set share a variable, access \r
+ * to which is guarded by a semaphore.\r
+ * \r
+ * Each task starts by attempting to obtain the semaphore. On obtaining a \r
+ * semaphore a task checks to ensure that the guarded variable has an expected \r
+ * value. It then clears the variable to zero before counting it back up to the \r
+ * expected value in increments of 1. After each increment the variable is checked \r
+ * to ensure it contains the value to which it was just set. When the starting \r
+ * value is again reached the task releases the semaphore giving the other task in \r
+ * the set a chance to do exactly the same thing. The starting value is high \r
+ * enough to ensure that a tick is likely to occur during the incrementing loop.\r
+ *\r
+ * An error is flagged if at any time during the process a shared variable is \r
+ * found to have a value other than that expected. Such an occurrence would \r
+ * suggest an error in the mutual exclusion mechanism by which access to the \r
+ * variable is restricted.\r
+ *\r
+ * The first set of two tasks poll their semaphore. The second set use blocking \r
+ * calls.\r
+ *\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 "semtest.h"\r
+\r
+/* The value to which the shared variables are counted. */\r
+#define semtstBLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xfff )\r
+#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xff )\r
+\r
+#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE\r
+\r
+#define semtstNUM_TASKS ( 4 )\r
+\r
+#define semtstDELAY_FACTOR ( ( portTickType ) 10 )\r
+\r
+/* The task function as described at the top of the file. */\r
+static portTASK_FUNCTION_PROTO( prvSemaphoreTest, pvParameters );\r
+\r
+/* Structure used to pass parameters to each task. */\r
+typedef struct SEMAPHORE_PARAMETERS\r
+{\r
+ xSemaphoreHandle xSemaphore;\r
+ volatile unsigned long *pulSharedVariable;\r
+ portTickType xBlockTime;\r
+} xSemaphoreParameters;\r
+\r
+/* Variables used to check that all the tasks are still running without errors. */\r
+static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 };\r
+static volatile short sNextCheckVariable = 0;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters;\r
+const portTickType xBlockTime = ( portTickType ) 100;\r
+\r
+ /* Create the structure used to pass parameters to the first two tasks. */\r
+ pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );\r
+\r
+ if( pxFirstSemaphoreParameters != NULL )\r
+ {\r
+ /* Create the semaphore used by the first two tasks. */\r
+ vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore );\r
+\r
+ if( pxFirstSemaphoreParameters->xSemaphore != NULL )\r
+ {\r
+ /* Create the variable which is to be shared by the first two tasks. */\r
+ pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) );\r
+\r
+ /* Initialise the share variable to the value the tasks expect. */\r
+ *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE;\r
+\r
+ /* The first two tasks do not block on semaphore calls. */\r
+ pxFirstSemaphoreParameters->xBlockTime = ( portTickType ) 0;\r
+\r
+ /* Spawn the first two tasks. As they poll they operate at the idle priority. */\r
+ xTaskCreate( prvSemaphoreTest, ( signed char * ) "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
+ xTaskCreate( prvSemaphoreTest, ( signed char * ) "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
+ }\r
+ }\r
+\r
+ /* Do exactly the same to create the second set of tasks, only this time \r
+ provide a block time for the semaphore calls. */\r
+ pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );\r
+ if( pxSecondSemaphoreParameters != NULL )\r
+ {\r
+ vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore );\r
+\r
+ if( pxSecondSemaphoreParameters->xSemaphore != NULL )\r
+ {\r
+ pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) );\r
+ *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE;\r
+ pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_RATE_MS;\r
+\r
+ xTaskCreate( prvSemaphoreTest, ( signed char * ) "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL );\r
+ xTaskCreate( prvSemaphoreTest, ( signed char * ) "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL );\r
+ }\r
+ }\r
+\r
+ /* vQueueAddToRegistry() adds the semaphore to the registry, if one is\r
+ in use. The registry is provided as a means for kernel aware \r
+ debuggers to locate semaphores and has no purpose if a kernel aware debugger\r
+ is not being used. The call to vQueueAddToRegistry() will be removed\r
+ by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is \r
+ defined to be less than 1. */\r
+ vQueueAddToRegistry( ( xQueueHandle ) pxFirstSemaphoreParameters->xSemaphore, ( signed char * ) "Counting_Sem_1" );\r
+ vQueueAddToRegistry( ( xQueueHandle ) pxSecondSemaphoreParameters->xSemaphore, ( signed char * ) "Counting_Sem_2" );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( prvSemaphoreTest, pvParameters )\r
+{\r
+xSemaphoreParameters *pxParameters;\r
+volatile unsigned long *pulSharedVariable, ulExpectedValue;\r
+unsigned long ulCounter;\r
+short sError = pdFALSE, sCheckVariableToUse;\r
+\r
+ /* See which check variable to use. sNextCheckVariable is not semaphore \r
+ protected! */\r
+ portENTER_CRITICAL();\r
+ sCheckVariableToUse = sNextCheckVariable;\r
+ sNextCheckVariable++;\r
+ portEXIT_CRITICAL();\r
+\r
+ /* A structure is passed in as the parameter. This contains the shared \r
+ variable being guarded. */\r
+ pxParameters = ( xSemaphoreParameters * ) pvParameters;\r
+ pulSharedVariable = pxParameters->pulSharedVariable;\r
+\r
+ /* If we are blocking we use a much higher count to ensure loads of context\r
+ switches occur during the count. */\r
+ if( pxParameters->xBlockTime > ( portTickType ) 0 )\r
+ {\r
+ ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;\r
+ }\r
+ else\r
+ {\r
+ ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE;\r
+ }\r
+\r
+ for( ;; )\r
+ {\r
+ /* Try to obtain the semaphore. */\r
+ if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )\r
+ {\r
+ /* We have the semaphore and so expect any other tasks using the\r
+ shared variable to have left it in the state we expect to find\r
+ it. */\r
+ if( *pulSharedVariable != ulExpectedValue )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+ \r
+ /* Clear the variable, then count it back up to the expected value\r
+ before releasing the semaphore. Would expect a context switch or\r
+ two during this time. */\r
+ for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ )\r
+ {\r
+ *pulSharedVariable = ulCounter;\r
+ if( *pulSharedVariable != ulCounter )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Release the semaphore, and if no errors have occurred increment the check\r
+ variable. */\r
+ if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+\r
+ if( sError == pdFALSE )\r
+ {\r
+ if( sCheckVariableToUse < semtstNUM_TASKS )\r
+ {\r
+ ( sCheckVariables[ sCheckVariableToUse ] )++;\r
+ }\r
+ }\r
+\r
+ /* If we have a block time then we are running at a priority higher\r
+ than the idle priority. This task takes a long time to complete\r
+ a cycle (deliberately so to test the guarding) so will be starving\r
+ out lower priority tasks. Block for some time to allow give lower\r
+ priority tasks some processor time. */\r
+ vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );\r
+ }\r
+ else\r
+ {\r
+ if( pxParameters->xBlockTime == ( portTickType ) 0 )\r
+ {\r
+ /* We have not got the semaphore yet, so no point using the\r
+ processor. We are not blocking when attempting to obtain the\r
+ semaphore. */\r
+ taskYIELD();\r
+ }\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+portBASE_TYPE xAreSemaphoreTasksStillRunning( void )\r
+{\r
+static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 };\r
+portBASE_TYPE xTask, xReturn = pdTRUE;\r
+\r
+ for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ )\r
+ {\r
+ if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+\r
+ sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ];\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+ \r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+ >>>NOTE<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details. You should have received a copy of the GNU General Public\r
+ License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+ by writing to Richard Barry, contact details for whom are available on the\r
+ FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\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
+ * Creates eight tasks, each of which loops continuously performing a floating \r
+ * point calculation - using single precision variables.\r
+ *\r
+ * All the tasks run at the idle priority and never block or yield. This causes \r
+ * all eight tasks to time slice with the idle task. Running at the idle priority \r
+ * means that these tasks will get pre-empted any time another task is ready to run\r
+ * or a time slice occurs. More often than not the pre-emption will occur mid \r
+ * calculation, creating a good test of the schedulers context switch mechanism - a \r
+ * calculation producing an unexpected result could be a symptom of a corruption in \r
+ * the context of a task.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <math.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* Demo program include files. */\r
+#include "flop.h"\r
+\r
+#define mathSTACK_SIZE configMINIMAL_STACK_SIZE\r
+#define mathNUMBER_OF_TASKS ( 8 )\r
+\r
+/* Four tasks, each of which performs a different floating point calculation. \r
+Each of the four is created twice. */\r
+static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );\r
+static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );\r
+static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );\r
+static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );\r
+\r
+/* These variables are used to check that all the tasks are still running. If a \r
+task gets a calculation wrong it will\r
+stop incrementing its check variable. */\r
+static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartMathTasks( unsigned portBASE_TYPE uxPriority )\r
+{\r
+ xTaskCreate( vCompetingMathTask1, ( signed char * ) "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask2, ( signed char * ) "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask3, ( signed char * ) "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask4, ( signed char * ) "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask1, ( signed char * ) "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask2, ( signed char * ) "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask3, ( signed char * ) "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );\r
+ xTaskCreate( vCompetingMathTask4, ( signed char * ) "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vCompetingMathTask1, pvParameters )\r
+{\r
+volatile float f1, f2, f3, f4;\r
+volatile unsigned short *pusTaskCheckVariable;\r
+volatile float fAnswer;\r
+short sError = pdFALSE;\r
+\r
+ f1 = 123.4567F;\r
+ f2 = 2345.6789F;\r
+ f3 = -918.222F;\r
+\r
+ fAnswer = ( f1 + f2 ) * f3;\r
+\r
+ /* The variable this task increments to show it is still running is passed in \r
+ as the parameter. */\r
+ pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
+\r
+ /* Keep performing a calculation and checking the result against a constant. */\r
+ for(;;)\r
+ {\r
+ f1 = 123.4567F;\r
+ f2 = 2345.6789F;\r
+ f3 = -918.222F;\r
+\r
+ f4 = ( f1 + f2 ) * f3;\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ /* If the calculation does not match the expected constant, stop the \r
+ increment of the check variable. */\r
+ if( fabs( f4 - fAnswer ) > 0.001F )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+\r
+ if( sError == pdFALSE )\r
+ {\r
+ /* If the calculation has always been correct, increment the check \r
+ variable so we know this task is still running okay. */\r
+ ( *pusTaskCheckVariable )++;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vCompetingMathTask2, pvParameters )\r
+{\r
+volatile float f1, f2, f3, f4;\r
+volatile unsigned short *pusTaskCheckVariable;\r
+volatile float fAnswer;\r
+short sError = pdFALSE;\r
+\r
+ f1 = -389.38F;\r
+ f2 = 32498.2F;\r
+ f3 = -2.0001F;\r
+\r
+ fAnswer = ( f1 / f2 ) * f3;\r
+\r
+\r
+ /* The variable this task increments to show it is still running is passed in \r
+ as the parameter. */\r
+ pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
+\r
+ /* Keep performing a calculation and checking the result against a constant. */\r
+ for( ;; )\r
+ {\r
+ f1 = -389.38F;\r
+ f2 = 32498.2F;\r
+ f3 = -2.0001F;\r
+\r
+ f4 = ( f1 / f2 ) * f3;\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+ \r
+ /* If the calculation does not match the expected constant, stop the \r
+ increment of the check variable. */\r
+ if( fabs( f4 - fAnswer ) > 0.001F )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+\r
+ if( sError == pdFALSE )\r
+ {\r
+ /* If the calculation has always been correct, increment the check \r
+ variable so we know\r
+ this task is still running okay. */\r
+ ( *pusTaskCheckVariable )++;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vCompetingMathTask3, pvParameters )\r
+{\r
+volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition;\r
+volatile unsigned short *pusTaskCheckVariable;\r
+const size_t xArraySize = 10;\r
+size_t xPosition;\r
+short sError = pdFALSE;\r
+\r
+ /* The variable this task increments to show it is still running is passed in \r
+ as the parameter. */\r
+ pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
+\r
+ pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );\r
+\r
+ /* Keep filling an array, keeping a running total of the values placed in the \r
+ array. Then run through the array adding up all the values. If the two totals \r
+ do not match, stop the check variable from incrementing. */\r
+ for( ;; )\r
+ {\r
+ fTotal1 = 0.0F;\r
+ fTotal2 = 0.0F;\r
+ fPosition = 0.0F;\r
+ \r
+ for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
+ {\r
+ pfArray[ xPosition ] = fPosition + 5.5F;\r
+ fTotal1 += fPosition + 5.5F; \r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
+ {\r
+ fTotal2 += pfArray[ xPosition ];\r
+ }\r
+\r
+ fDifference = fTotal1 - fTotal2;\r
+ if( fabs( fDifference ) > 0.001F )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ if( sError == pdFALSE )\r
+ {\r
+ /* If the calculation has always been correct, increment the check \r
+ variable so we know this task is still running okay. */\r
+ ( *pusTaskCheckVariable )++;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vCompetingMathTask4, pvParameters )\r
+{\r
+volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition;\r
+volatile unsigned short *pusTaskCheckVariable;\r
+const size_t xArraySize = 10;\r
+size_t xPosition;\r
+short sError = pdFALSE;\r
+\r
+ /* The variable this task increments to show it is still running is passed in \r
+ as the parameter. */\r
+ pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
+\r
+ pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );\r
+\r
+ /* Keep filling an array, keeping a running total of the values placed in the \r
+ array. Then run through the array adding up all the values. If the two totals \r
+ do not match, stop the check variable from incrementing. */\r
+ for( ;; )\r
+ {\r
+ fTotal1 = 0.0F;\r
+ fTotal2 = 0.0F;\r
+ fPosition = 0.0F;\r
+\r
+ for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
+ {\r
+ pfArray[ xPosition ] = fPosition * 12.123F;\r
+ fTotal1 += fPosition * 12.123F; \r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
+ {\r
+ fTotal2 += pfArray[ xPosition ];\r
+ }\r
+\r
+ fDifference = fTotal1 - fTotal2;\r
+ if( fabs( fDifference ) > 0.001F )\r
+ {\r
+ sError = pdTRUE;\r
+ }\r
+\r
+ #if configUSE_PREEMPTION == 0\r
+ taskYIELD();\r
+ #endif\r
+\r
+ if( sError == pdFALSE )\r
+ {\r
+ /* If the calculation has always been correct, increment the check \r
+ variable so we know this task is still running okay. */\r
+ ( *pusTaskCheckVariable )++;\r
+ }\r
+ }\r
+} \r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is called to check that all the created tasks are still running. */\r
+portBASE_TYPE xAreMathsTaskStillRunning( void )\r
+{\r
+/* Keep a history of the check variables so we know if they have been incremented \r
+since the last call. */\r
+static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };\r
+portBASE_TYPE xReturn = pdTRUE, xTask;\r
+\r
+ /* Check the maths tasks are still running by ensuring their check variables \r
+ are still incrementing. */\r
+ for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )\r
+ {\r
+ if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )\r
+ {\r
+ /* The check has not incremented so an error exists. */\r
+ xReturn = pdFALSE;\r
+ }\r
+\r
+ usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+\r
+\r
+\r