42解除任务挂起 vTaskResume 源码voidvTaskResume(TaskHandle_t xTaskToResume)// tasks.c 1868 形参不能为 NULL 或 pxCurrentTCB{TCB_t*constpxTCBxTaskToResume;configASSERT(xTaskToResume);// 确认断言if((pxTCB!pxCurrentTCB)(pxTCB!NULL))// 形参不能为 NULL 或 pxCurrentTCB{taskENTER_CRITICAL();// 进入临界区{if(prvTaskIsTaskSuspended(pxTCB)!pdFALSE)// 要求形参任务在挂起链表中{traceTASK_RESUME(pxTCB);// 统计(void)uxListRemove((pxTCB-xStateListItem));// 其实就是在 xSuspendedTaskList 链表里prvAddTaskToReadyList(pxTCB);// 宏函数注释过了插入对应的就绪链表并更新对应的 bit 位// 本函数不是 vTaskResumeFromISR故可直接操作临界区不用插入到 xPendingReadyList待就绪任务链表if(pxTCB-uxPrioritypxCurrentTCB-uxPriority)// 形参任务比当前任务的优先级要高{taskYIELD_IF_USING_PREEMPTION();// 宏函数//宏taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() 宏 portYIELD()}elsemtCOVERAGE_TEST_MARKER();}elsemtCOVERAGE_TEST_MARKER();}taskEXIT_CRITICAL();// 结束临界区}elsemtCOVERAGE_TEST_MARKER();}// vTaskResume43vTaskResume 调用了下面的函数 prvTaskIsTaskSuspendedstaticBaseType_tprvTaskIsTaskSuspended(constTaskHandle_t xTask)// tasks.c 1658{BaseType_t xReturnpdFALSE;constTCB_t*constpxTCBxTask;configASSERT(xTask);// xPendingReadyList 解除挂起的待就绪任务//判断形参任务是否是真的被挂起的任务//宏listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( pxListItem -pxContainer pxList ) ? pdTRUE : pdFALSEif(listIS_CONTAINED_WITHIN(xSuspendedTaskList,(pxTCB-xStateListItem))!pdFALSE){// 形参任务不能是已解除挂起等待恢复就绪态的任务if(listIS_CONTAINED_WITHIN(xPendingReadyList,(pxTCB-xEventListItem))pdFALSE){// 要求本任务的 pxTCB-xEventListItem-pxContainer NULL 才可以不能在等待事件或无限期阻塞/* Is it in the suspended list because it is in the Suspended state, or because is is blocked with no timeout? */if(listIS_CONTAINED_WITHIN(NULL,(pxTCB-xEventListItem))!pdFALSE)xReturnpdTRUE;elsemtCOVERAGE_TEST_MARKER();}elsemtCOVERAGE_TEST_MARKER();}elsemtCOVERAGE_TEST_MARKER();returnxReturn;}44从中断中恢复挂起任务 xTaskResumeFromISR源码BaseType_txTaskResumeFromISR(TaskHandle_t xTaskToResume)// tasks.c 1758{BaseType_t xYieldRequiredpdFALSE;// 本函数的返回值TCB_t*constpxTCBxTaskToResume;UBaseType_t uxSavedInterruptStatus;// 寄存器 BASEPRI 的值configASSERT(xTaskToResume);//处于 5 - 15 中断优先级之间的中断函数才可以调用这些 xxFromISR函数portASSERT_IF_INTERRUPT_PRIORITY_INVALID();// 空的宏// #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()// #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )uxSavedInterruptStatusportSET_INTERRUPT_MASK_FROM_ISR();//设置 寄存器 BASEPRI{if(prvTaskIsTaskSuspended(pxTCB)!pdFALSE)// 这个函数在上面出现过记录过了{traceTASK_RESUME_FROM_ISR(pxTCB);if(uxSchedulerSuspended(UBaseType_t)pdFALSE)// 查看调度器是否被挂起{/* Ready lists can be accessed so move the task from the suspended list to the ready list directly. */if(pxTCB-uxPrioritypxCurrentTCB-uxPriority)// 形参优先级太高{xYieldRequiredpdTRUE;// 这是本函数的局部变量作为本函数的返回值xYieldPendingpdTRUE;// 软中断标志}elsemtCOVERAGE_TEST_MARKER();// 这里虽然也是操作了临界区资源但这是在中断函数里对于单核的 M3 CPU是不会出现数据竞争的(void)uxListRemove((pxTCB-xStateListItem));prvAddTaskToReadyList(pxTCB);// 直接插入就绪链表}else// 注意下面操作的是 pxTCB-xEventListItem 链表不再是上面的 pxTCB-xStateListItem 链表vListInsertEnd((xPendingReadyList),(pxTCB-xEventListItem));}elsemtCOVERAGE_TEST_MARKER();}portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);//宏portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x )returnxYieldRequired;}补充 pxTCB-xEventListItem 和 pxTCB-xStateListItem 这俩节点的区别上面的 函数 使用了俩操作 寄存器 BASEPRI 的宏函数调整中断屏蔽阈值。如下staticportFORCE_INLINEuint32_tulPortRaiseBASEPRI(void){//#define configMAX_SYSCALL_INTERRUPT_PRIORITY \// ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY (8 - configPRIO_BITS) )uint32_tulReturn,ulNewBASEPRIconfigMAX_SYSCALL_INTERRUPT_PRIORITY;//应该只是为了挪到高位 bit__asm{/* Set BASEPRI to the max syscall priority to effect a critical section. *//* *INDENT-OFF* */// 如此中断优先级 5 以上的全部被屏蔽了mrs ulReturn,basepri msr basepri,ulNewBASEPRI dsb isb/* *INDENT-ON* */}returnulReturn;}staticportFORCE_INLINEvoidvPortSetBASEPRI(uint32_tulBASEPRI){__asm{/* Barrier instructions are not used as this function is only used to * lower the BASEPRI value. */// 恢复原来的屏蔽优先级/* *INDENT-OFF* */msr basepri,ulBASEPRI/* *INDENT-ON* */}}45ARM 内核里的寄存器 BASEPRI、PRIMASK、FAULTMASK46谢谢