]> git.sur5r.net Git - freertos/commitdiff
Changes ready for V4.1.0.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 27 Aug 2006 14:09:54 +0000 (14:09 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 27 Aug 2006 14:09:54 +0000 (14:09 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@28 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/Common/Minimal/blocktim.c [new file with mode: 0644]
Demo/Common/include/blocktim.h [new file with mode: 0644]
Demo/PC/main.c
Demo/PC/rtosdemo.tgt
Demo/PC/rtosdemo.wpj
Source/include/projdefs.h
Source/include/task.h
Source/queue.c
Source/tasks.c

diff --git a/Demo/Common/Minimal/blocktim.c b/Demo/Common/Minimal/blocktim.c
new file mode 100644 (file)
index 0000000..754604c
--- /dev/null
@@ -0,0 +1,467 @@
+/*\r
+       FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 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
+*/\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
+/* 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 vCreateBlockTimeTasks( void )\r
+{\r
+       /* Create the queue on which the two tasks block. */\r
+    xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );\r
+\r
+       /* Create the two test tasks. */\r
+       xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );\r
+       xTaskCreate( vSecondaryBlockTimeTestTask, "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
+       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( 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
+                       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( xQueueSend( 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( 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
+                       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( 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
+       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( 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
+               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( xQueueReceive( 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 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
diff --git a/Demo/Common/include/blocktim.h b/Demo/Common/include/blocktim.h
new file mode 100644 (file)
index 0000000..762f29e
--- /dev/null
@@ -0,0 +1,41 @@
+/*\r
+       FreeRTOS.org V4.0.5 - Copyright (C) 2003-2006 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
+*/\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
index fa64a4e31e2f6f443c90fb9a32a354168c602222..3bd08d5867055284b286a941e240977b5c84a8cc 100644 (file)
@@ -115,6 +115,7 @@ Changes from V3.2.4
 #include "dynamic.h"\r
 #include "mevents.h"\r
 #include "crhook.h"\r
+#include "blocktim.h"\r
 \r
 /* Priority definitions for the tasks in the demo application. */\r
 #define mainLED_TASK_PRIORITY          ( tskIDLE_PRIORITY + 1 )\r
@@ -171,6 +172,7 @@ portSHORT main( void )
        vStartComTestTasks( mainCOM_TEST_PRIORITY, serCOM1, ser115200 );\r
        vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
        vStartBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY );\r
+       vCreateBlockTimeTasks();\r
        \r
        vStartSemaphoreTasks( mainSEMAPHORE_TASK_PRIORITY );\r
        vStartDynamicPriorityTasks();\r
@@ -380,6 +382,12 @@ static portSHORT sErrorHasOccurred = pdFALSE;
                sErrorHasOccurred = pdTRUE;\r
        }\r
 \r
+       if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
+       {\r
+               vDisplayMessage( "Error in block time test tasks!\r\n" );\r
+               sErrorHasOccurred = pdTRUE;\r
+       }\r
+\r
        if( sErrorHasOccurred == pdFALSE )\r
        {\r
                vDisplayMessage( "OK " );\r
index 469fba3a404327d6130b2171026798c2b3178469..7b5f2d66ddc6f1114d3b00221d32064d0ad2c663 100644 (file)
@@ -75,7 +75,7 @@ WVList
 0\r
 19\r
 WPickList\r
-48\r
+50\r
 20\r
 MItem\r
 3\r
@@ -706,8 +706,8 @@ WVList
 0\r
 168\r
 MItem\r
-27\r
-..\COMMON\MINIMAL\crflash.c\r
+28\r
+..\COMMON\MINIMAL\blocktim.c\r
 169\r
 WString\r
 4\r
@@ -724,8 +724,8 @@ WVList
 0\r
 172\r
 MItem\r
-26\r
-..\COMMON\MINIMAL\crhook.c\r
+27\r
+..\COMMON\MINIMAL\crflash.c\r
 173\r
 WString\r
 4\r
@@ -742,8 +742,8 @@ WVList
 0\r
 176\r
 MItem\r
-15\r
-fileio\fileio.c\r
+26\r
+..\COMMON\MINIMAL\crhook.c\r
 177\r
 WString\r
 4\r
@@ -760,8 +760,8 @@ WVList
 0\r
 180\r
 MItem\r
-6\r
-main.c\r
+15\r
+fileio\fileio.c\r
 181\r
 WString\r
 4\r
@@ -778,8 +778,8 @@ WVList
 0\r
 184\r
 MItem\r
-17\r
-partest\partest.c\r
+6\r
+main.c\r
 185\r
 WString\r
 4\r
@@ -796,8 +796,8 @@ WVList
 0\r
 188\r
 MItem\r
-15\r
-serial\serial.c\r
+17\r
+partest\partest.c\r
 189\r
 WString\r
 4\r
@@ -814,26 +814,26 @@ WVList
 0\r
 192\r
 MItem\r
-3\r
-*.h\r
+15\r
+serial\serial.c\r
 193\r
 WString\r
-3\r
-NIL\r
+4\r
+COBJ\r
 194\r
 WVList\r
 0\r
 195\r
 WVList\r
 0\r
--1\r
+20\r
 1\r
 1\r
 0\r
 196\r
 MItem\r
-31\r
-..\..\SOURCE\INCLUDE\croutine.h\r
+3\r
+*.h\r
 197\r
 WString\r
 3\r
@@ -844,14 +844,14 @@ WVList
 199\r
 WVList\r
 0\r
-192\r
-1\r
+-1\r
 1\r
 0\r
+0\r
 200\r
 MItem\r
-27\r
-..\..\source\include\list.h\r
+31\r
+..\..\SOURCE\INCLUDE\croutine.h\r
 201\r
 WString\r
 3\r
@@ -862,14 +862,14 @@ WVList
 203\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 204\r
 MItem\r
-31\r
-..\..\source\include\portable.h\r
+27\r
+..\..\source\include\list.h\r
 205\r
 WString\r
 3\r
@@ -880,14 +880,14 @@ WVList
 207\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 208\r
 MItem\r
 31\r
-..\..\source\include\projdefs.h\r
+..\..\source\include\portable.h\r
 209\r
 WString\r
 3\r
@@ -898,14 +898,14 @@ WVList
 211\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 212\r
 MItem\r
-28\r
-..\..\source\include\queue.h\r
+31\r
+..\..\source\include\projdefs.h\r
 213\r
 WString\r
 3\r
@@ -916,14 +916,14 @@ WVList
 215\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 216\r
 MItem\r
-29\r
-..\..\source\include\semphr.h\r
+28\r
+..\..\source\include\queue.h\r
 217\r
 WString\r
 3\r
@@ -934,14 +934,14 @@ WVList
 219\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 220\r
 MItem\r
-27\r
-..\..\source\include\task.h\r
+29\r
+..\..\source\include\semphr.h\r
 221\r
 WString\r
 3\r
@@ -952,14 +952,14 @@ WVList
 223\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 224\r
 MItem\r
-55\r
-..\..\source\portable\owatcom\16bitdos\common\portasm.h\r
+27\r
+..\..\source\include\task.h\r
 225\r
 WString\r
 3\r
@@ -970,14 +970,14 @@ WVList
 227\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 228\r
 MItem\r
-53\r
-..\..\source\portable\owatcom\16bitdos\pc\portmacro.h\r
+55\r
+..\..\source\portable\owatcom\16bitdos\common\portasm.h\r
 229\r
 WString\r
 3\r
@@ -988,14 +988,14 @@ WVList
 231\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 232\r
 MItem\r
-26\r
-..\common\include\blockq.h\r
+53\r
+..\..\source\portable\owatcom\16bitdos\pc\portmacro.h\r
 233\r
 WString\r
 3\r
@@ -1006,14 +1006,14 @@ WVList
 235\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 236\r
 MItem\r
-27\r
-..\common\include\comtest.h\r
+26\r
+..\common\include\blockq.h\r
 237\r
 WString\r
 3\r
@@ -1024,14 +1024,14 @@ WVList
 239\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 240\r
 MItem\r
-26\r
-..\COMMON\INCLUDE\crhook.h\r
+28\r
+..\COMMON\INCLUDE\blocktim.h\r
 241\r
 WString\r
 3\r
@@ -1042,14 +1042,14 @@ WVList
 243\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 244\r
 MItem\r
-25\r
-..\common\include\death.h\r
+27\r
+..\common\include\comtest.h\r
 245\r
 WString\r
 3\r
@@ -1060,14 +1060,14 @@ WVList
 247\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 248\r
 MItem\r
-27\r
-..\COMMON\INCLUDE\dynamic.h\r
+26\r
+..\COMMON\INCLUDE\crhook.h\r
 249\r
 WString\r
 3\r
@@ -1078,14 +1078,14 @@ WVList
 251\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 252\r
 MItem\r
-26\r
-..\common\include\fileio.h\r
+25\r
+..\common\include\death.h\r
 253\r
 WString\r
 3\r
@@ -1096,14 +1096,14 @@ WVList
 255\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 256\r
 MItem\r
-25\r
-..\common\include\flash.h\r
+27\r
+..\COMMON\INCLUDE\dynamic.h\r
 257\r
 WString\r
 3\r
@@ -1114,14 +1114,14 @@ WVList
 259\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 260\r
 MItem\r
-24\r
-..\common\include\flop.h\r
+26\r
+..\common\include\fileio.h\r
 261\r
 WString\r
 3\r
@@ -1132,14 +1132,14 @@ WVList
 263\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 264\r
 MItem\r
-27\r
-..\common\include\partest.h\r
+25\r
+..\common\include\flash.h\r
 265\r
 WString\r
 3\r
@@ -1150,14 +1150,14 @@ WVList
 267\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 268\r
 MItem\r
-25\r
-..\common\include\pollq.h\r
+24\r
+..\common\include\flop.h\r
 269\r
 WString\r
 3\r
@@ -1168,14 +1168,14 @@ WVList
 271\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 272\r
 MItem\r
-25\r
-..\common\include\print.h\r
+27\r
+..\common\include\partest.h\r
 273\r
 WString\r
 3\r
@@ -1186,14 +1186,14 @@ WVList
 275\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 276\r
 MItem\r
-27\r
-..\common\include\semtest.h\r
+25\r
+..\common\include\pollq.h\r
 277\r
 WString\r
 3\r
@@ -1204,14 +1204,14 @@ WVList
 279\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 280\r
 MItem\r
-26\r
-..\common\include\serial.h\r
+25\r
+..\common\include\print.h\r
 281\r
 WString\r
 3\r
@@ -1222,14 +1222,14 @@ WVList
 283\r
 WVList\r
 0\r
-192\r
+196\r
 1\r
 1\r
 0\r
 284\r
 MItem\r
-16\r
-FreeRTOSConfig.h\r
+27\r
+..\common\include\semtest.h\r
 285\r
 WString\r
 3\r
@@ -1240,7 +1240,43 @@ WVList
 287\r
 WVList\r
 0\r
-192\r
+196\r
+1\r
+1\r
+0\r
+288\r
+MItem\r
+26\r
+..\common\include\serial.h\r
+289\r
+WString\r
+3\r
+NIL\r
+290\r
+WVList\r
+0\r
+291\r
+WVList\r
+0\r
+196\r
+1\r
+1\r
+0\r
+292\r
+MItem\r
+16\r
+FreeRTOSConfig.h\r
+293\r
+WString\r
+3\r
+NIL\r
+294\r
+WVList\r
+0\r
+295\r
+WVList\r
+0\r
+196\r
 1\r
 1\r
 0\r
index 4c9ff86286a89e5a683276d71ec71a150b13837b..1b02cfb2fc52011dda8458414ddbce65738d477a 100644 (file)
@@ -31,7 +31,7 @@ WRect
 0\r
 0\r
 7168\r
-7353\r
+7168\r
 0\r
 0\r
 9\r
@@ -39,5 +39,5 @@ WFileName
 12\r
 rtosdemo.tgt\r
 0\r
-19\r
+25\r
 7\r
index 36c80215f5c16f0961108f6095ef6a9087959ab0..ff28ca50eb786d377a44c2510f04c4324edc60dc 100644 (file)
@@ -39,16 +39,18 @@ typedef void (*pdTASK_CODE)( void * );
 #define pdTRUE         ( 1 )\r
 #define pdFALSE                ( 0 )\r
 \r
-#define pdPASS         ( 1 )\r
-#define pdFAIL         ( 0 )\r
+#define pdPASS                                                                 ( 1 )\r
+#define pdFAIL                                                                 ( 0 )\r
+#define errQUEUE_EMPTY                                                 ( 0 )\r
+#define errQUEUE_FULL                                                  ( 0 )\r
 \r
 /* Error definitions. */\r
 #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY  ( -1 )\r
 #define errNO_TASK_TO_RUN                                              ( -2 )\r
-#define errQUEUE_FULL                                                  ( -3 )\r
 #define errQUEUE_BLOCKED                                               ( -4 )\r
 #define errQUEUE_YIELD                                                 ( -5 )\r
 \r
-#endif\r
+#endif /* PROJDEFS_H */\r
+\r
 \r
 \r
index 2b1dac8db2034a09014ff8db5ef83ac641102e9a..56ca2535021272f4426ad0bf5d136a342ebedfc6 100644 (file)
  */\r
 typedef void * xTaskHandle;\r
 \r
+/*\r
+ * Used internally only.\r
+ */\r
+typedef struct xTIME_OUT\r
+{\r
+    portBASE_TYPE xOverflowCount;\r
+    portTickType  xTimeOnEntering;\r
+} xTimeOutType;\r
+\r
 /*\r
  * Defines the priority used by the idle task.  This must not be modified.\r
  *\r
@@ -919,6 +928,22 @@ inline void vTaskSwitchContext( void );
  */\r
 xTaskHandle xTaskGetCurrentTaskHandle( void );\r
 \r
+/*\r
+ * Capture the current time status for future reference.\r
+ */\r
+void vTaskSetTimeOutState( xTimeOutType *pxTimeOut );\r
+\r
+/*\r
+ * Compare the time status now with that previously captured to see if the\r
+ * timeout has expired.\r
+ */\r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait );\r
+\r
+/*\r
+ * Shortcut used by the queue implementation to prevent unnecessary call to\r
+ * taskYIELD();\r
+ */\r
+void vTaskMissedYield( void );\r
 \r
 #endif /* TASK_H */\r
 \r
index 9bb773414c3abaa4039d20ef59ac0116d1fb4d96..28850485d2489aa40f173ce79dfa683b403de65c 100644 (file)
@@ -54,6 +54,12 @@ Changes from V3.2.3
 \r
        + Added the queue functions that can be used from co-routines.\r
 \r
+Changes from V4.0.5\r
+\r
+       + Added a loop within xQueueSend() and xQueueReceive() to prevent the\r
+         functions exiting when a block time remains and the function has\r
+         not completed.\r
+\r
 */\r
 \r
 #include <stdlib.h>\r
@@ -68,6 +74,7 @@ Changes from V3.2.3
 \r
 /* Constants used with the cRxLock and cTxLock structure members. */\r
 #define queueUNLOCKED  ( ( signed portBASE_TYPE ) -1 )\r
+#define queueERRONEOUS_UNBLOCK                                 ( -1 )\r
 \r
 /*\r
  * Definition of the queue used by the scheduler.\r
@@ -128,7 +135,7 @@ signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer,
  * to indicate that a task may require unblocking.  When the queue in unlocked\r
  * these lock counts are inspected, and the appropriate action taken.\r
  */\r
-static signed portBASE_TYPE prvUnlockQueue( xQueueHandle pxQueue );\r
+static void prvUnlockQueue( xQueueHandle pxQueue );\r
 \r
 /*\r
  * Uses a critical section to determine if there is any data in a queue.\r
@@ -230,10 +237,14 @@ size_t xQueueSizeInBytes;
 signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )\r
 {\r
 signed portBASE_TYPE xReturn;\r
+xTimeOutType xTimeOut;\r
 \r
        /* Make sure other tasks do not access the queue. */\r
        vTaskSuspendAll();\r
 \r
+       /* Capture the current time status for future reference. */\r
+       vTaskSetTimeOutState( &xTimeOut );\r
+\r
        /* It is important that this is the only thread/ISR that modifies the\r
        ready or delayed lists until xTaskResumeAll() is called.  Places where\r
        the ready/delayed lists are modified include:\r
@@ -272,108 +283,105 @@ signed portBASE_TYPE xReturn;
        */\r
                \r
        /* If the queue is already full we may have to block. */\r
-       if( prvIsQueueFull( pxQueue ) )\r
+       do\r
        {\r
-               /* The queue is full - do we want to block or just leave without\r
-               posting? */\r
-               if( xTicksToWait > ( portTickType ) 0 )\r
+               if( prvIsQueueFull( pxQueue ) )\r
                {\r
-                       /* We are going to place ourselves on the xTasksWaitingToSend event\r
-                       list, and will get woken should the delay expire, or space become\r
-                       available on the queue.\r
-                       \r
-                       As detailed above we do not require mutual exclusion on the event\r
-                       list as nothing else can modify it or the ready lists while we\r
-                       have the scheduler suspended and queue locked.\r
-                       \r
-                       It is possible that an ISR has removed data from the queue since we\r
-                       checked if any was available.  If this is the case then the data\r
-                       will have been copied from the queue, and the queue variables\r
-                       updated, but the event list will not yet have been checked to see if\r
-                       anything is waiting as the queue is locked. */\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. we\r
-                       unblock) we will leave the critical section as normal.\r
-                       \r
-                       It is possible that an ISR has caused an event on an unrelated and\r
-                       unlocked queue.  If this was the case then the event list for that\r
-                       queue will have been updated but the ready lists left unchanged -\r
-                       instead the readied task will have been added to the pending ready\r
-                       list. */\r
-                       taskENTER_CRITICAL();\r
+                       /* The queue is full - do we want to block or just leave without\r
+                       posting? */\r
+                       if( xTicksToWait > ( portTickType ) 0 )\r
                        {\r
-                               /* We can safely unlock the queue and scheduler here as\r
-                               interrupts are disabled.  We must not yield with anything\r
-                               locked, but we can yield from within a critical section.\r
+                               /* We are going to place ourselves on the xTasksWaitingToSend event\r
+                               list, and will get woken should the delay expire, or space become\r
+                               available on the queue.\r
+                               \r
+                               As detailed above we do not require mutual exclusion on the event\r
+                               list as nothing else can modify it or the ready lists while we\r
+                               have the scheduler suspended and queue locked.\r
+                               \r
+                               It is possible that an ISR has removed data from the queue since we\r
+                               checked if any was available.  If this is the case then the data\r
+                               will have been copied from the queue, and the queue variables\r
+                               updated, but the event list will not yet have been checked to see if\r
+                               anything is waiting as the queue is locked. */\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. we\r
+                               unblock) we will leave the critical section as normal.\r
                                \r
-                               Tasks that have been placed on the pending ready list cannot\r
-                               be tasks that are waiting for events on this queue.  See\r
-                               in comment xTaskRemoveFromEventList(). */\r
-                               prvUnlockQueue( pxQueue );\r
-\r
-                               /* Resuming the scheduler may cause a yield.  If so then there\r
-                               is no point yielding again here. */\r
-                               if( !xTaskResumeAll() )\r
+                               It is possible that an ISR has caused an event on an unrelated and\r
+                               unlocked queue.  If this was the case then the event list for that\r
+                               queue will have been updated but the ready lists left unchanged -\r
+                               instead the readied task will have been added to the pending ready\r
+                               list. */\r
+                               taskENTER_CRITICAL();\r
                                {\r
-                                       taskYIELD();\r
+                                       /* We can safely unlock the queue and scheduler here as\r
+                                       interrupts are disabled.  We must not yield with anything\r
+                                       locked, but we can yield from within a critical section.\r
+                                       \r
+                                       Tasks that have been placed on the pending ready list cannot\r
+                                       be tasks that are waiting for events on this queue.  See\r
+                                       in comment xTaskRemoveFromEventList(). */\r
+                                       prvUnlockQueue( pxQueue );\r
+       \r
+                                       /* Resuming the scheduler may cause a yield.  If so then there\r
+                                       is no point yielding again here. */\r
+                                       if( !xTaskResumeAll() )\r
+                                       {\r
+                                               taskYIELD();\r
+                                       }\r
+       \r
+                                       /* Before leaving the critical section we have to ensure\r
+                                       exclusive access again. */\r
+                                       vTaskSuspendAll();\r
+                                       prvLockQueue( pxQueue );                                \r
                                }\r
-\r
-                               /* Before leaving the critical section we have to ensure\r
-                               exclusive access again. */\r
-                               vTaskSuspendAll();\r
-                               prvLockQueue( pxQueue );                                \r
+                               taskEXIT_CRITICAL();\r
                        }\r
-                       taskEXIT_CRITICAL();\r
                }\r
-       }\r
-               \r
-       /* When we are here it is possible that we unblocked as space became\r
-       available on the queue.  It is also possible that an ISR posted to the\r
-       queue since we left the critical section, so it may be that again there\r
-       is no space.  This would only happen if a task and ISR post onto the\r
-       same queue. */\r
-       taskENTER_CRITICAL();\r
-       {\r
-               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
-               {\r
-                       /* There is room in the queue, copy the data into the queue. */                 \r
-                       prvCopyQueueData( pxQueue, pvItemToQueue );             \r
-                       xReturn = pdPASS;\r
-\r
-                       /* Update the TxLock count so prvUnlockQueue knows to check for\r
-                       tasks waiting for data to become available in the queue. */\r
-                       ++( pxQueue->xTxLock );\r
-               }\r
-               else\r
+                       \r
+               /* When we are here it is possible that we unblocked as space became\r
+               available on the queue.  It is also possible that an ISR posted to the\r
+               queue since we left the critical section, so it may be that again there\r
+               is no space.  This would only happen if a task and ISR post onto the\r
+               same queue. */\r
+               taskENTER_CRITICAL();\r
                {\r
-                       xReturn = errQUEUE_FULL;\r
+                       if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+                       {\r
+                               /* There is room in the queue, copy the data into the queue. */                 \r
+                               prvCopyQueueData( pxQueue, pvItemToQueue );             \r
+                               xReturn = pdPASS;\r
+       \r
+                               /* Update the TxLock count so prvUnlockQueue knows to check for\r
+                               tasks waiting for data to become available in the queue. */\r
+                               ++( pxQueue->xTxLock );\r
+                       }\r
+                       else\r
+                       {\r
+                               xReturn = errQUEUE_FULL;\r
+                       }\r
                }\r
-       }\r
-       taskEXIT_CRITICAL();\r
+               taskEXIT_CRITICAL();\r
 \r
-       /* We no longer require exclusive access to the queue.  prvUnlockQueue\r
-       will remove any tasks suspended on a receive if either this function\r
-       or an ISR has posted onto the queue. */\r
-       if( prvUnlockQueue( pxQueue ) )\r
-       {\r
-               /* Resume the scheduler - making ready any tasks that were woken\r
-               by an event while the scheduler was locked.  Resuming the\r
-               scheduler may cause a yield, in which case there is no point\r
-               yielding again here. */\r
-               if( !xTaskResumeAll() )\r
+               if( xReturn == errQUEUE_FULL )\r
                {\r
-                       taskYIELD();\r
+                       if( xTicksToWait > 0 )\r
+                       {\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               {\r
+                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                               }\r
+                       }\r
                }\r
        }\r
-       else\r
-       {\r
-               /* Resume the scheduler - making ready any tasks that were woken\r
-               by an event while the scheduler was locked. */\r
-               xTaskResumeAll();\r
-       }\r
+       while( xReturn == queueERRONEOUS_UNBLOCK );\r
+\r
+       prvUnlockQueue( pxQueue );\r
+       xTaskResumeAll();\r
 \r
        return xReturn;\r
 }\r
@@ -424,6 +432,7 @@ signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItem
 signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )\r
 {\r
 signed portBASE_TYPE xReturn;\r
+xTimeOutType xTimeOut;\r
 \r
        /* This function is very similar to xQueueSend().  See comments within\r
        xQueueSend() for a more detailed explanation.\r
@@ -431,68 +440,76 @@ signed portBASE_TYPE xReturn;
        Make sure other tasks do not access the queue. */\r
        vTaskSuspendAll();\r
 \r
+       /* Capture the current time status for future reference. */\r
+       vTaskSetTimeOutState( &xTimeOut );\r
+\r
        /* Make sure interrupts do not access the queue. */\r
        prvLockQueue( pxQueue );\r
 \r
-       /* If there are no messages in the queue we may have to block. */\r
-       if( prvIsQueueEmpty( pxQueue ) )\r
+       do\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
+               /* If there are no messages in the queue we may have to block. */\r
+               if( prvIsQueueEmpty( pxQueue ) )\r
                {\r
-                       vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
-                       taskENTER_CRITICAL();\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
-                               prvUnlockQueue( pxQueue );\r
-                               if( !xTaskResumeAll() )\r
+                               vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
+                               taskENTER_CRITICAL();\r
                                {\r
-                                       taskYIELD();\r
+                                       prvUnlockQueue( pxQueue );\r
+                                       if( !xTaskResumeAll() )\r
+                                       {\r
+                                               taskYIELD();\r
+                                       }\r
+       \r
+                                       vTaskSuspendAll();\r
+                                       prvLockQueue( pxQueue );\r
                                }\r
-\r
-                               vTaskSuspendAll();\r
-                               prvLockQueue( pxQueue );\r
+                               taskEXIT_CRITICAL();\r
                        }\r
-                       taskEXIT_CRITICAL();\r
                }\r
-       }\r
-\r
-       taskENTER_CRITICAL();\r
-       {\r
-               if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
+       \r
+               taskENTER_CRITICAL();\r
                {\r
-                       pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
-                       if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+                       if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
                        {\r
-                               pxQueue->pcReadFrom = pxQueue->pcHead;\r
+                               pxQueue->pcReadFrom += pxQueue->uxItemSize;\r
+                               if( pxQueue->pcReadFrom >= pxQueue->pcTail )\r
+                               {\r
+                                       pxQueue->pcReadFrom = pxQueue->pcHead;\r
+                               }\r
+                               --( pxQueue->uxMessagesWaiting );\r
+                               memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
+       \r
+                               /* Increment the lock count so prvUnlockQueue knows to check for\r
+                               tasks waiting for space to become available on the queue. */\r
+                               ++( pxQueue->xRxLock );\r
+                               xReturn = pdPASS;\r
+                       }\r
+                       else\r
+                       {\r
+                               xReturn = errQUEUE_EMPTY;\r
                        }\r
-                       --( pxQueue->uxMessagesWaiting );\r
-                       memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
-\r
-                       /* Increment the lock count so prvUnlockQueue knows to check for\r
-                       tasks waiting for space to become available on the queue. */\r
-                       ++( pxQueue->xRxLock );\r
-                       xReturn = pdPASS;\r
                }\r
-               else\r
+               taskEXIT_CRITICAL();\r
+\r
+               if( xReturn == errQUEUE_EMPTY )\r
                {\r
-                       xReturn = pdFAIL;\r
+                       if( xTicksToWait > 0 )\r
+                       {\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
+                               {\r
+                                       xReturn = queueERRONEOUS_UNBLOCK;\r
+                               }\r
+                       }\r
                }\r
-       }\r
-       taskEXIT_CRITICAL();\r
+       } while( xReturn == queueERRONEOUS_UNBLOCK );\r
 \r
        /* We no longer require exclusive access to the queue. */\r
-       if( prvUnlockQueue( pxQueue ) )\r
-       {\r
-               if( !xTaskResumeAll() )\r
-               {\r
-                       taskYIELD();\r
-               }\r
-       }\r
-       else\r
-       {\r
-               xTaskResumeAll();\r
-       }\r
+       prvUnlockQueue( pxQueue );\r
+       xTaskResumeAll();\r
 \r
        return xReturn;\r
 }\r
@@ -571,10 +588,8 @@ void vQueueDelete( xQueueHandle pxQueue )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static signed portBASE_TYPE prvUnlockQueue( xQueueHandle pxQueue )\r
+static void prvUnlockQueue( xQueueHandle pxQueue )\r
 {\r
-signed portBASE_TYPE xYieldRequired = pdFALSE;\r
-\r
        /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
 \r
        /* The lock counts contains the number of extra data items placed or\r
@@ -600,7 +615,7 @@ signed portBASE_TYPE xYieldRequired = pdFALSE;
                                {\r
                                        /* The task waiting has a higher priority so record that a\r
                                        context switch is required. */\r
-                                       xYieldRequired = pdTRUE;\r
+                                       vTaskMissedYield();\r
                                }\r
                        }                       \r
                }\r
@@ -620,14 +635,12 @@ signed portBASE_TYPE xYieldRequired = pdFALSE;
                        {\r
                                if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
                                {\r
-                                       xYieldRequired = pdTRUE;\r
+                                       vTaskMissedYield();\r
                                }\r
                        }                       \r
                }\r
        }\r
        taskEXIT_CRITICAL();\r
-\r
-       return xYieldRequired;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index 74c59303559b102c86d9c4b502aae206d472b5f2..30e00f942d5702fce7a6e556674a4d32047e4c54 100644 (file)
@@ -176,6 +176,11 @@ Changed from V4.0.4
          This has not been necessary since V4.0.1 when the xMissedYield handling\r
          was added.\r
        + Implement xTaskResumeFromISR().\r
+\r
+Changes from V4.0.5\r
+\r
+       + Added utility functions and xOverflowCount variable to facilitate the\r
+         queue.c changes.\r
 */\r
 \r
 #include <stdio.h>\r
@@ -261,13 +266,13 @@ static xList xPendingReadyList;                                                   /*< Tasks that have been readied while the
 /* File private variables. --------------------------------*/\r
 static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks  = ( unsigned portBASE_TYPE ) 0;\r
 static volatile portTickType xTickCount                                                        = ( portTickType ) 0;\r
-static unsigned portBASE_TYPE uxTopUsedPriority                                = tskIDLE_PRIORITY;\r
+static unsigned portBASE_TYPE uxTopUsedPriority                                        = tskIDLE_PRIORITY;\r
 static volatile unsigned portBASE_TYPE uxTopReadyPriority              = tskIDLE_PRIORITY;\r
 static volatile signed portBASE_TYPE xSchedulerRunning                 = pdFALSE;\r
 static volatile unsigned portBASE_TYPE uxSchedulerSuspended            = ( unsigned portBASE_TYPE ) pdFALSE;\r
 static volatile unsigned portBASE_TYPE uxMissedTicks                   = ( unsigned portBASE_TYPE ) 0;\r
 static volatile portBASE_TYPE xMissedYield                                             = ( portBASE_TYPE ) pdFALSE;\r
-\r
+static volatile portBASE_TYPE xNumOfOverflows                                  = ( portBASE_TYPE ) 0;\r
 /* Debugging and trace facilities private variables and macros. ------------*/\r
 \r
 /*\r
@@ -1281,6 +1286,7 @@ inline void vTaskIncrementTick( void )
                        pxTemp = pxDelayedTaskList;\r
                        pxDelayedTaskList = pxOverflowDelayedTaskList;\r
                        pxOverflowDelayedTaskList = pxTemp;\r
+            xNumOfOverflows++;\r
                }\r
 \r
                /* See if this tick has made a timeout expire. */\r
@@ -1481,10 +1487,47 @@ portBASE_TYPE xReturn;
 \r
        return xReturn;\r
 }\r
+/*-----------------------------------------------------------*/\r
 \r
+void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )\r
+{\r
+    pxTimeOut->xOverflowCount = xNumOfOverflows;\r
+    pxTimeOut->xTimeOnEntering = xTickCount;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait )\r
+{\r
+portBASE_TYPE xReturn;\r
 \r
+    if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xTickCount > pxTimeOut->xTimeOnEntering ) )\r
+    {\r
+        /* The tick count is greater than the time at which vTaskSetTimeout() \r
+               was called, but has also overflowed since vTaskSetTimeOut() was called.\r
+        It must have wrapped all the way around and gone past us again. This\r
+        passed since vTaskSetTimeout() was called. */\r
+        xReturn = pdTRUE;\r
+    }\r
+    else if( ( xTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )\r
+    {\r
+        /* Not a genuine timeout. Adjust parameters for time remaining. */\r
+        *pxTicksToWait -= ( xTickCount - pxTimeOut->xTimeOnEntering );\r
+        vTaskSetTimeOutState( pxTimeOut );\r
+        xReturn = pdFALSE;\r
+    }\r
+    else\r
+    {\r
+        xReturn = pdTRUE;\r
+    }\r
+\r
+    return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
+void vTaskMissedYield( void )\r
+{\r
+       xMissedYield = pdTRUE;\r
+}\r
 \r
 /*\r
  * -----------------------------------------------------------\r