tag 标签: ucos

相关博文
  • 热度 24
    2013-10-16 15:04
    1761 次阅读|
    4 个评论
        很多新入群的网友,都在问一个问题,msOS跟uC/OS有什么区别,觉得有uC/OS就已经足够了啊,为什么还要msOS呢?       其实大家都忘了一件事情,当嵌入式人员熟悉嵌入式之后,往往有一个来自内心的呼唤:“ 我要搭建属于自己的平台系统,为将来开发产品定下统一的框架 ”,但往往因为工作的紧张、生活的压力,最后都没有腾出时间来实现自己当初的想法。今天群内“破浪前行”再一次的提到,让我想起当年写“实用单片机系统”的时候,记录里面就有类似这样的话,本书前言里面也有这样的话,只是随着msOS的发展而遗忘了。这是最原始的内心需求,msOS存在最好的理由: Myself OS 。       我们需要的是一个开发平台,并不是RTOS,我们之所以把RTOS当作我们的需求,是因为之前嵌入式行业还没有一个真正的为中小嵌入式行业提供通用的开发平台,大家只有借助RTOS建立自己的开发平台,花大量精力学会RTOS,之后再在这个RTOS上添加按键、串口、屏幕、等必要的设备,通过消息、信号量等整合成为一个为自己所用的开发平台。       这么做,对于一个高手,或许没什么问题,但对于绝大部分只有一定基础的嵌入式群体来说,这么一个复杂的平台是搭建不好的,甚至可以说能否把复杂的uC/OS用好都值得怀疑,还谈什么平台,谈什么可靠性,最后往往与初衷相悖而失败。此外,就算是自己把平台建起来了,一个公司十个人,十个平台,大家代码如何统一又是一个大问题。       msOS是我内心的呼唤,也是我实际的需求,经过与公司内多位具有大型软件经验的同事思维碰撞之后,借助当前比较领先的一些理念,尤其是C#中一些理念引入到嵌入式中建立初步模型,再在QQ群中与大家一起讨论修改而成现在这个版本,可以说msOS是我们大家的嵌入式开发平台,它来源于大家,服务于大家。
  • 热度 13
    2013-2-20 20:23
    1773 次阅读|
    0 个评论
      /*-------------------------------------------------------------------------------------------------------------------------*/ 堆管理   而这里的内存管理,实质是预先分配固定大小的内存, 使用时只能使用相应大小的内存。 因为在裸机上做内存管理,固定分配的要优于动态分配。(应该说是,uCOS使用固定分配来模拟动态分配) 因为一般使用uCOS的地方,内存都不多,这时固定分配反而是更优的选择。 (对于内存受限系统(memory constrainted system)的嵌入式编程,这种方式应该说是最合适的方式了)   /*-------------------------------------------------------------------------------------------------------------------------*/ 栈管理   那么在uCOS中一个任务操作超过了其堆栈设置会有什么样的后果呢? 从uCOS中os_tcb 结构体中发现默认的只有一个栈顶指针,这里的栈顶指针是如何使用的。   OSCtxSw(uCOS_II_V2.86/uC_Port/os_cpu_a.asm)这个函数,是由汇编语言写成的,为了触发pendsv中断引起切换。   `~uCOS_II_V2.86/ |     |+Core/ |     |+uC_CPU/ |     |+uC_LIB/ |     |~uC_Port/ |     | |+ini/ |     | `~src/ |     |   |-os_cpu_a.asm |     |   |-os_cpu_c.c |     |   `-os_dbg.c |     `+uCOS-II/   这里边在第一次切换时,使用的是最高优先级的代码。 对于栈空间的使用,方法如下: 首先由Task_Create函数设置好栈顶指针, 在任务切换时,将这个栈顶指针(而这里的这个栈顶指针既是在创建任务时,传入的一个数组的首地址,拿来当做栈使用)传递给sp,实现sp的切换。   当任务切换时, 除了保存所有寄存器意外, 最重要的就是要   在OSStartHighRdy函数中,将OSRunning置位TRUE,表示系统开始执行。   问题是,这个修改的栈指针,是什么时候修改的? 在切换时,sp保存在当前任务的OS_TCB结构体中,此时sp和OSTCBCur-OSTCBStkPtr指向的是任务堆栈的都一个内存位置。 里边有第一次切换的判断。第一次切换时,不保存堆栈,如果是以后切换需要保存堆栈。   这里确实没有关于栈溢出的操作,因为如果栈溢出,将覆盖其他任务的栈内容,修改备份的寄存器内容。 会造成其他任务运行异常,这样就会引起错误。 (栈空间的大小至少要能保存,芯片体系结构要求保存的所有寄存器内容)   //STM32F103CBT6任务切换代码 Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing ;              context switches with Cortex-M3.  This is because the Cortex-M3 auto-saves half of the ;              processor context on any exception, and restores same on return from exception.  So only ;              saving of R4-R11 is required and fixing up the stack pointers.  Using the PendSV exception ;              this way means that context saving and restoring is identical whether it is initiated from ;              a thread or occurs due to an interrupt or exception. ; ;           2) Pseudo-code is: ;              a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch); ;              b) Save remaining regs r4-r11 on process stack; ;              c) Save the process SP in its TCB, OSTCBCur-OSTCBStkPtr = SP; ;              d) Call OSTaskSwHook(); ;              e) Get current high priority, OSPrioCur = OSPrioHighRdy; ;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; ;              g) Get new process SP from TCB, SP = OSTCBHighRdy-OSTCBStkPtr; ;              h) Restore R4-R11 from new process stack; ;              i) Perform exception return which will restore remaining context. ; ;           3) On entry into PendSV handler: ;              a) The following have been saved on the process stack (by processor): ;                 xPSR, PC, LR, R12, R0-R3 ;              b) Processor mode is switched to Handler mode (from Thread mode) ;              c) Stack is Main stack (switched from Process stack) ;              d) OSTCBCur      points to the OS_TCB of the task to suspend ;                 OSTCBHighRdy  points to the OS_TCB of the task to resume ; ;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we ;              know that it will only be run when no other exception or interrupt is active, and ;              therefore safe to assume that context being switched out was using the process stack (PSP). OS_CPU_PendSVHandler     CPSID   I                                                   ; Prevent interruption during context switch     MRS     R0, PSP                                             ; PSP is process stack pointer     CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time     SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack     STM     R0, {R4-R11}     LDR     R1, =OSTCBCur                                       ; OSTCBCur-OSTCBStkPtr = SP;     LDR     R1,     STR     R0,                                             ; R0 is SP of process being switched out                                                                 ; At this point, entire context of process has been saved OS_CPU_PendSVHandler_nosave     PUSH    {R14}                                               ; Save LR exc_return value     LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();     BLX     R0     POP     {R14}     LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;     LDR     R1, =OSPrioHighRdy     LDRB    R2,     STRB    R2,     LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;     LDR     R1, =OSTCBHighRdy     LDR     R2,     STR     R2,     LDR     R0,                                             ; R0 is new process SP; SP = OSTCBHighRdy-OSTCBStkPtr;     LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack     ADDS    R0, R0, #0x20     MSR     PSP, R0                                             ; Load PSP with new process SP     ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack     CPSIE   I     BX      LR                                                  ; Exception return will restore remaining context     END   关于切换的具体实现, 到这里感觉清楚很多。
  • 热度 16
    2013-2-20 20:15
    1138 次阅读|
    0 个评论
      uCos中的时钟节拍可以基于软中断实现或者基于时钟节拍任务(但是这个任务要给予很高的优先级) 对于STM32(Cortex-M3)来说这个就是SysTick中断0x0000003C 当中断发生时调用OS_CPU_SysTickHandler函数, 这样就提供了系统的时钟节拍   uCos中扩展的应用都是在HOOK函数中实现的, 程序关于Time的调用, 首先都是基于OSTime的,   其次由于在OSTimeTick函数中预留了OSTimeTickHook()函数 这样可以方便我们在OSTimeTickHook()函数中添加我们自己的代码实现在系统中的调用 由于OSTimeTickHook()函数在OSTimeTick函数中, 所以每次Tick时都会调用这个函数,所以也就给了我们可以添加每次时钟Tick都被系统 调用的机会。 由于OSTimeTickHook()函数中预留了App_TimeTickHook()函数提供给应用层的程序实现相应的扩充, 这样就可以在应用层APP中,扩展一些我们想要的功能,例如Ctimer函数。 同时函数指针的应用更大程度的扩展了,我们可以扩展函数的功能的范围。   在系统启动多任务后 的第一个任务TaskStart中(即调用过OSStart()函数后)调用OS_CPU_SysTickInit()完成对系统Tick的设定。 在设置Tick的时候,是由OS_CPU_SysTickClkFreq函数来获得硬件的时钟频率 通过除以OS_TICKS_PER_SEC得到一个定时中断时间,以后每隔一定的时间中断一次。   追踪的过程 App_TimeTickHook()(app.c)--OSTimeTickHook()(os_cpu_c.c)--OSTimeTick()(cpu_core.c) \ --OS_CPU_SysTickHandler()(os_cpu_c.c)--DCD  OS_CPU_SysTickHandler(vectors.s)   在追寻代码路径的过程中, 沿着最容易看到的代码追踪到它的上一级代码, 直到它的最底层实现, 这样就可以把与这个相关的系统上的东西都可以了解了。   参考: 《嵌入式实时操作系统uC/OS-2》
  • 热度 14
    2013-2-20 20:09
    1188 次阅读|
    0 个评论
      首先在main函数中调用OSTaskCreate的理解。 OSTCBPrioTbl    OSTaskStkInit() 设置堆栈 OS_TCBInit()TCB任务控制块初始化 OS_Sched()任务调度   在OS_Sched中,OS_SchedNew()函数负责找到新的最高优先级的 任务,并赋值给OSPrioHighRdy      OSTCBHighRdy = OSTCBPrioTbl ; 这行语句中的三个全局变量都是实现任务切换的优先级判断的关键。 OS_TASK_SW()宏定义,因为C不能操作寄存器,所以对于任务的切换是由这个宏定义,定义的汇编代码实现。 这个宏定义展开是汇编代码。   这些由uS/OC的书中的第三章都可以更详细的获得。   OS_ENTER_CRITICAL();  OS_EXIT_CRITICAL(); uC/OS中用来实现,开关中断的一组宏定义。当调用功能函数时,必须关闭中断。   uC/OS中的互斥操作是由信号灯机制来实现的,  OSSemCreate函数创建信号灯。 OSMutexCreate   uC/OS中的任务间通信机制 分为邮箱和队列。  OSMboxCreate()创建一个邮箱 OSQCreate()创建一个队列。   他们传递的都是一个指针,队列可以看做是一组邮箱构成的数组,只不过他们是由相同的任务控制。 这里的指针可以是一个变量的地址,也可以是一个结构体变量的地址。 因为指针的存在,实现了不同任务间,大量数据的传输。   OSStart()函数开启us/os中真正多任务的开始。 没有返回。  OS_SchedNew();找到最高优先级, OSStartHighRdy();通过汇编代码,跳转到需要的地方执行,此时系统才开始真正运行起来。   uC/OS的任务切换是通过汇编代码实现的, 这里边使用的是 中断切换。 所有的切换代码是在 os_cpu_a.asm中, 依靠系统的时钟中断, 触发任务切换,实现当前任务的寄存器入栈及下一个将要运行任务的寄存器出栈, 完成切换。
  • 热度 56
    2013-1-17 15:54
    5329 次阅读|
    32 个评论
    对很多只具有MCU51,Cortex基础的网友来说,学习RTOS是一件痛苦的事情,以uCOS为例,博主以前看过2遍,虽然有些概念,但因为涉及内容较多,理解不深,加上没做项目,过段时间就忘记了。这次为了做msPLC系统:一种网络化PLC,需要解决网络通讯,特意引入RTOS实现任务分离,所以把目前资料最为广泛的uCOS与博主自己设计的“实用单片机系统MS5”结合起来,uCOS具备RTOS的多任务,并且资料丰富,MS5博主自己开发的,最为熟悉,并且在单任务下代码简洁,功能齐全,尤其是对时间分割管理、消息机制、界面设计上,都有一定的模式,所以可以理解为基于MS5下,把单任务变成多任务处理,比较完美的结合。 uCOS可以认为是比较标准的一种RTOS,就RTOS来说,它不算复杂,但对于绝大部分只有单任务设计经验的嵌入式人员,已经足够复杂,主要有几点原因: 1、刚接触RTOS思想,对很多名词,功能、变量都不熟悉,这些一多就混淆了 2、文件结构、头文件定义复杂,条件编译、函数指针、结构体过多 3、外围函数过多,任务核心不突出   基于以上三点,本人以普通嵌入式人员的思维,做以下几点精简: 1、去掉一般项目不常用的函数,比如信号量事件(SEM)、开关量事件(MUX)、标记事件(FLAG)、内存管理(MEM),只保留消息邮箱(MBox)和消息队列(MQ)。 2、精简头文件,按常规写法修改,去掉不必要的条件编译 3、去掉统计任务(StatTask)和空闲任务(IdleTask),系统内部精简掉相关的变量,加入MS5,作为它的IdleTask,设置为最低优先级。 4、加入MBox和MQ例子,让其可以在Keil的Debug的UART1窗口下直接调试模拟。   初学者基于精简版本的uCOS,对照书本,学起来应该更容易,起码不会有强烈的排斥心里,在理解了uCOS内核后,再看完整的源码,就非常容易。   msOS今后将基于MS5为基础,引入其他免费公开的RTOS的一些优点,比如FreeRTOS和RT-Thread,形成自己的风格,避免版权,主要超工业自动化方向进化,专注于工业自动化领域。   附件中uCOS.rar为精简后的uCOSII msOS为基于MS5结合精简后的uCOS的msOS  
相关资源