Presentation is loading. Please wait.

Presentation is loading. Please wait.

Ch6. uC/OS-II分析 宋健建 南京大学软件学院.

Similar presentations


Presentation on theme: "Ch6. uC/OS-II分析 宋健建 南京大学软件学院."— Presentation transcript:

1 Ch6. uC/OS-II分析 宋健建 南京大学软件学院

2 内容 uC/OS-II概述 一些基本概念 内核情景分析 完整的程序 源代码文件结构 任务、任务控制块、任务间通信、共享与互斥、中断
从boot到操作系统,操作系统初始化,任务创建,启动多任务,任务调度,任务切换,任务定时等待… 完整的程序

3 uC/OS-II概述 源代码开放 微内核 内核与应用软件没有明确区分 易移植 共享同一个地址空间,一个映像,一个main()入口函数
与通用操作系统,或其他比较大比较通用的嵌入式操作系统如Linux,Windows CE的比较; 方便由test case改造;

4 Application Software CPU Timer uC/OS-II Port uC/OS-II
(Processor Independent Code) OS_MBOX.C OS_CORE.C OS_MEM.C uCOS_II.C OS_Q.C uCOS_II.H OS_SEM.C OS_TASK.C OS_FLAG.C OS_TIME.C OS_MUTEX.C uC/OS-II Configuration (Application Specific) OS_CFG.H INCLUDE.H uC/OS-II Port (Processor Specific Code) OS_CPU.H OS_CPU_A.A OS_CPU_C.C CPU Timer

5 uC/OS-II源代码组成 核心部分(OS_Core.c) 任务处理部分(OS_Task.c) 时钟部分(OS_Time.c)
操作系统的处理核心。包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。 任务处理部分(OS_Task.c) 与任务的操作密切相关,包括任务的建立、删除、挂起、恢复等等。 时钟部分(OS_Time.c) uC/OS-II中的最小时钟单位是timetick(时钟节拍)。任务延时等操作在这里完成的。

6 uC/OS-II源代码组成(续) 任务同步和通信部分 与CPU的接口部分
事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。 与CPU的接口部分 uC/OS-II针对所使用的CPU的移植部分。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。由于涉及SP等系统指针,通常用汇编语言编写。

7 应用范例 一个PC机上的基于uC/OS-II的应用范例 13个任务 空闲任务和统计任务(OSInit产生) TaskStart任务
10个任务在屏幕随机的位置显示0-9的数字,每个任务只显示同一个数字

8 内容 uC/OS-II概述 一些基本概念 内核情景分析 完整的程序 源代码文件结构 任务、任务控制块、任务间通信、共享与互斥、中断
从boot到操作系统,操作系统初始化,任务创建,启动多任务,任务调度,任务切换,任务定时等待… 完整的程序

9 任务 实时应用程序的设计过程包括如何把问题分割成多个任务 每个任务 任务与进程/线程 是整个应用的一部分 被赋予一定的优先级
有自己的一套CPU寄存器和栈空间 任务与进程/线程

10 任务的创建 Interface Example INT8U OSTaskCreate ( void (*task)(void *pd),
void *pdata, OS_STK *ptos, INT8U prio); Example OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0); OSTaskCreate(Task, (void *)&TaskData[i], &TaskStk[i][TASK_STK_SIZE – 1], i+1);

11

12 SetTickIn5MS() IRQ_Handler() OSTaskStkInit() OSStartHighRdy() IntTaskSwitch()

13 任务控制块 OS_TCB (in uCOS_II.h) typedef struct os_tcb {
OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */ #if OS_TASK_CREATE_EXT_EN > 0 #endif struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */ struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */ #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0) OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */

14 任务控制块(续) OS_TCB (in uCOS_II.h)
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */ #endif #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) #if OS_TASK_DEL_EN > 0 OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */ OS_FLAGS OSTCBFlagsRdy; /*Event flags that made task ready to run*/

15 任务控制块(续2) OS_TCB (in uCOS_II.h)
INT16U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */ INT8U OSTCBStat; /* Task status */ INT8U OSTCBPrio; /* Task priority (0: highest, 63: lowest) */ INT8U OSTCBX; INT8U OSTCBY; INT8U OSTCBBitX; INT8U OSTCBBitY; #if OS_TASK_DEL_EN > 0 BOOLEAN OSTCBDelReq; /* Indicates whether a task needs to delete itself */ #endif } OS_TCB;

16 任务间通信 途径 uC/OS-II提供的机制 全局变量 消息传递
Event, Mail box, Message queue, Semaphore,Mutex

17 共享与互斥 共享 互斥的方法? 实现任务间通信最简单的办法就是使用共享数据结构。特别是当所有任务都在一个单一地址空间时,这种方法尤其方便
关中断 使用“Test-And-Set”(TAS)操作 某些微处理器(如Motorola 68k系列)具有硬件TAS指令 禁止任务切换 利用信号量

18 临界区(Critical Region) 禁中断临界区 禁调度临界区 禁共享临界区 OS_ENTER_CRITICAL()
OS_EXIT_CRITICAL() (in os_cpu.h) 禁调度临界区 OSSchedLock() OSSchedUnlock() (in os_core.c) 禁共享临界区 Semaphore, etc.

19 中断 中断:一种硬件机制 中断处理完成后: 异步事件的发生
中断一旦被识别,CPU保存部分或全部现场(context),即部分或全部寄存器的值,跳转到中断服务子程序(ISR)。 中断处理完成后: 对前后台系统,程序回到后台程序 对不可剥夺型内核,程序回到被中断的任务 读可剥夺型内核,重新调度选择任务执行 ->OSIntExit()函数

20 中断的几个概念 中断延迟 中断响应时间 中断恢复时间 中断延迟 = 关中断的最长时间 + 开始执行中断服务子程序第一条指令的时间
从中断发生到开始执行用户的中断服务程序来处理中断的时间 中断响应时间 = 中断延迟 + 保存CPU内部寄存器的时间 + … 中断恢复时间 微处理器返回到被中断了的程序代码所需要的时间,或返回到更高优先级任务的时间

21 中断的几个概念(续)

22 内容 uC/OS-II概述 一些基本概念 内核情景分析 完整的程序 源代码文件结构 任务、任务控制块、任务间通信、共享与互斥、中断
从boot到操作系统,操作系统初始化,任务创建,启动多任务,任务调度,任务切换,任务定时等待… 完整的程序

23 从boot到操作系统 入口方式 ldr pc,=dummyOs bl CEntry

24 操作系统初始化 OSInit() (os_core.c) 初始化uC/OS-II所有的变量和数据结构;
创建空闲任务OS_TaskIdle(),该任务优先级最低(OS_LOWEST_PRIO),总处于就绪状态 (可选的)创建统计任务OS_TaskStat(),该任务优先级次低(OS_LOWEST_PRIO - 1)

25 任务创建 OSTaskCreate() (os_task.c) 附: 数组OSTCBPrioTbl[] (ucos_II.h)

26 OSTaskCreate() OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing */ OS_EXIT_CRITICAL(); psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize the task's stack */ err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0); if (err == OS_NO_ERR) { OSTaskCtr++; /* Increment the #tasks counter */ if (OSRunning == TRUE) { /* Find highest priority task if multitasking has started */ OS_Sched(); } } else { OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ return (err); return (OS_PRIO_EXIST);

27 启动多任务 OSStart(): (os_core.c) 真正启动操作系统,启动进程和进程调度
OSStartHighRdy() (os_cpu_a.s)

28 OSStart() void OSStart (void) { INT8U y; INT8U x;
if (OSRunning == FALSE) { y = OSUnMapTbl[OSRdyGrp]; /* Find highest priority's task priority number */ x = OSUnMapTbl[OSRdyTbl[y]]; OSPrioHighRdy = (INT8U)((y << 3) + x); OSPrioCur = OSPrioHighRdy; OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */ OSTCBCur = OSTCBHighRdy; OSStartHighRdy(); /* Execute target specific code to start task */ }

29 任务调度 数据结构: 编组就绪位图OSRdyGrp, 组内就绪位图OSRdyTbl[] (ucos_II.h)
OSMapTbl[] (os_core.c) Priority Resolution Table: OSUnMapTbl[] (os_core.c)

30

31

32

33

34 调度时机 OSStart(): (os_core.c) 任务级调度和中断级调度 OSStartHighRdy() (os_cpu_a.s)
OS_Sched(): (os_core.c) OSIntExit(): (os_core.c)

35 OS_Sched() #if OS_CRITICAL_METHOD == /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif INT8U y; OS_ENTER_CRITICAL(); if ((OSIntNesting == 0) && (OSLockNesting == 0)) { y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to HPT ready to run */ OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; /* Increment context switch counter */ OS_TASK_SW(); /* Perform a context switch */ } OS_EXIT_CRITICAL();

36 OSIntExit() if (OSRunning == TRUE) { OS_ENTER_CRITICAL();
if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */ OSIntNesting--; } if ((OSIntNesting == 0) && (OSLockNesting == 0)) { OSIntExitY = OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]); if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; /* Keep track of the number of ctx switches */ OSIntCtxSw(); /* Perform interrupt level ctx switch */ OS_EXIT_CRITICAL();

37 任务切换 OSStartHighRdy() (os_cpu_a.s) OS_TASK_SW() (os_cpu_a.s)
OSIntCtxSw()

38 Main()>OSStart()>OSStartHighRdy()
EXPORT OSStartHighRdy OSStartHighRdy ; Store the address of OSTCBHighRdy in r0 LDR sp, [r0] ; switch to the new stack LDMFD sp!, {r0} ; get saved SPSR; popup LDMFD sp!, {r0} ; get CPSR from top of the stack MSR CPSR_cxsf, r0 ; CPSR should be SVC32Mode LDMFD sp!, {r0-r12,pc} ; start the new task END

39 OS_TASK_SW() EXPORT OS_TASK_SW OS_TASK_SW ; store old
STMFD sp!, {r0-r12, lr} ; save register file and ret address MRS r0, CPSR STMFD sp!, {r0} ; save current PSR STMFD sp!, {r0} ; save SPSR ; store old sp in PCB BL GetOSTCBCur; STR sp, [r0] ;the Same as OSStartHighRdy

40 进程定时等待 时间管理 SetTickIn5MS() OSTickISR(): OSTimeDly(): (os_time.c)
OSTimeTick() OSTimeDly(): (os_time.c)

41 OSTickISR() IRQ_Hander()完成的任务如下: 保存被中断任务的上下文; 调用函数OSIntEnter();
调用函数OSTimeTick(); 清中断源; 调用函数OSIntExit(); 如果进行任务切换,则调用IntTaskSwitch(),否则恢复被中断任务的上下文,并返回该任务。

42 一个完整的程序 完整程序 实验

43

44

45 Highest Priority OS_LOWEST_PRO Wait for ISR… OSStart()


Download ppt "Ch6. uC/OS-II分析 宋健建 南京大学软件学院."

Similar presentations


Ads by Google