实时操作系统μC/OS- II在真空炉控制系统中的应用
出处:xlg357300 发布于:2007-05-24 17:50:02
真空炉控制系统具有数据采集、处理、动作实施、监控、保护和网络通信等功能。在正常工作时,负责采集真空炉的运行参数,例如温度、真空度、加热元件的电压、电流等相关参数。并对数据进行处理,把处理结果与给定的工艺设置进行比较后,发出相关执行命令,在系统发生故障时,控制系统还提供检测、记录、保护等功能。 该基于ARM的工业嵌入式系统价格便宜,功能强大,维护操作简单,运行稳定,安全可靠。软件部分工作,主要包括μC/OS-II的移植以及应用软件的编写。 移植μc/OS-II的主要工作是处理器和编译器相关代码及BSP的编写。 前提条件 (1) 处理器的c编译器支持可重人函数; (2) 程序中打开和关闭中断; (3) 处理器支持中断,并且能产生定时器中断(uC/OS-II是通过定时器中断来实现多任务的调度,即时间片的产生); (4) 处理器要具有一定的硬件堆栈数量。 (5) 处理器要有将堆栈指针和其他CPU寄存器存储和读出堆栈(或者内存)的指令。 在此次系统改造中,使用的Atmel工业级处理器AT91RM9200(ARM920T)完全满足以上条件。 UCOS肩动中,系统在完成初的硬件初始化以后便转入由开发者提供的main(),在main()中再调用一个内核函数OSInit()来完成内核的初始化,然后在完成了与应用相关的初始化以后,就可以调用一个内核函数OSStart()启动内核的进程调度。从上面的过程看出,main()函数其实是一个回调函数,整个系统的人口是建立在特定CPU(汇编语言编写的底层函数和数据结构)硬件初始化环境的程序中。 UCOS内核引导装入程序与硬件初始化程序连接,或者说在其上构建内核引导装入程序。 引导程序针对具体的微处理器及其配置,完成系统内存映射、中断向量初始化、系统堆栈空间的分配和C语言变量初始化。,通过跳转指令转向C语言主程序main,在主程序中CPU的控制权交给操作系统。其中,内存映射是对系统所使用的外部存储器以及内部使用的所有功能模块的初始化,以便程序能正确地操作。中断向量的初始化是将中断处理程序存储在相应的中断向量位置。系统堆栈空间的分配主要是对处理器的7种工作模式分别设置栈底和堆栈大小,这保证多任务切换或者异常中断时,当前CPU的运行状态被保存,从而保证系统正常运行。 主要包括如下步骤:标志整个代码的初始人口点;设置异常中断向量表;初始化存储系统;初始化MMU;将已经初始化的数据搬运到可写的数据区;初始化各个模式下的数据栈;初始化一些特殊外围接口;中断处理程序;使能IRQ异常中断等。以上的步骤中根据处理器中相应的寄存器,进行数据的读写即可。 μC/OS-II移植 虽然μC/OS-II的大部分代码是用C语言编写,但还存在了一些与处理器相关的汇编语言代码,从而实现对处理器寄存器的访问以及堆栈的操作。μC/OS-II的体系结构如图1所示,可以看出μC/OS-II操作系统的移植主要是改写如下3个文件:
OS_CPU.H OS_CPU.H包括一系列用#define定义的与处理器相关的数据类型、宏和常量,如关中断、开中断、任务切换和堆栈增长方式等。 (1) 数据类型定义 数据类型的修改与所用的编译器相关,不同的编译器使用不同的字节长度表示同一数据类型。在系统中定义整型数据结构为32位的整数。 (2) 堆栈单位及增长方向 在任务切换时,CPU现场的寄存器将保存在当前运行任务的堆栈中,所以OS_STK数据类型应与CPU的寄存器长度一致。 AT91RM9200堆栈由高地址向低地址增长。在函数调用时,人口参数和返回地址一般保存在当前任务的堆栈中,编译器的编译选项和由此生成的堆栈指令就会决定堆栈的增长方向。置Os_stk_growth为0,表示堆栈从下(低地址)往上递增。 (3) 宏定义 包括开关中断的宏定义,以及进行任务切换的宏定义。 μc/OS-II在处理临界代码时要先关中断,处置完后再打开,这样可保护临界代码不被多任务和中断服务子程序破坏,处理器提供汇编指令os_enter_critical()、os_exit_critical()来开关中断。通过对os_critical_method赋值来选择方式。 Os_task_sw()是从低优先级任务切换到高优先级任务时须用到的一个宏。Os_task_sw()总是在任务级代码中被调用。 OS_GPU_C.C OS_CPU_C.C中包括一系列C语言函数:OSTaskStkInit()和若干个Hook函数。必要的是OSTaskStkInit(),其他9个只须声明,并不一定包含任何代码。 实现任务初始化时的堆栈设计。在ARM体系结构下,任务堆栈空间由高至低依次保存着pc、lr等寄存器。一方面,当前任务堆栈初始化完成后,OSTaskStkInit返回新的堆栈指针STK,OSTaskCreate()执行时,将会调用OSTaskStkInit的初始化过程,然后通过OSTCBInit()函数调用,将返回的SP指针保存到该任务的TCB块中;其次,初始状态的堆栈是模拟了中断后的堆栈结构,因为任务创建后并不是直接就获得执行,而是通过OSSched()函数进行调度分配,满足执行条件后才能获得执行。为使调度简单一致,预先将该任务的PC指针和返回地址LR都指向函数人口,以便被调度时从堆栈中恢复刚开始运行时的CPU现场。 OSTaskstkInit()在创建任务时被OSTaskCreate()或OSTaskCreateExt()调用来初始化任务的堆栈结构。表1显示了在AT91RM9200中需要放到任务堆栈中的寄存器及其顺序。
OSTaskStkInit()的代码如下,4个参数中,task是任务的起始地址,pdata是传给任务的数据指针,ptos是初的SP,opt没有用到。函数返回的是全部人栈操作完成后的新的SP。 OS_CPU_C.ASM OS_CPU_A.ASM中包括4个汇编语言函数:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、OSTickISR()。 Osstart()调用OSStartHighRdy()函数使就绪态任务中优先级的任务开始运行。任务级的切换是通过执行软中断指令,或依据处理器的不同,执行陷阱指令实现。中断服务子程序、陷阱或异常处理的向量地址必须指向OSCtxSw()。 OSIntCtxSw0实现中断级的任务切换,在ISR中被调用的,由于所有的CPU寄存器都已经被ISR正确地保存到了被中断任务的堆栈之中,并且如果该ISR是中断嵌套的层,则ISR已经将SP保存到被中断任务的任务控制块(TCB)中了。因此除了不需要再保存CPU寄存器和堆栈指针外,OSIntCtxSw()完全可以采用OSCtxSw()中的大部分代码,实际上本系统中的中断级切换就是直接跳转到OSCtxSw()中的标号为_OSIntCtxSw的那一行的。 μC/OS-II要求用户提供一个周期性的时钟源实现时间的延迟和超时功能,可以使用硬件定时器,也可以从交流电中获得50/60Hz的时钟频率。Osintexit()通过调用osintctxsw ()函数在ISR中执行任务切换功能。 OSTickISR()的主要任务就是调用函数OSTimeTick(),其作用是给每个需要延时的任务的延时时间OSTCBDly减1(如果该项不为零的话)。当某个任务的OSTCBDly减到了零,这个任务就进入了就绪态。具体代码如下: 将μC/OS-II引入嵌入式系统后,应用程序的设计就变得非常简单。尽管真空炉控制功能繁多,但可以将比较复杂的程序层次化,按照功能划分为多个任务,各个任务可以分别编写,但要事先设计好任务间的通信方式,这样程序将更容易开发与维护。 我们根据应完成的功能将应用软件划分为十个用户任务和4个ISR,按照任务的重要性和是否具有硬实时性来分配优先级,优先级数值越低,任务的优先级越高。所有给任务分配的优先级都是在用户自定义头文件userdef.h中用宏来定义的,由于保护处理任务需要大量的局部变量空间,故而该任务的堆栈非常大,为2048字节,其余任务均为128字节。所有任务的编号、名称和功能描述如表2所列。
任务其实就是一个简单的无限循环的程序,该程序可以认为CPU完全只属于它自己。在循环中必须调用延时或等待消息等函数,以便将CPU控制权交给其他的任务。在上述任务中,比较复杂的就是保护处理任务。它根据A/D中断子程序中采集到的瞬时值计算出电流的基波及二次谐波分量,结合相应的电压信号,判断是否有线路故障,如是则启动故障后录波,然后向主站上报故障信息。除此之外,该任务还能配合通信任务进行远方或当地定值整定。任务流程从略。 μC/OS-Ⅱ提供一个计算CPU使用率的统计任务OSTaskStat()。该任务每秒钟运行,计算当前的CPU使用率。如果应用程序打算使用统计任务,必须在初始化时建立一个的任务,并且只在这个任务中调用OSStatInit()。换句话说,在调用系统启动函数OSStart()之前,必须先建立一个任务,在这个任务中调用统计初始化函数OSStatInit(),然后再建立应用程序中的其他任务。 有时候决定任务实际所需的堆栈大小是很有必要的,这样我们就可以避免为任务分配过多的堆栈空间。μC/OS-II提供的函数OSTaskStkChk()可以为开发者提供这种有价值的信息。每调用该函数,就会执行堆栈检验。每次在调用OSTaskStkChk()的时候,可能会得到不同的空闲空间数。应该让应用程序运行足够长的时间,才有可能经历坏的堆栈使用情况,这样才能得到正确的信息,我们就可以据此重新设置堆栈的终容量了。 实测证明,采用μC/OS-II提高了系统的实时性,特别是提高了通信处理和保护处理等较高优先级任务的响应速度。在满足系统对实时性的整体要求的基础上,μC/OS-II所采用的基于优先级的调度策略可以限度地满足关键的任务。同时以μC/OS-II作为整个软件体系的基础,非常方便应用软件的模块化设计。各个任务之间除通过μC/OS-II提供的函数进行通信之外,没有其他的联系途径,这种松耦合结构提高了整个软件的可靠性。 | |||
上一篇:浅谈ARM仿真器中的断点资源
下一篇:嵌入式系统中的零功耗设计
版权与免责声明
凡本网注明“出处:维库电子市场网”的所有作品,版权均属于维库电子市场网,转载请必须注明维库电子市场网,https://www.dzsc.com,违反者本网将追究相关法律责任。
本网转载并注明自其它出处的作品,目的在于传递更多信息,并不代表本网赞同其观点或证实其内容的真实性,不承担此类作品侵权行为的直接责任及连带责任。其他媒体、网站或个人从本网转载时,必须保留本网注明的作品出处,并自负版权等法律责任。
如涉及作品内容、版权等问题,请在作品发表之日起一周内与本网联系,否则视为放弃相关权利。
- 深入解析嵌入式 OPENAMP 框架:开启异核通信新时代2025/7/22 16:27:29
- 一文快速了解OPENWRT基础知识2025/7/14 16:59:04
- 独立 ADC 优势大揭秘:为何不可替代?2025/7/7 16:21:04
- 深入剖析:嵌入式中 RS485、RS422 和 RS232 的特点差异2025/7/5 15:07:54
- 揭秘嵌入式 MCU:浮点数据处理难点及应对策略2025/6/20 15:19:07