• FreeRTOS内核启动


    本文屏蔽了大量的技术细节,只是简单的阐述内核启动的实现。由于本人才疏学浅知识有限,如有错误,还请各位不吝赐教。

    从任务调度开始

    void vTaskStartScheduler( void ) /* 这个函数创建了idle任务,并且创建软件定时器任务 ,到最后调用xPortStartScheduler */

    看看xPortStartScheduler 函数做了什么

     1 BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
     2 {
     3     /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
     4 
     5     /* 设置PendSV和Systick中断优先级为最低,这里是操作寄存器直接设置,为什么要设置最低,因为任务切换就是在PendSV中运行,为了让其他中断能够及时的运行,为什么要在PendSV中切换任务,因为PendSV可以挂起延迟执行,具体参考Cortex-M3 权威指南 第7章异常SVC和PendSV */
     6     portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
     7 
     8     portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
     9 
    10     #if ( configENABLE_MPU == 1 )
    11         {
    12             /* Setup the Memory Protection Unit (MPU). */
    13             prvSetupMPU();
    14         }
    15     #endif /* configENABLE_MPU */
    16 
    17     /* Start the timer that generates the tick ISR. Interrupts are disabled
    18      * here already. */
    19     vPortSetupTimerInterrupt();
    20 
    21     /* Initialize the critical nesting count ready for the first task. */
    22     ulCriticalNesting = 0;     /* 此变量表示临界段嵌套次数,可以表示是否在中断里 */
    23 
    24     /* Start the first task. */
    25     vStartFirstTask();         
    26 
    27     /* Should never get here as the tasks will now be executing. Call the task
    28      * exit error function to prevent compiler warnings about a static function
    29      * not being called in the case that the application writer overrides this
    30      * functionality by defining configTASK_RETURN_ADDRESS. Call
    31      * vTaskSwitchContext() so link time optimization does not remove the
    32      * symbol. */
    33     vTaskSwitchContext();  /* 查找最高的优先级 */
    34     prvTaskExitError();
    35 
    36     /* Should not get here. */
    37     return 0;
    38 }
    39     

    taskSELECT_HIGHEST_PRIORITY_TASK 函数实现了优先级的查找,提供了两种办法,这里只研究一种

     1 #define taskSELECT_HIGHEST_PRIORITY_TASK()                                
     2     {                                                                         
     3         UBaseType_t uxTopPriority = uxTopReadyPriority;                       
     4                                                                               
     5         /* Find the highest priority queue that contains ready tasks. */      
     6         while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) 
     7         {                                                                     
     8             configASSERT( uxTopPriority );                                    
     9             --uxTopPriority;                                                  
    10         }                                                                     
    11                                                                               
    12         /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of 
    13          * the  same priority get an equal share of the processor time. */                    
    14         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); 
    15         uxTopReadyPriority = uxTopPriority;                                                   
    16     } /* taskSELECT_HIGHEST_PRIORITY_TASK */
    寻找最高的优先级,更新pxCurrentTCB
      while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) )
      表示就绪表中是否有任务。没有任务就下标减一继续找,因为下标就是优先级,直到找到了优先级。
      如果跳出while,表示找到了最高优先级的任务。有任务表示最高的优先级,因为下标越小,优先级越低。
      listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) )
      找到的列表项更新到当前Tcb.
      uxTopReadyPriority = uxTopPriority;  
      更新最高的就绪优先级
      pxReadyTasksLists里面存放的是Tcb(准确来说应该是存放Tcb里面的 xStateListItem 列表项)
     
    第二种是使用前导零指令CLZ,意思是32个bit表示优先级,哪个位是0就减掉。

    参考野火教程的一句话: 任务控制块里面有一个 xStateListItem 成员, 数据类型为 ListItem_t, 我们将任务插入
    到就绪列表里面,就是通过将任务控制块的 xStateListItem 这个节点插入到就绪列表中来实
    现的。如果把就绪列表比作是晾衣架, 任务是衣服,那 xStateListItem 就是晾衣架上面的钩
    子,每个任务都自带晾衣架钩子,就是为了把自己挂在各种不同的链表中 。

    xPortPendSVHandler,次函数进行任务切换。

    邮箱:422705581@qq.com
  • 相关阅读:
    导热硅胶片的特性
    电子器件热设计估算技巧 1
    什么是热阻
    功率器件的热设计
    ESP8266EX 电路设计
    STM8S005 ADC采集 5位共阴数码管显示
    PCB设计-Allegro软件入门系列第九讲-Class分类和Subclass应用
    STM32 滴答时钟 SysTick 的使用 STM32F103C8T6
    SPI 串行Flash闪存W25Q128FV 的使用(STM32F407)_基础篇
    如何居中一个元素
  • 原文地址:https://www.cnblogs.com/yangdh/p/13845521.html
Copyright © 2020-2023  润新知