以STM32平台为例,在STM32中数值优先级越低,逻辑优先级越高。
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB;
uint8_t ucOriginalNotifyState;
UBaseType_t uxSavedInterruptStatus;
configASSERT( xTaskToNotify ); (1)
/* 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:
http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); (2)
pxTCB = ( TCB_t * ) xTaskToNotify;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); (3)
{
ucOriginalNotifyState = pxTCB->ucNotifyState; (4)
pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; (5)
/* 'Giving' is equivalent to incrementing a count in a counting
semaphore. */
( pxTCB->ulNotifiedValue )++;/*任务通知值+1*/
traceTASK_NOTIFY_GIVE_FROM_ISR();
/* 如果任务在阻塞等待通知 */
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{
/* 该任务不应该出现在事件列表中,如果在则触发断言. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
/* 如果任务调度器运行中 */
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
/*唤醒任务,将任务从阻塞列表中移除,添加到就绪列表中*/
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
{
/* 调度器处于挂起状态,中断依然正常发生,但是不能直接操作就绪列表
将任务加入到就绪挂起列表,任务调度恢复后会移动到就绪列表 */
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
/*如果刚刚唤醒的任务优先级比当前任务高,则设置上下文切换标识,等退出函数后手动切换上下文,
或者在系统节拍中断服务程序中自动切换上下文*/
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* 设置返回参数,表示需要任务切换,在退出中断前进行任务切换. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
/* 设置自动切换标志. */
xYieldPending = pdTRUE;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
}
(1) 断言机制,如果 xTaskToNotify
为NULL,那么程序无法向后面运行
(2)
默认情况下源码定义的优先级如下
LIBRARY_LOWEST_INTERRUPT_PRIORITY 15
LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
如果一个中断的数值优先级小于5,那么他将被永久启用,即使是处于RTOS的临界区,并且该中断不能调用任何FreeRTOS的 API函数,否者将触发断言(如果启用了断言)。如果中断数值优先级处于5~15之间(包括等于),那么它能并且只能调用以FromISR 结尾的 FreeRTOS API函数。中断要尽可能简单。
(3) 关中断,中断数值优先级大于等于LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
的都将被屏蔽。
(4) 保存一份任务通知的原始状态,看看任务是否在等待通知,方便在发送通知后恢复任务。
(5)设置当前任务通知的状态为taskNOTIFICATION_RECEIVED