uCOS-II在STM32上的移植.ppt

上传人:牧羊曲112 文档编号:5451406 上传时间:2023-07-08 格式:PPT 页数:32 大小:886.50KB
返回 下载 相关 举报
uCOS-II在STM32上的移植.ppt_第1页
第1页 / 共32页
uCOS-II在STM32上的移植.ppt_第2页
第2页 / 共32页
uCOS-II在STM32上的移植.ppt_第3页
第3页 / 共32页
uCOS-II在STM32上的移植.ppt_第4页
第4页 / 共32页
uCOS-II在STM32上的移植.ppt_第5页
第5页 / 共32页
点击查看更多>>
资源描述

《uCOS-II在STM32上的移植.ppt》由会员分享,可在线阅读,更多相关《uCOS-II在STM32上的移植.ppt(32页珍藏版)》请在三一办公上搜索。

1、8/17/2010,1,C/OS-II 的移植,8/17/2010,2,7.1 概述,User目录Main.CMain.HIncludes.HOS_Cfg.H,C/OS-II Source目录OS_CORE.C OS_FLAG.C OS_MBOX.C OS_MEM.C OS_MUTEX.C OS_Q.C OS_SEM.C OS_TASK.C OS_TIME.C OS_TMR.C uCOS_II.H,C/OS-II Ports目录Cortex M3 OS_CPU_C.C OS_CPU_A.ASM OS_CPU.H,BSP(板级支持包)Startup.STarget.CTarget.H,ARM C

2、ortex-M3 目标板,与处理器无关操作系统内核代码,与处理器有关需要移植代码,开发板相关代码,8/17/2010,3,内核文件,移植的部分,用户代码,板级代码,主程序,8/17/2010,4,ARM Cortex-M3的寄存器模型,LM3S系列单片机采用ARM Cortex-M3内核;在移植之前,先简述可见寄存器模型。ARM Cortex-M3总共有20个寄存器,每个都是32位宽度。,8/17/2010,5,8/17/2010,6,状态,中断,8/17/2010,7,控制寄存器,8/17/2010,8,7.1.1 移植条件,移植C/OS-II到处理器上必须满足以下条件,(1)处理器的C编译

3、器能产生可重入代码,C/OS是多任务内核,函数可能会被多个任务调用,代码的重入性是保证完成多任务的基础。可重入代码指的是可被多个体任务同时调用,而不会破坏数据的一段代码,或者说代码具有在执行过程中打断后再次被调用的能力。,举例说明:Swap1函数代码:Int temp;void swap1(int*x,int*y)temp=*x;*x=*y;*y=temp;,举例说明:Swap2函数代码:void swap2(int*x,int*y)int temp;temp=*x;*x=*y;*y=temp;,可重入,不可重入,编译器还得支持,MDK开发环境,可生成可重入代码,8/17/2010,9,(2)

4、用C语言可打开和关闭中断,ARM处理器核包含一个CPSR寄存器,该寄存器包括一个全局的中断禁止位,控制它便可打开和关闭中断。,PRIMASK,(3)处理器支持中断并且能产生定时中断,C/OS-II通过处理器产生的定时器中断来实现多任务之间的调度。ARM Cortex-M3的处理器都支持中断并能产生定时器中断,专门有一个SysTick定时器来实现。,(4)处理器支持能够容纳一定量数据的硬件堆栈(通常需要几十KByte字节),比如AT98C51处理器,内部只有128字节的RAM,要运行,需外扩RAM。CM3的芯片,内部可多达128KByte的容量,因此可直接使用。,(5)处理器有将堆栈指针和其他C

5、PU寄存器读出和存储到堆栈(或内存)的指令,C/OS-II进行任务调度时,会把当前任务的CPU寄存器存到此任务的堆栈中,然后,再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以,寄存器的入栈和出栈是C/OS-II多任务调度的基础。,运行TCP、UDP需要的内存会更大,通常要100K左右,8/17/2010,10,7.1.2 移植步骤,所谓移植,就是使一个实时操作系统能够在某个微处理器平台上或微控制器平台上运行。由C/OS-II的文件系统可知,在移植过程中,用户需要关注的就是与处理器相关的代码。这部分包括一个头文件OS_CPU.H、一个汇编文件OS_CPU_A.ASM和一个C代

6、码文件OS_CPU_C.C。,OS_CPU.H,OS_CPU_C.C,OS_CPU_A.ASM,#define设置一个常量的值声明10个数据类型用#define声明三个宏,用C语言编写六个简单的函数,编写四个汇编语言函数,移植,实际中,写一个就行,8/17/2010,11,1、INCLUDES.H,INCLUDES.H是一个头文件,它在所有.C文件的第一行被包含。,#include includes.h,INCLUDES.H使得用户项目中的每个.C文件不用分别去考虑它实际上需要哪些头文件。使用INCLUDES.H的唯一缺点是它可能会包含一些实际不相关的头文件。这意味着每个文件的编译时间可能会增

7、加。但由于它增强了代码的可移植性,所以我们还是决定使用这一方法。用户可以通过编辑INCLUDES.H来增加自己的头文件,但是用户的头文件必须添加在头文件列表的最后。,2、基本配置和定义OS_CPU.H,(1)用#define 设置一个常量的值,#ifdef OS_CPU_GLOBALS#define OS_CPU_EXT#else#define OS_CPU_EXT extern#endif,8/17/2010,12,(2)定义与编译器相关的数据类型,为了保证可移植性,程序中没有直接使用C语言中的short、int和long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。程序中自

8、己定义了一套数据类型,如INT16U表示16位无符号整型。对于ARM这样的32位内核,INT16U是unsigned short型;如果是16位处理器,则是unsinged int型。,typedef unsigned char BOOLEAN;/*Boolean 布尔变量*/typedef unsigned char INT8U;/*无符号8位实体*/typedef signed char INT8S;/*有符号8位实体*/typedef unsigned short INT16U;/*无符号16位实体*/typedef signed short INT16S;/*有符号16位实体*/typ

9、edef unsigned int INT32U;/*无符号32位实体*/typedef signed int INT32S;/*有符号32位实体*/typedef float FP32/*单精度浮点数*/typedef double FP64;/*双精度浮点数*/typedef unsigned int OS_STK;/*堆栈是32位宽度*/typedef unsigned int OS_CPU_SR;/*申明状态寄存器是32位*/,C/OS-II内核的代码需要与处理器位有关,8/17/2010,13,(3)定义临界段(允许和禁止中断宏),与所有实时内核一样,C/OS-II需要先禁止中断,再

10、访问代码的临界区,并且在访问完毕后,重新允计中断。这就是C/OS-II能够保护临界段代码免受多任务或中断服务例程ISR的破坏。中断禁止时间是商业实时内核公司提供的重要指标之一,因为它将影响到用户的系统对实时事件的响应能力。虽然C/OS-II尽量使中断禁止时间达到最短,但是C/OS-II的中断禁止时间还主要依赖于处理器结构和编译器产生的代码的质量。通常每个处理器都会提供一定的指令来禁止/允许中断,因此用户的C编译器必须由一定的机制来直接从C中执行这些操作。,OS_ENTER_CRITICAL(),OS_EXIT_CRITICAL(),C/OS-II定义了两个宏来禁止和允许中断:,#define

11、OS_CRITICAL_METHOD 3#define OS_ENTER_CRITICAL()cpu_sr=OS_CPU_SR_Save();#define OS_EXIT_CRITICAL()OS_CPU_SR_Restore(cpu_sr);,OS_CPU_A.ASM中具体实现,C/OS-II定义了三种方法关闭和打开中断(OS_CRITICAL_METHED=1,2,3),通常情况下,我们都是选用的方法3。,8/17/2010,14,OS_CPU_SR_Save MRS R0,PRIMASK CPSID I BX LR,OS_CPU_SR_Restore MSR PRIMASK,R0 BX

12、 LR,关中断,开中断,(4)定义栈的增长方向,C/OS-II使用结构常量OS_STK_GROWTH来指定堆栈的增长方式:置OS_STK_GROWTH为0,表示堆栈从下往上增长;置OS_STK_GROWTH为1,表示堆栈从上往下增长。Cortex-M3支持从上往下增长的方式。因此,我们在移植时,需将OS_STK_GROWTH=1,如果是51系列单片机,则OS_STK_GROWTH=0。,#define OS_STK_GROWTH 1,8/17/2010,15,(5)定义OS_TASK_SW()宏,任务级上下文切换,任务级上下文切换(即任务切换)调用宏定义OS_TASK_SW()。因为上下文切换

13、跟处理器有密切关系,OS_TASK_SW()实质上是调用汇编函数OSCtxSW(),它在OS_CPU_A.ASM文件中定义。,#define OS_TASK_SW()OSCtxSw(),OSCtxSw PUSH R4,R5 LDR R4,=NVIC_INT_CTRL;触发软件中断 LDR R5,=NVIC_PENDSVSET STR R5,R4 POP R4,R5 BX LR,原型如下:,打开MDK查看原始代码,NVIC_INT_CTRL EQU 0 xE000ED04 NVIC_PENDSVSET EQU 0 x10000000,当执行完这段代后,自运的产生PendSV中断,也即14号异常,

14、自动跳到14号异常服务程序执行。在本移植中则会直接去执行:OSPendSV部分内容,8/17/2010,16,中断控制及状态寄存器ICSR 0 xE000_ED04,设置1将挂起中断,8/17/2010,17,#ifndef _OS_CPU_H#define _OS_CPU_H#ifdef OS_CPU_GLOBALS#define OS_CPU_EXT#else#define OS_CPU_EXT extern#endif/*Date types(Compiler specific)数据类型(和编译器相关)*/typedef unsigned char BOOLEAN;/*Boolean 布

15、尔变量*/typedef unsigned char INT8U;/*Unsigned 8 bit quantity*/typedef signed char INT8S;/*Signed 8 bit quantity*/typedef unsigned short INT16U;/*Unsigned 16 bit quantity*/typedef signed short INT16S;/*Signed 16 bit quantity*/typedef unsigned int INT32U;/*Unsigned 32 bit quantity*/typedef signed int IN

16、T32S;/*Signed 32 bit quantity*/typedef float FP32;/*Single precision floating point*/typedef double FP64;/*Double precision floating point*/typedef unsigned int OS_STK;/*wide 堆栈是32位宽度*/typedef unsigned int OS_CPU_SR;/*Define size of CPU statusregister*/*Method of critical section management 临界区管理方法*

17、/#define OS_CRITICAL_METHOD 4/*Other definitions 其他定义*/#define OS_STK_GROWTH 1#define OS_TASK_SW()OSCtxSw()/*Prototypes(see OS_CPU_A.ASM)原型声明(见OS_CPU_A.ASM)*/,#if OS_CRITICAL_METHOD=4void OS_ENTER_CRITICAL(void);void OS_EXIT_CRITICAL(void);#endifvoid OSCtxSw(void);void OSIntCtxSw(void);void OSStartH

18、ighRdy(void);void OSPendSV(void);OS_CPU_EXT INT32U OsEnterSum;#endif/*END FILE*/,8/17/2010,18,3、移植汇编语言编写的4个与处理器相关的函数OS_CPU_A.ASM,(1)OSStartHighRdy():运行优先级最高的就绪任务,OSStartHighRdy(),OSCtxSw(),OSIntCtxSw(),OSTickISR(),OSStartHighRdy()函数是在OSStart()多任务启动之后,负责从最高优先级任务的TCB控制中获得该任务的堆栈指针SP,并通过SP依次将CPU现场恢复。这时系

19、统就将控制权交给用户创建的任务进程,直到该任务被阻塞或都被其他更高优先级的任务抢占CPU。该函数仅仅在多任务启动时被执行一次,用来启动最高优先级的任务执行。移植该函数的原因是,它涉及将处理器寄存器保存到堆栈的操作。,8/17/2010,19,8/17/2010,20,(2)OSCtxSw():任务优先级切换函数,该函数由OS_TASK_SW()宏调用,OS_TASK_SW()由OSSched()函数调用,OSSched()函数负责任务之间的调度。OSCtxSw()函数的工作是,先将当前任务的CPU现场保存到该任务的堆栈中,然后获得最高优先级任务的堆栈指针,并从该堆栈中恢复此任务的CPU现场,使

20、之继续执行,该函数就完了一次任切换。,OSCtxSw PUSH R4,R5 LDR R4,=NVIC_INT_CTRL;触发软件中断 LDR R5,=NVIC_PENDSVSET STR R5,R4 POP R4,R5 BX LR,产生PendSV异常,PendSV并没有马上执行,因为OS_TASK_SW()(实际是OSCtxSw())被调用前中断是关闭的。PednSV只能在中断使能后才能执行。OS_TASK_SW()总是被OS_Sched()调用(见OS_CORE.C文件),8/17/2010,21,8/17/2010,22,触发PendSV异常,当PendSV使能,执行此后将进入中断服务程

21、序,8/17/2010,23,(3)OSInitCtxSw():中断级的任务切换函数,该函数由OSIntExit()调用。由于中断可能会使更高优先级的任务进入就绪态,因此,为了让更高优先级的任务能立即运行,在中断服务子程序的最后,OSInitExit()函数会调用OSInitCtxSw()做任务切换。这样做的目的主要是能够尽快地让高优先级的任务得到响应,保证系统的实时性能。OSInitCtxSw()与OSCtxSw()都是用于任务切换函数,其区别在于,在OSIntCtxSw()中无需再保存CPU寄存器,因为在调用OSIntCtxSw()之前已发生了中断,OSIntCtxSw()已将默认的CPU

22、寄存器保存到被中断的任务堆栈中。,OSIntCtxSw PUSH R4,R5 LDR R4,=NVIC_INT_CTRL;触发软件中断 LDR R5,=NVIC_PENDSVSET STR R5,R4 POP R4,R5 BX LR NOP,OSCtxSw()OSIntCtxSw()这两个函最终都会触发PendSV异常,8/17/2010,24,OSPendSV()函数,OSPendSV()是PendSV(可挂起中断服务)的中断处理函数,它负责C/OS-II的全部上下文切换。这是ARM Cortex-M3提倡的上下文切换方法。使用这程方法的好处理当发生任何的异常时,Cortex-m3自动保存C

23、PU的一半通用寄存器到预先指定的堆栈中,并且在退出异常前按顺序恢复寄存器。OSPendSV()只需保存剩下的R4-R11寄存器并且调整好堆栈指针。这种方法速度快,充分体现了ARM Cortex-M3的优势,而且无论是任务还是异常均可触发此函数切换上下文。注意使用前应在Startup.S中申明。,8/17/2010,25,8/17/2010,26,ARM Cortex-M3任务切换示意图,8/17/2010,27,(4)OSTickISR():时钟节拍中断服务函数,时钟节拍是特定的周期性中断,是由硬件定时器产生的。时钟节拍式中断使得内核可将任务延时若干个整数时钟节拍,以及当任务等待事件发生时,提

24、供等待超时的依据。时钟节拍频率越高,系统的额外开销越大。中断间的时间间隔取决于不同的应用。OSTickISR()首先将CPU寄存器的值保存在被中断任务的堆栈中,之后调用OSIntEnter()。随后,OSTickISR()调用OSTimeTick,检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务。OSTickISR()最后调用OSIntExit()。如果在中断中(或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层,那么OSIntExit()将进行任务调度。,8/17/2010,28,*Function name:tickInit*Descriptions:初

25、始化uC/OS-II的时钟源(系统定时器)static void tickInit(void)SysTickPeriodSet(INT32U)(SysCtlClockGet()/OS_TICKS_PER_SEC)-1);SysTickEnable();SysTickIntEnable();*Function name:tickISRHandler*Descriptions:系统定时器超时中断void tickISRHandler(void)#if OS_CRITICAL_METHOD=3 OS_CPU_SR cpu_sr;#endif OS_ENTER_CRITICAL();OSIntNest

26、ing+;OS_EXIT_CRITICAL();OSTimeTick();/*Call uC/OS-IIs OSTimeTick()*/OSIntExit();,uC/OS-II里面的东东,20,8/17/2010,29,4、移植C语言编写的6个与操作系统相关的函数OS_CPU_C.C,OS_CPU_C.C文件中包含6个和CPU相关的函数,这6个函数为:,这些函数中,唯一必须移植的是任务堆栈初始化函数OSTaskStkInit()。这个函数在任务创建时被调用,负责初始化任务的堆栈结构并返回新堆栈的指针stk。堆栈初始化工作结束后,返回新的堆栈栈顶指针。,OSTaskStkInit()OSTaskDelHook()OSTaskSwHook()OSTaskStartHook()OSTimeHook(),8/17/2010,30,初始化堆栈,8/17/2010,31,8/17/2010,32,THE END,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号