你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【安富莱STM32F407之uCOS-III教程】第11章 μCOS-III内核函数分析

[复制链接]
baiyongbin2009 发布时间:2014-12-24 19:55
阅读主题, 点击返回1楼
收藏 评论23 发布时间:2014-12-24 19:55
23个回答
baiyongbin2009 回答时间:2014-12-25 17:07:16
巅峰残狼 发表于 2014-12-24 21:04
很好很强大,支持更新

谢谢支持!!
baiyongbin2009 回答时间:2014-12-25 17:12:01
11.11  Round-Robin调度
    μCOS-III中的时间片调度功能做的很完善,支持全局的时间片设置,也支持每个任务的单独设置。关于时间片调度,咱们在前几期教程也有讲解。
11.11.1      配置参数OSSchedRoundRobinCfg()
  1. /*
  2. ***********************************************************************************************************
  3. *                                      配置ROUND-ROBIN调度参数
  4. *
  5. * 函数功能: 调用此函数用更改ROUND-ROBIN调度的参数。
  6. * 形    参: en                DEF_EN:使能ROUND-ROBIN
  7. *                             DEF_DIS:禁止ROUND-ROBIN
  8. *           dflt_time_quanta  默认的时间片数,如果是0 那么就表示时间片是默认的OSCfg_TickRate_Hz / 10.
  9. *           p_err             错误代码指针变量
  10. *                             OS_ERR_NONE       调用成功
  11. * 返 回 值: 无
  12. ***********************************************************************************************************
  13. */

  14. #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
  15. void  OSSchedRoundRobinCfg (CPU_BOOLEAN   en,
  16.                             OS_TICK       dflt_time_quanta,
  17.                             OS_ERR       *p_err)
  18. {
  19.     CPU_SR_ALLOC();


  20. #ifdef OS_SAFETY_CRITICAL
  21.     if (p_err == (OS_ERR *)0) {
  22.         OS_SAFETY_CRITICAL_EXCEPTION();
  23.         return;
  24.     }
  25. #endif

  26.     CPU_CRITICAL_ENTER();                                                                        (1)
  27.     if (en != DEF_ENABLED) {                                                                     (2)
  28.         OSSchedRoundRobinEn = DEF_DISABLED;
  29.     } else {
  30.         OSSchedRoundRobinEn = DEF_ENABLED;
  31.     }

  32.     if (dflt_time_quanta > (OS_TICK)0) {                                                         (3)
  33.         OSSchedRoundRobinDfltTimeQuanta = dflt_time_quanta;
  34.     } else {
  35.         OSSchedRoundRobinDfltTimeQuanta = (OS_TICK)(OSCfg_TickRate_Hz / (OS_RATE_HZ)10);
  36.     }
  37.     CPU_CRITICAL_EXIT();
  38.    *p_err = OS_ERR_NONE;
  39. }
  40. #endif
复制代码
1.    由于这几个参数是全局变量,所以必须关闭中断。
2.    根据形参设置是否使能时间片调度。
3.    变量OSSchedRoundRobinDfltTimeQuanta是用来设置默认的时间片个数,也就是说,如果程序中没有单独配置任务的时间片个数,就会使用这个默认时间片个数。

11.11.2      放弃剩余时间片OSSchedRoundRobinYield ()
    这个函数的主要功能就是任务在完成工作的情况下,如果还有剩余的时间片,可以放弃这些时间去执行另外的同优先级任务(切记,是另外的同优先级任务)
  1. /*
  2. ***********************************************************************************************************
  3. *                                    当任务不再需要剩余时间片时放弃CPU使用权
  4. *
  5. * 功能说明: 当任务的时间片还没用完的时候,可以通过此函数放弃剩余时间片,也就是放弃CPU使用权。
  6. * 形    参: p_err  错误代码指针变量
  7. *                  OS_ERR_NONE                   函数调用成功
  8. *                  OS_ERR_ROUND_ROBIN_1          此优先级下只有这一个任务,能够放弃CPU权
  9. *                  OS_ERR_ROUND_ROBIN_DISABLED   Round Robin调度没有使能
  10. *                  OS_ERR_SCHED_LOCKED           调度器被锁
  11. *                  OS_ERR_YIELD_ISR              不能在中断服务程序中调用此函数
  12. * 返 回 值: 无
  13. * 注    意: 1) 此函数必须在任务中调用
  14. ***********************************************************************************************************
  15. */

  16. #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
  17. void  OSSchedRoundRobinYield (OS_ERR  *p_err)
  18. {
  19.     OS_RDY_LIST  *p_rdy_list;
  20.     OS_TCB       *p_tcb;
  21.     CPU_SR_ALLOC();



  22. #ifdef OS_SAFETY_CRITICAL
  23.     if (p_err == (OS_ERR *)0) {
  24.         OS_SAFETY_CRITICAL_EXCEPTION();
  25.         return;
  26.     }
  27. #endif

  28. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  29.     if (OSIntNestingCtr > (OS_NESTING_CTR)0) {      /* 不能在ISR中调用此函数 */
  30.        *p_err = OS_ERR_YIELD_ISR;
  31.         return;
  32.     }
  33. #endif

  34.     if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) {  /* 调度器被锁不能执行此函数  */
  35.        *p_err = OS_ERR_SCHED_LOCKED;
  36.         return;
  37.     }

  38.     if (OSSchedRoundRobinEn != DEF_TRUE) {            /* 确认round-robin已经使能 */
  39.        *p_err = OS_ERR_ROUND_ROBIN_DISABLED;
  40.         return;
  41.     }

  42.     CPU_CRITICAL_ENTER();
  43.     p_rdy_list = &OSRdyList[OSPrioCur];                /* 此优先级下仅有这一个任务  */               (1)
  44.     if (p_rdy_list->NbrEntries < (OS_OBJ_QTY)2) {
  45.         CPU_CRITICAL_EXIT();
  46.        *p_err = OS_ERR_ROUND_ROBIN_1;
  47.         return;
  48.     }

  49.     OS_RdyListMoveHeadToTail(p_rdy_list);               /* 移动当前任务的TCB到列表末  */            (2)
  50.     p_tcb = p_rdy_list->HeadPtr;                        /* 获取列表首端的TCB  */
  51.     if (p_tcb->TimeQuanta == (OS_TICK)0) {              /* 是0,使用默认的时间片数 */                (3)
  52.         p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
  53.     } else {
  54.         p_tcb->TimeQuantaCtr = p_tcb->TimeQuanta;       /* 加载新的时间片数  */
  55.     }

  56.     CPU_CRITICAL_EXIT();

  57.     OSSched();                                          /* 运行调度器  */                             (4)
  58.    *p_err = OS_ERR_NONE;
  59. }
  60. #endif
复制代码
1.    获取此优先级的就绪链表。从而得到此优先级下任务的个数,如果同优先级下只有一个任务,将退出这个函数。
2.    移动同优先级就绪链表中任务的位置,从实现同优先级下任务的切换。
3.    参数p_tcb->TimeQuanta = 0的时候就会使用默认的时间片个数,如果非0,就会给这个任务的时间片计数器赋予相应的时间片个数。
4.    执行任务调度。

baiyongbin2009 回答时间:2014-12-25 17:13:09
(续)11.11  Round-Robin调度

11.11.3       Round-Robin调度算法OS_SchedRoundRobin ()
    当多个任务有相同的优先级时,μCOS-III允许任务在切换到另一个任务前运行特定的时间,也就是大家常说的时间片。这个过程就是Round-Robin调度或者时间片调度。如果任务不需要将所有的时间片用完,可以调用上面讲的函数OSSchedRoundRobinYield (),放弃剩余时间片从而切换到同优先级的另一个任务。μCOS-III支持用户在系统运行过程中使能或者禁止时间片调度,同时也支持全局的时间片设置,也支持每个任务的单独设置。
    为了更好的说明Round-Robin调度算法,下面举一个例子(截图来自官方书籍):Task #1,Task #2,Task #3都运行在优先级 X,任务运行的时间片个数都是4。
11.4.png
1.     一开始是Task #3在运行,运行期间每个嘀嗒定时器中断都会让Task #3的时间片计数减一。
2.     第四次进入嘀嗒定时器中断后,Task #3的4个时间片已经用完。
3.     切换到同优先级就绪链表中下一个任务Task #1。
4.     Task #1开始运行直到时间片用完。
5.     切换到Task #3运行。
6.     Task #3运行一段时间后,调用函数OSSchedRoundRobinYield ()放弃剩余时间片。
7.     切换到Task #1运行。
8.     这里要特别注意:Task #1会运行4个时间片,图片上面画的不是很准确。
    有了上面基础后,在解析一下相关函数。
  1. /*
  2. ***********************************************************************************************************
  3. * 运行ROUND-ROBIN 调度算法
  4. *
  5. * 函数说明: 此函数每个嘀嗒定时器中断被调用,通过此函数来计算同优先级中是否有任务要执行。
  6. * 形 参: p_rdy_list 就绪链表指针
  7. * 返 回 值: 无
  8. * 注 意: 1) 内部函数调用,用户程序不能调用
  9. ***********************************************************************************************************
  10. */

  11. #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
  12. void OS_SchedRoundRobin (OS_RDY_LIST *p_rdy_list)
  13. {
  14. OS_TCB *p_tcb;
  15. CPU_SR_ALLOC();



  16. if (OSSchedRoundRobinEn != DEF_TRUE) { /* 确认round-robin调度已经使能 */ (1)
  17. return;
  18. }

  19. CPU_CRITICAL_ENTER();
  20. p_tcb = p_rdy_list->HeadPtr;

  21. if (p_tcb == (OS_TCB *)0) { (2)
  22. CPU_CRITICAL_EXIT();
  23. return;
  24. }

  25. if (p_tcb == &OSIdleTaskTCB) { (3)
  26. CPU_CRITICAL_EXIT();
  27. return;
  28. }

  29. if (p_tcb->TimeQuantaCtr > (OS_TICK)0) { /* 时间片计数减一 */ (4)
  30. p_tcb->TimeQuantaCtr--;
  31. }

  32. if (p_tcb->TimeQuantaCtr > (OS_TICK)0) { /* 时间片还没有用完 */ (5)
  33. CPU_CRITICAL_EXIT();
  34. return;
  35. }

  36. if (p_rdy_list->NbrEntries < (OS_OBJ_QTY)2) { /* 是否只有一个同优先级任务 */ (6)
  37. CPU_CRITICAL_EXIT(); /* 是的,退出 */
  38. return;
  39. }

  40. if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* 调度器被锁,不能执行round-robin */ (7)
  41. CPU_CRITICAL_EXIT();
  42. return;
  43. }

  44. OS_RdyListMoveHeadToTail(p_rdy_list); /* 将当前的OS_TCB移到就绪链表的末尾 */ (8)
  45. p_tcb = p_rdy_list->HeadPtr; /* 获取修改后的就绪链表头部OS_TCB */
  46. if (p_tcb->TimeQuanta == (OS_TICK)0) { /* 检测是否需要使用默认的时间片 */ (9)
  47. p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
  48. } else {
  49. p_tcb->TimeQuantaCtr = p_tcb->TimeQuanta; /* 加载新的时间片 */
  50. }
  51. CPU_CRITICAL_EXIT();
  52. }
  53. #endif
复制代码
1.     检测Round-Robin调度是否使能。
2.     确保此优先级下存在任务。
3.     这句话的意思是说:不允许用户将应用任务的优先级设置的和空闲任务优先级一样,也就是说空闲任务的优先级下不能有其它任务。
4.     时间片减一。
5.     任务的时间片还没有用完,退出继续执行。
6.     同优先级下必须有两个及其以上的任务才能继续往下执行。
7.     如果调度器被锁,不能执行Round-Robin调度。
8.     通过调整同优先级下的就绪链表获得下一个要执行的任务。
9.     判断使用全局的默认时间片个数还是使用单独设计的时间片个数。

11.11.4       函数使用举例
  1. /*
  2. *********************************************************************************************************
  3. * 函数名: main
  4. * 功能说明: 标准c程序入口。
  5. * 形 参:无
  6. * 返回值: 无
  7. *********************************************************************************************************
  8. */

  9. int main(void)
  10. {
  11. OS_ERR err;

  12. OSInit(&err);

  13. /* 使能并设置全局时间片个数 */
  14. OSSchedRoundRobinCfg(DEF_ENABLED,
  15. 8,
  16. &err);

  17. OSTaskCreate((OS_TCB *)&AppTaskStartTCB,
  18. (CPU_CHAR *)"App Task Start",
  19. (OS_TASK_PTR )AppTaskStart,
  20. (void *)0,
  21. (OS_PRIO )APP_CFG_TASK_START_PRIO,
  22. (CPU_STK *)&AppTaskStartStk[0],
  23. (CPU_STK_SIZE )APP_CFG_TASK_START_STK_SIZE / 10,
  24. (CPU_STK_SIZE )APP_CFG_TASK_START_STK_SIZE,
  25. (OS_MSG_QTY )0,
  26. (OS_TICK )0,
  27. (void *)0,
  28. (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
  29. (OS_ERR *)&err);

  30. OSStart(&err);

  31. return (0);
  32. }


  33. /*
  34. *********************************************************************************************************
  35. * 函 数 名: AppTaskCom
  36. * 功能说明: 此任务未使用
  37. * 形 参:p_arg 是在创建该任务时传递的形参
  38. * 返 回 值: 无
  39. *********************************************************************************************************
  40. */

  41. static void AppTaskCOM(void *p_arg)
  42. {
  43. OS_ERR err;

  44. (void)p_arg;


  45. while(1)
  46. {
  47. ……
  48. OSSchedRoundRobinYield (&err);
  49. ……
  50. }


  51. }
复制代码



baiyongbin2009 回答时间:2014-12-25 17:14:11
11.12  总结
    本期教程涉及到的内容较多,如果是初学的,一定要多花点时间消耗下,如果学习过程中遇到很多问题,不要担心,随着后面教程的进行会理解的更深刻。

caiyuhui74748 回答时间:2015-8-6 16:21:23
辛苦。。。。。。。。。。。学习
yigerenday 回答时间:2015-8-7 08:27:54
赞赞赞;
yanhaijian 回答时间:2015-8-7 08:49:11
工作很细致。
那就地方 回答时间:2015-8-7 08:58:42
楼主费心了,赞一个
党国特派员 回答时间:2015-8-7 09:33:06
很好,学习了。
12
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版