加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【FreeRTOS操作系统教程】第13章 FreeRTOS任务优先级修改及其分配方案

(2016-08-22 15:21:27)
标签:

fatfs

freertos

stemwin

stm32

usb

分类: FreeRTOS

第13章     FreeRTOS任务优先级修改及其分配方案

本文完整版地址:http://bbs.armfly.com/read.php?tid=21119

本章节主要为大家讲解FreeRTOS任务优先级设置的注意事项、任务优先级的分配方案及其相关的一个例子,内容相对比较简单。

本章教程配套的例子含Cortex-M3内核的STM32F103Cortex-M4内核的STM32F407以及F429

13.1 任务优先级说明

13.2 任务优先级分配方案

13.3 中断优先级和任务优先级的区别

13.4 任务优先级修改

13.5 任务优先级获取

13.6 实验例程说明

13.7       总结

 

13.1  任务优先级说明

下面对FreeRTOS优先级相关的几个重要知识点进行下说明,这些知识点在以后的使用中务必要掌握牢固。

u  FreeRTOS中任务的最高优先级是通过FreeRTOSConfig.h文件中的configMAX_PRIORITIES进行配置的,用户实际可以使用的优先级范围是0configMAX_PRIORITIES – 1。比如我们配置此宏定义为5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。

u  用户配置任务的优先级数值越小,那么此任务的优先级越低,空闲任务的优先级是0

u  建议用户配置宏定义configMAX_PRIORITIES的最大值不要超过32,即用户任务可以使用的优先级范围是031。因为对于CM内核的移植文件,用户任务的优先级不是大于等于32的话,portmacro.h文件中的宏定义configUSE_PORT_OPTIMISED_TASK_SELECTION会优化优先级列表中要执行的最高优先级任务的获取算法(对于CM内核的移植文件,此宏定义默认是使能的,当然,用户也可以在FreeRTOSConfig.h文件中进行配置)。相比通用的最高优先级任务获取算法,这两种方式的对比如下:

Ø  通用方式,没有优化---配置宏定义configUSE_PORT_OPTIMISED_TASK_SELECTION0

²  所有平台的移植文件都可以配置为0,因为这是通用方式。

²  C编写,比专用方式效率低。

²  可用的优先级数量不限制。

Ø  专用方式,进行优化---配置宏定义configUSE_PORT_OPTIMISED_TASK_SELECTION为为1

²  部分平台支持。

²  这些平台架构有专用的汇编指令,比如CLZCount Leading Zeros)指令,通过这些指令可以加速算法执行速度。

²  比通用方式高效。

²  有最大优先级数限制,通常限制为32个。

u  如果用户在FreeRTOSConfig.h文件中配置宏定义configUSE_TIME_SLICING1,或者没有配置此宏定义,时间片调度都是使能的。另外,只要芯片资源允许,可以配置任意多个同优先级任务。

(备注:没有定义configUSE_TIME_SLICING,也能使用时间片调度是因为此宏定义默认已经在FreeRTOS.h文件中使能)

u  FreeRTOS中处于运行状态的任务永远是当前能够运行的最高优先级任务。下一章节讲解调度器,大家会对这个知识点有一个全面的认识。

13.2 任务优先级分配方案

对于初学者,有时候会纠结任务优先级设置为多少合适,因为任务优先级设置多少是没有标准的。对于这个问题,我们这里为大家推荐一个标准,任务优先级设置推荐方式如下图13.1所示:

【FreeRTOS操作系统教程】第13章 <wbr>FreeRTOS任务优先级修改及其分配方案

 

13.1 任务优先级分配方案

u  IRQ任务:IRQ任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。

u  高优先级后台任务:比如按键检测,触摸检测,USB消息处理,串口消息处理等,都可以归为这一类任务。

u  低优先级的时间片调度任务:比如emWin的界面显示,LED数码管的显示等不需要实时执行的都可以归为这一类任务。实际应用中用户不必拘泥于将这些任务都设置为优先级1的同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。

u  空闲任务:空闲任务是系统任务。

u  特别注意:IRQ任务和高优先级任务必须设置为阻塞式(调用消息等待或者延迟等函数即可),只有这样,高优先级任务才会释放CPU的使用权,,从而低优先级任务才有机会得到执行。

这里的优先级分配方案是我们推荐的一种方式,实际项目也可以不采用这种方法。调试出适合项目需求的才是最好的。

13.3 中断优先级和任务优先级区别

部分初学者也容易在这两个概念上面出现问题。简单的说,这两个之间没有任何关系,不管中断的优先级是多少,中断的优先级永远高于任何任务的优先级,即任务在执行的过程中,中断来了就开始执行中断服务程序。

另外对于STM32F103F407F429来说,中断优先级的数值越小,优先级越高。而FreeRTOS的任务优先级是,任务优先级数值越小,任务优先级越低。

13.4任务优先级修改

使用如下函数可以实现FreeRTOS的任务优先级修改:

u  vTaskPrioritySet ()

关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:

【FreeRTOS操作系统教程】第13章 <wbr>FreeRTOS任务优先级修改及其分配方案

 

这里也对此函数进行下介绍。

函数原型:

void vTaskPrioritySet( TaskHandle_t xTask,          

                       UBaseType_t uxNewPriority );  

函数描述:

函数vTaskPrioritySet用于实现FreeRTOS任务优先级的修改。

u  1个参数是任务句柄,用于区分不同的任务。

u  2个参数是给任务配置的新优先级。

使用这个函数要注意以下问题:

1.     使用此函数需要在FreeRTOSConfig.h配置文件中配置如下宏定义为1

#define INCLUDE_vTaskPrioritySet      1

2.     如果第二个参数里面填的是NULL,即数值0的话,那么配置的就是当前正在执行的任务。

3.     如果被修改的任务的优先级,修改后高于正在执行的任务,将执行任务切换,切换到修改好的高优先级任务。

4.     第二个参数数值不可大于等于FreeRTOSConfig.h文件中的宏定义:

#define  configMAX_PRIORITIES 配置的数值。

使用举例:

 

static TaskHandle_t xHandleTaskLED = NULL;

 

 

static void vTaskTaskUserIF(void *pvParameters)

{

     uint8_t ucKeyCode;

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                  

                  

                   case KEY_DOWN_K2:          

                       printf("K2键按下,设置任务vTaskLED的优先级为1\r\n");

                       vTaskPrioritySet( xHandleTaskLED, 1);

                       printf("K2键按下,任务vTaskLED的优先级已经设置为:%d\r\n",

 (int)uxTaskPriorityGet(xHandleTaskLED));

                       break;

                  

                  

                   case KEY_DOWN_K3:          

                       printf("K3键按下,设置任务vTaskLED的优先级为2\r\n");

                       vTaskPrioritySet( xHandleTaskLED, 2);

                       printf("K3键按下,任务vTaskLED的优先级已经设置为:%d\r\n",

  (int)uxTaskPriorityGet(xHandleTaskLED));

                       break;

                  

                  

                   default:                    

                       break;

              }

         }

        

         vTaskDelay(20);

     }

}

 

 

static void AppTaskCreate (void)

{

     xTaskCreate( vTaskLED,          

                 "vTaskLED",        

                 512,               

                 NULL,              

                 2,                 

                 &xHandleTaskLED );

}

13.5任务优先级获取

使用如下函数可以实现FreeRTOS的任务优先级获取:

u  vTaskPriorityGet ()

关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:

【FreeRTOS操作系统教程】第13章 <wbr>FreeRTOS任务优先级修改及其分配方案

 

这里也对此函数进行下介绍。

函数原型:

UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );

函数描述:

函数vTaskPriorityGet用于获取FreeRTOS任务优先级。

u  1个参数是任务句柄,用于区分不同的任务。

使用这个函数要注意以下问题:

1.     使用此函数需要在FreeRTOSConfig.h配置文件中配置如下宏定义为1

#define INCLUDE_vTaskPriorityGet      1

2.     如果第二个参数里面填的是NULL,即数值0的话,那么获取的优先级就是当前正在执行的任务。

使用举例:

 

static TaskHandle_t xHandleTaskLED = NULL;

 

 

static void vTaskTaskUserIF(void *pvParameters)

{

     uint8_t ucKeyCode;

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                  

                  

                   case KEY_DOWN_K2:          

                       printf("K2键按下,设置任务vTaskLED的优先级为1\r\n");

                       vTaskPrioritySet( xHandleTaskLED, 1);

                       printf("K2键按下,任务vTaskLED的优先级已经设置为:%d\r\n",

 (int)uxTaskPriorityGet(xHandleTaskLED));

                       break;

                  

                  

                   case KEY_DOWN_K3:          

                       printf("K3键按下,设置任务vTaskLED的优先级为2\r\n");

                       vTaskPrioritySet( xHandleTaskLED, 2);

                       printf("K3键按下,任务vTaskLED的优先级已经设置为:%d\r\n",

  (int)uxTaskPriorityGet(xHandleTaskLED));

                        break;

                  

                  

                   default:                    

                       break;

              }

         }

        

         vTaskDelay(20);

     }

}

 

 

static void AppTaskCreate (void)

{

     xTaskCreate( vTaskLED,          

                 "vTaskLED",        

                 512,               

                 NULL,              

                 2,                 

                 &xHandleTaskLED );

}

13.6实验例程说明

13.6.1STM32F103开发板实验

配套例子:

V4-307_FreeRTOS实验_任务优先级修改

实验目的:

1. 学习FreeRTOS的任务优先级修改。

实验内容:

1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。

2.     K2按键按下,设置任务vTaskLED的优先级为1

3.     K3按键按下,设置任务vTaskLED的优先级为2

4.     各个任务实现的功能如下:

              vTaskUserIF任务   :按键消息处理。

              vTaskLED任务     LED闪烁。

              vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。

              vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。

FreeRTOS的配置:

FreeRTOSConfig.h文件中的配置如下:

 

#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)

 #include

 extern volatile uint32_t ulHighFrequencyTimerTicks;

#endif

 

#define configUSE_PREEMPTION         1

#define configUSE_IDLE_HOOK          0

#define configUSE_TICK_HOOK          0

#define configCPU_CLOCK_HZ           ( ( unsigned long ) 72000000 )  

#define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )

#define configMAX_PRIORITIES         ( 5 )

#define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )

#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )

#define configMAX_TASK_NAME_LEN      ( 16 )

#define configUSE_TRACE_FACILITY      1

#define configUSE_16_BIT_TICKS       0

#define configIDLE_SHOULD_YIELD      1

 

 

#define configGENERATE_RUN_TIME_STATS                1

#define configUSE_STATS_FORMATTING_FUNCTIONS         1

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)

#define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks

//#define portALT_GET_RUN_TIME_COUNTER_VALUE           1

 

 

#define configUSE_CO_ROUTINES            0

#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

 

 

 

#define INCLUDE_vTaskPrioritySet          1

#define INCLUDE_uxTaskPriorityGet         1

#define INCLUDE_vTaskDelete               1

#define INCLUDE_vTaskCleanUpResources      0

#define INCLUDE_vTaskSuspend              1

#define INCLUDE_vTaskDelayUntil           1

#define INCLUDE_vTaskDelay                1

 

 

#ifdef __NVIC_PRIO_BITS

    

     #define configPRIO_BITS              __NVIC_PRIO_BITS

#else

     #define configPRIO_BITS                   

#endif

 

 

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f

 

 

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01


FreeRTOS任务调试信息(按K1按键,串口打印):

【FreeRTOS操作系统教程】第13章 <wbr>FreeRTOS任务优先级修改及其分配方案

 

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:

#define tskBLOCKED_CHAR          ( 'B' )  任务阻塞

#define tskREADY_CHAR           ( 'R' )  任务就绪

#define tskDELETED_CHAR           ( 'D' )  任务删除

#define tskSUSPENDED_CHAR   ( 'S' )  任务挂起

程序设计:

u  任务栈大小分配:

vTaskUserIF任务   2048字节

vTaskLED任务     2048字节

vTaskMsgPro任务 :2048字节

vTaskStart任务    2048字节

任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的

#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )

u  系统栈大小分配:

【FreeRTOS操作系统教程】第13章 <wbr>FreeRTOS任务优先级修改及其分配方案

 

u  FreeROTS初始化:

 

int main(void)

{

    

     __set_PRIMASK(1); 

    

    

     bsp_Init();

    

    

     vSetupSysInfoTest();

    

    

     AppTaskCreate();

    

   

    vTaskStartScheduler();

 

    

     while(1);

}

u  硬件外设初始化

硬件外设的初始化是在bsp.c文件实现:

 

void bsp_Init(void)

{

    

    

          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

 

     bsp_InitUart();   

     bsp_InitLed();    

     bsp_InitKey();    

}

u  FreeRTOS任务创建:

 

static void AppTaskCreate (void)

{

    xTaskCreate( vTaskTaskUserIF,  

                 "vTaskUserIF",    

                 512,              

                 NULL,             

                 1,                

                 &xHandleTaskUserIF );  /* 任务句柄  */

    

    

     xTaskCreate( vTaskLED,          

                 "vTaskLED",        

                 512,               

                 NULL,              

                 2,                 

                 &xHandleTaskLED );

    

     xTaskCreate( vTaskMsgPro,           

                 "vTaskMsgPro",          

                 512,                    

                 NULL,                   

                 3,                      

                 &xHandleTaskMsgPro );  /* 任务句柄  */

    

    

     xTaskCreate( vTaskStart,            

                 "vTaskStart",           

                 512,                    

                 NULL,                   

                 4,                      

                 &xHandleTaskStart );   

}

u  四个FreeRTOS任务的实现:

 

static void vTaskTaskUserIF(void *pvParameters)

{

     uint8_t ucKeyCode;

     uint8_t pcWriteBuffer[500];

 

    while(1)

    {

         ucKeyCode = bsp_GetKey();

        

         if (ucKeyCode != KEY_NONE)

         {

              switch (ucKeyCode)

              {

                  

                   case KEY_DOWN_K1:          

                       printf("=================================================\r\n");

                       printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");

                       vTaskList((char *)&pcWriteBuffer);

                       printf("%s\r\n", pcWriteBuffer);

                  

                       printf("\r\n任务名       运行计数         使用率\r\n");

                       vTaskGetRunTimeStats((char *)&pcWriteBuffer);

                       printf("%s\r\n", pcWriteBuffer);

                       break;

                  

                  

                   case KEY_DOWN_K2:          

                       printf("K2键按下,设置任务vTaskLED的优先级为1\r\n");

                       vTaskPrioritySet( xHandleTaskLED, 1);

                       printf("K2键按下,任务vTaskLED的优先级已经设置为:%d\r\n",

 (int)uxTaskPriorityGet(xHandleTaskLED));

                       break;

                  

                  

                   case KEY_DOWN_K3:          

                       printf("K3键按下,设置任务vTaskLED的优先级为2\r\n");

                       vTaskPrioritySet( xHandleTaskLED, 2);

                       printf("K3键按下,任务vTaskLED的优先级已经设置为:%d\r\n",

  (int)uxTaskPriorityGet(xHandleTaskLED));

                       break;

 

                  

                   default:                    

                       break;

              }

         }

        

         vTaskDelay(20);

     }

}

 

 

static void vTaskLED(void *pvParameters)

{

    while(1)

    {

         bsp_LedToggle(2);

        vTaskDelay(200);

    }

}

 

 

static void vTaskMsgPro(void *pvParameters)

{

    while(1)

    {

         bsp_LedToggle(3);

        vTaskDelay(300);

    }

}

 

 

static void vTaskStart(void *pvParameters)

{

    while(1)

    {

        

         bsp_KeyScan();

        vTaskDelay(10);

    }

}


 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有