搜索
查看: 3525|回复: 6

[分享] 【安富莱】【RTX操作系统教程】第8章 任务优先级修改

[复制链接]

该用户从未签到

296

主题

930

帖子

29

蝴蝶豆

金牌会员

最后登录
2020-11-20
发表于 2016-1-22 15:57:57 | 显示全部楼层 |阅读模式
第8章      任务优先级修改
    本章节主要为大家讲解RTX任务优先级设置的注意事项,任务优先级的分配方案及其相关的一个例子,内容相对比较简单。
    本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。
8.1 任务优先级设置注意事项
8.2 任务优先级分配方案
8.3 任务优先级设置
8.4 实验例程说明
8.5         总结
8.1  任务优先级设置注意事项
    RTX操作系统任务优先级的设置要注意以下几个问题:
1.  设置任务的优先级时,数值越小优先级越低。
2.  最低任务优先级是0,此优先级被空闲任务使用,任何其它任务都不可以使用。
3.  用户可以设置的优先级范围是1-254,由于RTX支持时间片调度,所以也是支持用户任务设置为相同的优先级。
4.  优先级255被保留,用于最重要的任务。

回复

使用道具 举报

该用户从未签到

296

主题

930

帖子

29

蝴蝶豆

金牌会员

最后登录
2020-11-20
 楼主| 发表于 2016-1-22 16:02:54 | 显示全部楼层
8.2  任务优先级分配方案
    对于初学者,有时候会纠结任务优先级设置为多少合适,因为任务优先级设置多少是没有标准的。对于这个问题,RTX有一个推荐的设置标准,任务优先级设置推荐方式如下图8.1所示:
                              
8.1.png
图8.1 任务优先级分配方案
IRQ任务:IRQ任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。
高优先级后台任务:比如按键检测,触摸检测,USB消息处理,串口消息处理等,都可以归为这一类任务。
低优先级的时间片调度任务:比如emWin的界面显示,LED数码管的显示等不需要实时执行的都可以归为这一类任务。实际应用中用户不必拘泥于将这些任务都设置为优先级1的同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。
空闲任务:空闲任务是系统任务。
特别注意:IRQ任务和高优先级任务必须设置为阻塞式(调用消息等待或者延迟等函数即可),只有这样高优先级任务才会释放CPU的使用权,从低优先级任务才有机会得到执行。
     这里的优先级分配方案是RTX操作系统推荐的一种方式,实际项目也可以不采用这种方法。调试出适合项目需求的才是最好的。

回复 支持 反对

使用道具 举报

该用户从未签到

296

主题

930

帖子

29

蝴蝶豆

金牌会员

最后登录
2020-11-20
 楼主| 发表于 2016-1-22 16:10:33 | 显示全部楼层
8.3    任务优先级设置
    除了创建任务时可以设置任务优先级,也可以通过下面两个函数修改任务优先级:
关于这两个函数的讲解及其使用方法可以看教程第3章3.3小节里面说的参考资料rlarm.chm文件
8.2.png
                              
这里重点的说一下函数os_tsk_prio。
函数原型:
  1. OS_RESULT os_tsk_prio (
  2.     OS_TID task_id,       /* 任务ID */
  3.     U8     new_prio );    /* 新的任务优先级 (1-254) */
复制代码

函数描述:
函数os_tsk_prio用于修改任务的优先级。
  (1)第1个参数填任务的ID。如果ID参数是0,那么设置就是当前任务的优先级。
(2)第2个参数修改任务的优先级,如果new_prio的数值比当前执行任务的优先级大,将触发一次任务切换,切换到任务ID为task_id的任务中。如果new_pro的数值比当前执行任务的优先级小,当前任务会继续执行。
(3)如果任务优先级修改成功,函数返回OS_R_OK,其余所有情况返回OS_R_NOK,比如所写的任务ID不存在或者任务还没有启动。

使用这个函数要注意以下几个问题
1.     参数new_prio的范围是1-254。
2.     被修改任务的新优先级会一直保持有效直到用户再次修改。
3.     优先级0用于空闲任务,如果用户将这个参数设置为0的话,RTX系统会将其更改为1。优先级255被保留用于最重要的任务。
4.    对于RTX操作系统来说,优先级参数中数值越小优先级越低,也就是说空闲任务的优先级是最低的,因为它的优先级数值是0
使用举例:
  1. /*
  2. **********************************************************************************************************
  3.                                                     变量
  4. **********************************************************************************************************
  5. */
  6. static uint64_t AppTaskUserIFStk[512/8];  /* 任务栈 */

  7. /* 任务句柄 */
  8. OS_TID HandleTaskUserIF = NULL;
  9. /*
  10. *********************************************************************************************************
  11. *    函 数 名: AppTaskChangePrio
  12. *    功能说明: 修改任务优先级
  13. *    形    参: 无
  14. *    返 回 值: 无
  15. *********************************************************************************************************
  16. */
  17. static void AppTaskDelete (void)
  18. {
  19.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  20.                                            1,                         /* 任务优先级 */
  21.                                            &AppTaskUserIFStk,         /* 任务栈 */
  22.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */

  23.      if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
  24.      {
  25.          printf("任务AppTaskLED优先级修改成功\r\n");
  26.      }
  27.      else
  28.      {
  29.          printf("任务AppTaskLED优先级修改失败\r\n");                    
  30.      }
  31.    
  32. }
复制代码


回复 支持 反对

使用道具 举报

该用户从未签到

296

主题

930

帖子

29

蝴蝶豆

金牌会员

最后登录
2020-11-20
 楼主| 发表于 2016-1-22 16:38:03 | 显示全部楼层
8.4  实验例程说明

8.4.1     STM32F103开发板实验
配套例子:
    V4-403_RTX实验_任务优先级修改
实验目的:
    1. 学习RTX的任务优先级修改。
实验内容:
    1. K1按键按下,串口打印。
    2. K2按键按下,将任务AppTaskLED的优先级由2修改为3。
    3. k3按键按下,将任务AppTaskLED的优先级由3修改为2。
    4. 各个任务实现的功能如下:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
      AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
8.3.png
                              
Task Configuration
(1)Number of concurrent running tasks
    允许创建4个任务,实际创建了如下四个任务
                    AppTaskUserIF任务   :按键消息处理。
                    AppTaskLED任务     :LED闪烁。
                    AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
(2)Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:
8.4.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
      将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
8.5.png
RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码

RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码

四个RTX任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskUserIF
  4. *    功能说明: 按键消息处理     
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. __task void AppTaskUserIF(void)
  11. {
  12.      uint8_t ucKeyCode;

  13.     while(1)
  14.     {
  15.          ucKeyCode = bsp_GetKey();
  16.         
  17.          if (ucKeyCode != KEY_NONE)
  18.          {
  19.               switch (ucKeyCode)
  20.               {
  21.                    /* K1键按下,打印调试说明 */
  22.                    case KEY_DOWN_K1:
  23.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
  24.                        break;
  25.                   
  26.                    /* K2键按下,修改任务AppTaskLED优先级 */
  27.                    case KEY_DOWN_K2:
  28.                        printf("K2键按下,将任务AppTaskLED的优先级由2修改为3\r\n");
  29.                        if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
  30.                        {
  31.                             printf("任务AppTaskLED优先级修改成功\r\n");
  32.                        }
  33.                        else
  34.                        {
  35.                             printf("任务AppTaskLED优先级修改失败\r\n");                    
  36.                        }
  37.                        break;  

  38.                   /* K3键按下,修改任务AppTaskLED优先级 */
  39.                    case KEY_DOWN_K3:
  40.                        printf("K3键按下,将任务AppTaskLED的优先级由3修改为2\r\n");
  41.                        if(os_tsk_prio(HandleTaskLED, 2) == OS_R_OK)
  42.                        {
  43.                             printf("任务AppTaskLED优先级修改成功\r\n");
  44.                        }
  45.                        else
  46.                        {
  47.                             printf("任务AppTaskLED优先级修改失败\r\n");                    
  48.                        }
  49.                        break;                          
  50.                   
  51.                   
  52.                    /* 其他的键值不处理 */
  53.                    default:                    
  54.                        break;
  55.               }
  56.          }
  57.         
  58.          os_dly_wait(20);
  59.      }
  60. }

  61. /*
  62. *********************************************************************************************************
  63. *    函 数 名: AppTaskLED
  64. *    功能说明: LED闪烁
  65. *    形    参: 无
  66. *    返 回 值: 无
  67. *   优 先 级: 2
  68. *********************************************************************************************************
  69. */
  70. __task void AppTaskLED(void)
  71. {
  72.     while(1)
  73.     {
  74.          bsp_LedToggle(2);
  75.          bsp_LedToggle(3);
  76.         os_dly_wait(200);
  77.     }
  78. }

  79. /*
  80. *********************************************************************************************************
  81. *    函 数 名: AppTaskMsgPro
  82. *    功能说明: 信息处理,这里是用作LED闪烁   
  83. *    形    参: 无
  84. *    返 回 值: 无
  85. *   优 先 级: 3
  86. *********************************************************************************************************
  87. */
  88. __task void AppTaskMsgPro(void)
  89. {
  90.     while(1)
  91.     {
  92.          bsp_LedToggle(1);
  93.          bsp_LedToggle(4);
  94.         os_dly_wait(300);
  95.     }
  96. }

  97. /*
  98. *********************************************************************************************************
  99. *    函 数 名: AppTaskStart
  100. *    功能说明: 启动任务,也就是最高优先级任务。
  101. *    形    参: 无
  102. *    返 回 值: 无
  103. *   优 先 级: 4
  104. *********************************************************************************************************
  105. */
  106. __task void AppTaskStart(void)
  107. {
  108.      AppTaskCreate();
  109.    
  110.     while(1)
  111.     {
  112.          /* 按键扫描 */
  113.          bsp_KeyScan();
  114.         os_dly_wait(10);
  115.     }
  116. }
复制代码


8.4.2     STM32F407开发板实验
配套例子:
    V5-403_RTX实验_任务优先级修改
实验目的:
    1. 学习RTX的任务优先级修改。
实验内容:
    1. K1按键按下,串口打印。
    2. K2按键按下,将任务AppTaskLED的优先级由2修改为3。
    3. k3按键按下,将任务AppTaskLED的优先级由3修改为2。
    4. 各个任务实现的功能如下:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
      AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
8.6.png
Task Configuration
(1)Number of concurrent running tasks
     允许创建4个任务,实际创建了如下四个任务
                     AppTaskUserIF任务   :按键消息处理。
                     AppTaskLED任务     :LED闪烁。
                     AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                     AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
(2)Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:
8.7.png
程序设计:
任务栈大小分配:
     staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
      将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
8.8.png
RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码

RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码




回复 支持 反对

使用道具 举报

该用户从未签到

296

主题

930

帖子

29

蝴蝶豆

金牌会员

最后登录
2020-11-20
 楼主| 发表于 2016-1-22 16:38:34 | 显示全部楼层
续8.4.2

四个RTX任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. * 函 数 名: AppTaskUserIF
  4. * 功能说明: 按键消息处理
  5. * 形 参: 无
  6. * 返 回 值: 无
  7. * 优 先 级: 1 (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. __task void AppTaskUserIF(void)
  11. {
  12. uint8_t ucKeyCode;

  13. while(1)
  14. {
  15. ucKeyCode = bsp_GetKey();

  16. if (ucKeyCode != KEY_NONE)
  17. {
  18. switch (ucKeyCode)
  19. {
  20. /* K1键按下,打印调试说明 */
  21. case KEY_DOWN_K1:
  22. printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
  23. break;

  24. /* K2键按下,修改任务AppTaskLED优先级 */
  25. case KEY_DOWN_K2:
  26. printf("K2键按下,将任务AppTaskLED的优先级由2修改为3\r\n");
  27. if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
  28. {
  29. printf("任务AppTaskLED优先级修改成功\r\n");
  30. }
  31. else
  32. {
  33. printf("任务AppTaskLED优先级修改失败\r\n");
  34. }
  35. break;

  36. /* K3键按下,修改任务AppTaskLED优先级 */
  37. case KEY_DOWN_K3:
  38. printf("K3键按下,将任务AppTaskLED的优先级由3修改为2\r\n");
  39. if(os_tsk_prio(HandleTaskLED, 2) == OS_R_OK)
  40. {
  41. printf("任务AppTaskLED优先级修改成功\r\n");
  42. }
  43. else
  44. {
  45. printf("任务AppTaskLED优先级修改失败\r\n");
  46. }
  47. break;


  48. /* 其他的键值不处理 */
  49. default:
  50. break;
  51. }
  52. }

  53. os_dly_wait(20);
  54. }
  55. }

  56. /*
  57. *********************************************************************************************************
  58. * 函 数 名: AppTaskLED
  59. * 功能说明: LED闪烁
  60. * 形 参: 无
  61. * 返 回 值: 无
  62. * 优 先 级: 2
  63. *********************************************************************************************************
  64. */
  65. __task void AppTaskLED(void)
  66. {
  67. while(1)
  68. {
  69. bsp_LedToggle(2);
  70. bsp_LedToggle(3);
  71. os_dly_wait(200);
  72. }
  73. }

  74. /*
  75. *********************************************************************************************************
  76. * 函 数 名: AppTaskMsgPro
  77. * 功能说明: 信息处理,这里是用作LED闪烁
  78. * 形 参: 无
  79. * 返 回 值: 无
  80. * 优 先 级: 3
  81. *********************************************************************************************************
  82. */
  83. __task void AppTaskMsgPro(void)
  84. {
  85. while(1)
  86. {
  87. bsp_LedToggle(1);
  88. bsp_LedToggle(4);
  89. os_dly_wait(300);
  90. }
  91. }

  92. /*
  93. *********************************************************************************************************
  94. * 函 数 名: AppTaskStart
  95. * 功能说明: 启动任务,也就是最高优先级任务。
  96. * 形 参: 无
  97. * 返 回 值: 无
  98. * 优 先 级: 4
  99. *********************************************************************************************************
  100. */
  101. __task void AppTaskStart(void)
  102. {
  103. AppTaskCreate();

  104. while(1)
  105. {
  106. /* 按键扫描 */
  107. bsp_KeyScan();
  108. os_dly_wait(10);
  109. }
  110. }
复制代码

回复 支持 反对

使用道具 举报

该用户从未签到

296

主题

930

帖子

29

蝴蝶豆

金牌会员

最后登录
2020-11-20
 楼主| 发表于 2016-1-22 16:39:21 | 显示全部楼层
8.5  总结
    本章节内容相对比较容易,重点是学习任务优先级分配方案,随着后面的学习,初学者需要慢慢积累这方面的经验。

回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

20

帖子

0

蝴蝶豆

新手上路

最后登录
2016-1-23
发表于 2016-1-23 13:51:31 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-5-5 07:59 , Processed in 1.167063 second(s), 38 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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