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
}
}