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