您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > uCOS-II在51单片机上的移植
1uc/os-II操作系统的移植所谓操作系统的移植,是指使一个实时操作系统能够在某个特定的微处理器平台上运行。COS-II的主要代码都是由标准的C语言写成的,移植方便。但仍需要用汇编语言写一些与处理器相关的代码,这是因为µC/OS-Ⅱ在读写处理器寄存器时只能通过汇编语言来实现。移植的主要工作是修改部分与处理器硬件相关的代码。2处理器的C编译器能产生可重入代码。在程序中可以打开或者关闭中断。处理器支持中断,并且能产生定时中断(通常在10-100Hz之间)。处理器支持能够容纳一定量数据的硬件堆栈(可能达几KB)处理器有将堆栈指针和其他CPU寄存器存储和读出到堆栈(或者内存)的指令。7.1.1移植uC/OS-II满足的条件uC/OS-II是通过硬件中断来实现系统时钟,并在时钟中断服务程序中来处理与时间相关的问题的。因此,用户所选用的处理器必须具有响应中断的能力。一般情况下应该使用硬件定时器来作为时钟中断源,这个定时器可以是与微处理器集成在一个芯片上的,也可以是分立的。3可重入的代码指的是一段代码(比如:一个函数)可以被多个任务同时调用,而不必担心会破坏数据。也就是说,可重入型函数在任何时候都可以被中断执行,过一段时间以后又可以继续运行,而不会因为在函数中断的时候被其他的任务重新调用,影响函数中的数据。可重入的代码的实现主要是编程技术,所有嵌入式集成开发环境都能产生可重入的代码。7.1.2什么是可重入代码inttemp;voidSwap(int*x,int*y){temp=*x;*x=*y;*y=temp;}例如,任务A和任务B都要调用函数Swap(),而该函数又使用了全局变量temp。于是当任务A调用Swap()函数期间,系统发生了任务切换而使任务B也调用了Swap(),那么任务B将要改变全局变量temp的值,使任务A传递给全局变量temp的值丢失而出现错误。一般来说,一个可重入函数应该在函数中只使用局部变量,因为函数的局部变量存储在任务的堆栈中,所以可保证不同的任务在调用同一个函数时不会发生冲突。47.1.3系统栈与任务栈的关系……被中止运行的任务堆栈……被运行的任务堆栈……系统堆栈CPUSP图7-1系统栈与任务栈的关系有些处理器对于堆栈的设置有特殊的要求,即要求堆栈必须设置在一个特定的区域,比如片内RAM。由于片内的RAM极其有限,不可能把应用程序中所有任务的堆栈都设置在片内RAM中,所以就只能把应用程序中各个任务堆栈的内容存放在片外RAM中,而只在片内RAM中设置一个公用的堆栈。片外的RAM用来存放任务堆栈,片内RAM中是系统的公共堆栈,当系统运行某个任务时,就要把该任务的堆栈映像复制到系统堆栈中;而在中止这个任务时,再把系统堆栈中的内容复制回任务堆栈映像中。57.1.4uC/OS-II文件结构图7-2uC/OS-II的文件结构6名称函数/宏定义所在文件语言功能OS_CRITICAL_METHOD宏定义OS_CPU.HC语言处理临界段方式选择OS_STK_GROWTH宏定义OS_CPU.HC语言堆栈增长方向OS_ENTER_CRITICAL()宏定义OS_CPU.HC语言进入临界区OS_EXIT_CRITICAL()宏定义OS_CPU.HC语言退出临界区OSStartHighRdy()函数OS_CPU_A.ASM汇编就绪态最高优先级任务运行OSCtxSw()函数OS_CPU_A.ASM汇编任务级任务切换OSIntCtxSw()函数OS_CPU_A.ASM汇编中断级任务切换OSTickISR()函数OS_CPU_A.ASM汇编时钟节拍OSTaskStkInit()函数OS_CPU_C.CC语言任务堆栈初始化表7-1需要修改的关键函数和宏定义7.1.5需要修改的关键函数和宏定义77.1.6INCLUDES.H使得项目中的每个.c文件不用分别考虑它实际上需要那些头文件。它会包含一些不相关的头文件INCLUDES.H是一个头文件,它在所有的.c文件的第一行被包含。#include“includes.h”/****************************************************************************uC/OS-II实时内核*(c)Copyright1992-1998,JeanJ.Labrosse,Plantation,FL*版权所有*MCU-51专用代码KEILC51大模式编译**文件名:INCLUDES.H*作者:JeanJ.Labrosse****************************************************************************/#includeos_cpu.h#includeos_cfg.h#includeucos_ii.h#includereg51.h#includestring.h87.1.7OS_CPU.H/*******************数据类型(与编译器相关的内容)********************/typedefunsignedcharBOOLEAN;typedefunsignedcharINT8U;typedefsignedcharINT8S;typedefunsignedintINT16U;typedefsignedintINT16S;typedefunsignedlongINT32U;typedefsignedlongINT32S;typedeffloatFP32;typedefdoubleFP64;typedefunsignedintOS_STK;OS_CPU.H中包括与处理器相关的常量、宏以及类型。97.1.7OS_CPU.H(续)/*******************与处理器相关的代码********************/#defineOS_CRITICAL_METHOD??#ifOS_CRITICAL_METHOD==1#defineOS_ENTER_CRITICAL()??#defineOS_EXIT_CRITICAL()??#endif#ifOS_CRITICAL_METHOD==2#defineOS_ENTER_CRITICAL()??#defineOS_EXIT_CRITICAL()??#endif#ifOS_CRITICAL_METHOD==3#defineOS_ENTER_CRITICAL()??#defineOS_EXIT_CRITICAL()??#endif#defineOS_STK_GROWTH1#defineOS_TASK_SW()???107.1.8OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()临界代码的概念。uC/OS-II定义的两个宏。{OS_ENTER_CRITICAL();/*µC/OS-II临界代码段*/OS_EXIT_CRITICAL();}三种实现方法。方法1:在OS_ENTER_CRITICAL()中调用处理器指令来禁止中断,以及在OS_EXIT_CRITICAL()中调用允许中断指令。方法2:是先将中断禁止状态保存到堆栈中,然后禁止中断。方法3:有些编译器提供扩展功能,可以得到当前处理器状态字的值。#defineOS_ENTER_CRITICAL()EA=0#defineOS_EXIT_CRITICAL()EA=1#defineOS_ENTER_CRITICAL()\asm(“PUSHPSW”);asm(“DI”);#defineOS_EXIT_CRITICAL()\asm(“POPPSW”);voidsome_ucos_ii_service(){OS_CPU_SRcpu_sr;cpu_sr=get_processor_psw();disable_interrupts();/*µC/OS-II临界代码段*/set_processor_psw(cpu_sr);}117.1.9OS_STK_GROWTH绝大多数的微处理器和微控制器的堆栈是从上往下长的。但是某些处理器是用另外一种方式工作的。µC/OS-Ⅱ被设计成两种情况都可以处理,只要在结构常量OS_STK_GROWTH(在OS_CPU.H中)中指定堆栈的生长方式(如下所示)就可以了。置OS_STK_GROWTH为0表示堆栈从下往上长。置OS_STK_GROWTH为1表示堆栈从上往下长。127.1.10OS_TASK_SW()OS_TASK_SW()是一个宏,它是在µC/OS-Ⅱ从低优先级任务切换到最高优先级任务时被调用的。在µC/OS-Ⅱ中,处于就绪状态的任务的堆栈结构看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。换句话说,µC/OS-Ⅱ要运行处于就绪状态的任务必须要做的事就是将所有处理器寄存器从任务堆栈中恢复出来,并且执行中断的返回。为了切换任务可以通过执行OS_TASK_SW()来产生中断。大部分的处理器会提供软中断或是陷阱(TRAP)指令来完成这个功能。例如,在Intel或者80x86处理器上可以使用INT指令。但是中断处理向量需要指向OSCtxSw()。一些处理器并不提供软中断机制。在这种情况下,用户需要尽自己的所能将堆栈结构设置成与中断堆栈结构一样,再用函数调用方式来实现任务切换,也就是说通过函数来模仿软中断指令。如#defineOS_TASK_SW()OSCtxSw()当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态,即CPU寄存器中的全部内容。这些内容保存在任务的当前状态保存区,也就是任务自己的堆栈区中。入栈工作完成后,就是把下一个将要运行任务的当前状态从该任务的堆栈中重新装入CPU寄存器,并开始下一个任务的运行,这个过程叫任务切换。137.1.11OS_CPU_C.COSTaskStkInit()OSTaskCreateHook()OSTaskDelHook()OSTaskSwHook()OSTaskIdleHook()OSTaskStatHook()OSTimeTickHook()OSInitHookBegin()OSInitHookEnd()OSTCBInitHook()OS_CPU_C.C文件包含10个C函数:唯一必要的函数是OSTaskStkInit(),其它九个属于钩子函数,必须得声明但没必要包含代码。147.1.11.1OSTaskStkInit()OSTaskCreate()和OSTaskCreateExt()通过调用OSTaskStkInt()来初始化任务的堆栈结构,因此,堆栈看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。编写OSTaskStkInit()函数的第一步就是堆栈设计。需要考虑以下因素:①CPU自动入栈的寄存器及压栈顺序。②需要额外保存哪些寄存器。③所采用的编译器对形式参数的传递方法。④堆栈的增长方向。⑤堆栈指针是指向下一个可用空间还是指向上次入栈数据。⑥所采用的CPU是否存在系统堆栈。⑦堆栈深度。任务按函数形式编写,但永远不被调用,而是通过模仿中断的方式来运行其中的代码。既然任务通过模仿中断的方式来进行,而且拥有自己单独的任务栈,那么需要做的就是执行中断返回指令,让任务中的内容出栈,让系统觉得该任务(或者说是所谓的“函数”)刚刚被中断过,现在需要继续执行。但在系统刚开始运行的时候,任务是没有被系统中断过的,也没有被切换过,任务栈里没有内容。所以需要通过OSTaskStkInit()来初始化任务栈,模拟一次压栈动作,使得系统认为任务刚刚被中断过。157.1.11.2HOOK类函数OSTaskCreateHook()当用OSTaskCreate()或OSTaskCreateExt()建立任务的时候就会调用OSTaskCreateHook()。OSTaskDelHook()当任务被删除的时候就会调用OSTaskDelHook()。OSTaskSwHook()当发生任务切换的时候调用OSTaskS
本文标题:uCOS-II在51单片机上的移植
链接地址:https://www.777doc.com/doc-4904501 .html