--- /dev/null
+/*\r
+ FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section\r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license\r
+ and contact details. Please ensure to read the configuration and relevant\r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+/*\r
+ * This is a version of BlockQ.c that uses the alternative (Alt) API.\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
+#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 "AltBlckQ.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 portSHORT *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 portSHORT sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 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 portSHORT sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 };\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartAltBlockingQueueTasks( 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 portSHORT ) );\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 portCHAR * ) "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );\r
+ xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "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 portSHORT ) );\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 portCHAR * ) "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "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 portSHORT ) );\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 portCHAR * ) "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters )\r
+{\r
+unsigned portSHORT usValue = 0;\r
+xBlockingQueueParameters *pxQueueParameters;\r
+portSHORT sErrorEverOccurred = pdFALSE;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Alt blocking queue producer task started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\r
+\r
+ pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;\r
+\r
+ for( ;; )\r
+ { \r
+ if( xQueueAltSendToBack( 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 portSHORT usData, usExpectedValue = 0;\r
+xBlockingQueueParameters *pxQueueParameters;\r
+portSHORT sErrorEverOccurred = pdFALSE;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\r
+\r
+ pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;\r
+\r
+ for( ;; )\r
+ { \r
+ if( xQueueAltReceive( 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 xAreAltBlockingQueuesStillRunning( void )\r
+{\r
+static portSHORT sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 };\r
+static portSHORT sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 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.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section\r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license\r
+ and contact details. Please ensure to read the configuration and relevant\r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+/*\r
+ * This is a version of BlockTim.c that uses the light weight API.\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 "AltBlock.h"\r
+\r
+/* Task priorities. */\r
+#define bktPRIMARY_PRIORITY ( 3 )\r
+#define bktSECONDARY_PRIORITY ( 2 )\r
+\r
+/* Task behaviour. */\r
+#define bktQUEUE_LENGTH ( 5 )\r
+#define bktSHORT_WAIT ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )\r
+#define bktPRIMARY_BLOCK_TIME ( 10 )\r
+#define bktALLOWABLE_MARGIN ( 12 )\r
+#define bktTIME_TO_BLOCK ( 175 )\r
+#define bktDONT_BLOCK ( ( portTickType ) 0 )\r
+#define bktRUN_INDICATOR ( ( unsigned portBASE_TYPE ) 0x55 )\r
+\r
+/* The queue on which the tasks block. */\r
+static xQueueHandle xTestQueue;\r
+\r
+/* Handle to the secondary task is required by the primary task for calls\r
+to vTaskSuspend/Resume(). */\r
+static xTaskHandle xSecondary;\r
+\r
+/* Used to ensure that tasks are still executing without error. */\r
+static portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;\r
+static portBASE_TYPE xErrorOccurred = pdFALSE;\r
+\r
+/* Provides a simple mechanism for the primary task to know when the\r
+secondary task has executed. */\r
+static volatile unsigned portBASE_TYPE xRunIndicator;\r
+\r
+/* The two test tasks. Their behaviour is commented within the files. */\r
+static void vPrimaryBlockTimeTestTask( void *pvParameters );\r
+static void vSecondaryBlockTimeTestTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vCreateAltBlockTimeTasks( void )\r
+{\r
+ /* Create the queue on which the two tasks block. */\r
+ xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );\r
+\r
+ /* Create the two test tasks. */\r
+ xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
+ xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"FBTest2", 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
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Alt primary block time test started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\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
+ /* A critical section is used to minimise the jitter in the time\r
+ measurements. */\r
+ portENTER_CRITICAL();\r
+ {\r
+ xTimeWhenBlocking = xTaskGetTickCount();\r
+ \r
+ /* We should unblock after xTimeToBlock having not received\r
+ anything on the queue. */\r
+ if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* How long were we blocked for? */\r
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
+ }\r
+ portEXIT_CRITICAL();\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( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\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
+ portENTER_CRITICAL();\r
+ {\r
+ xTimeWhenBlocking = xTaskGetTickCount();\r
+ \r
+ /* We should unblock after xTimeToBlock having not received\r
+ anything on the queue. */\r
+ if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* How long were we blocked for? */\r
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
+ }\r
+ portEXIT_CRITICAL();\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
+ /*********************************************************************\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( xQueueAltReceive( 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( xQueueAltSendToBack( 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( xQueueAltReceive( 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( xQueueAltSendToBack( 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( xQueueAltReceive( 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
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Alt secondary block time test started.\r\n";\r
+\r
+ /* Queue a message for printing to say the task has started. */\r
+ vPrintDisplayMessage( &pcTaskStartMsg );\r
+ #endif\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
+ portENTER_CRITICAL();\r
+ {\r
+ xTimeWhenBlocking = xTaskGetTickCount();\r
+ \r
+ /* We should unblock after bktTIME_TO_BLOCK having not received\r
+ anything on the queue. */\r
+ xData = 0;\r
+ xRunIndicator = bktRUN_INDICATOR;\r
+ if( xQueueAltSendToBack( 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
+ portEXIT_CRITICAL();\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
+ portENTER_CRITICAL();\r
+ {\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( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;\r
+ }\r
+ portEXIT_CRITICAL();\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 xAreAltBlockTimeTestTasksStillRunning( 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.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section\r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license\r
+ and contact details. Please ensure to read the configuration and relevant\r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+/*\r
+ * This is a version of PollQ.c that uses the alternative (Alt) API.\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 portLONG.\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 "AltPollQ.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 vStartAltPolledQueueTasks( 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 portSHORT ) );\r
+\r
+ /* Spawn the producer and consumer. */\r
+ xTaskCreate( vPolledQueueConsumer, ( signed portCHAR * ) "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL );\r
+ xTaskCreate( vPolledQueueProducer, ( signed portCHAR * ) "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portTASK_FUNCTION( vPolledQueueProducer, pvParameters )\r
+{\r
+unsigned portSHORT usValue = ( unsigned portSHORT ) 0;\r
+signed portBASE_TYPE xError = pdFALSE, xLoop;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Alt polling queue producer task 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
+ for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ )\r
+ {\r
+ /* Send an incrementing number on the queue without blocking. */\r
+ if( xQueueAltSendToBack( *( ( 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 portSHORT usData, usExpectedValue = ( unsigned portSHORT ) 0;\r
+signed portBASE_TYPE xError = pdFALSE;\r
+\r
+ #ifdef USE_STDIO\r
+ void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );\r
+ \r
+ const portCHAR * const pcTaskStartMsg = "Alt blocking queue consumer task 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
+ /* Loop until the queue is empty. */\r
+ while( uxQueueMessagesWaiting( *( ( xQueueHandle * ) pvParameters ) ) )\r
+ {\r
+ if( xQueueAltReceive( *( ( 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 xAreAltPollingQueuesStillRunning( 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.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section\r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license\r
+ and contact details. Please ensure to read the configuration and relevant\r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+\r
+/* \r
+ * This file implements the same demo and test as GenQTest.c, but uses the \r
+ * light weight API in place of the fully featured API.\r
+ *\r
+ * See the comments at the top of GenQTest.c for a description.\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 "AltQTest.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 xQueueAltSendToFront() and xQueueAltSendToBack()\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 vStartAltGenericQueueTasks( 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
+ /* 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 * ) "FGenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );\r
+\r
+ /* Create the mutex used by the prvMutexTest task. */\r
+ xMutex = xSemaphoreCreateMutex();\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 * ) "FMuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
+ xTaskCreate( prvMediumPriorityMutexTask, ( signed portCHAR * ) "FMuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
+ xTaskCreate( prvHighPriorityMutexTask, ( signed portCHAR * ) "FMuHigh", 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 = "Alt 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
+ xQueueAltSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueAltReceive( 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
+ xQueueAltSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+\r
+ if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueAltReceive( 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
+ xQueueAltSendToBack( 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
+ xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+ ulData = 0;\r
+ xQueueAltSendToFront( 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( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueAltSendToBack( 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( xQueueAltPeek( 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( xQueueAltReceive( 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( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+ ulData = 11;\r
+ if( xQueueAltSendToBack( 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( xQueueAltSendToFront( 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( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+ {\r
+ xErrorDetected = pdTRUE;\r
+ }\r
+\r
+ if( xQueueAltSendToBack( 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( xQueueAltReceive( 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 = "Fast 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
+ ( void ) pvParameters;\r
+\r
+\r
+ for( ;; )\r
+ {\r
+ /* Take the mutex. It should be available now. */\r
+ if( xSemaphoreAltTake( 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( xSemaphoreAltGive( 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
+ ( void ) 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( xSemaphoreAltTake( 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( xSemaphoreAltGive( 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 xAreAltGenericQueueTasksStillRunning( 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.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section \r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license \r
+ and contact details. Please ensure to read the configuration and relevant \r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+#ifndef ALT_BLOCK_Q_H\r
+#define ALT_BLOCK_Q_H\r
+\r
+void vStartAltBlockingQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreAltBlockingQueuesStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section \r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license \r
+ and contact details. Please ensure to read the configuration and relevant \r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+#ifndef FAST_BLOCK_TIME_TEST_H\r
+#define FAST_BLOCK_TIME_TEST_H\r
+\r
+void vCreateAltBlockTimeTasks( void );\r
+portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section \r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license \r
+ and contact details. Please ensure to read the configuration and relevant \r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+#ifndef ALT_POLLED_Q_H\r
+#define ALT_POLLED_Q_H\r
+\r
+void vStartAltPolledQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreAltPollingQueuesStillRunning( void );\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section\r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license\r
+ and contact details. Please ensure to read the configuration and relevant\r
+ port sections of the online documentation.\r
+\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
+ ***************************************************************************\r
+*/\r
+\r
+#ifndef FAST_GEN_Q_TEST_H\r
+#define FAST_GEN_Q_TEST_H\r
+\r
+void vStartAltGenericQueueTasks( unsigned portBASE_TYPE uxPriority );\r
+portBASE_TYPE xAreAltGenericQueueTasksStillRunning( void );\r
+\r
+#endif /* GEN_Q_TEST_H */\r
+\r
+\r
+\r
#define configUSE_CO_ROUTINES 1\r
#define configUSE_MUTEXES 1\r
#define configUSE_COUNTING_SEMAPHORES 1\r
+#define configUSE_ALTERNATIVE_API 1\r
\r
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 10 )\r
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )\r
#include "mevents.h"\r
#include "crhook.h"\r
#include "blocktim.h"\r
+#include "AltBlock.h"\r
#include "GenQTest.h"\r
#include "QPeek.h"\r
#include "countsem.h"\r
+#include "AltQTest.h"\r
+#include "AltPollQ.h"\r
+#include "AltBlckQ.h"\r
\r
/* Priority definitions for the tasks in the demo application. */\r
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
vStartMultiEventTasks();\r
vStartQueuePeekTasks();\r
vStartCountingSemaphoreTasks();\r
-\r
+ vStartAltGenericQueueTasks( mainGENERIC_QUEUE_PRIORITY );\r
+ vCreateAltBlockTimeTasks();\r
+ vStartAltBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY ); \r
+ vStartAltPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
+ \r
/* Create the "Print" task as described at the top of the file. */\r
xTaskCreate( vErrorChecks, "Print", mainPRINT_STACK_SIZE, NULL, mainPRINT_TASK_PRIORITY, NULL );\r
\r
sErrorHasOccurred = pdTRUE;\r
}\r
\r
+ if( xAreAltBlockingQueuesStillRunning() != pdTRUE )\r
+ {\r
+ vDisplayMessage( "Alt blocking queues count unchanged!\r\n" );\r
+ sErrorHasOccurred = pdTRUE;\r
+ }\r
+\r
if( xArePollingQueuesStillRunning() != pdTRUE )\r
{\r
vDisplayMessage( "Polling queue count unchanged!\r\n" );\r
sErrorHasOccurred = pdTRUE;\r
}\r
\r
+ if( xAreAltPollingQueuesStillRunning() != pdTRUE )\r
+ {\r
+ vDisplayMessage( "Alt polling queue count unchanged!\r\n" );\r
+ sErrorHasOccurred = pdTRUE;\r
+ }\r
+\r
if( xIsCreateTaskStillRunning() != pdTRUE )\r
{\r
vDisplayMessage( "Incorrect number of tasks running!\r\n" );\r
sErrorHasOccurred = pdTRUE;\r
}\r
\r
+ if( xAreAltBlockTimeTestTasksStillRunning() != pdTRUE )\r
+ {\r
+ vDisplayMessage( "Error in fast block time test tasks!\r\n" );\r
+ sErrorHasOccurred = pdTRUE;\r
+ }\r
+\r
if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
{\r
vDisplayMessage( "Error in generic queue test task!\r\n" );\r
sErrorHasOccurred = pdTRUE; \r
}\r
\r
+ if( xAreAltGenericQueueTasksStillRunning() != pdTRUE )\r
+ {\r
+ vDisplayMessage( "Error in fast generic queue test task!\r\n" );\r
+ sErrorHasOccurred = pdTRUE; \r
+ }\r
+\r
if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
{\r
vDisplayMessage( "Error in queue peek test task!\r\n" );\r
0\r
19\r
WPickList\r
-55\r
+63\r
20\r
MItem\r
3\r
168\r
MItem\r
28\r
-..\COMMON\MINIMAL\blocktim.c\r
+..\COMMON\MINIMAL\AltBlckQ.c\r
169\r
WString\r
4\r
172\r
MItem\r
28\r
-..\COMMON\MINIMAL\countsem.c\r
+..\COMMON\MINIMAL\AltBlock.c\r
173\r
WString\r
4\r
0\r
176\r
MItem\r
-27\r
-..\COMMON\MINIMAL\crflash.c\r
+28\r
+..\COMMON\MINIMAL\AltPollQ.c\r
177\r
WString\r
4\r
0\r
180\r
MItem\r
-26\r
-..\COMMON\MINIMAL\crhook.c\r
+28\r
+..\COMMON\MINIMAL\AltQTest.c\r
181\r
WString\r
4\r
184\r
MItem\r
28\r
-..\COMMON\MINIMAL\GenQTest.c\r
+..\COMMON\MINIMAL\blocktim.c\r
185\r
WString\r
4\r
0\r
188\r
MItem\r
-25\r
-..\COMMON\MINIMAL\QPeek.c\r
+28\r
+..\COMMON\MINIMAL\countsem.c\r
189\r
WString\r
4\r
0\r
192\r
MItem\r
-15\r
-fileio\fileio.c\r
+27\r
+..\COMMON\MINIMAL\crflash.c\r
193\r
WString\r
4\r
0\r
196\r
MItem\r
-6\r
-main.c\r
+26\r
+..\COMMON\MINIMAL\crhook.c\r
197\r
WString\r
4\r
0\r
200\r
MItem\r
-17\r
-partest\partest.c\r
+28\r
+..\COMMON\MINIMAL\GenQTest.c\r
201\r
WString\r
4\r
0\r
204\r
MItem\r
-15\r
-serial\serial.c\r
+25\r
+..\COMMON\MINIMAL\QPeek.c\r
205\r
WString\r
4\r
0\r
208\r
MItem\r
-3\r
-*.h\r
+15\r
+fileio\fileio.c\r
209\r
WString\r
-3\r
-NIL\r
+4\r
+COBJ\r
210\r
WVList\r
0\r
211\r
WVList\r
0\r
--1\r
+20\r
+1\r
1\r
-0\r
0\r
212\r
MItem\r
-31\r
-..\..\SOURCE\INCLUDE\croutine.h\r
+6\r
+main.c\r
213\r
WString\r
-3\r
-NIL\r
+4\r
+COBJ\r
214\r
WVList\r
0\r
215\r
WVList\r
0\r
-208\r
+20\r
1\r
1\r
0\r
216\r
MItem\r
-27\r
-..\..\source\include\list.h\r
+17\r
+partest\partest.c\r
217\r
WString\r
-3\r
-NIL\r
+4\r
+COBJ\r
218\r
WVList\r
0\r
219\r
WVList\r
0\r
-208\r
+20\r
1\r
1\r
0\r
220\r
MItem\r
-31\r
-..\..\source\include\portable.h\r
+15\r
+serial\serial.c\r
221\r
WString\r
-3\r
-NIL\r
+4\r
+COBJ\r
222\r
WVList\r
0\r
223\r
WVList\r
0\r
-208\r
+20\r
1\r
1\r
0\r
224\r
MItem\r
-31\r
-..\..\source\include\projdefs.h\r
+3\r
+*.h\r
225\r
WString\r
3\r
227\r
WVList\r
0\r
-208\r
-1\r
+-1\r
1\r
0\r
+0\r
228\r
MItem\r
-28\r
-..\..\source\include\queue.h\r
+31\r
+..\..\SOURCE\INCLUDE\croutine.h\r
229\r
WString\r
3\r
231\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
232\r
MItem\r
-29\r
-..\..\source\include\semphr.h\r
+27\r
+..\..\source\include\list.h\r
233\r
WString\r
3\r
235\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
236\r
MItem\r
-27\r
-..\..\source\include\task.h\r
+31\r
+..\..\source\include\portable.h\r
237\r
WString\r
3\r
239\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
240\r
MItem\r
-55\r
-..\..\source\portable\owatcom\16bitdos\common\portasm.h\r
+31\r
+..\..\source\include\projdefs.h\r
241\r
WString\r
3\r
243\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
244\r
MItem\r
-53\r
-..\..\source\portable\owatcom\16bitdos\pc\portmacro.h\r
+28\r
+..\..\source\include\queue.h\r
245\r
WString\r
3\r
247\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
248\r
MItem\r
-26\r
-..\common\include\blockq.h\r
+29\r
+..\..\source\include\semphr.h\r
249\r
WString\r
3\r
251\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
252\r
MItem\r
-28\r
-..\COMMON\INCLUDE\blocktim.h\r
+27\r
+..\..\source\include\task.h\r
253\r
WString\r
3\r
255\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
256\r
MItem\r
-27\r
-..\common\include\comtest.h\r
+55\r
+..\..\source\portable\owatcom\16bitdos\common\portasm.h\r
257\r
WString\r
3\r
259\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
260\r
MItem\r
-28\r
-..\COMMON\INCLUDE\countsem.h\r
+53\r
+..\..\source\portable\owatcom\16bitdos\pc\portmacro.h\r
261\r
WString\r
3\r
263\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
264\r
MItem\r
-26\r
-..\COMMON\INCLUDE\crhook.h\r
+28\r
+..\COMMON\INCLUDE\AltBlckQ.h\r
265\r
WString\r
3\r
267\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
268\r
MItem\r
-25\r
-..\common\include\death.h\r
+28\r
+..\COMMON\INCLUDE\AltBlock.h\r
269\r
WString\r
3\r
271\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
272\r
MItem\r
-27\r
-..\COMMON\INCLUDE\dynamic.h\r
+28\r
+..\COMMON\INCLUDE\AltPollQ.h\r
273\r
WString\r
3\r
275\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
276\r
MItem\r
-26\r
-..\common\include\fileio.h\r
+28\r
+..\COMMON\INCLUDE\AltQTest.h\r
277\r
WString\r
3\r
279\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
280\r
MItem\r
-25\r
-..\common\include\flash.h\r
+26\r
+..\common\include\blockq.h\r
281\r
WString\r
3\r
283\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
284\r
MItem\r
-24\r
-..\common\include\flop.h\r
+28\r
+..\COMMON\INCLUDE\blocktim.h\r
285\r
WString\r
3\r
287\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
288\r
MItem\r
-28\r
-..\COMMON\INCLUDE\GenQTest.h\r
+27\r
+..\common\include\comtest.h\r
289\r
WString\r
3\r
291\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
292\r
MItem\r
-27\r
-..\common\include\partest.h\r
+28\r
+..\COMMON\INCLUDE\countsem.h\r
293\r
WString\r
3\r
295\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
296\r
MItem\r
-25\r
-..\common\include\pollq.h\r
+26\r
+..\COMMON\INCLUDE\crhook.h\r
297\r
WString\r
3\r
299\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
300\r
MItem\r
25\r
-..\common\include\print.h\r
+..\common\include\death.h\r
301\r
WString\r
3\r
303\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
304\r
MItem\r
27\r
-..\common\include\semtest.h\r
+..\COMMON\INCLUDE\dynamic.h\r
305\r
WString\r
3\r
307\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
308\r
MItem\r
26\r
-..\common\include\serial.h\r
+..\common\include\fileio.h\r
309\r
WString\r
3\r
311\r
WVList\r
0\r
-208\r
+224\r
1\r
1\r
0\r
312\r
MItem\r
-16\r
-FreeRTOSConfig.h\r
+25\r
+..\common\include\flash.h\r
313\r
WString\r
3\r
315\r
WVList\r
0\r
-208\r
+224\r
+1\r
+1\r
+0\r
+316\r
+MItem\r
+24\r
+..\common\include\flop.h\r
+317\r
+WString\r
+3\r
+NIL\r
+318\r
+WVList\r
+0\r
+319\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+320\r
+MItem\r
+28\r
+..\COMMON\INCLUDE\GenQTest.h\r
+321\r
+WString\r
+3\r
+NIL\r
+322\r
+WVList\r
+0\r
+323\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+324\r
+MItem\r
+27\r
+..\common\include\partest.h\r
+325\r
+WString\r
+3\r
+NIL\r
+326\r
+WVList\r
+0\r
+327\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+328\r
+MItem\r
+25\r
+..\common\include\pollq.h\r
+329\r
+WString\r
+3\r
+NIL\r
+330\r
+WVList\r
+0\r
+331\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+332\r
+MItem\r
+25\r
+..\common\include\print.h\r
+333\r
+WString\r
+3\r
+NIL\r
+334\r
+WVList\r
+0\r
+335\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+336\r
+MItem\r
+27\r
+..\common\include\semtest.h\r
+337\r
+WString\r
+3\r
+NIL\r
+338\r
+WVList\r
+0\r
+339\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+340\r
+MItem\r
+26\r
+..\common\include\serial.h\r
+341\r
+WString\r
+3\r
+NIL\r
+342\r
+WVList\r
+0\r
+343\r
+WVList\r
+0\r
+224\r
+1\r
+1\r
+0\r
+344\r
+MItem\r
+16\r
+FreeRTOSConfig.h\r
+345\r
+WString\r
+3\r
+NIL\r
+346\r
+WVList\r
+0\r
+347\r
+WVList\r
+0\r
+224\r
1\r
1\r
0\r
VpeMain\r
1\r
WRect\r
-6\r
-9\r
-6229\r
-7197\r
+0\r
+0\r
+6209\r
+7168\r
2\r
MProject\r
3\r
0\r
0\r
7168\r
-8270\r
+8192\r
0\r
0\r
9\r
12\r
rtosdemo.tgt\r
0\r
-25\r
+0\r
7\r
#error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.\r
#endif\r
\r
+#ifndef configUSE_MUTEXES\r
+ #define configUSE_MUTEXES 0\r
+#endif\r
+\r
#ifndef configUSE_COUNTING_SEMAPHORES\r
#define configUSE_COUNTING_SEMAPHORES 0\r
#endif\r
\r
-#ifndef configUSE_MUTEXES\r
- #define configUSE_MUTEXES 0\r
+#ifndef configUSE_ALTERNATIVE_API\r
+ #define configUSE_ALTERNATIVE_API 0\r
#endif\r
\r
#if ( configUSE_MUTEXES == 1 )\r
*/\r
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
\r
+/* \r
+ * xQueueAltGenericSend() is a light weight version of xQueueGenericSend().\r
+ * Likewise xQueueAltGenericReceive() is a light weight version of\r
+ * xQueueGenericReceive().\r
+ *\r
+ * The source code that implements the light weight (fast) API is much \r
+ * simpler because it executes everything from within a critical section. \r
+ * This is the approach taken by many other RTOSes, but FreeRTOS.org has the \r
+ * fully featured API as an alternative. The fully featured API has more \r
+ * complex code that takes longer to execute, but makes much less use of \r
+ * critical sections. Therefore the light weight API sacrifices interrupt \r
+ * responsiveness to gain execution speed, whereas the fully featured API\r
+ * sacrifices execution speed to ensure better interrupt responsiveness.\r
+ */\r
+signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
+signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
+\r
+/*\r
+ * The light weight versions of the fully featured macros.\r
+ */\r
+#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT )\r
+#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )\r
+#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE )\r
+#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE )\r
\r
/*\r
* The functions defined above are for passing data to and from tasks. The\r
* \defgroup xSemaphoreTake xSemaphoreTake\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime )\r
+#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )\r
+#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )\r
\r
/**\r
* semphr. h\r
* \defgroup xSemaphoreGive xSemaphoreGive\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )\r
+#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )\r
+#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )\r
\r
/**\r
* semphr. h\r
/* Trap routine used by taskYIELD() to manually cause a context switch. */\r
static void __interrupt __far prvYieldProcessor( void );\r
\r
+/* The timer initialisation functions leave interrupts enabled,\r
+which is not what we want. This ISR is installed temporarily in case\r
+the timer fires before we get a change to disable interrupts again. */\r
+static void __interrupt __far prvDummyISR( void );\r
+\r
/*-----------------------------------------------------------*/\r
/* See header file for description. */\r
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void __interrupt __far prvDummyISR( void )\r
+{\r
+ /* The timer initialisation functions leave interrupts enabled,\r
+ which is not what we want. This ISR is installed temporarily in case\r
+ the timer fires before we get a change to disable interrupts again. */\r
+ outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
/* The ISR used depends on whether the preemptive or cooperative scheduler\r
is being used. */\r
#if( configUSE_PREEMPTION == 1 )\r
static void prvSetupTimerInterrupt( void )\r
{\r
const unsigned portSHORT usTimerACompare = portTIMER_COMPARE, usTimerAMode = portENABLE_TIMER_AND_INTERRUPT;\r
+const unsigned portSHORT usT2_IRQ = 0x13;\r
+\r
+ /* Configure the timer, the dummy handler is used here as the init\r
+ function leaves interrupts enabled. */\r
+ t2_init( usTimerAMode, usTimerACompare, prvDummyISR );\r
+\r
+ /* Disable interrupts again before installing the real handlers. */\r
+ portDISABLE_INTERRUPTS();\r
\r
#if( configUSE_PREEMPTION == 1 )\r
/* Tick service routine used by the scheduler when preemptive scheduling is\r
being used. */\r
- t2_init( usTimerAMode, usTimerACompare, prvPreemptiveTick );\r
+ setvect( usT2_IRQ, prvPreemptiveTick );\r
#else\r
/* Tick service routine used by the scheduler when cooperative scheduling is\r
being used. */\r
- t2_init( usTimerAMode, usTimerACompare, prvNonPreemptiveTick );\r
+ setvect( usT2_IRQ, prvNonPreemptiveTick );\r
#endif\r
}\r
\r
xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */\r
xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */\r
\r
- unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
+ volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */\r
unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */\r
unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */\r
\r
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
xQueueHandle xQueueCreateMutex( void );\r
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );\r
+signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
+signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
\r
#if configUSE_CO_ROUTINES == 1\r
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );\r
}\r
/*-----------------------------------------------------------*/\r
\r
+#if configUSE_ALTERNATIVE_API == 1\r
+\r
+ signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )\r
+ {\r
+ signed portBASE_TYPE xReturn;\r
+ xTimeOutType xTimeOut;\r
+\r
+ /* The source code that implements the light weight (fast) API is much \r
+ simpler because it executes everything from within a critical section. \r
+ This is the approach taken by many other RTOSes, but FreeRTOS.org has the \r
+ fully featured API as an alternative. The fully featured API has more \r
+ complex code that takes longer to execute, but makes much less use of \r
+ critical sections. Therefore the light weight API sacrifices interrupt \r
+ responsiveness to gain execution speed, whereas the fully featured API\r
+ sacrifices execution speed to ensure better interrupt responsiveness. */\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ /* Capture the current time status for future reference. */\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+\r
+ /* If the queue is already full we may have to block. */\r
+ do\r
+ {\r
+ if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
+ {\r
+ /* The queue is full - do we want to block or just leave without\r
+ posting? */\r
+ if( xTicksToWait > ( portTickType ) 0 )\r
+ {\r
+ /* We are going to place ourselves on the xTasksWaitingToSend \r
+ event list, and will get woken should the delay expire, or \r
+ space become available on the queue. */\r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
+ \r
+ /* Force a context switch now as we are blocked. We can do\r
+ this from within a critical section as the task we are\r
+ switching to has its own context. When we return here (i.e.\r
+ we unblock) we will leave the critical section as normal. */\r
+ taskYIELD();\r
+ }\r
+ }\r
+ \r
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+ {\r
+ /* There is room in the queue, copy the data into the queue. */ \r
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
+ xReturn = pdPASS;\r
+\r
+ if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )\r
+ {\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
+ {\r
+ /* The task waiting has a higher priority. */\r
+ taskYIELD();\r
+ }\r
+ } \r
+ }\r
+ else\r
+ {\r
+ xReturn = errQUEUE_FULL;\r
+\r
+ if( xTicksToWait > 0 )\r
+ { \r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+ {\r
+ /* Another task must have accessed the queue between \r
+ this task unblocking and actually executing. */\r
+ xReturn = queueERRONEOUS_UNBLOCK;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ \r
+ }\r
+ }\r
+ }\r
+ while( xReturn == queueERRONEOUS_UNBLOCK );\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_ALTERNATIVE_API */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_ALTERNATIVE_API == 1\r
+\r
+ signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )\r
+ {\r
+ signed portBASE_TYPE xReturn = pdTRUE;\r
+ xTimeOutType xTimeOut;\r
+ signed portCHAR *pcOriginalReadPosition;\r
+\r
+ /* The source code that implements the light weight (fast) API is much \r
+ simpler because it executes everything from within a critical section. \r
+ This is the approach taken by many other RTOSes, but FreeRTOS.org has the \r
+ fully featured API as an alternative. The fully featured API has more \r
+ complex code that takes longer to execute, but makes much less use of \r
+ critical sections. Therefore the light weight API sacrifices interrupt \r
+ responsiveness to gain execution speed, whereas the fully featured API\r
+ sacrifices execution speed to ensure better interrupt responsiveness. */\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ /* Capture the current time status for future reference. */\r
+ vTaskSetTimeOutState( &xTimeOut );\r
+\r
+ do\r
+ {\r
+ /* If there are no messages in the queue we may have to block. */\r
+ if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )\r
+ {\r
+ /* There are no messages in the queue, do we want to block or just\r
+ leave with nothing? */ \r
+ if( xTicksToWait > ( portTickType ) 0 )\r
+ {\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ vTaskPriorityInherit( ( void * const ) pxQueue->pxMutexHolder );\r
+ }\r
+ }\r
+ #endif\r
+ \r
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+ taskYIELD();\r
+ }\r
+ }\r
+ \r
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+ {\r
+ /* Remember our read position in case we are just peeking. */\r
+ pcOriginalReadPosition = pxQueue->pcReadFrom;\r
+\r
+ prvCopyDataFromQueue( pxQueue, pvBuffer );\r
+\r
+ if( xJustPeeking == pdFALSE )\r
+ {\r
+ /* We are actually removing data. */\r
+ --( pxQueue->uxMessagesWaiting );\r
+ \r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
+ {\r
+ /* Record the information required to implement\r
+ priority inheritance should it become necessary. */\r
+ pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();\r
+ }\r
+ }\r
+ #endif\r
+\r
+ if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )\r
+ {\r
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
+ {\r
+ /* The task waiting has a higher priority. */\r
+ taskYIELD();\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* We are not removing the data, so reset our read\r
+ pointer. */\r
+ pxQueue->pcReadFrom = pcOriginalReadPosition;\r
+ }\r
+ \r
+ xReturn = pdPASS; \r
+ }\r
+ else\r
+ {\r
+ xReturn = errQUEUE_EMPTY;\r
+\r
+ if( xTicksToWait > 0 )\r
+ {\r
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+ {\r
+ xReturn = queueERRONEOUS_UNBLOCK;\r
+ }\r
+ }\r
+ }\r
+\r
+ } while( xReturn == queueERRONEOUS_UNBLOCK );\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_ALTERNATIVE_API */\r
+/*-----------------------------------------------------------*/\r
+\r
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )\r
{\r
/* Similar to xQueueGenericSend, except we don't block if there is no room\r