收藏 分享(赏)

uCOS-II内核架构解析.doc

上传人:gnk289057 文档编号:4409968 上传时间:2018-12-27 格式:DOC 页数:25 大小:1,021.50KB
下载 相关 举报
uCOS-II内核架构解析.doc_第1页
第1页 / 共25页
uCOS-II内核架构解析.doc_第2页
第2页 / 共25页
uCOS-II内核架构解析.doc_第3页
第3页 / 共25页
uCOS-II内核架构解析.doc_第4页
第4页 / 共25页
uCOS-II内核架构解析.doc_第5页
第5页 / 共25页
点击查看更多>>
资源描述

1、目录嵌入式 RTOS31. 嵌入式系统基本模型 32. RTOS 设计原则 .33. GPOS 与 RTOS .34. 嵌入式开发模式 35. (不)可重入 46. 互斥条件 47. 临界状态 4uC/OS-II 基本介绍 .51. uC/OS-II 文件结构 52. uC/OS-II 组成部分 53. uC/OS-II 任务状态 6uC/OS-II 系统核心 .61. uC/OS-II 任务调度 6(1) uC/OS-II 调度算法 .6(2) 任务就绪表 .6(3) 任务级任务调度 .7(4) 中断级任务调度 .7(5) 调度器上锁与解锁 .8(6) 中断管理函数 .9(7) 中断相关问题

2、 .92. uC/OS-II 系统启动 10(1) 初始化函数 OSInit().10(2) 启动函数 OSStart().11(3) 统计任务 OSTaskStat .113. uC/OS-II 系统时钟 114. uC/OS-II 事件管理 12(1) 事件控制块 .12(2) ECB 管理机制 12(3) ECB 管理函数 12uC/OS-II 任务管理 .131. C 可执行代码结构 132. 任务结构 133. 任务栈 144. 任务控制块 14(1) TCB 描述 14(2) TCB 主要成员 14(3) TCB 全局变量 145. 任务状态切换 146. 任务管理函数 15uC/

3、OS-II 通信与同步 .151. 消息邮箱 Mbox .152. 消息队列 msgQ .16(1) msgQ 基本内容 .16(2) msgQ 全局变量 .16(3) msgQ 管理函数 .17(4) msgQ 几个问题 .173. 信号量 Sem174. 互斥锁 Mutex 18(1) Mutex 基本原理 18(2) 提升/恢复优先级 18(3) Mutex 管理函数 195. 事件组标志 Flag19(1) Flag 基本原理 .19(2) Flag 数据结构 .20(3) Flag 管理函数 .216. Task 就绪状态判断? .22uC/OS-II 内存管理 .221. memP

4、art 基本原理 222. memPart 管理函数 233. memPart 几个问题 23uC/OS-II 应用开发 .231. 开发步骤 232 编写任务函数 243堆栈设计扩展 244 一些借鉴经验 25uC/OS-II 内核移植 .251. uC/OS-II 正常运行的条件 252. 运行态代码分布 253. 移植的几个问题 26嵌入式 RTOS1. 嵌入式系统基本模型2. RTOS 设计原则采用各种算法和策略,始终保持系统行为的可预测性。即在任何情况下,在系统运行的任何时刻,OS 的资源配置策略都能为争夺资源(包括 CPU、内存、网络带宽等)的多个实时任务合理地分配资源,使每个实时

5、任务的实时性要求都能得到满足。3. GPOS 与 RTOS GPOS:注重每次执行的平均响应时间,而不是某次特定执行的响应时间。 RTOS:除满足应用功能需求外,还要满足实时性要求,始终保证系统行为的可预测性(predictability) 。与 GPOS 不同,RTOS 注重的不是系统的平均表现,而是要满足每个实时任务在最坏情况下的实时性要求。也就是说,RTOS 注重的是个体表现,更准确地说是个体最坏情况表现。RTOS 与 GPOS 的差别主要表现在:a) 任务调度策略不同;b) 内存管理方式不同;c) 中断处理方式不同;d) 系统管理方式不同;4. 嵌入式开发模式 单片机系统的前后台程序:

6、不使用 OS,将应用程序设计成死循环,系统轮流处理各事件,对时间响应要求高的异步事件采用中断进行处理。 基于任务(进程)的软件设计方法:使用 OS,由 OS 管理硬件资源,任务只是在需要资源时申请即可,至于 when/which,完全由 OS 决定。5. (不)可重入 (1) 可重入函数:指函数代码在运行过程中可以被中断,中断返回后仍能够恢复到原来的状态,并能准确无误执行的函数。可重入函数可以被一个以上的任务调用,而不必担心数据被破坏。可重入函数或者只使用局部变量,即变量保存在 CPU 寄存器或堆栈中;或者使用全局变量,则要对全局变量予以保护。(2) 不可重入函数 :函数在运行过程中不可以被中

7、断。6. 互斥条件实现任务间通信最简便的办法是使用共享数据,但要保证任务在处理共享数据时的排它性。使共享资源满足互斥条件,最一般的方法有:(1) 关中断使用某种实时内核,一般情况下关中断的时间最长不超过内核本身的关中断时间,这样就不会影响系统中断延迟。(2) 使用测试并置位指令TestOS_EXT INT8U OSRdyGrp;OS_EXT INT8U OSRdyTblOS_RDY_TBL_SIZE; 添加就绪任务至就绪表; 从就绪表删除就绪任务; 查找最高优先级就绪任务 OS_SchedNew();(3) 任务级任务调度指在非中断返回时进行任务调度,一般发生在当前任务因时间延迟或等待某事件而

8、阻塞或被挂起,或有更高优先级的任务处于就绪状态。任务的基本信息: CPU 的 PC 寄存器:任务当前执行的位置; CPU 的通用寄存器:任务当前执行涉及的临时数据; CPU 的状态寄存器:存储当前 CPU 的状态。任务级任务切换:从一个任务直接切换至另一个任务,不涉及 CPU 状态的切换,OS_TASK_SW()既保存当前任务上下文,又恢复新任务上下文。过程:OS_Sched() - OS_SchedNew() - OS_TASK_SW()(4) 中断级任务调度中断级任务切换:在中断处理完成后,通过 OSIntExit()判断是否有更高优先级就绪任务。如果有,调用 OSIntCtxSW()恢复

9、新任务上下文。注意:在中断处理中,已经保存了被中断任务的上下文,所以这里仅仅恢复。过程:OSIntExt() OSIntEnter() - ISR OSIntExit() - OSIntCtxSW()(5) 调度器上锁与解锁uC/OS-II 提供调度器锁定功能,在锁定期间不能进行任务调度。 uC/OS-II使用全局变量 OSLockNesting 标识是否锁定了任务调度器。 OS_EXT INT8U OSLockNesting; void OSSchedLock(void); void OSSchedUnlock(void);(6) 中断管理函数在中断处理中,不允许进行任务管理、事件管理及任务

10、调度等操作。uC/OS-II 通过全局变量 OSIntNesting 标识当前是否处于中断状态。在所有任务及事件管理的程序中,都有对 OSIntNesting 进行判断的语句。 void OSIntEnter(void); void OSIntExit(void);(7) 中断相关问题 OS_ENTER_CRITICAL() OS_EXIT_CRITICAL()关中断使得 uC/OS-II 能够同时避免有其他任务或中断服务进入临界代码段 。调用 uC/OS-II 功能函数时,中断总应当是开着的。 uC/OS-II 如何禁止调度? 在中断中允许调度吗?为什么? uC/OS-II 如何屏蔽中断?2

11、. uC/OS-II 系统启动uC/OS-II 首先调用 OSInit()进行初始化,然后创建任务(此时还未启动系统,仅仅为其分配资源) ,然后调用 OSStart()启动系统,将 CPU 控制权交给 uC/OS-II,OS 根据任务优先级选择由哪个任务开始执行,或创建新的任务。(1) 初始化函数 OSInit()OSInit()主要完成初始化操作,包括初始化全局变量(在 OS_InitMisc()中) 、任务就绪表、TCB、ECB、FCB、内存单元、消息队列,并创建空闲任务。如果有必要,创建统计任务。 OS_InitMisc(); /初始化部分全局变量 OS_InitRdyList(); /

12、初始化任务就绪表 OS_InitTCBList(); /初始化空闲 TCB 链表 OS_InitEventList(); /初始化 ECB 链表 OS_FlagInit(); /初始化事件组标志结构 OS_MemInit(); /初始化内存管理 OS_QInit(); /初始化消息队列 OS_InitTaskIdle(); /创建空闲任务 OS_InitTaskStat(); /创建统计任务uC/OS-II 初始化了 5 个空的数据结构缓冲区,每个缓冲区都是单向链表,允许 uC/OS-II 从缓冲区中迅速取得或释放一个缓冲区中的元素。(2) 启动函数 OSStart()OSStart()在一切

13、准备就绪且需要首先创建的任务都被创建后,启动 uC/OS-II。它从就绪表中查找最高优先级就绪任务,并恢复其上下文开始执行。过程:OSStart() - OS_SchedNew() - OSStartHighRdy()问题:任务第一次被调用时,哪来的上下文供其恢复呢?创建任务时,调用了 OSTaskStkInit()初始化任务堆栈,可此函数中没有涉及任务的上下文呀?(3) 统计任务 OSTaskStatOSTaskStat 用于计算 CPU 利用率。设置 OS_CFG.H 中的OS_TASK_STAT_EN 为 1,创建统计任务,在系统启动后一直处于就绪状态。刚开始时,空闲任务运行 1S,为计

14、算 CPU 利用率提供一个基准值,并保存在统计任务的堆栈中,这个值不会改变除非重新启动 CPU。此后空闲任每次被其它任务抢去 CPU 时,它里面的计数器就会直接记录下 CPU 空闲的时间。3. uC/OS-II 系统时钟任何实时系统的时钟硬件设备每隔一段时间(一个系统 tick)产生一个硬件中断,OS 接收到该中断后,更新时间计数器,更新所有对时钟依赖的程序代码,从而维持系统有序稳定的运行。主要包含在 C 源文件 OS_TIME.C 中。 #define OS_TICKS_PER_SEC 100 /系统时钟中断间隔 OS_EXT volatile INT32U OSTime; /系统运行的时间

15、值 void OSTimeTick(void); /时钟中断服务程序 void OSTimeDly(INT16U ticks); /延迟指定时钟节拍 INT8U OSTimeDlyHMSM(); /延迟指定时间长度 INT8U OSTimeDlyResume(prio); /恢复 等待(时延 /阻塞) 任务 INT32U OSTimeGet(void); /读取当前时间 void OSTimeSet(INT32U ticks); /设置当前时间4. uC/OS-II 事件管理(1) 事件控制块 INT8U OSEventType; /事件类型 void *OSEventPtr; /指向 MBo

16、x 或 Queue INT16U OSEventCnt; /信号量计数器( 注: Mutex) INT8U OSEventGrp; /事件等待组标志 INT8U OSEventTbl; /时间任务等待表 INT8U OSEventName; /时间名称(2) ECB 管理机制 OS_EXT OS_EVENT *OSEventFreeList; /空闲 ECB 链表指针 OS_EXT OS_EVENT OSEventTbl; /ECB 结构体数组(3) ECB 管理函数 OS_InitEventList():初始化 ECB; OS_EventWaitListInit():在创建事件时调用,初始化

17、 ECB 任务等待表; OS_EventTaskRdy():在事件发生时调用,修改此事件中最高优先级任务的 TCB 成员变量,在任务就绪表中添加此任务,将相应信息传递给该任务 TCB,并将此任务从事件的任务等代表中删除; OS_EventTaskWait():在申请资源失败而暂停当前任务时被调用,将任务从任务就绪表中删除,并添加到事件的任务等代表中; OS_EventTO():在事件等待超时时调用,将此任务从事件的任务等代表中删除,并修改该任务的 TCB 成员变量;uC/OS-II 任务管理1. C 可执行代码结构 代码段.text:存放 CPU 执行的机器指令,通常.text 是可共享且只读

18、的。 数据段.data:.rodata(常量数据)、.rwdata(已初始化全局变量、静态变量) 。 未初始化数据段.bss:未初始化的全局变量、静态变量。 栈.stack:存放函数参数、局部变量及任务切换时的上下文。 堆.heap:用于动态内存分配。2. 任务结构在 uC/OS-II 中,任务是事件运行和管理的基本单元。一个 uC/OS-II 任务至少包含程序代码、栈和 TCB,还可选择性使用相当于堆的动态内存空间。程序运行时,uC/OS-II 中的任务相当于可执行代码(可单独运行的单元) 。uC/OS-II 任务的各部分如何管理?3. 任务栈 任务栈数据类型: typedef unsign

19、ed short OS_STK 任务栈增长方向: #define OS_STK_GROWTH 0/1 任务栈 基本功能 : ?4. 任务控制块(1) TCB 描述主要用来存储任务的当前属性。 (问:任务第一次被调度时,该如何运行?)(2) TCB 主要成员 任务栈空间位置: OSTCBStkPtr、 OSTCBStkBottom、 OSTCBStkSize; 任务通信与同步: OSTCBEventPtr、 OSTCBMsg; 任务事件组标志: OSTCBFlagNode、 OSTCBFlagsRdy; 任务等待 /阻塞: OSTCBDly、 OSTCBPendTO; 任务当前状态: OSTCB

20、Stat; 任务优先级: OSTCBPrio;(3) TCB 全局变量 OS_EXT OS_TCB OSTCBTblOS_MAX_TASKS + OS_N_SYS_TASKS; OS_EXT OS_TCB OSTCBPrioTblOS_LOWEST_PRIO + 1; OS_EXT OS_TCB *OSTCBFreeList; OS_EXT OS_TCB *OSTCBList; OS_EXT OS_TCB *OSTCBHighRdy; OS_EXT OS_TCB *OSTCBCur;5. 任务状态切换6. 任务管理函数OS_TASK.C:11 个函数 OSTaskCreate(); OSTas

21、kCreateExt(); OSTaskDel(); OSTaskDelReq(); OSTaskChangePrio(); OSTaskSuspend(); OSTaskResume(); OSTaskNameGet(); OSTaskNameSet(); OSTaskStkChk(); OS_TaskStkClr(); OSTaskQuery();uC/OS-II 通信与同步1. 消息邮箱 MboxMbox 用于多任务间单一消息的传递,uC/OS-II 使用 ECB 管理 Mbox 的基本信息,OSEventPtr 指向创建 Mbox 时指定的内存空间。事件的创建由具体的事件管理程序实现。

22、主要包含在 C 源文件 OS_MBOX.C 中。 OS_EVENT *OSMboxCreate(void *msg); void *OSMboxPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); void *OSMboxAccept(OS_EVENT *pevent); INT8U OSMboxPost(OS_EVENT *pevent, void *msg); INT8U OSMboxPostOpt(OS_EVENT *pevent, void *msg, INT8U opt); OS_EVENT *OSMboxDel(OS_EVENT *

23、pevent, INT8U opt, INT8U *err); INT8U OSMboxQuery(OS_EVENT *pevent, OS_MBOX_DATA *);2. 消息队列 msgQ(1) msgQ 基本内容msgQ 是 uC/OS-II 任务间通信的机制,可实现多条消息传递,即可以同时存储多条消息。uC/OS-II 使用循环队列管理机制。主要包含在 C 源文件OS_Q.C 中。msgQ 管理:使用指针数组存储所有消息的位置;使用 QCB 标识指针数组中消息的基本信息;使用 ECB 管理整个 msgQ。QCB 在编译时分配空间,即当前系统中可用的 msgQ 个数是预先设置的,系统运行

24、时不能修改。(2) msgQ 全局变量 OS_EXT OS_Q *OSQTblOS_MAX_QS; /QCB 结构体数组 OS_EXT OS_Q *OSQFreeList; /空闲 QCB 头指针 typedef struct os_q /消息队列控制块struct os_q *OSQPtr; /用于构建空闲 QCB 链表void *OSQStart; /指向 msgQ 指针数组的起始位置void *OSQEnd; /指向 msgQ 指针数组的结束位置void *OSQIn; /指向 msgQ 指针数组下一个可以插入消息的位置void *OSQOut; /指向 msgQ 指针数组下一个可以读出

25、消息的位置INT16U OSQSize; /msgQ 指针数组的大小INT16U OSQEntries; /msgQ 指针数组当前可以读取的消息个数OS_Q;(3) msgQ 管理函数 OS_EVENT *OSQCreate(void *start, INT16U size); INT8U OSQPost(OS_EVENT *pevent, void *msg); /发送消息到队尾 INT8U OSQPostFront(OS_EVENT *pevent, void *msg);/msg 至队首 INT8U OSQPostOpt(OS_EVENT *pevent, void *msg, INT8

26、U opt); void *OSQPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); void *OSQAccept(OS_EVENT *pevent, INT8U *err); OS_EVENT *OSQDel(OS_EVENT *pevent, INT8U opt, INT8U *err); INT8U OSQQuery(OS_EVENT *pevent, OS_Q_DATA*); INT8U OSQFlush(OS_EVENT *pevent);(4) msgQ 几个问题uC/OS-II 中,什么是事件?事件是 uC/OS-II 管理任

27、务间同步与通信的机制。事件是处理事件的对象感兴趣的,能够感知或捕获到一种事件状态的改变。3. 信号量 SemSem 主要用来实现任务间同步及标识某类资源的可用个数,即某个特定资源可供多少任务同时使用。主要包含在 C 源文件 OS_SEM.C 中。 OS_EVENT *OSSemCreate(INT16U cnt); void OSSemPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); INT16U OSSemAccept(OS_EVENT *pevent); INT8U OSSemPost(OS_EVENT *pevent); OS_EVE

28、NT *OSSemDel(OS_EVENT *pevent, INT8U opt, INT8U *err); INT8U OSSemQuery(OS_EVENT *pevent, OS_SEM_DATA*); void OSSemSet(OS_EVENT *pevent, INT16U cnt, INT8U *err);4. 互斥锁 Mutex(1) Mutex 基本原理Mutex 用来实现对资源的排他性访问,可能引起优先级反转 。任何任务在占有某个互斥锁事件时,都不能阻塞等待其它任何事件,否则会造成死锁。主要包含在 C 源文件 OS_MUTEX.C 中。优先级反转是指,低优先级任务占有高优先

29、级任务运行所需的资源,而使高优先级不得不等低优先级任务把资源释放才能执行。uC/OS-II 使用 ECB 管理 Mutex,其成员变量 OSEventCnt:高 8 位存储Mutex 被使用时提供给任务的 prio;低 8 位在没有任务占有 Mutex 时为 0xFF,否则为占有任务的 prio。(2) 提升/恢复优先级a) 提升 Mutex 拥有者任务的优先级的相关操作: 如果该任务原来处于就绪状态,则从就绪表中将其删除;如果该任务正在等待某个事件,则从该事件的任务等待表中将其删除; 修改拥有 Mutex 的 TCB,将其 OSTCBPrio 修改为欲提升的优先级; 如果该任务处于就绪状态,

30、则将提升的优先级加载到任务就绪表中;如果该任务未就绪且正在等待某个事件,则将提升的优先级添加到该事件的任务等待表中,并修改 TCB 中 OSTCBEventPtr; 修改 TCB 中与优先级相关的成员变量。b) 恢复 Mutex 拥有任务的优先级的相关操作: 从任务就绪表中删除提升过的优先级值,修改当前 TCB 中与优先级相关的所有成员变量; 再次保留提升的优先级值控制块入口,避免将其分配给其它任务。(3) Mutex 管理函数 #define OS_MUTEX_KEEP_LOWER_8 0x00FF #define OS_MUTEX_KEEP_UPPER_8 0xFF00 #define O

31、S_MUTEX_AVAILABLE 0x00FF OS_EVENT *OSMutexCreate(INT8U prio, INT8U *err); void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); INT8U OSMutexAccept(OS_EVENT *pevent, INT8U *err); INT8U OSMutexPost(OS_EVENT *pevent); OS_EVENT *OSMutexDel(OS_EVENT*, INT8U opt, INT8U *err); INT8U OSMutexQuery

32、(OS_EVENT*, OS_MUTEX_DATA*);5. 事件组标志 Flag(1) Flag 基本原理uC/OS-II 提供事件组标志实现多事件管理。Flag 只是使用 0/1 来表示某个事件是否发生过,而不能直接被用来传递数据和消息。可以选择性地设置一个Flag 最多可以管理的任务同步状态。主要包含在 C 源文件 OS_FLAG.C 中。(2) Flag 数据结构 #define OS_FLAGS_NBITS 8/16/32 /定义 OS_FLAGS 的位数 FCB 结构体:typedef struct os_flag_grpINT8U OSFlagType; /事件类型void *O

33、SFlagWaitList; /指向等待的任务链表OS_FLAGS OSFlagFlags; /信号列表INT8U OSFlagNameOS_FLAG_NAME_SIZE;OS_FLAG_GRP; 事件标志等待链表结点typedef struct os_flag_nodevoid *OSFlagNodeNext;void *OSFlagNodePrev;void *OSFlagNodeTCB;void *OSFlagNodeFlagGrp; /指向此任务所等待的事件组标志OS_FLAGS OSFlagNodeFlags; /等待的事件INT8U OSFlagNodeWaitType; /等待方

34、式OS_FLAG_NODE; OS_EXT OS_FLAG_GRP OSFlagTblOS_MAX_FLAGS; OS_EXT OS_FLAG_GRP *OSFlagFreeList;(3) Flag 管理函数 OS_FLAG_GRP *OSFlagCreate(OS_FLAGS flags, INT8U *err); OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp, OS_FLAGS flags,INT8U wait_type, INT16U timeout, INT8U *err); Static void OS_FlagBlock(OS_FLAG_GRP *p

35、grp, OS_FLAG_NODE *pnode,OS_FLAGS flags,INT8U wait_type, /挂起任务,INT16U timeout); /直到等待的事件或超时类似于: OS_EventTaskWait(); void OS_FlagUnlink(OS_FLAG_NODE *pnode); /等待超时删除结点类似于: OS_EventTO(); OS_FLAGS OSFlagAccept(OS_FLAG_GRP *pgrp,OS_FLAGS flags,INT8U wait_type,INT8U *err); OS_FLAGS OSFlagPost(OS_FLAG_GRP

36、 *pgrp,OS_FLAGS flags,INT8U opt,INT8U *err); static BOOLEAN OS_FLAGTaskRdy(OS_FLAG_NODE *pnode,OS_FLAGS flags_rdy); OS_FLAG_GRP *OSFlagDel(OS_FLAG_GRP*, INT8U opt, INT8U *err); OS_FLAGS OSFlagPendGetFlagsRdy(void); /获取任务就绪标志 OS_FLAGS OSFlagQuery(OS_FLAG_GRP*, INT8U *err); INT8U OSFlagNameGet(OS_FLAG

37、_GRP*, INT8U *pname, INT8U *err); void OSFlagNameSet(OS_FLAG_GRP*, INT8U *pname, INT8U *err);6. Task 就绪状态判断?a) OSRdyTblptcb-OSTCBY OS_EXT OS_MEM *OSMemFreeList; memPart 控制块结构体:typedef struct os_menvoid *OSMemAddr; /首地址void *OSMemFreeList; /分区中空闲空间的起始地址INT32U OSMemBlkSize; /分区中块成员空间大小INT32U OSMemNBlk

38、s; /块结构数量INT32U OSMemNFree; /剩余空闲块个数INT8U OSMemName;OS_MEM;2. memPart 管理函数 OS_MEM *OSMemCreate(void *addr, INT32U nblks, INT32U blksize, INT8U *err); void *OSMemGet(OS_MEM *pmem, INT8U *err); /申请内存分区块 INT8U OSMemPut(OS_MEM *pmem, void *pblk); /释放内存分区块 INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA*); IN

39、T8U OSMemNameGet(OS_MEM *pmem, INT8U *pname, INT8U *err); INT8U OSMemNameSet(OS_MEM *pmem, INT8U *pname, INT8U *err);3. memPart 几个问题 uC/OS-II 在申请栈空间和堆空间时有什么不同? 能不能一次申请 1B 的堆空间?uC/OS-II 应用开发1. 开发步骤(1) 包含 uC/OS-II 的总头文件 includes.h;(2) 定义任务栈的大小和任务栈;(3) 分配任务优先级;(4) 实现任务功能;(5) 调用 OSInit()函数初始化 uC/OS-II 的

40、数据结构;(6) 创建用户任务,启动 uC/OS-II;2 编写任务函数用户任务函数必须是无限循环,程序执行流由 OS 内核改变。在执行完用户代码后最好调用系统服务,主动把 CPU 使用权让给有需要的任务。模式一:void YourTask(void *pdata)for(;) /*用户代码*/调用 uC/OS II 的服务;OSMboxPend();OSQPend();OSSemPend();OSTimeDlyHMSM();/*用户代码*/模式二(自删除任务)void YourTask(void *pdata) /*用户代码*/OSTaskDel(OS_PRIO_SELF); /这种任务运行

41、完后就自我删除了。3堆栈设计扩展方法:中断堆栈和任务堆栈分开设计原因:uC/OS-II 占用 RAM 主要用于任务 TCB、任务堆栈等方面,任务堆栈大是由于硬件设计中没有把中断堆栈和任务堆栈分开,造成了考虑任务堆栈大小时,不仅要计算任务中局部变量和函数嵌套层数,还要考虑中断的最大嵌套层数,导致大量 RAM 被浪费。可以把中断堆栈和任务堆栈分开设计,这样计算任务堆栈时,就不需要把中断处理(包括中断嵌套)中的内存占用计算到任务堆栈中,只需计算每个任务本身需要的内存大小即可。4 一些借鉴经验(1) 编写中断程序时,有条件的情况下尽量使用汇编语言,这样可以避免一些编译器自身的操作,减少指针调整次数。(2) 用 C 编写 ISR 时,有时要调用汇编函数,其中一些压栈的 PC 可能破坏堆栈结构,这就要调整堆栈,保证正确的格式。 (3)由于 uC/OS-II 中断处理原始设计中可能不调整 SP,需要在调用 OSIntExit()返回后,判断程序是否处于中断嵌套状态。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 中等教育 > 职业教育

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报