gentleman 发表于 2024-2-28 11:38:18

FreeRTOS for STC32G12K128内核代码解读(一)任务建立(上),后续文章见二楼的链接

FreeRTOS for STC32G12K128内核代码解读(一)任务建立(上)
===后续文章见二楼的链接

本篇核心内容



源码工程为官网下载的 FreeRTOS 库函数版本



一 任务建立函数参数


         

      这就是今天的主角

      任务建立函数
      跳进去 函数定义

   BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )




       解释一下这些参数
       参数1pxTaskCode    任务函数名   
       参数2pcName      任务名字 (就是个字符串,别和参数1搞混)
       参数3usStackDepth(堆) 栈深度
       参数4pvParameters任务函数参数

       参数5uxPriority    任务优先级

       参数6pxCreatedTask 任务句柄(这个是传出来的,不是传进去的)

         
二 TCB 任务控制块 结构
      函数内 建了一个TCB (任务控制块)的指针
      我们跳转,查看这个数据结构的内容

      


       条件编译我们先跳过
       需要时再看

      解释一下这个数据结构的内容
      


       看不懂没关系,后面的代码会 给结构体赋值的
三 TCB 申请(堆)栈空间
       回到 函数体
      


    pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );

   上面这行,给新的TCB 分配了一块空间
   如何分配的 有点长 暂时先不看 -属于内存管理的内容了
      继续阅读
   753 行 pxNewTCB->pxStack =给TCB 的栈 分配了一块(堆)栈空间

      
四 初始化新任务
      如果 (堆)栈申请成功了
      调用            prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
    初始化新任务,看到 这堆参数 基本能猜到 要给TCB 赋值了
      

   跳转到该函数
    876行             pxTopOfStack = pxNewTCB->pxStack;
    先配置一下(堆)栈顶,栈顶指向起始栈
      条件编译先跳过
      888行 开始     if( pcName != NULL )判断一下名字是否为空
    非空就赋值给TCB的pcTaskName[]任务名字             pxNewTCB->pcTaskName[ x ] = pcName[ x ];


   

   938行     vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
          vListInitialiseItem( &( pxNewTCB->xEventListItem ) );

      这两行初始化了 状态链表 和事件链表
      之前这两个链表没有展开
   现在展开看一下
      

   常见的双向链表
   前三个是 项值, 前项与后项指针
   pvOwner         链表持有者指针(TCB)
   pxContainer   项所在的链表指针(如果有)

      看看初始化函数
      


    pxItem->pxContainer = NULL;

   把pxContainer项所在的链表指针设为空
   返回到prvInitialiseNewTask()
      



          调查宏定义 发现这几行是给 链表项/持有者赋值
    #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )    ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
    #define listSET_LIST_ITEM_VALUE( pxListItem, xValue )   ( ( pxListItem )->xItemValue = ( xValue ) )
      


    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );

    /* Event lists are always in priority order. */
    listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );

   即:
    给两个链表的pvOwner 赋值为 pxNewTCB 我们刚刚建立的新TCB任务控制块
   给事件链表xEventListItem 的项值xItemValue 赋值为 uxPriority 优先级
   跳过中间的条件编译

   1052行 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
   初始化 (堆)栈


    看第76行:

    ulAddress = ( uint32_t ) pxCode;
    *pxTopOfStack = ( StackType_t ) ( ulAddress >> 16 );    /* PC */
    pxTopOfStack++;
    *pxTopOfStack = ( StackType_t ) ( ulAddress >> 8 );   /* PC */
    pxTopOfStack++;
    *pxTopOfStack = ( StackType_t ) ( ulAddress );          /* PC */

    把函数名(地址) 先存到(堆)栈
       c251地址总线是24位
       这里函数的地址 也是24位
       下面补充两个关于函数调用的基础知识 (知道的可以跳过)
          1.pc指针
          这里解释一下 pc指针 就是指向当前所运行代码的地址
                                  我们调用函数      =》   将pc指针 指向被调函数的地址
            下图是调用函数时PC 指针的值与函数地址
                           

               

         
                2. 栈(保存现场)
                     大家都知道 cpu运行时离不开寄存器
                     
                     而调用函数时,这些寄存器的值怎么办
                     这些值要保存到内存中,这个内存空间叫栈
                     
                  
                  

      继续看代码
            
             PSW DPTR DR28~DR4 的(堆)栈空间初始化
             继续
               
             这几行把 函数的参数存起来了
             将会占用DR0 这个四字节的寄存器
    return pxTopOfStack;

             返回栈顶,该函数结束

      回到xTaskCreate()了
五 添加任务
      第805行
            prvAddNewTaskToReadyList( pxNewTCB );
   添加任务到就绪链表(数组)函数
   跳进去
         

      1077行      uxCurrentNumberOfTasks++;
      当前任务数+1
            pxCurrentTCB = pxNewTCB;
      如果新任务 不是空的
      将新任务设置为 当前任务
            if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
      如果第一个任务
                prvInitialiseTaskLists();
      初始化任务链表
   跳进去

    for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
    {
      vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
    }

    vListInitialise( &xDelayedTaskList1 );
    vListInitialise( &xDelayedTaskList2 );
    vListInitialise( &xPendingReadyList );

内容有点多
分两期吧
















gentleman 发表于 2024-2-28 11:39:17

本帖最后由 gentleman 于 2024-3-28 10:46 编辑

目录
1.任务创建(上)    FreeRTOS内核代码解读(一)任务建立(上) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
2. 任务建立(下)FreeRTOS for STC32G12K128内核代码解读(一)任务建立(下) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
3. 任务调度 (上)   FreeRTOS for STC32G12K128内核代码解读(二)任务调度(上) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
4.任务调度(中) FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

5.任务调度(中下)FreeRTOS for STC32G12K128内核代码解读(二)任务调度(中下) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

6.任务调度 (下)FreeRTOS for STC32G12K128内核代码解读(二)任务调度(下) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

7.队列1 FreeRTOS for STC32G12K128内核代码解读(三)队列(1) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)
8.队列2FreeRTOS for STC32G12K128内核代码解读(三)队列(2) - FreeRTOS/实时操作系统/文件系统/嵌入式系统软件,TFT-GUI/uGFX - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

9.队列3FreeRTOS for STC32G12K128内核代码解读(三)队列(3) - FreeRTOS/uCOS,GUI-uGFX/U8g2,文件系统/嵌入式系统/实时操作系统 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

gentleman 发表于 2024-2-28 17:05:05

再占一层
二楼改目录了

llyymm 发表于 2024-3-9 14:17:47

学习中,感谢分享经验

龙腾四海 发表于 2024-3-13 11:08:49

请问这是什么编译器,不像KEIL啊

gentleman 发表于 2024-3-13 11:46:22

龙腾四海 发表于 2024-3-13 11:08
请问这是什么编译器,不像KEIL啊


VSCODE

VSCode 开发51单片机 简单教程(欢迎回帖分享优质插件/技巧) - SDCC, IAR C++ for STC8, GCC, VSCode,Linux, MacOS - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)




龙腾四海 发表于 2024-3-13 19:44:17

gentleman 发表于 2024-3-13 11:46
VSCODE

VSCode 开发51单片机 简单教程(欢迎回帖分享优质插件/技巧) - SDCC, IAR C++ for STC8, GCC, ...

十分感谢
页: [1]
查看完整版本: FreeRTOS for STC32G12K128内核代码解读(一)任务建立(上),后续文章见二楼的链接