in tasks.c [4992:5124]
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue,
BaseType_t * pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB;
uint8_t ucOriginalNotifyState;
BaseType_t xReturn = pdPASS;
UBaseType_t uxSavedInterruptStatus;
configASSERT( xTaskToNotify );
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
/* RTOS ports that support interrupt nesting have the concept of a
* maximum system call (or maximum API call) interrupt priority.
* Interrupts that are above the maximum system call priority are keep
* permanently enabled, even when the RTOS kernel is in a critical section,
* but cannot make any calls to FreeRTOS API functions. If configASSERT()
* is defined in FreeRTOSConfig.h then
* portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has
* been assigned a priority above the configured maximum system call
* priority. Only FreeRTOS functions that end in FromISR can be called
* from interrupts that have been assigned a priority at or (logically)
* below the maximum system call interrupt priority. FreeRTOS maintains a
* separate interrupt safe API to ensure interrupt entry is as fast and as
* simple as possible. More information (albeit Cortex-M specific) is
* provided on the following link:
* https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
pxTCB = xTaskToNotify;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if( pulPreviousNotificationValue != NULL )
{
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
}
ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
switch( eAction )
{
case eSetBits:
pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
break;
case eIncrement:
( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
break;
case eSetValueWithOverwrite:
pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
break;
case eSetValueWithoutOverwrite:
if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{
pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
}
else
{
/* The value could not be written to the task. */
xReturn = pdFAIL;
}
break;
case eNoAction:
/* The task is being notified without its notify value being
* updated. */
break;
default:
/* Should not get here if all enums are handled.
* Artificially force an assert by testing a value the
* compiler can't assume is const. */
configASSERT( xTickCount == ( TickType_t ) 0 );
break;
}
traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
/* If the task is in the blocked state specifically to wait for a
* notification then unblock it now. */
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{
/* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
{
/* The delayed and ready lists cannot be accessed, so hold
* this task pending until the scheduler is resumed. */
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* The notified task has a priority above the currently
* executing task so a yield is required. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
/* Mark that a yield is pending in case the user is not
* using the "xHigherPriorityTaskWoken" parameter to an ISR
* safe FreeRTOS function. */
xYieldPending = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
}