首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

实时操作系统mC/OS-II在AT91上的移植 01

实时操作系统mC/OS-II在AT91上的移植 01

mC/OS-II内核工作原理
    实时嵌入式操作系统mC/OS-II内核的工作原理如图1所示。首先,在主程序中对操作系统进行初始化,完成mC/OS-II所有变量和数据结构的初始化,包括任务控制块(TCB)初始化,TCB优先级表初始化,TCB链表初始化,事件控制块(ECB)链表初始化以及空闲任务的创建等。
    然后,根据应用程序的需要,用户可以调用OSTaskCreate()函数创建多个任务(至少1个)。该函数为新任务建立任务堆栈(OSTaskStkInit())以及初始化任务控制块TCB(OS_ TCBInit())。
    最后,通过调用OSStart()启动多任务调度。程序将跳到就绪表中优先级最高的任务开始执行。这里假设启动多任务调度前创建了一个任务Task1()。
程序进入Task1()后,首先初始化时钟和启动时钟节拍源开始计时。此节拍源给系统提供周期性的时钟中断信号,实现延时和超时确认。然后根据应用程序要求,完成该任务的基本功能。最后,调用OSTimeDly(),将自己挂起,即从就绪表中删除。直到等待延时时间到,才将该任务恢复到就绪表中,并等待调度器的调度。
    OSTimeDly()将任务挂起的同时,为其做好延时记号,然后调用OS_Sched()进行任务级的任务调度。若此时没有任何任务进入就绪态,就切换到空闲任务。
    当时钟中断来临时,系统进入中断服务程序OSTickISR()。系统把当前正在执行的任务挂起,保护现场,进行中断处理OSTimeTick(),判断有无任务延时到期,若有,则使该任务进入就绪态。最后调用OSIntExit()进行中断级的任务调度,从而切换到优先级最高的任务,若没有别的任务进入就绪态,则恢复现场继续执行原任务。

AT91FR40162简介
    AT91FR40162是ATMEL公司出品的一款基于arm7TDMI内核的AT91 16/32位微控制器,其核心为高性能的32位RISC体系结构,并具有高密度的16位指令集和极低的功耗。
arm处理器共有7种运行模式,处理器模式可以通过软件控制进行切换,也可以通过外部中断或异常处理过程进行切换。在每一种处理器模式中有一组相应的寄存器组。任意时刻(也就是任意的处理器模式下),可见的寄存器包括15个通用寄存器(R0~R14)、一个或两个状态寄存器及程序计数器(PC)。
    CPSR(当前程序状态寄存器)可以在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器)。当特定的异常中断发生时,这个寄存器用于存放CPSR的内容。在异常中断程序退出时,可以用SPSR中保存的值来恢复CPSR。

    mC/OS-II在
    AT91FR40162上的移植
    本文使用的内核是mC/OS-II v2.76,选用ADS1.2中的C编译器。
    整个移植过程主要分为两个方面:与应用相关的mC/OS-II配置(OS_CFG.H,INCLUDES.H);与处理器相关的mC/OS-II移植(OS_CPU.H,OS_CPU_A.ASM,OS_CPU_C.C)。
    OS_CPU.H
    此文件中主要是定义了一些与处理器相关的常数、宏以及类型。根据ADS1.2的编译手册,char型变量为8位,short型为16位,int型为32位,堆栈为32位宽。另外,v2.76版本中新增加了一个全局变量OSIntCtxSwFlag,如果需要中断级的任务切换时,就令OSIntCtxSwFlag=TRUE。
    OS_CPU_C.C
    在这里需要编写两个函数:OSInitHookBegin()和OSTaskStkInit()。
    OSInitHookBegin()在OSInit()中调用,用来初始化移植中出现的特殊变量。这里将OSIntCtxSwFlag初始化为0。
    OSTaskStkInit()在OSTaskCreate()和OSTaskCreateExt()中调用,用来初始化任务的栈结构。图2显示了初始化后任务栈的结构。堆栈从上往下递减。mC/OS-II规定任务工作在SVC模式下。另外,根据ATPCS规定,子程序间通过R0~R3传递参数,所以参数p_arg放在R0里。
    与以往的版本不同,这里OSIntCtxSw()(由OSIntExit()调用)并不完成任务的切换工作,仅将OSIntCtxSwFlag变量置1,标志需要进行任务切换。当OSIntExit()调用返回到ISR时,检查OSIntCtxSwFlag变量,如果为1,则跳到OS_IntCtxSw()函数执行任务切换。
    OS_CPU_A.S
    由于C语言不能对寄存器进行直接操作,所以必须用汇编语言编写以下函数。
    OSStartHighRdy()由OSStart()调用。该函数使就绪态任务中优先级最高的任务开始运行。注意开始要将IRQ和FIQ中断禁止,最后从堆栈弹出所有寄存器时,必须按照OSTaskStkInit()中相反的顺序弹出。
    OSCtxSw()由OSSched()调用,完成任务级的任务切换。任务级的任务切换包括将当前任务在SVC模式下的寄存器压入任务栈中,并且将新任务的堆栈弹出到SVC模式下的寄存器中。注意必须按照OSTaskStkInit()中任务栈的结构对任务栈进行操作。
    OS_CPU_SR_Save()用于关中断,OS_CPU_SR_Restore()用于开中断。OS_CPU_SR_Save()将CPSR保存到R0中,通过将CPSR中I位和F位置1来禁止IRQ和FIQ中断。OS_CPU_SR_Restore()只需将R0中保存的CPSR恢复即可。
    OS_IntCtxSw()完成中断级的任务切换。当检查OSIntCtxSwFlag变量为1时,就调用该函数。因为OS_IntCtxSw()是在ISR中被调用的,所以所有的处理器寄存器都已经被正确地保存到了被中断任务的堆栈中。
    mC/OS-II 要求用户提供一个周期性的时钟源,来实现时间的延迟和超时功能。
返回列表