void vTaskSwitchContext(void)
{
? ? //my_printf( "uxSchedulerSuspended = %d\n", uxSchedulerSuspended );
/* 調度器處于掛起狀態 */
if (uxSchedulerSuspended != (UBaseType_t)pdFALSE) {
/**
* The scheduler is currently suspended - do not allow a context
* switch.
*/
xYieldPending = pdTRUE;
} else {
xYieldPending = pdFALSE;
traceTASK_SWITCHED_OUT();
/* Check for stack overflow, if configured. */
taskCHECK_FOR_STACK_OVERFLOW();
? ? ? ? /* Before the currently running task is switched out, save its errno. */
#if (configUSE_POSIX_ERRNO == 1)
{bbb
pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
}
#endif
? ? ? ? /**
* Select a new task to run using either the generic C or port
* optimised asm code. ?debug_stamp
* 選擇優先級最高的任務
*/
//taskSELECT_HIGHEST_PRIORITY_TASK();
UBaseType_t uxTopPriority; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
/* Find the highest priority list that contains ready tasks. */ ? ? ? ? ? ? ? ? ? ? ? ?
//portGET_HIGHEST_PRIORITY(uxTopPriority, uxTopReadyPriority); ? ?
//#define portGET_HIGHEST_PRIORITY xxx( uxTopPriority, uxReadyPriorities )?
//my_printf( "ccccuxTopReadyPriority = %#x\n", uxTopReadyPriority );
uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxTopReadyPriority ) ) );
//configASSERT(listCURRENT_LIST_LENGTH(&(pxReadyTasksLists[uxTopPriority])) > 0); ? ?
//listGET_OWNER_OF_NEXT_ENTRY(pxCurrentTCB, &(pxReadyTasksLists[uxTopPriority]));?
//|------->volatile UBaseType_t uxNumberOfItems = 1 ? ?//鏈表中元素的個數
//| |<-----ListItem_t *pxIndex;?? ??? ??? ??? ??? ? ? ? ? //總是指向xListEnd節點,在鏈表尾部插入的時候,方便找到位置?? ?
//| |->|-->TickType_t xItemValue = portMAX_DELAY ? ? ? [MiniListItem_t xListEnd] ??
//| ? ?| ? struct xLIST_ITEM *pxNext; ? ? ----->| ? ? ?//后繼節點
//| ? ?| ? struct xLIST_ITEM *pxPrevious; ----->| ? ? ?//前驅節點?? ?
//| ? ?| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
//| ? ?| ? TickType_t xItemValue; <-------------| ? ? ?//鏈表節點的值
//| ? ?|<--struct xLIST_ITEM *pxNext; ? ? ? ? ? ? ? ? ?//后繼節點
//| ? ?|<--struct xLIST_ITEM *pxPrevious; ? ? ? ? ? ? ?//前驅節點
//| ? ? ? ?void * pvOwner; ? ? ? ? ? ? ? ? ? ? ? ? ? ? //保存私有數據
//|<------ struct xLIST *pxContainer; ? ? ? ? ? ? ? ? ?//節點所在的鏈表
//|------->volatile UBaseType_t uxNumberOfItems = 1 ? ?//鏈表中元素的個數
//| |<-----ListItem_t *pxIndex;?? ??? ??? ??? ??? ? ? ? ? //總是指向xListEnd節點,在鏈表尾部插入的時候,方便找到位置?? ?
//| | ?|-->TickType_t xItemValue = portMAX_DELAY ? ? ? [MiniListItem_t xListEnd] ??
//| | ?| ? struct xLIST_ITEM *pxNext; ? ? ----->| ? ? ?//后繼節點
//| | ?| ? struct xLIST_ITEM *pxPrevious; ----->| ? ? ?//前驅節點?? ?
//| | ?| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
//| |--|-->TickType_t xItemValue; <-------------| ? ? ?//鏈表節點的值
//| ? ?|<--struct xLIST_ITEM *pxNext; ? ? ? ? ? ? ? ? ?//后繼節點
//| ? ?|<--struct xLIST_ITEM *pxPrevious; ? ? ? ? ? ? ?//前驅節點
//| ? ? ? ?void * pvOwner; ? ? ? ? ? ? ? ? ? ? ? ? ? ? //保存私有數據
//|<------ struct xLIST *pxContainer; ? ? ? ? ? ? ? ? ?//節點所在的鏈表
?? ??? ?
my_printf( "\nuxTopPriority = %d\n", uxTopPriority );
my_printf( "pxCurrentTCB->pcTaskName1 = %s\n", pxCurrentTCB->pcTaskName );
List_t * const pxConstList = &pxReadyTasksLists[uxTopPriority];?? ?
//my_printf( "pxConstList = %p\n", pxConstList );
my_printf( "pxConstList->pxIndex before = %p\n", pxConstList->pxIndex );
?? ??? ?
/* Increment the index to the next item and return the item, ensuring */?? ??? ? ??
/* we don't return the marker used at the end of the list.?? ?*/?? ??? ??? ??? ??? ? ??
pxConstList->pxIndex = pxConstList->pxIndex->pxNext;
//此處有指針的指向偏移 由 xListEnd -> xLIST_ITEM
?? ??? ?my_printf( "pxConstList->pxIndex hou = %p\n", pxConstList->pxIndex );
my_printf( " &pxConstList->xListEnd = %p\n", ?&pxConstList->xListEnd );
if( (void *)pxConstList->pxIndex == (void *)&pxConstList->xListEnd ){?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ??
pxConstList->pxIndex = pxConstList->pxIndex->pxNext;?? ?
my_printf( "pxConstList->pxIndexxx = %p\n", pxConstList->pxIndex );
? ? ? ? ? ? //空閑任務由于不能掛起,其指向內容有些不一樣 pxIndex->pxNext 指向 &xListEnd, 而不是指向xLIST_ITEM
//而對于其他有掛起和恢復的任務 不一樣
//空閑任務不會有鏈表xLIST_ITEM的刪除和插入動作
//第一次進空閑任務不會走這里 后續由于沒有刪除和插入對pxIndex復位?
//pxConstList->pxIndex = pxConstList->pxIndex->pxNext; 指向了xLIST_ITEM?
//然后達到了循環的穩定點?
//總結下來:第一次指向 &xListEnd,后續運行指向 xLIST_ITEM?
//為啥后續不交錯指向? 2次運行 pxConstList->pxIndex = pxConstList->pxIndex->pxNext; 回到原點.
//第一次運行:
//|------->volatile UBaseType_t uxNumberOfItems = 1 ? ?//鏈表中元素的個數
//| |<-----ListItem_t *pxIndex;?? ??? ??? ??? ??? ? ? ? ? //總是指向xListEnd節點,在鏈表尾部插入的時候,方便找到位置?? ?
//| |->|-->TickType_t xItemValue = portMAX_DELAY ? ? ? [MiniListItem_t xListEnd] ??
//| ? ?| ? struct xLIST_ITEM *pxNext; ? ? ----->| ? ? ?//后繼節點
//| ? ?| ? struct xLIST_ITEM *pxPrevious; ----->| ? ? ?//前驅節點?? ?
//| ? ?| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
//| ? ?| ? TickType_t xItemValue; <-------------| ? ? ?//鏈表節點的值 xLIST_ITEM xLIST_ITEM
//| ? ?|<--struct xLIST_ITEM *pxNext; ? ? ? ? ? ? ? ? ?//后繼節點
//| ? ?|<--struct xLIST_ITEM *pxPrevious; ? ? ? ? ? ? ?//前驅節點
//| ? ? ? ?void * pvOwner; ? ? ? ? ? ? ? ? ? ? ? ? ? ? //保存私有數據
//|<------ struct xLIST *pxContainer; ? ? ? ? ? ? ? ? ?//節點所在的鏈表
?? ??? ??? ?//第2次運行:
//|------->volatile UBaseType_t uxNumberOfItems = 1 ? ?//鏈表中元素的個數
//| |<-----ListItem_t *pxIndex;?? ??? ??? ??? ??? ? ? ? ? //總是指向xListEnd節點,在鏈表尾部插入的時候,方便找到位置?? ?
//| | ?|-->TickType_t xItemValue = portMAX_DELAY ? ? ? [MiniListItem_t xListEnd] ??
//| | ?| ? struct xLIST_ITEM *pxNext; ? ? ----->| ? ? ?//后繼節點
//| | ?| ? struct xLIST_ITEM *pxPrevious; ----->| ? ? ?//前驅節點?? ?
//| | ?| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
//| |--|-->TickType_t xItemValue; <-------------| ? ? ?//鏈表節點的值 xLIST_ITEM xLIST_ITEM
//| ? ?|<--struct xLIST_ITEM *pxNext; ? ? ? ? ? ? ? ? ?//后繼節點
//| ? ?|<--struct xLIST_ITEM *pxPrevious; ? ? ? ? ? ? ?//前驅節點
//| ? ? ? ?void * pvOwner; ? ? ? ? ? ? ? ? ? ? ? ? ? ? //保存私有數據
//|<------ struct xLIST *pxContainer; ? ? ? ? ? ? ? ? ?//節點所在的鏈表
?? ??? ??? ?
?? ??? ??? ?
}?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ??
pxCurrentTCB = pxConstList->pxIndex->pvOwner;?? ??? ?
my_printf( "pxCurrentTCB->pcTaskName2 = %s\n", pxCurrentTCB->pcTaskName );
?? ?
traceTASK_SWITCHED_IN();
? ? ? ? /* After the new task is switched in, update the global errno. */
#if (configUSE_POSIX_ERRNO == 1)
{
FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
}
#endif
}
}