找回密码
 立即注册
查看: 393|回复: 3

FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中)

[复制链接]
  • TA的每日心情
    奋斗
    2024-5-5 08:35
  • 签到天数: 143 天

    [LV.7]常住居民III

    29

    主题

    558

    回帖

    2138

    积分

    荣誉版主

    积分
    2138
    发表于 2024-3-3 12:32:43 | 显示全部楼层 |阅读模式
    本帖最后由 gentleman 于 2024-3-3 15:03 编辑

    FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中)
    任务轮询
    截图202403031230583707.jpg

    2.1 调整中断堆栈内容
    上次我们成功启动了 第一个任务
        如果 任务中,它不挂起自己,或进入延时状态。 (正常不会这么干,下期会讲)
        那么 任务会执行到 1tick后
        cpu进入定时器0中断
          截图202403031331289801.jpg

        配置定时器0 中断函数
        vTimer0ISR()
        跳进去
        截图202403031334556069.jpg
        180行      portNORMALIZE_INTERRUPT_STACK();
         再跳进去
          截图202403031340406748.jpg
          发现 它执行了一系列 出栈 入栈 操作
        目的是什么
        因为中断的栈 格式是不一样的

        我们可通过对比 RETI 与 ERET 来比较
        截图202403031344363508.jpg       截图202403031344593186.jpg

           很明显 中断栈顶元素 是PC15~8
               而函数栈顶元素  是PC7~0
         所以这里 将几个栈元素都 弹出来
               按照函数栈 顺序 重新入一遍栈
    2.2  寄存器入栈 配置Tick计数器  

    截图202403031400438498.jpg
             将寄存器入栈
           继续看代码
              截图202403031403419675.jpg

          接下来进入到这个函数
              截图202403031402496152.jpg

             
                    const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
             将tick计数器+1
             freeRTOS 就是靠这个计数器计时的
          xConstTickCount == ( TickType_t ) 0U
       
          计数器什么时候==0
          溢出的时候
          切换 延时任务列表 (看过之前的文章知道,这列表有两个)
          关于延时任务部分 下期再说
          这期主要看轮询
    2.3  保存当前任务堆栈指针

    截图202403031424009324.jpg
                 阅读过之前内容
                 就知道 DR60 是SP指针  指向堆栈的栈顶
                 这里把 SP指针 保存到了当前任务TCB(pxTopOfStack)中

             DR0 与WR2 ,DR4 与WR6 的关系大家应该都清楚吧,不多解释了
    2.4  取出下个任务

         返回去
           截图202403031411374074.jpg
             跳入这个函数
           截图202403031413374561.jpg
             判读了一下 任务调度是否启动
          启动了就执行这个函数
           截图202403031415002085.jpg

              while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \

            {                                                                     \
                configASSERT( uxTopPriority );                                    \
                --uxTopPriority;                                                  \
            }                                                                     \



             优先级列表空就看下个优先级列表
          listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );
       取出下一个任务的PCB  这块展开讲内容也有点多,后面我会画张图,补充在本贴下面3L
    2.5  恢复到新任务栈顶指针
          好的,现在已经获取到了下个任务的TCB
          回到这里
           截图202403031422219486.jpg
          portRESTORE_SPX()             
          这里和上期一样, 修改SP 为 新任务的TCB(pxEndOfStack
          让SP指向新任务的(堆)栈
    2.6  出(新任务)栈

    截图202403031436042484.jpg
            弹出新任务用的寄存器
    2.7  压入RETI需要的栈元素 ,调用RETI退出中断

    截图202403031438472382.jpg
           $ 指当前行
         $+10 指的是哪一行
         我们来分析一下
         这是PUSH
          截图202403031441195368.jpg
              指令长度3 (因为立即数也要占一个)
           3条PUSH 长度9   
           截图202403031442407502.jpg
               而RETI 长度1
          所以$+10 就是 RETI 的下一条指令
          同理 +7 +4 也是
         最后调用RETI 退出中断
             至于为啥要这么干,用RETI 清楚标志位,退出中断。不然下次就不进中断了,CPU认为还在中断内部。

    2.8  ERET 进入新任务函数

              截图202403031447339941.jpg
                这部分也和上期一样
             截图202403031449019474.jpg
               通过ERET 修改PC指针
             让PC指针指向新的任务入口

             到此完成了新任务的切换






    1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
    回复 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-5-5 08:35
  • 签到天数: 143 天

    [LV.7]常住居民III

    29

    主题

    558

    回帖

    2138

    积分

    荣誉版主

    积分
    2138
     楼主| 发表于 2024-3-3 12:33:09 | 显示全部楼层
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-5-5 08:35
  • 签到天数: 143 天

    [LV.7]常住居民III

    29

    主题

    558

    回帖

    2138

    积分

    荣誉版主

    积分
    2138
     楼主| 发表于 2024-3-3 14:59:51 | 显示全部楼层
    本帖最后由 gentleman 于 2024-3-4 10:47 编辑

    补充 FreeRTOS (xLIST)链表结构内容  

        便于大家理解  在任务就绪链表取出下个任务TCB过程
        截图202403041045307222.jpg

       下图为FreeRTOS 三个链表的定义
        截图202403041017455108.jpg

         xLIST 中包含 xMINI_LIST_ITEM  与xLIST_ITEM
       
       pxReadyTasksLists[2]中 包含pxIndex 与xListEnd

    而在任务就绪链表链表初始化时




      
    截图202403041022305156.jpg
         可以看到初始化 时  把pxIndex 设为了 xListEnd
        截图202403041028378250.jpg
         新建任务时
        插入链表尾部的函数
         把 新项 的下一项 设为 pxIndex (初始化时为xListEnd)
         前项 设为 pxIndex(初始化时为xListEnd)的前一项  (就是上个任务)
                
         这里可以看第一张图 去理解


        截图202403041034512339.jpg
         取出下个任务
       还是对照图来看
       很清晰的看出 pxIndex 的pxNext 是哪一项
       当pxNext 为 xListEnd 时 就再取pxNext一遍

       
       
       
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-5-5 08:35
  • 签到天数: 143 天

    [LV.7]常住居民III

    29

    主题

    558

    回帖

    2138

    积分

    荣誉版主

    积分
    2138
     楼主| 发表于 2024-3-4 10:48:41 | 显示全部楼层
    3L 用了  补充了一些内容

    再占一楼
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-15 14:14 , Processed in 0.072294 second(s), 44 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表