以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