ucosiii_ucosiii临界区 - CSDN
精华内容
参与话题
  • UCOSIII学习笔记

    千次阅读 2018-08-04 15:22:39
     UCOS是Micrium公司出品的RTOS类实时操作系统,UCOS目前有两个版本:UCOSII和UCOSIII。 UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。UCOSIII提供了实时操作系统所需的所有功能,包括资源管理...

    1.概念:

            UCOS是Micrium公司出品的RTOS类实时操作系统,UCOS目前有两个版本:UCOSII和UCOSIII。 UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。UCOSIII提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。

    2.任务管理:

    2.1滴答定时器

         定时器来产生“滴答”中断来作为系统时基,SysTick有4个控制寄存器;

    2.2任务

       在UCOSIII中任务就是程序实体,UCOSIII能够管理和调度这些小任务(程序)。    

       UCOSIII中的任务由三部分组成:任务堆栈、任务控制块和任务函数。    

        任务堆栈:上下文切换的时候用来保存任务的工作环境,就是STM32的内部寄存器值。    

        任务控制块:任务控制块用来记录任务的各个属性。    

       任务函数:由用户编写的任务处理代码,是实实在在干活的。一般写法如下

    void XXX_task(void *p_arg)
       {
           while(1)
           {
            。。。。。//任务处理过程
            }
        }
    

    任务的参数是一个void类型的,这么做的目的是可以可以传递不同类型的数据甚至是函数。任务函数其实就是一个C语言的函数,但是在使用UCOIII的情况下这个函数不能有用户自行调用,任务函数何时执行执行,何时停止完全有操作系统来控制。

    2.3UCOSIII系统任务

    UCOSIII默认有5个系统任务:    

    1、空闲任务:UCOSIII创建的第一个任务,UCOSIII必须创建的任务,此任务有UCOSIII自动创建,不需要用户手动创建。    

    2、时钟节拍任务:此任务也是必须创建的任务。    

    3、统计任务:可选任务,用来统计CPU使用率和各个任务的堆栈使用量。此任务是可选任务,由宏OS_CFG_STAT_TASK_EN控制是否使用此任务。    

    4、定时任务:用来向用户提供定时服务,也是可选任务,由宏OS_CFG_TMR_EN控制是否使用此任务。    

    5、中断服务管理任务:可选任务,由宏OS_CFG_ISR_POST_DEFERRED_EN控制是否使用此任务。

    任务状态:

    从用户的角度看,UCOSIII的任务一共有5种状态:    

    1、休眠态:任务已经在CPU的flash中了,但是还不受UCOSIII管理。    

    2、就绪态:系统为任务分配了任务控制块,并且任务已经在就绪表中登记,这时这个任务就具有了运行的条件,此时任务的状态就是就绪态。    

    3、运行态:任务获得CPU的使用权,正在运行。    

    4、等待态:正在运行的任务需要等待一段时间,或者等待某个事件,这个任务就进入了等待态,此时系统就会把CPU使用权转交给别的任务。    

    5、中断服务态:当发送中断,当前正在运行的任务会被挂起,CPU转而去执行中断服务函数,此时任务的任务状态叫做中断服务态。

    3.UCOSIII任务堆栈

    任务堆栈用来切换任务和调用其他函数时保存现场(现场就是CPU的内部各个寄存器),因此每个任务都应该有自己的堆栈。

    任务堆栈的创建:

    #define START_STK_SIZE 		512	//堆栈大小
    CPU_STK START_TASK_STK[START_STK_SIZE];	//定义一个数组来作为任务堆栈
    

     CPU_STK为CPU_INT32U类型,也就是unsigned int类型,为4字节的,那么任务堆栈START_TASK_STK的大小就为:512 X 4=2048字节!

    UCOSIII任务控制块:

    任务控制块是用来记录与任务相关的信息的数据结构,每个任务都要有自己的任务控制块。任务控制块由用户自行创建,如下代码为创建一个任务控制块:

     OS_TCB StartTaskTCB;  //创建一个任务控制块
    

    OS_TCB为一个结构体,描述了任务控制块,任务控制块中的成员变量用户不能直接访问,更不可能改变他们。

    UCOSIII任务就绪表:存放UCOSIII中已经就绪的任务。

    优先级:    UCOSIII中任务优先级数由宏OS_CFG_PRIO_MAX来配置,UCOSIII中数值越小,优先级越高,最低可用优先级就是OS_CFG_PRIO_MAX-1。

    函数OS_PrioGetHighest()用于找到就绪了的最高优先级的任务;

    OS_PRIO  OS_PrioGetHighest (void)
    {
        CPU_DATA  *p_tbl;
        OS_PRIO    prio;
    
        prio  = (OS_PRIO)0;
        p_tbl = &OSPrioTbl[0];
        while (*p_tbl == (CPU_DATA)0) {
    	prio += DEF_INT_CPU_NBR_BITS; 
    	p_tbl++;
        }
        prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl); 
        return (prio);
    }
    

    就绪表: UCOSIII中就绪表由2部分组成:    

    1、优先级位映射表OSPrioTbl[]:用来记录哪个优先级下有任务就绪。    

    2、就绪任务列表OSRdyList[]:用来记录每一个优先级下所有就绪的任务。

     同一优先级下如果有多个 任务的话最先运行的永远是 HeadPtr所指向的任务!

    先执行1,后来1到最尾端,顺序变为2、3、1,开始执行2; 轮流执行。

    4.

    4.1UCOSIII任务调度:任务调度就是中止当前正在运行的任务转而去执行其他的任务。

    UCOSIII是可剥夺型内核,因此当一个高优先级的任务准备就绪,并且此时发生了任务调度,那么这个高优先级的任务就会获得CPU的使用权!        

    UCOSIII中的任务调度是由任务调度器来完成的,任务调度器有2种:任务级调度器和中断级调度器。    

    任务级调度器为函数OSSched()。    

    中断级调度器为函数OSIntExit(),当退出外部中断服务函数的时候使用中断级任务调度。

    4.2UCOSIII任务切换

    当UCOSIII需要切换到另外一个任务时,它将保存当前任务的现场到当前任务的堆栈中,主要是CPU寄存器值,然后恢复新的现场并且执行新的任务,这个过程就是任务切换。

    任务切换分为两种:任务级切换和中断级切换。

    任务级切换函数为:OSCtxSw()。

    中断级切换函数为:OSIntCtxSw()。

    5.任务相关API函数(应用程序编程接口)

    5.1任务创建和删除:UCOSIII是多任务系统,创建任务就是将任务堆栈、任务控制块、任务函数等联系在一起,并初始化任务控制块相应字段。

    OSTaskCreate()函数创建任务;OSTaskDel()删除任务;

    void  OSTaskDel (OS_TCB  *p_tcb, OS_ERR  *p_err)

    OSTaskDel((OS_TCB*)0,&err),当传递给函数OSTaskDel()的参数p_tcb的值为0时,表示删除掉任务自身

    5.2任务挂起和恢复

            当我们想暂停某个任务,但是又不想删除掉这个任务的时候就可以使用函数OSTaskSuspend()来将这个任务挂起,函数原型如下:void   OSTaskSuspend ( OS_TCB  *p_tcb,//*p_tcb指向需要挂起任务的的OS_TCB

                                                   OS_ERR  *p_err)//指向一个变量,用来保存该函数的错误码

      恢复:     OSTaskResume

    ( OS_TCB  *p_tcb,//*p_tcb指向需要挂起任务的的OS_TCB

                                                   OS_ERR  *p_err)//指向一个变量,用来保存该函数的错误码

    5.3UCOSIII时间片轮转调度

    处于同一优先级的多个任务,采用时间片轮转调度来轮流执行;

    OSSchedRoundRobinCfg()(CPU_BOOLEAN   en,//打开/关闭时间片轮转调度机制,

                                        OS_TICK       dflt_time_quanta, //设置默认时间片长度,n=dflt_time_quanta;n*5ms;若n=0,默认为100ms. 

                                           OS_ERR       *p_err)调用本函数后返回的错误码

     

    OSSchedRoundRobinYield (OS_ERR  *p_err)放弃本次时间片函数

     6.UCOSIII中断和时间管理

    stm32支持中断,中断是一个硬件机制,主要用来通知CPU一个异步事件发生,这样CPU就会将当前CPU寄存器的值存入栈,进而去处理中断服务函数。

    6.1

     OSIntEnter();  OSIntExit();进入和退出中断服务函数。

    OSIntNestingCtr来记录中断嵌套次数,UCOSIII最多支持250级的中断嵌套。退出中断服务函数时要调用函数OSIntExit()。

    6.2UCOSIII临界段代码保护

     临界段代码也叫做临界区,是指那些必须完整连续运行,不可被打断的代码段。当访问这些临界段代码的时候需要对这些临界段代码进行保护。    

    当宏OS_CFG_ISR_POST_DEFERRED_EN为0时,UCOSIII使用关中断的方式来保护临界段代码,当设置为1的时候就会采用给调度器上锁的方式来保护临界段代码。

    UCOSIII定义了一个进入临界段代码的宏:OS_CRITICAL_ENTER(),定义了两个退出临界段代码的宏:OS_CRITICAL_EXIT和OS_CRITICAL_EXIT_NO_SCHED()。

    6.3任务延时

    延时:

    延时函数有两种,OSTimeDly()和OSTimeDlyHMSM()。

    取消:

    延时任务任务可通过在其他任务中调用函数OSTimeDlyResume()取消延时而进入就绪状态,此函数最后会引发一次任务调度。

    获取和设置系统时间:

    UCOSIII定义了一个CPU_INT32U类型的全局变量OSTickCtr来记录系统时钟节拍数,在调用OSInit()时被初始化为0,以后每发生1个时钟节拍,OSTickCtr加1。  

    OSTimeSet()允许用户改变当前时钟节拍计数器的值,慎用!!!!!  

    OSTimeGet()用来获取动迁时钟节拍计数器的值。

    7.UCOSIII软件定时器

           单片机中使用定时器来进行定时任务属于硬件定时。

    模式:单词定时器、无初始延时周期模式、有初始延时周期模式

    8.UCOSIII信号量和互斥信号量

    8.1.UCOSIII信号量

    信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行。

    信号量用于控制对共享资源的保护,但是现在基本用来做任务同步用。

     8.2互斥信号量:

    为了避免优先级反转这个问题,UCOSIII支持一种特殊的二进制信号量:互斥信号量, 用它可以解决优先级反转问题。

    8.3UCOSIII任务内嵌信号量 

    在UCOSIII中每个任务都有自己的内嵌的信号量,这种功能不仅能够简化代码,而且比使用独立的信号量更有效。任务信号量是直接内嵌在UCOSIII中的,任务信号量相关代码在os_task.c中。

    9.UCOSIII消息传递

        信号量用于多个任务同时访问同一公共资源,即任务与资源之间的通道;

        消息用于任务互相之间的通信和交流;任务间的消息传递可以通过2种途径:一是通过全局变量,二是通过发布消息。        

    使用全局变量的时候每 个任务或者中断服务程序都必须保证其对全局变量的独占访问。

        消息包含一下几个部分:指向数据的指针,数据的长度和记录消息发布时刻的 时间戳,指针指向的可以是一块数据区域或者甚至是一个函数。

    消息队列中有一个列表,记录了所有正在等待消息的任务队列;

     

     

     

    展开全文
  • 官方 uCOS-III 源码

    2020-07-30 23:31:59
    由官方 提供的uCOS-III 源码,可在官网下载,嵌入式实时操作系统,
  • uCOS-III学习笔记

    万次阅读 多人点赞 2015-05-04 14:18:51
    前一段时间笔者学习uCOS-III,第一次接触OS这个概念吧。下面把个人的学习笔记分享出来,仅供参考。

    前一段时间笔者学习uCOS-III,第一次接触OS这个概念吧。下面把个人的学习笔记分享出来,仅供参考。


    1、前后台系统:后台程序是一个死循环,也称为“任务级”,前台程序则是中断服务程序,也称为“中断级”;一般的低成本应用多采用这种程序结构。

    2、实时内核:仅为一段软件代码,它把系统功能划分为多个任务,每个任务只完成特定的一个功能,通常都为死循环;CPU在任意时刻只能执行一个任务,但每个任务都认为自己在独自使用整个CPU,由于处理器速度非常快,任务切换的速度也非常快,所以看起来几乎多个任务同时被执行;对多任务的管理就是实时内核所要做的工作,实现CPU资源的最大化利用。

    3、uC/OS-III是一个可剥夺型内核(抢占式内核,Preemptive Kernel),它总是执行当前就绪任务中优先级最高的那个;uC/OS-III被设计用于32位处理器;uC/OS-III至少需要4KB RAM资源的微控制器上运行

    4、uC/OS-III的特性:

    • l   同优先级任务的时间片轮转调度
    • l   任务数目不受限制
    • l   优先级数目不受限制
    • l   内核对象数目不受限制
    • l   可嵌套的任务挂起(suspension),嵌套挂起深度最大可达250层
    • l   直接向任务发送信号
    • l   直接向任务发送消息
    • l   任务级时钟节拍处理

    5、临界段代码:不可被打断的代码(在运行这些代码时,需要关闭中断,运行完后再开启)。有两种方式保护临界段代码:1、关中断;2、调度器上锁。两种方法均可以测得中断关闭时间

    6、任务的类型有两种:运行至完成型无限循环型(大多数嵌入式系统采用这种);任务与C函数不同,任务不允许返回;在创建一个任务时,必须为任务分配一个任务控制块(OS_TCB);每一个任务都要有属于自己的栈(类型为CPU_STK);每一个任务都必须调用一个可以引发任务“等待某事件”的函数,比如一段延迟结束(OSTimeDly()或OSTimeDlyHMSM()),在等待一个事件时,它不会占用CPU时间,这是与前后台系统不同的地方;任务的三个重要参数:任务控制模块TCB、优先级、栈空间(存放局部变量、函数调用返回地址、ISR嵌套。如果出现一些很奇怪的结果,首先怀疑占空间是否给小了);每个任务都有自己独立的CPU寄存器

    7、uC/OS-III 允许任务停止自身或者停止另外的任务。停止一个任务意味着这个任务将不再执行直到被其他的任务恢复。停止可以被嵌套到250级。换句话说,一个任务可以停止另外的任务多达250次。当然,这个任务必须被恢复同等次数才有资格再次获得 CPU。

    8、OSInit()会创建2~5个任务,其中空闲任务(OS_IdleTask())和时钟节拍任务(OS_TickTask())是必须要创建的2个任务,其他的统计任务(OS_StatTask())、定时任务(OS_TmrTask())和中断处理队列管理任务(OS_IntQTask())由#define使能;main函数必须在调用其他任务uC/OS-III函数之前调用OSInit()

    • l  空闲任务(OS_IdleTask(),os_core.c)

    【必须创建】uC/OS-III创建的第一个任务,优先级总是OS_CFG_PRIO_MAX-1(最低优先级)

    真正的无限循环,即不会调用任务会使其进入等待状态的服务函数

    • l  时钟节拍任务(OS_TickTask(),os_tick.c)

    【必须创建】该任务的优先级应当只比用户的系统中最重要的任务的优先级略低一点[注:P77]

    时钟节拍列表=数据表(OSCfg_TickWheel[])+计数器(OSTickCtr),数据表的表项数目OS_CFG_TICK_WHEEL_SIZE一般设置为任务数的1/4左右,且最好为素数;每当时钟节拍任务接收到时钟节拍ISR发送的信号量时,OSTickCtr自动+1

    每次节拍中断发生时,只有其中一个表项上的任务可能延迟结束

    • l  统计任务(OS_StatTask(),os_stat.c)

    总CPU利用率、各任务的CPU利用率和各任务的堆栈使用量

    在main()函数创建的第一个也是唯一一个应用任务中调用OSStatTaskCPUUsageInit(),这个应用任务应该分配一个很高的优先级(0除外);uC/OS-III允许用户在调用OSStart()之前创建任意数目的任务,然而,要使用统计任务时,只能创建一个任务,在该任务中调用OSStatTaskCPUUsageInit()。

    • l  定时任务(OS_TmrTask(),os_tmr.c)

    一个递减的计数器,减为0时,可以启动一个用户自定义的回调函数(Callback Funcion),避免在回调函数中使用阻塞调用(OSTimeDly()、OSTimeDlyHMSM()、OS???Pend()),回调函数的执行实在定时器任务内完成的;与时钟节拍任务使用相同的中断源

    优先级一般为中等优先级

    • l  中断处理队列管理任务(OS_IntQTask(),os_int.c)

    相当于在ISR和任务中插入了一脚,负责“延迟”(deferring)在ISR中调用的系统post服务函数的行为[注:P86]

    优先级永远为最高的0,系统保留优先级

    9、通过OSTaskCreate()函数创建一个任务,该任务有13个参数

    10、任务的优先级:数值越小,优先级越高,其范围为1~(OS_CFG_PRIO_MAX-2);0和OS_CFG_PRIO_MAX-1为两个保留的优先级

    11、多任务系统管理函数OSStart()一般为main函数的最后一步,注意:uC/OS-III会首先运行在调用OSStart()之前已经创建的优先级最高的任务,并且可以创建任务数量的任务,但是建议只创建一个任务[注:P33]

    12、任务状态:从用户角度来看,任务的状态只有5种:休眠态、就绪态、运行态、等待态中断服务态;在uC/OS-III内部,状态则有8种:延迟、就绪、带超时检测的等待、等待、延迟被挂起、被挂起、带超时检测的等待且被挂起等待且被挂起


    13、任务被删除OSTaskDel(),代表任务进入休眠态,使得该代码无法获得CPU的使用权

    14、一个任务可以创建其它任务(OSTaskCreate())、停止或者恢复其它(OSTaskSuspned()和OSTaskResume())、提交信号量到其它任务、发送消息到其它任务、提供共享资源等。换句话说,任务不是只被限制于“等待事件”。

    15、就绪表=就绪优先级位映射表OSPrioTbl[](标明哪个优先级下有任务就绪)+就绪任务列表OSRdyList[](包含指向就绪任务的指针)

    16、拥有“计算前导零”(CLZ, Count Leading Zeros)的处理器可以加速查找最高优先级任务的过程

    17、uC/OS-III有两种不同方法处理中断服务程序发布的事件:直接发布(direct post)和延迟发布(deferred post),其最终的结果都是高优先级的任务获得了CPU控制权,但是延迟发布多了一个中断处理任务,ISR发布消息后由ISR hander task接管,而非“直接发布”中的直接跳转到高优先级的任务中(这样做是为了避免使用关中断的方法来保护临界段代码);直接发布,uC/OS-III必须关闭中断以保护临界段代码,防止中断处理程序访问这些临界段代码;延迟发布,uC/OS-III通过给任务调度器上锁的方式来保护临界段代码

    18、时间片轮转调度:当两个或更多的任务拥有相同的优先级时,uC/OS-III允许一个任务运行一段指定的时间,然后轮到下一个任务;如果一个任务不需要执行完时间片,则主动放弃CPU的控制权让下一个任务运行,称为“礼让”(yielding)

    19、任务调度通过两个函数来执行:OSSched()(任务级代码使用)和OSIntExit()(中断服务程序结束时使用);OSSched()的任务切换部分的工作由OSCtxSw()完成,OSIntExit()中任务的切换工作由OSIntCtxSw()完成

    20、时钟节拍通常频率设置为10~1000Hz,过高的频率会增加系统的额外开销

    21、当一个任务等待信号量、互斥型信号量、事件标志组消息队列时,该任务就被放入任务挂起表(pend lists)或等待表中(wait lists)

    22、常见时间服务用户程序:

    OSTimeDly()                  任务延时n个时钟节拍;三种模式(相对模式、周期模式、绝对模式,推荐使用周期模式以获得长时间运行的周期性延迟,比如周期扫描键盘,周期采集某传感器的值,绝对模式一般用于上电后指定的时间执行具体动作,比如上电10s后关闭某盏灯)

    OSTimeDlyHMSM()       任务延时指定的时间,采用“时:分:秒:毫秒”方式;延迟精度极大取决与时钟节拍频率,如果频率设定为1000Hz,那么延时的精度为1ms

    OSTimeDlyResume()       恢复被延迟的任务;谨慎使用,因为它无法分辨是延时结束还是被恢复

    OSTimeGet()                  获取当前时钟节拍计数器的值

    OSTimeSet()                   设置时钟节拍计数器的值

    OSTimeTick()                 触发一次时钟节拍任务;每次时钟节拍中断到来时,中断服务程序必须调用该函数

    23、uC/OS-III中定时器的时间分辨率由定时器任务频率来配置(OS_CFG_TMR_TASK_RATE_HZ),若定时器任务频率为10Hz,那么所有定时器的时间分辨率为1/10s;定时器的运行模式有三种:单次定时器、周期定时器(无初始延迟)、周期定时器(有初始延迟)

    24、最常用的独占共享资源和创建临界区的方法:

    • l  关中断                                         不推荐,会增加系统中断延迟;而这种方法也是任务中断服务程序享变量的唯一方法
    • l  禁止任务调度                             不推荐,有悖于可剥夺型内核的设计初衷,因为该任务即为最高优先级任务
    • l  使用信号量                                 速度比互斥型信号量稍快一些,但是会遇到优先级反转问题
    • l  使用互斥型信号量(mutex)  比信号量稍慢,但是解决了优先级反转问题

    25、信号量就像一种上锁机制,必须获得对应的钥匙才能执行代码;信号量通常分为两种:二进制信号量计数型信号量在共享资源时,只有任务才能使用信号量,中断服务程序则不能使用,当用信号量发送信号时,则没有限制;信号量一般用于访问I/O设备

    26、在使用信号量之前必须先创建信号量

    27、无界优先级反转问题:低优先级的任务正在访问某共享资源,此时高优先级的任务进行内核剥夺,抢走CPU使用权,但是高优先级也要访问该共享资源,因此调度器再次转回低优先级任务等待其释放信号量,如果此时有中优先级的任务插入,那么调度器会直接进入该任务,忽略高优先级的任务。导致的结果就是高优先级反转。解决办法:互斥型信号量(mutex),原理为将使用共享资源的低优先级的任务提升至与高优先级任务一样,此时调度器再次返回低优先级任务,等待其执行完毕释放信号量后回到高优先级处继续执行,中优先级则不会插入。因此,低优先级的任务访问共享资源的速度越快越好

    28、如果没有任务对共享资源的访问有截止时间,那么普通信号量就可以替代互斥型信号量

    29、死锁(deadlock)也称为抱死(deadly embrace),指两个任务无限制的等待对方控制的资源。解决办法:

    • l  先得到全部资源,再进行下一步操作
    • l  用相同的顺序申请多个资源
    • l  在调用请求信号量的函数时设定超过时间

    30、uC/OS-III中有两种基本的同步机制:信号量事件标志(第三种为任务信号量)

    31、任务或者ISR可以使用信号量同步任务,这种同步操作叫做单向同步;当多个任务等待同一个信号量时,可以在发布信号时指定OS_OPT_POST_ALL开启“广播”功能;任务或者ISR也可以使用任务信号量同步任务,这种方法比较常用,在uC/OS-III中,每个任务都有自己的内嵌信号量;事件标志给与了任务同步更多的同步选择和方法,在事件标志组(OS_FLAG_GRP)中可以用“与AND”“或OR”产生更多的不同事件(flag)组合,注意:事件标志组必须在启动uC/OS-III之前创建

    32、如果任务或者ISR需要给单个任务发信号,则使用任务信号量更为恰当,因为此时不需要再声明一个外部信号量对象,而且任务信号服务函数的执行速度比信号服务函数的执行速度要快

    33、消息传递:任务或者中断服务程序需要交流信息,这种交流有两种途径:

    • l  全局变量

    如果一个资源有中断服务程序的参与,唯一保证对共享变量独占访问的方法就是关中断

    如果只是两个任务共享数据:关中断、给调度器上锁、使用信号量或者使用互斥型信号量(推荐)

    注意:任务想要与中断服务通讯,只能通过全局变量

    • l  发布消息

    34、消息队列的相关函数,中断服务程序只能调用OSQPost();消息队列的读取一般采用先进先出(FIFO),有时候也会使用后进先出(LIFO)的方式;消息的获取可以设置按照优先级或者广播

    35、更为广泛使用的消息队列一般为任务内建的消息队列(更高效,不用创建外部消息队列,如同信号量与任务信号量的关系)。

    36、同事件标志组,消息队列也要求在启动uC/OS-III之前创建

    37、发送的消息通常是一个指针,这些数据必须保持不变,直到接收者完成相应的数据处理

    38、移植uC/OS-III需要修改的文件:

    • l  uC/CPU:cpu.h(数据类型与字长)、cpu_c.c(中断控制器)、cpu_a.asm(开、关中断,CLZ指令)

     

    39、 


    展开全文
  • uCOS-III

    千次阅读 2018-05-28 00:44:56
    uC/OS-III 学习笔记(一)uC/OS-III移植前言 最近毕设要做一个嵌入式设备,需要用到操作系统。本人只会制板和写ARM裸机程序,OS方面是一个小白,只对uC/OS和Linux两种系统略有了解。鉴于嵌入式Linux学习周期较长,...

    uC/OS-III 学习笔记(一)

    uC/OS-III移植


    前言

      最近毕设要做一个嵌入式设备,需要用到操作系统。本人只会制板和写ARM裸机程序,OS方面是一个小白,只对uC/OS和Linux两种系统略有了解。鉴于嵌入式Linux学习周期较长,有可能在毕设结束之前都不能学到能够开发项目的地步。故选择uC/OS作为设备的操作系统。
      之所以选择uC/OS-III,是本着“要学就学最新”的想法来的。uC/OS-III相比II,加入了时间片轮转功能,能够允许定义相同优先级的任务。其好处balabalabala…好吧,我没仔细学过II,说不出来。估计以后就可以填这个大坑了。
      至于FreeRTOS等操作系统的比较——算了吧,我一个OS都不会用,没什么可比性,写出来也没人信。
      
    废话到此为止,下面开始正文


    uC/OS-III 的移植

      首先讲讲我的开发环境:STM32F103RET6 + KEIL5 + ST 3.5.0 库

    • STM32F103RET6:是Cortex-M3内核的芯片,有PendSV和Systick中断供操作系统使用。
    • Keil5:用来管理工程,当然也可以用IAR,个人感觉Keil5漂亮一点。
    • ST 3.5.0 库:之所以使用ST 3.5.0 的库,而不是现在流行的HAL库,主要原因是目前国内的比较完善的教程主要是针对ST 3.5.0库来写的,一点有个什么bug还可以有个参考。不过之后当我对uC有了较深入的认识后,肯定会想办法移植到HAL库上。

        移植比较简单,具体步骤如下:
        


    1#下载源码

    上Micrium官网下载源码https://www.micrium.com/(未墙,慢的可以上4G)
    下载源码
    用F107的做F103的移植没毛病。F103的只有uC/OS-II的工程。

    下载源码需要注册,然而Micrium的官网经常出问题。如果无法注册也没有关系,可以从这里下载(度盘)。


    2#找一个好的教程

    网上随便搜搜都能找到如何移植的。这里我参考的是野火团队的《uCOS-III 应用开发指南——基于 STM32F103系列》,该书及配套文档在STM32&STM8社区技术论坛上就有这里。注册个账号即可下载。(什么?你懒得注册?那么这里好了)

    该书讲解的比较全面,不仅讲解了如何移植,还通过阅读源码的方式,讲解了uC/OS-III的各个机制,且每一部分都有相应的例程帮助读者巩固理解。但不是很通俗易懂,且关于Cortex-M3的一些内核机制,包括PendSV、Systick、双堆栈等没有进行说明,也没有对操作系统做一个入门级的解说。这对于从来没有接触过OS的小伙伴可能有点困难。

    这里建议初学者先仔细看一下这两篇文档:《初探uCOS-II》、《uCOS-II 移植与深入实战指南》,照着做一遍,先大致了解一下uCOS-II的工作原理。其中第二本书要求读者阅读一下《CM3权威指南》。这里我都有。

    (uCOS-II那本书用的工程文件跟uCOS-III的不一样,其实也只是BSP的接口函数不一样啦,改一改就行。当然不放心的同学可以下这个uCOS-II对应的工程)

    除了野火的书外,还有一本叫《STM32F4 UCOS开发手册V2.1》的书,书里的内容是是针对STM32F4系列,是战舰系列的配套教程(有一本F1的,但实际内容是F4的)。这本书讲的就比较通俗易懂,里面从uC/OS-II、讲到M3/M4内核机制,再讲到uC/OS-III的内容,图文并茂,讲的比较生动。个人建议手头已经有STM32F407开发板的同学,可以直接按照此教程来学习。但如果各位和我一样只有F103板子的话,还是看野火的书吧,这本书完全可以当个参考,毕竟没必要花那个冤枉钱。

    本人也是按照野火的书一步步学的,从这里开始就写一下我对该书的理解好了,因为书已经讲得很细了嘛


    3#移植

    移植就按照教程一步步来就好了。个人认为最重要的是修改SysTick和PendSV的中断处理函数入口名称。该向量定义在启动文件stm32f10x_hd.s中,共两处:

    DCD     PendSV_Handler             ; PendSV Handler
    DCD     SysTick_Handler            ; SysTick Handler
    • 1
    • 2
    PendSV_Handler  PROC
                    EXPORT  PendSV_Handler             [WEAK]
                    B       .
                    ENDP
    SysTick_Handler PROC
                    EXPORT  SysTick_Handler            [WEAK]
                    B       .
                    ENDP
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    uC/OS给的官方例程中,这两个中断函数入口名称分别为:OS_CPU_PendSVHandler和OS_CPU_SysTickHandler,跟Keil给出的启动文件不一样。这里需要修改启动文件中这两处名称,让其能够与uC的源码正确的连接起来。

    之所以特地把这里拎出来,是因为这两个中断至关重要。至于为什么重要,去好好看看这张图吧:
    Cortex-M3上下文切换
    这张图的讲解在《uCOS-II 移植与深入实战指南》和《CM3权威指南》中,请务必把这张图搞清楚,不然真是学的一脸阿库娅。


    展开全文
  • ucos II与ucos III的区别

    万次阅读 2018-05-23 21:56:21
    邵贝贝:嵌入式操作系统μC/OS-III作者:邵贝贝 来源:嵌入式系统联谊会 邵老师长期从事单片机和嵌入式系统教学和应用工作,并负责清华大学飞思卡尔实验室工作。邵老师与大家分享了μC/OS的发展经历,即将发布的μC/...

    邵贝贝:嵌入式操作系统μC/OS-III
    作者:邵贝贝 来源:嵌入式系统联谊会

           邵老师长期从事单片机和嵌入式系统教学和应用工作,并负责清华大学飞思卡尔实验室工作。邵老师与大家分享了μC/OS的发展经历,即将发布的μC/OS-III的细节,以及他对未来嵌入式操作系统的认识。

    以下是文字实录。

           大家好,我讲讲μC/OS-III,原来是μC/OS-II,现在到了μC/OS-III。今年第一期《电子产品世界》里有一篇调查,有627份中国嵌入式系统工程师的调查问卷,显示出现在用的最多的38%使用Linux,排在第二个就是μC/OS-II占到34%,其中μC/OS-II还是专门为嵌入式设计的实时操作系统,说明μC/OS-II从前几年进到中国以来,是有影响力的操作系统,据我了解,在美国好像还没有这么多的影响。影响力比较大的是中国和印度这样大的发展中国家,也包括日本和韩国。我们可以看到几乎能想到的CPU,在网上都可以下载到、移植的范例,这还不是全部,很多像Altera软核里面都有μC/OS的移植。

           最早μC/OS是一本书,是93年出的,95年我到意大利国际物理中心准备做instructor,开一个叫做《嵌入式实时系统在物理学应用》的一个讲习班,讲习班大部分是印度人、中国人等,讲课老师大部分从欧洲核研究中心和美国大学来的,其中就拿了这个东西作为教材。它最早是为摩托罗拉68HC11增强型单片机写的,管理四个任务,用查表的办法来确定优先级。90%以上的代码是自己写的,和硬件无关,相关的代码不到200行,书上提供了一个可以在PC上跑的一个8088范例,可裁剪可固化,其实μC/OS这本书是个很好的教材,只有261页,其中有100页是源代码,解释了150页。后来这本书,96年以后,在我们实验室,给研究生用的较多,一直没找到哪个出版社愿意买它的版权。

    到了2000年的时候,再想回到μC/OS的时候,已经不太可能,μC/OS-II出来了,后来第二年,电力出版社买了版权,我们就翻译了一下,到了第三本书,μC/OS-II这本书,这个就有了差不多600页,而且把源码附在光盘上,就被美国航空航天管理局认可的可以上直升飞机的一个操作系统,是一个很好用的操作系统,对于学校教学来说,这个功能很强,又很复杂。在教学上不如老版本了。这是第三本书的中译文,2003年出的。我们看它的发展,在μC/OS一开始,书上有个μC/OS的故事,讲到他写的这个东西,当时发表文章都没人理他,后来放到网上,下载的人很多,慢慢得到认可,所以最早1.08的版本,是放在网上,是不要版权的。到了1.10版本以后,被认可了,如果想要拿去牟利的话,就要给他一些回报。但作为教学研究,不谋利的时候,还是可以使用的。μC/OS也好,μC/OS-II也好,它是基于优先级的,用查表的算法去管理64个任务,只能取0~63这64个优先级。今年3月,已经有μC/OS-III发布可以使用了。

           那么从μC/OS-II到μC/OS-III有哪些不同的地方呢?增加了什么,我们看改动还是很大的。一个是原来只有0~63个优先级,而且优先级不能重复,现在允许几个任务使用同一个优先级,在同一个优先级里面,支持时间片调度法;第二个是允许用户在程序运行中动态配置实时操作系统内核资源,比如,任务、任务栈、信号量、事件标志组、消息队列、消息数、互斥型信号量、存储块划分和定时器,可以在程序运行中变更。这样,用户可以避免在程序编译过程中出现资源不够分配的问题。在资源复用上,也做了一些改进。μC/OS-II中,最多任务数有64个,到了版本2.82以后是256个,μC/OS-III中,用户可以由任意多的任务、任意多的信号量、互斥型信号量、事件标志、消息列表、定时器和任意分配的存储块容量,仅受限于用户CPU可以使用的RAM量。这个也是一个很大的扩展。(问:邵老师,它的这个数是启动时就固定的,还是启动后随便定?)它是配置的时候可以自由定义的,只有你的RAM足够大的话。第四点是增加了很多功能,功能总是越来越多的,大伙可以看一下的。原来这些功能在μC/OS-II里面是没有的。  

           下面一点:除每个任务的最长关中断时间,内在性能测试允许用户测得系统的最长关中断时间。就是它提供了一些工具可以测量每个任务关中断的时间;用户在测得每个任务的最长禁止调度时间基础上,可以测得系统禁止任务调度的最长时间,也是说做了个测量;每次发出的信息都带有时间戳,用户也容易得到任务级的响应时间;性能测试还包括任务切换次数计数器和每个任务的CPU使用率等,这个在调试的时候,还是蛮有用的。第六,μC/OS-III设计成能方便地按照CPU架构优化,特别是其数据类型可按照CPU能适应的最佳位数宽度修改(8-16-32);选择和确定优先级的算法可以用汇编语言写,以发挥一些有特殊指令的CPU的优势,有很多CPU有置位和复位指令,计数器计到零,还有就是找出第一个不为零位指令等。第七条,有很多数需要自行处理的内部据结构和变量,是通过给调度器上锁的方式保护这些临界段代码的,不使用关中断的方式,内核关中断的时钟周期几乎为零,这就保证了μC/OS-III能够响应哪些最快的中断等。第八,μC/OS-III还支持内核觉察式调试,用户友好地使内置内核觉察调试器检查、显示μC/OS-III的变量、数据结构、支持μC/Probe工具在程序运行过程中动态显示修改各种变量。从这些改动上来看,μC/OS-III还是比以前做了很大的优化的,和以前的产品有很多的区别。

           我觉得从小内核μC/OS-II到μC/OS-III,已经有17年过去了,很多性能在往大的比较出名的操作系统,像VxWorks、Wind River上靠拢,何小庆告诉我Wind River最近被Intel收购了,看了Wind River的基本情况,应该说VxWorks是公认的最好的嵌入式RTOS,是一个完整的自成体系的软件包,但是在过去很多年,它曾经是一个靠BSP支持的黑盒子,用户可以不关心这些源码,它是这样一种思路。近年来也在公开源码。

           看到消息说,Wind River打算进一步转向Linux用于ARM和PowerPC,Intel为支持多核设计,打算发展软件,如嵌入式应用、Linux。多核应用是为了INTEL的重点。面前μC/OS-II的商业模式还是主要靠出书,让学生学习使用,现在它的团队有10人左右,比较小。我们知道如果一个软件没人维护,也是没有生命力的,它仅仅维护一个内核,在第三方有很多单位和它合作,做很多其他的事情,像人机界面、文件系统、TCP/IP等等,从网站上我们看到,大部分都是第三方合作开发的,我看第三方的报价也都不便宜,都在6000美元以上,当然有很多自由软件也在和它在结合。用户根据自己需要可以去组合。商业模式这些事情,其实我并不是很懂,我教书就想用老的,教书挺好的,所以商业模式这一块我也是瞎说,呵呵。  

           思考和体会,经过17年,从1个小内核发展成为1个可以和大的商业RTOS媲美的专门用于嵌入式系统的成熟的RTOS体系,一个特点就是开放源代码,让很多工程师,从学习,到认识,到使用。作为一个软件,一个内核,就需要维护,需要团队,它的团队现在很小,大概有10人;需要第三方的支持,靠这样的形式来组织起来的;也需要和它发展相适应的商业模式;也会是对VxWorks等大公司产品的一种冲击。我就总结了这么几条。关于μC/OS的实时性问题,其实有一个函数就是delay这个函数,如果有64个任务的话,就有64个需要delay的计数器,每次时间中断的时候,都要来查这张表,一个一个地把它去delay,任务多的时候,时间就长,任务少的时候,时间就少,这是μC/OS唯一达不到硬实时的地方,。在这个地方上,还不能说实时性还是硬实时,除非你把时间定义为这个表上的时间,解决办法呢?这是我们最近做的一些工作,就是用双核16位的freescale的HC12S这样一个单片机,它有一个协处理器是专门来响应中断的,把定时这个功能放到协处理器来做,一个是定时器timer可以很短,从10毫秒可以到微秒级,可以到50微秒,我们做了一个测试,就是把时钟节拍放到33微秒或者62微秒这样来处理的话,如果不加协处理器的话,时钟节拍就占到53%,那就没法用了。如果用协处理器做这些事,协处理器处理这些事大概在75微秒,这样就把硬实时用双内核就实现了,所以双内核对这个还是很有好处的。

           我就介绍到这,最后是Jean Labrosse他们两口子4月7号到中国玩,到我们实验室看看,照片是Labrosse和他夫人,其他是我们实验室青年教师和学生。我就说到这,谢谢!

    展开全文
  • 1、UCOSIII前后台操作系统介绍

    千次阅读 2019-06-15 14:18:55
    一、前后台系统介绍 通常把程序分为两部分:前台系统和后台系统。 简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这...
  • ucosIII 消息传递

    千次阅读 2015-12-30 13:21:18
    导读: 一共分为三部分:>第一部分:任务调度,讲述了任务级和中断级的任务调度和调度点>第二部分:任务切换>第三部分:系统初始化部分。重点在于第三部分代码讲解 任务间通信一个任务或者中断服务程序有时候需要...
  • STM32---ucosii和ucosiii

    千次阅读 2018-11-23 17:11:39
    一、关于ucos 几个 UCOSII 相关的概念需要大家了解一下。任务优先级,任务堆栈,任务控制块,任务就绪表和任务调度器。 任务优先级,这个概念比较好理解, ucos 中,每个任务都有唯一的一个优先级。优先级是任务的...
  • UcosIII基本介绍

    万次阅读 2016-11-01 16:18:48
    UcosII基本介绍 1.1 UCOSII特点 A:源代码开发 B:微内核 C:内核与应用软件没有区分 (共享同一个地址空间,一个映像,一个main()入口函数) D:易移植 基本结构图如下: 1.2 UCOSII源代码...
  • UCOSIIIUCOSIII的信号量

    千次阅读 2019-02-05 18:00:08
    信号量 信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次...
  • UCOSIIIUCOSIII的中断和时间管理

    千次阅读 2019-02-05 18:02:03
    UCOSIII的中断管理 UCOSIII中断处理过程 在STM32中是支持中断的,中断是一个硬件机制,主要用来向CPU通知一个异步事件发生了,这时CPU就会将当前CPU寄存器值入栈,然后转而执行中断服务程序,在CPU执行中断服务...
  • UCOSIIIUCOSIII软件定时器

    千次阅读 2019-02-05 18:01:30
    在学习STM32的时候会使用定时器来做很多定时任务,这个定时器是单片机自带的,也就是硬件定时器,在UCOSIII中提供了软件定时器,我们可以使用这些软件定时器完成一些功能,本文我们就讲解一下UCOSIII软件定时器。...
  • UCOSIIIUCOSIII的消息传递

    千次阅读 2019-02-05 17:53:12
    UCOSIII任务间通信 一个任务或者中断服务程序有时候需要和另一个任务交流信息,这个就是消息传递的过程就叫做任务间通信,任务间的消息传递可以通过两种途径:一是通过全局变量,二是通过发布消息。 使用全局变量...
  • UCOSIIIUCOSIII的存储管理

    千次阅读 2019-02-05 17:46:15
    UCOSIII内存管理简介 作为一个RTOS操作系统,内存管理是必备的功能,因此UCOSIII也就内存管理能力。通常应用程序可以调用ANSI C编译器的malloc()和free()函数来动态的分配和释放内存,但是在嵌入式事实操作系统中...
  • UCOSIIIUCOSIII系统内部任务

    千次阅读 2019-02-05 18:03:12
    之前讲到UCOSIII默认有5个系统任务: 空闲任务:UCOSIII创建的第一个任务,UCOSIII必须创建的任务,此任务有UCOSIII自动创建,不需要用户手动创建; 时钟节拍任务:此任务也是必须创建的任务; 统计任务:可选...
  • UCOSIIIUCOSIII的任务调度和切换

    万次阅读 2019-02-05 18:06:26
    UCOSIII任务调度 可剥夺型任务调度 任务调度就是中止当前正在运行的任务转而去执行其他的任务。 UCOSIII是可剥夺型内核,因此当一个高优先级的任务准备就绪,并且此时发生了任务调度,那么这个高优先级的任务就会...
  • UCOSIIIUCOSIII的事件标志组

    千次阅读 2019-02-05 17:50:55
    UCOSIII事件标志组 前面讲述了UCOSIII的信号量、互斥信号量,它们都可以完成任务的同步。但是有时候一个任务可能需要和多个事件同步,这个时候就需要使用事件标志组。事件标志组与任务之间有两种同步机制: “或”...
  • UCOSIIIUCOSIII的初始化和启动

    千次阅读 2019-02-05 18:05:21
    在使用UCOSIII之前我们必须先初始化UCOSIII,函数OSInit()用来完成UCOSIII的初始化,而且OSInit()必须先于其他UCOSIII函数调用,包括OSStart()。 一般UCOSIII的main函数遵循以下的格式编写: int main(void) { ...
  • 前后台系统和RTOS系统 前后台系统 早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。...
  • UCOSIIIUCOSIII的互斥信号量

    千次阅读 2019-02-05 17:57:45
    信号量用于控制对共享资源的保护,但是现在基本用来做任务同步用(不太清楚的可以参考链接:【UCOSIIIUCOSIII的信号量)。   优先级反转 优先级反转在可剥夺内核中是非常常见的,在实时系统中不允许出现这种...
1 2 3 4 5 ... 20
收藏数 3,128
精华内容 1,251
关键字:

ucosiii