uc/os 笔记(转)

1.uC/OS-II中使用互斥信号对象应该注意

互斥信号对象(Mutual Exclusion Semaphore)简称Mutex,是uC/OS-II的内核对象之一,用于管理那些需要独占访问的资源,并使其适应多任务环境。

创建每一个Mutex,都需要指定一个空闲的优先级号,这个优先级号的优先级必须比所有可能使用此Mutex的任务的优先级都高!

uC/OS-II的Mutex实现原理大致如下:
    当一个低优先级的任务A申请并得到了Mutex,于是它获得资源访问权。如果此后有一个高优先级的任务B开始运行(此时任务A已经被剥夺),而且也要求得到Mutex,系统就会把任务A的优先级提高到Mutex所指定的优先级。由于此优先级高于任何可能使用此Mutex的任务的优先级,所以任务A会马上获得CPU控制权。一直到任务A释放Mutex,任务A才回到它原有的优先级,这时任务B就可以拥有该Mutex了。

应该注意的是:当任务A得到Mutex后,就不要再等待其它内核对象(诸如:信号量、邮箱、队列、事件标志等等)了,而应该尽量快速的完成工作,释放Mutex。否则,这样的Mutex就失去了作用,而且效果比直接使用信号量(Sem)更糟糕!

虽然普通的信号量(Sem)也可以用于互斥访问某独占资源,但是它可能引起“优先级反转”的问题。假设上面的例子使用的是Sem,当任务A得到Sem后,那么任务C(假设任务C的优先级比A高,但比B低)就绪的话将获得CPU控制权,于是任务A和任务B都被剥夺CPU控制权。任务C的优先级比B低,却优先得到了CPU!而如果任务A是优先级最低的任务,那么它就要等到所有比它优先级高的任务都挂起之后才会拥有CPU,那么任务B(优先级最高的任务)跟着它一起倒霉!这就是优先级反转问题,这是违背“基于优先级的抢占式多任务实时操作系统”原则的!

综上所述,uC/OS-II中多个任务访问独占资源时,最好使用Mutex,但是Mutex是比较消耗CPU时间和内存的。如果某高优先级的任务要使用独占资源,但是不在乎久等的情况下,就可以使用Sem,因为Sem是最高效最省内存的内核对象。

2.  uC/OS-II应用程序调用OSSchedLock()和OSSchedUnlock()函数应注意

 uC/OS-II的OSSchedLock()和OSSchedUnlock()函数允许应用程序锁定当前任务不被其它任务抢占。使用时应当注意的是:当你调用了OSSchedLock()之后,而在调用OSSchedUnlock()之前,千万不要再调用诸如OSFlagPend()、OSMboxPend()、OSMutexPend()、OSQPend()、OSSemPend()之类的事件等待函数!而且应当确保OSSchedLock()和OSSchedUnlock()函数成对出现,特别是在有些分支条件语句中,要考虑各种分支情况,不要有遗漏!

需要一并提醒用户的是:当您调用开关中断函数OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()时也要确保成对出现,否则系统将可能崩溃!不过,在OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()函数之间调用OSFlagPend()、OSMboxPend()、OSMutexPend()、OSQPend()、OSSemPend()之类的事件等待函数是允许的。

3.uC/OS-II驱动程序编写规范,特别推荐
    
首先应该阐明的是,我们这里讨论的是“驱动程序”,而不是“中断服务程序”,这两个词语往往被用户混淆。
(1)中断服务程序指那种硬件中断一旦发生,就会立即被硬件中断控制器调用的一小段程序,它的操作追求简单明了,越快速越精简就越好。
(2)驱动程序是指封装了某种硬件操作细节的函数集,它提供给应用程序的是统一、标准、清晰、易用的API。

对于中断服务程序的编写,往往与驱动程序的设计相关联。比如驱动程序提供异步操作的功能,那么就需要中断服务程序为它准备缓冲区和一个结构体,并且中断服务程序会依照这个结构体的成员参数自动完成所要求的操作。又如,串口(UART)中断服务程序的设计有两种:基于数据包传输和基于单字节传输,前者适用于以数据包为单位的通信程序,而后者适用于如超级终端这样的应用程序。

如果在一个系统中,要求使用同一个硬件设备完成几种不同的操作方式,就需要设计一个通用的驱动程序,而该驱动程序可以根据需要安装各种针对性很强的中断服务程序。

在设计驱动程序时,特别需要注意的是,某些外设的操作往往以一个连续而严格的时序作为原子操作,比如用I/O端口来访问DS1302、24C01、LM75A等等。在这类设备的操作过程中,不允许有其它任务来控制对应的I/O端口,否则会引起数据错误甚至器件损坏。所以,这种设备的驱动程序都应该仔细设计“原子操作”,把必须连贯操作的时序控制代码用互斥对象封装成一个“原子操作”,以适应多任务环境。其实,大部分设备都是这样,需要确定“原子操作”,如LCD、RTL8019AS、Flash等等也是如此。

关于驱动程序的设计,还有很多很多的文章可作,需要具体问题具体分析。在这里我就不列出个条条目目了,希望有兴趣的朋友多多讨论。

时间: 2024-07-31 12:02:53

uc/os 笔记(转)的相关文章

【原创】uC/OS 中LES BX,DWORD PTR DS:_OSTCBCur的作用及原理

1 LES BX, DWORD PTR DS:_OSTCBCur ;取得任务堆栈指针ES:[BX] 2 MOV ES:[BX+2], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务堆栈的2,3内存单元 3 MOV ES:[BX+0], SP ;将当前SP(栈顶的偏移量)存放至当前任务堆栈的0,1内存单元 首先讲讲LES指针的功能:LES的功能有点像C语言的*. LES REG,MEM 参与操作的寄存器不仅有REG,还有ES寄存器.在16位系统中,寄存器为16位,很显然,MEM所指向的内存

uC/OS II 任务切换原理

今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引发一次中断,自动将CS.IP寄存器压入堆栈,再利用中断返回,将新任务的任务断点指针弹出到CPU的CS.IP寄存器中,实现任务切换.虽然明白个大概,但是其中的细节却有点模糊,为什么调用IRET中断返回指令后,弹入CPU的CS.IP寄存器的断点指针是新任务的断点指针,而不是当前任务的,UCOS II是如

uC/OS 的任务调度解析 (转)

uC/OS 的任务调度解析 1.任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务.uC/OS使用的是OSStartHighRdy OSStartHighRdy LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority LDR R1, =NVIC_PENDSV_PRI STRB R1, [R0] MOVS R0, #0 ; Set

关于uC/OS的简单学习(转)

1.微内核 与Linux的首要区别是,它是一个微内核,内核所实现的功能非常简单,主要包括: 一些通用函数,如TaskCreate(),OSMutexPend(),OSQPost()等. 中断处理函数,且处理函数非常简单,一般仅是向相应的Task发消息,唤醒该Task来处理中断任务. 一个高效的调度器,这是OS的灵魂,实现多任务间的调度(包括调度点.调度算法.任务切换等). 好像就这么点,呵呵.它不支持内存保护,即不像Linux那样分用户空间.内核空间.如一个Task运行时,可调用内核函数Task

uc os相关的C语言知识点1-函数指针

开始读uc os的代码了,发现很多C语言的东西,之前没搞懂的,慢慢积累. 就象某一数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也以存储在某个函数指针变量里的.这样,我就可以通过这个函数指针变量来调用所指向的函数了. 形式1:返回类型(*函数名)(参数表) ,例子如下: #include<stdio.h> void (*funp)(int); //定义一个函数指针,注意函数的返回类型和参数类型和指针的一致,才可以用. void print(int n); //函数申明 int

uc/os iii移植到STM32F4---IAR开发环境

也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢出警告(为何keil没有报堆栈溢出??),网上有人说不用理会,但是实际使用时发生了错误(定义的常量数组值被改变,怀疑是堆栈溢出导致),发现使用的IAR版本不能完美支持使用的STM32芯片,换用高版本测试..(高版本正确,与低版本对芯片的支持有关) 2.开始时虽然会堆栈溢出,但是能够进入异常中断,进入

30天自制OS笔记:2 汇编语言学习与Makefile入门

进一步提高代码的高级程度,在之前的代码基础上修改,所以先拷贝再重命名为helloos.nas: 感觉还是添加个git比较方便,等helloos3完成后添加个git,这样可以保留历史,而不用每次都被覆盖了. --------------------------------- 先回顾下昨天的程序结构: 只有显示部分,昨天看懂了,继续2016年9月7日18:37:10,说实话那个 因为只能提醒很麻烦,所以取消notepad++自动补全: ? ? 下面把对代码的注释添加上: 寄存器: ? ? X表示扩展

UC/OS操作系统 (转)

1.和其他一些著名的嵌入式操作系统不同,uC/OS-II在单片机系统中的启动过程比较简单,不像有些操作系统那样,需要把内核编译成一个映像文件写入ROM中,上电复位后,再从ROM中把文件加载到RAM中去,然后再运行应用程序.uC/OS-II的内核是和应用程序放在一起编译成一个文件的,使用者只需要把这个文件转换成HEX格式,写入ROM中就可以了,上电后,会像普通的单片机程序一样运行. 2.uC/OS-II的移植也是一件需要值得注意的工作.如果没有现成的移植实例的话,就必须自己来编写移植代码.虽然只需

整理uc/os的46个函数

Void OSInit(void); 所属文件 OS_CORE.C     调用者 启动代码    开关量 无 OSinit()初始化μC/OS-Ⅱ,对这个函数的调用必须在调用OSStart()函数之前,而OSStart()函数真正开始运行多任务. Void OSIntEnter(void); 所属文件 OS_CORE.C     调用者 中断      开关量 无 OSIntEnter()通知μC/OS-Ⅱ一个中断处理函数正在执行,这有助于μC/OS-Ⅱ掌握中断嵌套的情况.OSIntEnter