From b8a219b30c42ecb118a46b13f639eea9b66f61f8 Mon Sep 17 00:00:00 2001 From: Richard Barry Date: Fri, 28 Jun 2013 09:21:39 +0000 Subject: [PATCH] Update QueueOverwrite.c to include a call to xQueuePeekFromISR(). Default new QueuePeekFromISR() trace macros. --- FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c | 9 +++- FreeRTOS/Source/include/FreeRTOS.h | 8 +++ FreeRTOS/Source/include/queue.h | 37 +++++++++++++- FreeRTOS/Source/queue.c | 49 +++++++++++++++++-- 4 files changed, 96 insertions(+), 7 deletions(-) diff --git a/FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c b/FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c index e33dcdbff..b20f903a9 100644 --- a/FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c +++ b/FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c @@ -233,12 +233,19 @@ unsigned long ulRx; last parameter is not used because there are no tasks blocked on this queue. */ xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL ); + + /* Peek the queue to check it holds the expected value. */ + xQueuePeekFromISR( xISRQueue, &ulRx ); + if( ulRx != ulTx1 ) + { + xISRTestStatus = pdFAIL; + } break; case 1: /* The queue already holds ulTx1. Overwrite the value in the queue with ulTx2. */ - xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL ); + xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL ); break; case 2: diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 060523fee..fbd75e3d0 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -410,6 +410,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #define traceQUEUE_PEEK( pxQueue ) #endif +#ifndef traceQUEUE_PEEK_FROM_ISR + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + #ifndef traceQUEUE_RECEIVE_FAILED #define traceQUEUE_RECEIVE_FAILED( pxQueue ) #endif @@ -430,6 +434,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) #endif +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + #ifndef traceQUEUE_DELETE #define traceQUEUE_DELETE( pxQueue ) #endif diff --git a/FreeRTOS/Source/include/queue.h b/FreeRTOS/Source/include/queue.h index 915e2ab99..315b67e25 100644 --- a/FreeRTOS/Source/include/queue.h +++ b/FreeRTOS/Source/include/queue.h @@ -616,7 +616,9 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const * Successfully received items remain on the queue so will be returned again * by the next call, or a call to xQueueReceive(). * - * This macro must not be used in an interrupt service routine. + * This macro must not be used in an interrupt service routine. See + * xQueuePeekFromISR() for an alternative that can be called from an interrupt + * service routine. * * @param xQueue The handle to the queue from which the item is to be * received. @@ -691,6 +693,39 @@ signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const */ #define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) +/** + * queue. h + *
+ portBASE_TYPE xQueuePeekFromISR(
+									xQueueHandle xQueue,
+									void *pvBuffer,
+								);
+ * + * A version of xQueuePeek() that can be called from an interrupt service + * routine (ISR). + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, void * const pvBuffer ); + /** * queue. h *
diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c
index 4488169ea..b9024d535 100644
--- a/FreeRTOS/Source/queue.c
+++ b/FreeRTOS/Source/queue.c
@@ -1060,7 +1060,7 @@ xQUEUE *pxQueue;
 				{
 					traceQUEUE_RECEIVE( pxQueue );
 
-					/* We are actually removing data. */
+					/* Actually removing data, not just peeking. */
 					--( pxQueue->uxMessagesWaiting );
 
 					#if ( configUSE_MUTEXES == 1 )
@@ -1191,7 +1191,7 @@ xQUEUE *pxQueue;
 
 	uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
 	{
-		/* We cannot block from an ISR, so check there is data available. */
+		/* Cannot block in an ISR, so check there is data available. */
 		if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
 		{
 			traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
@@ -1199,9 +1199,10 @@ xQUEUE *pxQueue;
 			prvCopyDataFromQueue( pxQueue, pvBuffer );
 			--( pxQueue->uxMessagesWaiting );
 
-			/* If the queue is locked we will not modify the event list.  Instead
-			we update the lock count so the task that unlocks the queue will know
-			that an ISR has removed data while the queue was locked. */
+			/* If the queue is locked the event list will not be modified.  
+			Instead update the lock count so the task that unlocks the queue 
+			will know that an ISR has removed data while the queue was 
+			locked. */
 			if( pxQueue->xRxLock == queueUNLOCKED )
 			{
 				if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
@@ -1238,6 +1239,44 @@ xQUEUE *pxQueue;
 }
 /*-----------------------------------------------------------*/
 
+signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, void * const pvBuffer )
+{
+signed portBASE_TYPE xReturn;
+unsigned portBASE_TYPE uxSavedInterruptStatus;
+signed char *pcOriginalReadPosition;
+xQUEUE *pxQueue;
+
+	pxQueue = ( xQUEUE * ) xQueue;
+	configASSERT( pxQueue );
+	configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+
+	uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		/* Cannot block in an ISR, so check there is data available. */
+		if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+		{
+			traceQUEUE_PEEK_FROM_ISR( pxQueue );
+
+			/* Remember the read position so it can be reset as nothing is
+			actually being removed from the queue. */
+			pcOriginalReadPosition = pxQueue->u.pcReadFrom;
+			prvCopyDataFromQueue( pxQueue, pvBuffer );
+			pxQueue->u.pcReadFrom = pcOriginalReadPosition;
+
+			xReturn = pdPASS;
+		}
+		else
+		{
+			xReturn = pdFAIL;
+			traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
 {
 unsigned portBASE_TYPE uxReturn;