博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ucos ii 杂记
阅读量:4112 次
发布时间:2019-05-25

本文共 4051 字,大约阅读时间需要 13 分钟。

ucos ii在stm32上使用的时候一些杂记,给自己。

1.   中断嵌套时,在中断服务函数中

OS_CPU_SR  cpu_sr;

  OS_ENTER_CRITICAL();  //保存全局中断标志,关总中断 Tell uC/OS-II that we are starting an ISR
  OSIntNesting++;
  OS_EXIT_CRITICAL();  //恢复全局中断标志

......

最后加上 OSIntExit();           //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换(必须加上,因为ucosii并不一定回到之前被中断的任务现场)

2. 空闲任务OSTaskIdle永远被设为最低优先级,即os_LOWEST_PRIO,而系统任务的优先级为次低,负责统计当前CPU的利用率。

3.ucos ii一共可以支持64个任务,用户可以使用的是56个。 

4.在main()函数里调用多任务OSStart()之前必须已经创建了至少一个任务,因此习惯上,在调用OSStart()之前先创建一个任务,比如命名为App_TaskStart,并赋予它最高的优先级,使其成为启始任务,然后在这个任务中建立其他的任务。

   PS: 在调用OSStart之前,不要开启全局中断,否则系统就会崩溃。

                2   在调用OSStart之前,不要启动时钟节拍器

                3  在启示任务中App_TaskStart()中来启动时钟节拍器。

int main(void) 

{
   CPU_INT08U os_err; 
   /* 禁止所有中断 */
   CPU_IntDis();
   
   /* ucosII 初始化 */
   OSInit();                                                  
   /* 硬件平台初始化 */
   BSP_Init();                                          
   
  //建立主任务, 优先级最高  建立这个任务另外一个用途是为了以后使用统计任务
  os_err = OSTaskCreate((void (*) (void *)) App_TaskStart,                  //指向任务代码的指针
                          (void *) 0, //任务开始执行时,传递给任务的参数的指针
                    (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],//分配给任务的堆栈的栈顶指针   从顶向下递减
                         (INT8U) APP_TASK_START_PRIO);//分配给任务的优先级
             
   OSTimeSet(0); //ucosII的节拍计数器清0    节拍计数器是0-4294967295  
   OSStart();                //启动ucosII内核   
   return (0);
}

5  mian()函数只是负责创建任务,但是并不负责调用

6

7 任务调度器:一个是任务级调度器OS_Sched(),一个是中断级调度器OSIntEXT();

  1. //任务调度  
  2. //uCOS-II总是运行进入就绪态任务中优先级最高的那一个。确定哪个任务优先级最高,下面该哪个任务运行了的工作是  
  3. //由调度器(Scheduler)完成的。任务级的调度是由函数OSSched()完成的。中断级的调度是由另一个函数OSIntExt()完  
  4. //成的Scheduling。  
  5. //注意:1) 这是一个uCOS-II内部函数,你不能在应用程序中使用它  
  6. //     2) 给调度器上锁用于禁止任务调度(查看OSSchedLock()函数)  
  7. //说明:1)任务切换很简单,由以下两步完成,将被挂起任务的微处理器寄存器推入堆栈,然后将较高优先  
  8. //       级的任务的寄存器值从栈中恢复到寄存器中。在uCOS-II中,就绪任务的堆栈结构总是看起来  
  9. //       跟刚刚发生过中断一样,所有微处理器的寄存器都保存在栈中。换句话说,uCOS-II运行就绪态  
  10. //       的任务所要做的一切,只是恢复所有的CPU寄存器并运行中断返回指令。为了做任务切换,运行  
  11. //       OS_TASK_SW(),人为模仿了一次中断。多数微处理器有软中断指令或者陷阱指令TRAP来实现上  
  12. //       述操作。中断服务子程序或陷阱处理(Trap hardler),也称作事故处理(exception handler),  
  13. //       必须提供中断向量给汇编语言函数OSCtxSw()。OSCtxSw()除了需要OS_TCBHighRdy指向即将被  
  14. //       挂起的任务,还需要让当前任务控制块OSTCBCur指向即将被挂起的任务,移植uCOS-II,有关于  
  15. //       OSCtxSw()的更详尽的解释。  
  16. //     2)OS_Sched()的所有代码都属临界段代码。在寻找进入就绪态的优先级最高的任务过程中,为防止中  
  17. //       断服务子程序把一个或几个任务的就绪位置位,中断是被关掉的。为缩短切换时间,OSSched()全部  
  18. //       代码都可以用汇编语言写。为增加可读性,可移植性和将汇编语言代码最少化,OSSched()是用C写的。  
  19.   
  20. //任务调度函数  
  21. void  OS_Sched (void)  
  22. {  
  23. #if OS_CRITICAL_METHOD == 3                            //中断函数被设定为模式3  
  24.     OS_CPU_SR  cpu_sr;  
  25. #endif      
  26.     INT8U      y;                                      //定义一个8位整数y  
  27.   
  28.   
  29.     OS_ENTER_CRITICAL();                               //关闭中断  
  30.     //如果中断嵌套次数>0,且上锁(调度器)嵌套次数>0,函数退出,不做任何调度  
  31.     if ((OSIntNesting == 0) && (OSLockNesting == 0)) {   
  32.         //如果函数不是在中断服务子程序中调用的,且调度允许的,则任务调度函数将找出进入就绪态的  
  33.         //最高优先级任务,进入就绪态的任务在就绪表中OSRdyTbl[]中相应位置位。  
  34.         y             = OSUnMapTbl[OSRdyGrp];          /* Get pointer to HPT ready to run              */  
  35.         OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);  
  36.         //找到最高优先级任务后,函数检查这个优先级最高的任务是否是当前正在运行的任务,以避免不  
  37.         //必要的任务调度,多花时间  
  38.         if (OSPrioHighRdy != OSPrioCur) {              /* No Ctx Sw if current task is highest rdy     */  
  39.             //为实现任务切换,OSTCBHighRdy必须指向优先级最高的那个任务控制块OS_TCB,这是通过将  
  40.             //以OSPrioHighRdy为下标的OSTCBPrioTbl[]数组中的那个元素赋给OSTCBHighRdy来实现的  
  41.             OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];  
  42.             OSCtxSwCtr++;                              //统计计数器OSCtxSwCtr加1,以跟踪任务切换次数  
  43.             OS_TASK_SW();                              //最后宏调用OS_TASK_SW()来完成实际上的任务切换  
  44.         }  
  45.     }  
  46.     OS_EXIT_CRITICAL();                                //打开中断  
  47. }  
8  ucos ii在stm32中的系统时钟由systick提供。比如产生1ms一次的系统时钟节拍中断,在 os_cfg.h中

#define OS_TICKS_PER_SEC       1000    /* Set the number of ticks in one second                        */

void  OS_CPU_SysTickInit(void)

{
    RCC_ClocksTypeDef  rcc_clocks;
    INT32U         cnts;
    RCC_GetClocksFreq(&rcc_clocks);                        //获得系统时钟的值
    cnts = (INT32U)rcc_clocks.HCLK_Frequency/OS_TICKS_PER_SEC;//算出时钟节拍的值
   SysTick_Config(cnts); //设置时钟节拍
}

cnts=HCLK_Frequency/OS_TICKS_PER_SEC=72M/1000;

void SysTickHandler(void)

{
   OS_CPU_SR  cpu_sr;  
    OS_ENTER_CRITICAL();  //保存全局中断标志,关总中断/* Tell uC/OS-II that we are starting an ISR*/
    OSIntNesting++;  //是为了中断嵌套
    OS_EXIT_CRITICAL();  //恢复全局中断标志 
    OSTimeTick();     /* 在os_core.c文件里定义,目的是每次时钟节拍到来,μC/OS-II 都将执行OSTimeTick()函数。OSTimeTick()检查处于延时状态的任务是否达到延时时间(用OSTimeDly()或OSTimeDlyHMSM()函数延时),或检查正在等待事件的任务是否超时,如果延时时间到,则在延时函数中进行一次任务调度*/                                                                                                                                                                                                                                                                                                                              
    OSIntExit();  //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换     
}
9.ucos ii中引起任务调度的函数 :

OSStart(); //系统启动

OSTaskSuspend() //任务挂起

OSTaskResume()//任务恢复、

OSTimeDly()/OSTimeDlyHMSM()//延时

等待事件发生(OSSempend(),OSMutexPend(),OSflagPend(),OSMboxPend(),OSQPend())

10   任务优先级

OSRdyGrp与OSRdyTbl类似于一个二维数组,可大概表达为prio[OSRdyGrp][OSRdyTbl]

要知道哪个任务就绪,只要知道OSRdyGrp,OSRdyTbl的值,然后从表中找出就可以了

验证:例如优先级为22的任务,转为二进制为00 010 110 ,转为x=2,y=6,查表得为22。

 

未完待续

转载地址:http://pursi.baihongyu.com/

你可能感兴趣的文章
【增强学习在无人驾驶中的应用】
查看>>
OpenCV meanshift目标跟踪总结
查看>>
就在昨天,全球 42 亿 IPv4 地址宣告耗尽!
查看>>
听说玩这些游戏能提升编程能力?
查看>>
如果你还不了解 RTC,那我强烈建议你看看这个!
查看>>
沙雕程序员在无聊的时候,都搞出了哪些好玩的小玩意...
查看>>
Mysql复制表以及复制数据库
查看>>
Kafka
查看>>
9.1 为我们的角色划分权限
查看>>
维吉尼亚之加解密及破解
查看>>
TCP/IP协议三次握手与四次握手流程解析
查看>>
PHP 扩展开发 : 编写一个hello world !
查看>>
inet_ntoa、 inet_aton、inet_addr
查看>>
用模板写单链表
查看>>
链表各类操作详解
查看>>
C++实现 简单 单链表
查看>>
Linux的SOCKET编程 简单演示
查看>>
Linux并发服务器编程之多线程并发服务器
查看>>
C语言内存检测
查看>>
Linux epoll模型
查看>>