mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Preparing for new release...
Kernel changes: - Remove an assert that was preventing xQueueSendFromISR() being used to give a mutex from an ISR (mutexes cannot be given using xSemaphoreGiveFromISR()). - Introduce xTaskNotifyAndQueryFromISR() as the interrupt safe version of xTaskNotifyAndQuery(). Common demo task changes: - Update IntSemTest.c to prove the theory that it is safe to give a mutex type semaphore from an interrupt using xQueueSendFromISR() instead of xSemaphoreGiveFromISR(). - Update TaskNotify.c to test the new xTaskNotifyAndQuery() from ISR fuction.
This commit is contained in:
parent
25b911e0bd
commit
4c3722bd76
|
@ -163,7 +163,7 @@ static SemaphoreHandle_t xMasterSlaveMutex = NULL;
|
|||
/* Flag that allows the master task to control when the interrupt gives or does
|
||||
not give the mutex. There is no mutual exclusion on this variable, but this is
|
||||
only test code and it should be fine in the 32=bit test environment. */
|
||||
static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE;
|
||||
static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE, xOkToGiveMasterSlaveMutex = pdFALSE;
|
||||
|
||||
/* Used to coordinate timing between tasks and the interrupt. */
|
||||
const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );
|
||||
|
@ -217,6 +217,8 @@ static void vInterruptMutexMasterTask( void *pvParameters )
|
|||
|
||||
static void prvTakeAndGiveInTheSameOrder( void )
|
||||
{
|
||||
static BaseType_t xGiveFromTask = pdTRUE;
|
||||
|
||||
/* Ensure the slave is suspended, and that this task is running at the
|
||||
lower priority as expected as the start conditions. */
|
||||
#if( INCLUDE_eTaskGetState == 1 )
|
||||
|
@ -293,12 +295,29 @@ static void prvTakeAndGiveInTheSameOrder( void )
|
|||
/* Finally give back the shared mutex. This time the higher priority
|
||||
task should run before this task runs again - so this task should have
|
||||
disinherited the priority and the higher priority task should be in the
|
||||
suspended state again. */
|
||||
suspended state again. Alternatve beetween giving the mutex from this task,
|
||||
and giving it from the interrupt. */
|
||||
if( xGiveFromTask == pdTRUE )
|
||||
{
|
||||
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
||||
{
|
||||
xErrorDetected = pdTRUE;
|
||||
}
|
||||
|
||||
/* Give the mutex from the interrupt on the next go around. */
|
||||
xGiveFromTask = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for the mutex to be given from the interrupt. */
|
||||
xOkToGiveMasterSlaveMutex = pdTRUE;
|
||||
vTaskDelay( xInterruptGivePeriod + ( xInterruptGivePeriod >> 1 ) );
|
||||
xOkToGiveMasterSlaveMutex = pdFALSE;
|
||||
|
||||
/* Give the mutex from the task on the next go around. */
|
||||
xGiveFromTask = pdTRUE;
|
||||
}
|
||||
|
||||
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
||||
{
|
||||
xErrorDetected = pdTRUE;
|
||||
|
@ -514,15 +533,36 @@ TickType_t xTimeNow;
|
|||
xTimeNow = xTaskGetTickCountFromISR();
|
||||
if( ( ( TickType_t ) ( xTimeNow - xLastGiveTime ) ) >= pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )
|
||||
{
|
||||
configASSERT( xISRMutex );
|
||||
if( xOkToGiveMutex != pdFALSE )
|
||||
{
|
||||
configASSERT( xISRMutex );
|
||||
|
||||
/* Null is used as the second parameter in this give, and non-NULL
|
||||
in the other gives for code coverage reasons. */
|
||||
xSemaphoreGiveFromISR( xISRMutex, NULL );
|
||||
in the other gives, for code coverage reasons. NOTE: This is a
|
||||
Mutex, so xQueueGiveFromISR() should be used in place of
|
||||
xSemaphoreGiveFromISR() in case there is a mutex holder that has
|
||||
inherited a priority (although, in the case of xISRMutex, there
|
||||
isn't). The "item to queue" parameter is set to NULL as no data is
|
||||
copied into a mutex.*/
|
||||
xQueueSendFromISR( ( QueueHandle_t ) xISRMutex, NULL, NULL );
|
||||
|
||||
/* Second give attempt should fail. */
|
||||
configASSERT( xSemaphoreGiveFromISR( xISRMutex, &xHigherPriorityTaskWoken ) == pdFAIL );
|
||||
configASSERT( xQueueSendFromISR( xISRMutex, NULL, &xHigherPriorityTaskWoken ) == pdFAIL );
|
||||
}
|
||||
|
||||
if( xOkToGiveMasterSlaveMutex != pdFALSE )
|
||||
{
|
||||
configASSERT( xOkToGiveMasterSlaveMutex );
|
||||
|
||||
/* NOTE: This is a Mutex, so xQueueGiveFromISR() should be used in
|
||||
place of xSemaphoreGiveFromISR() in case there is a mutex holder
|
||||
that has inherited a priority (as indeed there is in this case).
|
||||
The "item to queue" parameter is set to NULL as no data is copied
|
||||
into a mutex. */
|
||||
xQueueSendFromISR( ( QueueHandle_t ) xMasterSlaveMutex, NULL, NULL );
|
||||
|
||||
/* Second give attempt should fail. */
|
||||
configASSERT( xQueueSendFromISR( xMasterSlaveMutex, NULL, &xHigherPriorityTaskWoken ) == pdFAIL );
|
||||
}
|
||||
|
||||
if( xOkToGiveCountingSemaphore != pdFALSE )
|
||||
|
|
|
@ -472,8 +472,10 @@ TickType_t xPeriod;
|
|||
|
||||
void xNotifyTaskFromISR( void )
|
||||
{
|
||||
static BaseType_t xCallCount = 0;
|
||||
static BaseType_t xCallCount = 0, xAPIToUse = 0;
|
||||
const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
|
||||
uint32_t ulPreviousValue;
|
||||
const uint32_t ulUnexpectedValue = 0xff;
|
||||
|
||||
/* The task performs some tests before starting the timer that gives the
|
||||
notification from this interrupt. If the timer has not been created yet
|
||||
|
@ -488,7 +490,28 @@ const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
|
|||
/* It is time to 'give' the notification again. */
|
||||
xCallCount = 0;
|
||||
|
||||
vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
|
||||
/* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
|
||||
and xTaskNotifyAndQueryFromISR(). */
|
||||
switch( xAPIToUse )
|
||||
{
|
||||
case 0: vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
|
||||
xAPIToUse++;
|
||||
break;
|
||||
|
||||
case 1: xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );
|
||||
xAPIToUse++;
|
||||
break;
|
||||
|
||||
case 2: ulPreviousValue = ulUnexpectedValue;
|
||||
xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );
|
||||
configASSERT( ulPreviousValue != ulUnexpectedValue );
|
||||
xAPIToUse = 0;
|
||||
break;
|
||||
|
||||
default:/* Should never get here!. */
|
||||
break;
|
||||
}
|
||||
|
||||
ulTimerNotificationsSent++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -302,6 +302,8 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
|
|||
( void ) ulLine;
|
||||
( void ) pcFileName;
|
||||
|
||||
printf( "ASSERT! Line %d, file %s\r\n", ulLine, pcFileName );
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Stop the trace recording. */
|
||||
|
|
|
@ -1563,7 +1563,9 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
|
|||
* \defgroup xTaskNotify xTaskNotify
|
||||
* \ingroup TaskNotifications
|
||||
*/
|
||||
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )
|
||||
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )
|
||||
|
||||
/**
|
||||
* task. h
|
||||
|
|
|
@ -1219,9 +1219,11 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
if the item size is not 0. */
|
||||
configASSERT( pxQueue->uxItemSize == 0 );
|
||||
|
||||
/* Normally a mutex would not be given from an interrupt, and doing so is
|
||||
definitely wrong if there is a mutex holder as priority inheritance makes no
|
||||
sense for an interrupts, only tasks. */
|
||||
/* Normally a mutex would not be given from an interrupt, especially if
|
||||
there is a mutex holder, as priority inheritance makes no sense for an
|
||||
interrupts, only tasks. However, on occasions when it is wanted to give
|
||||
a mutex from an interrupt, use xQueueSendFromISR() in place of
|
||||
xSemaphoreGiveFromISR(). */
|
||||
configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) );
|
||||
|
||||
/* RTOS ports that support interrupt nesting have the concept of a maximum
|
||||
|
|
|
@ -3489,12 +3489,6 @@ TCB_t *pxTCB;
|
|||
|
||||
if( pxMutexHolder != NULL )
|
||||
{
|
||||
/* A task can only have an inherited priority if it holds the mutex.
|
||||
If the mutex is held by a task then it cannot be given from an
|
||||
interrupt, and if a mutex is given by the holding task then it must
|
||||
be the running state task. */
|
||||
configASSERT( pxTCB == pxCurrentTCB );
|
||||
|
||||
configASSERT( pxTCB->uxMutexesHeld );
|
||||
( pxTCB->uxMutexesHeld )--;
|
||||
|
||||
|
@ -4236,7 +4230,7 @@ TickType_t uxReturn;
|
|||
|
||||
#if( configUSE_TASK_NOTIFICATIONS == 1 )
|
||||
|
||||
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )
|
||||
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
TCB_t * pxTCB;
|
||||
eNotifyValue eOriginalNotifyState;
|
||||
|
@ -4267,8 +4261,12 @@ TickType_t uxReturn;
|
|||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
eOriginalNotifyState = pxTCB->eNotifyState;
|
||||
if( pulPreviousNotificationValue != NULL )
|
||||
{
|
||||
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
|
||||
}
|
||||
|
||||
eOriginalNotifyState = pxTCB->eNotifyState;
|
||||
pxTCB->eNotifyState = eNotified;
|
||||
|
||||
switch( eAction )
|
||||
|
|
Loading…
Reference in a new issue