当前位置: 首页 > news >正文

freertos任务调度关键函数理解 vTaskSwitchContext


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

http://www.dtcms.com/a/293151.html

相关文章:

  • 编程基础:常见数据类型详解
  • Kubernetes 服务发布基础
  • 从云端到指尖:MNN实现端侧大模型“量子压缩”
  • Flask转发 [Siemens.Sistar.Api.dll] Braumat API--->DLL to restAPI
  • 鸿蒙开发:弹出库更新至1.2.2版本,新增模态页面弹出
  • Java中的泛型数据
  • K8S基础环境部署
  • 赋能未来数学课堂——基于Qwen3、LangChain与Agent架构的个性化教辅系统研究
  • Rocky Linux 9 快速安装 Node.js
  • 遇到JAVA问题
  • SQL 基础案例解析
  • Spring Boot 使用Jasypt加密
  • 我们能否承担微服务带来的复杂性和运维成本?
  • wps dispimg python 解析实现参考
  • ROS个人笔记
  • 【音视频协议篇】RTMP协议
  • A316-HF-I2S-V1:USB TO I2S HiFi音频转换器评估板技术解析
  • Flutter基础(前端教程①⑨-margin-padding)
  • 构建智能视频中枢--多路RTSP转RTMP推送模块在轨道交通与工业应用中的技术方案探究
  • List和Map的区别
  • Java值传递和构造函数
  • Java HttpClient使用手册
  • 【C语言进阶】动态内存管理(1)
  • Model Control Protocol 使用MCP进行各种任务适配,调用工具和资源进行客户端开发
  • OneCode3.0 UI组件注解详解手册
  • 前端之jQuery
  • Playwright 自动化测试系列(6)| 第三阶段:测试框架集成​指南:参数化测试 + 多浏览器并行执行
  • PCIe Base Specification解析(二)
  • Linux笔记2——常用命令-1
  • Sa-Token大师:第四章 - 企业级架构与源码实战