]> git.sur5r.net Git - freertos/commitdiff
Add xQueueOverwriteFromISR() and update the QueueOverwrite.c to demonstrate its use.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 27 Jun 2013 14:25:17 +0000 (14:25 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 27 Jun 2013 14:25:17 +0000 (14:25 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1954 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c
FreeRTOS/Demo/Common/include/QueueOverwrite.h
FreeRTOS/Demo/WIN32-MSVC/main.c
FreeRTOS/Source/include/queue.h
FreeRTOS/Source/queue.c

index e554201bd753e281246b0e1ad2a9e72b195abad8..e33dcdbff04bca9266eae0b8bc078f83480e4690 100644 (file)
@@ -98,18 +98,33 @@ static void prvQueueOverwriteTask( void *pvParameters );
 prvQueueOverwriteTask() has not found any errors. */\r
 static unsigned long ulLoopCounter = 0;\r
 \r
+/* Set to pdFALSE if an error is discovered by the\r
+vQueueOverwritePeriodicISRDemo() function. */\r
+static portBASE_TYPE xISRTestStatus = pdPASS;\r
+\r
+/* The queue that is accessed from the ISR.  The queue accessed by the task is\r
+created inside the task itself. */\r
+static xQueueHandle xISRQueue = NULL;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 void vStartQueueOverwriteTask( unsigned portBASE_TYPE uxPriority )\r
 {\r
-       /* Create the test task. */\r
+const unsigned portBASE_TYPE uxQueueLength = 1;\r
+\r
+       /* Create the queue used by the ISR.  xQueueOverwriteFromISR() should only\r
+       be used on queues that have a length of 1. */\r
+       xISRQueue = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( unsigned long ) );\r
+\r
+       /* Create the test task.  The queue used by the test task is created inside\r
+       the task itself. */\r
        xTaskCreate( prvQueueOverwriteTask, ( signed char * ) "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 static void prvQueueOverwriteTask( void *pvParameters )\r
 {\r
-xQueueHandle xQueue;\r
+xQueueHandle xTaskQueue;\r
 const unsigned portBASE_TYPE uxQueueLength = 1;\r
 unsigned long ulValue, ulStatus = pdPASS, x;\r
 \r
@@ -118,18 +133,18 @@ unsigned long ulValue, ulStatus = pdPASS, x;
 \r
        /* Create the queue.  xQueueOverwrite() should only be used on queues that\r
        have a length of 1. */\r
-       xQueue = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( unsigned long ) );\r
-       configASSERT( xQueue );\r
+       xTaskQueue = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( unsigned long ) );\r
+       configASSERT( xTaskQueue );\r
 \r
        for( ;; )\r
        {\r
                /* The queue is empty.  Writing to the queue then reading from the queue\r
                should return the item written. */\r
                ulValue = 10;\r
-               xQueueOverwrite( xQueue, &ulValue );\r
+               xQueueOverwrite( xTaskQueue, &ulValue );\r
 \r
                ulValue = 0;\r
-               xQueueReceive( xQueue, &ulValue, qoDONT_BLOCK );\r
+               xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK );\r
 \r
                if( ulValue != 10 )\r
                {\r
@@ -141,27 +156,27 @@ unsigned long ulValue, ulStatus = pdPASS, x;
                for( x = 0; x < qoLOOPS; x++ )\r
                {\r
                        /* Write to the queue. */\r
-                       xQueueOverwrite( xQueue, &x );\r
+                       xQueueOverwrite( xTaskQueue, &x );\r
 \r
                        /* Check the value in the queue is that written, even though the\r
                        queue was not necessarily empty. */\r
-                       xQueuePeek( xQueue, &ulValue, qoDONT_BLOCK );\r
+                       xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK );\r
                        if( ulValue != x )\r
                        {\r
                                ulStatus = pdFAIL;\r
                        }\r
 \r
                        /* There should always be one item in the queue. */\r
-                       if( uxQueueMessagesWaiting( xQueue ) != uxQueueLength )\r
+                       if( uxQueueMessagesWaiting( xTaskQueue ) != uxQueueLength )\r
                        {\r
                                ulStatus = pdFAIL;\r
                        }\r
                }\r
 \r
                /* Empty the queue again. */\r
-               xQueueReceive( xQueue, &ulValue, qoDONT_BLOCK );\r
+               xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK );\r
 \r
-               if( uxQueueMessagesWaiting( xQueue ) != 0 )\r
+               if( uxQueueMessagesWaiting( xTaskQueue ) != 0 )\r
                {\r
                        ulStatus = pdFAIL;\r
                }\r
@@ -180,7 +195,11 @@ portBASE_TYPE xIsQueueOverwriteTaskStillRunning( void )
 {\r
 portBASE_TYPE xReturn;\r
 \r
-       if( ulLoopCounter > 0 )\r
+       if( xISRTestStatus != pdPASS )\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+       else if( ulLoopCounter > 0 )\r
        {\r
                xReturn = pdPASS;\r
        }\r
@@ -194,4 +213,54 @@ portBASE_TYPE xReturn;
 \r
        return xReturn;\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+void vQueueOverwritePeriodicISRDemo( void )\r
+{\r
+static unsigned long ulCallCount = 0;\r
+const unsigned long ulTx1 = 10UL, ulTx2 = 20UL, ulNumberOfSwitchCases = 3UL;\r
+unsigned long ulRx;\r
+\r
+       /* This function should be called from an interrupt, such as the tick hook\r
+       function vApplicationTickHook(). */\r
+\r
+       configASSERT( xISRQueue );\r
+\r
+       switch( ulCallCount )\r
+       {\r
+               case 0:\r
+                       /* The queue is empty.  Write ulTx1 to the queue.  In this demo the\r
+                       last parameter is not used because there are no tasks blocked on\r
+                       this queue. */\r
+                       xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL );\r
+                       break;\r
+\r
+               case 1:\r
+                       /* The queue already holds ulTx1.  Overwrite the value in the queue\r
+                       with ulTx2. */\r
+                       xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL );\r
+                       break;\r
+\r
+               case 2:\r
+                       /* Read from the queue to empty the queue again.  The value read\r
+                       should be ulTx2. */\r
+                       xQueueReceiveFromISR( xISRQueue, &ulRx, NULL );\r
+\r
+                       if( ulRx != ulTx2 )\r
+                       {\r
+                               xISRTestStatus = pdFAIL;\r
+                       }\r
+                       break;\r
+       }\r
+\r
+       /* Run the next case in the switch statement above next time this function\r
+       is called. */\r
+       ulCallCount++;\r
+\r
+       if( ulCallCount >= ulNumberOfSwitchCases )\r
+       {\r
+               /* Go back to the start. */\r
+               ulCallCount = 0;\r
+       }\r
+}\r
 \r
index c4fba5ffbca677ffb09839eea64ad7541b83bad9..fc1231229c48368a3ae383b8de2a4c2aea85755d 100644 (file)
@@ -77,6 +77,7 @@
 \r
 void vStartQueueOverwriteTask( unsigned portBASE_TYPE uxPriority );\r
 portBASE_TYPE xIsQueueOverwriteTaskStillRunning( void );\r
+void vQueueOverwritePeriodicISRDemo( void );\r
 \r
 #endif /* QUEUE_OVERWRITE_H */\r
 \r
index 0dc4dcd45d7a17f19028d10fe96c52dfdd95eabb..b57938c7ba3f6781ab628790d569556fe62f23b9 100644 (file)
@@ -411,6 +411,9 @@ void vApplicationTickHook( void )
        can be called from an ISR. */\r
        vTimerPeriodicISRTests();\r
 \r
+       /* Call the periodic queue overwrite from ISR demo. */\r
+       vQueueOverwritePeriodicISRDemo();\r
+\r
        /* Write to a queue that is in use as part of the queue set demo to \r
        demonstrate using queue sets from an ISR. */\r
        vQueueSetAccessQueueSetFromISR();\r
index f81a91fae33423d308f092f26f8c442caa13b22a..915e2ab9988b7af6c6b400078b649f494e4b0708 100644 (file)
@@ -1053,6 +1053,84 @@ void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
  */\r
 #define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )\r
 \r
+/**\r
+ * queue. h\r
+ * <pre>\r
+ portBASE_TYPE xQueueOverwriteFromISR(\r
+                                                         xQueueHandle xQueue,\r
+                                                         const void * pvItemToQueue,\r
+                                                         portBASE_TYPE *pxHigherPriorityTaskWoken\r
+                                                );\r
+ * </pre>\r
+ *\r
+ * A version of xQueueOverwrite() that can be used from an interrupt service\r
+ * routine (ISR).\r
+ *\r
+ * Only for use with queues that can hold a single item - so the queue is either\r
+ * empty or full.\r
+ *\r
+ * Post an item on a queue.  If the queue is already full then overwrite the\r
+ * value held in the queue.  The item is queued by copy, not by reference.\r
+ *\r
+ * @param xQueue The handle to the queue on which the item is to be posted.\r
+ *\r
+ * @param pvItemToQueue A pointer to the item that is to be placed on the\r
+ * queue.  The size of the items the queue will hold was defined when the\r
+ * queue was created, so this many bytes will be copied from pvItemToQueue\r
+ * into the queue storage area.\r
+ *\r
+ * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set\r
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task\r
+ * to unblock, and the unblocked task has a priority higher than the currently\r
+ * running task.  If xQueueSendFromISR() sets this value to pdTRUE then\r
+ * a context switch should be requested before the interrupt is exited.\r
+ *\r
+ * @return xQueueOverwriteFromISR() is a macro that calls \r
+ * xQueueGenericSendFromISR(), and therefore has the same return values as \r
+ * xQueueSendToFrontFromISR().  However, as xQueueOverwriteFromISR() will write \r
+ * to the queue even when the queue is full pdPASS will be returned in all cases \r
+ * (errQUEUE_FULL will never be returned).\r
+ *\r
+ * Example usage:\r
+   <pre>\r
+\r
+ xQueueHandle xQueue;\r
\r
+ void vFunction( void *pvParameters )\r
+ {\r
+       // Create a queue to hold one unsigned long value.  It is strongly\r
+       // recommended *not* to use xQueueOverwrite() on queues that can\r
+       // contain more than one value, and doing so will trigger an assertion\r
+       // if configASSERT() is defined.\r
+       xQueue = xQueueCreate( 1, sizeof( unsigned long ) );\r
+}\r
+\r
+void vAnInterruptHandler( void )\r
+{\r
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.\r
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
+unsigned long ulVarToSend, ulValReceived;\r
+\r
+       // Write the value 10 to the queue using xQueueOverwriteFromISR().\r
+       ulVarToSend = 10;\r
+       xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );\r
+\r
+       // The queue is full, but calling xQueueOverwriteFromISR() again will still\r
+       // pass because the value held in the queue will be overwritten with the\r
+       // new value.\r
+       ulVarToSend = 100;\r
+       xQueueOverwrite( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );\r
+\r
+       // Reading from the queue will now return 100.\r
+\r
+       // ...\r
+}\r
+ </pre>\r
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR\r
+ * \ingroup QueueManagement\r
+ */\r
+#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE )\r
+\r
 /**\r
  * queue. h\r
  * <pre>\r
index cd1c8545e31480b758fb855281919c0ee69504e8..4488169ea8195b69ce58504d380c4c7a1b3c7fab 100644 (file)
@@ -939,6 +939,7 @@ xQUEUE *pxQueue;
        pxQueue = ( xQUEUE * ) xQueue;\r
        configASSERT( pxQueue );\r
        configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+       configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );\r
 \r
        /* Similar to xQueueGenericSend, except we don't block if there is no room\r
        in the queue.  Also we don't directly wake a task that was blocked on a\r
@@ -947,7 +948,7 @@ xQUEUE *pxQueue;
        by this post). */\r
        uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
-               if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
+               if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )\r
                {\r
                        traceQUEUE_SEND_FROM_ISR( pxQueue );\r
 \r