摘 要: 基于对ARM11架构的启动模式与内存分配的技术研究,通过对Nucleus内核的分析,在ARM11架构的芯片上实现Nucleus操作系统的移植。以S3C6410为例,详细介绍了从板级初始化到任务循环调度过程中的启动模块、中断设计、定时器设计、任务调度流程与触发方式。目前成功移植于TD-LTE系统中,实现操作系统基本功能的同时满足了实验项目中TD-LTE对系统实时性与任务资源管理的需求。
关键词: Nucleus操作系统;移植;启动加载;中断;任务调度
Nucleus操作系统作为一个实时性较强的嵌入式操作系统具有较高可移植性,目前在ARM(Advanced RISC Machines)架构上已经成功实现移植,现有文献中实现多基于较老的ARM7或是ARM9架构,并且介绍笼统,和实际结合不紧密[1-2]。本文详细介绍Nucleus在ARM11架构上的移植,以S3C6410芯片的实验数据为证,分析在移植过程的内存分配、堆栈配置、时钟、中断设置。文中详细阐述了具体应用于TD-LTE系统时,移植过程中启动模块设计对系统性能的影响,以及内核移植中的关键接口和系统任务调度方式。
1 基本启动流程与内存分配
移植过程中的基本流程如图1所示。
流程中的各个部分的设置并非是像框图这样独立开来的,在实际的应用设计中各个模块都是互相有联系的,会根据加载方式的不同、内存分配的差异或是具体功能的要求而产生关联性的改变。在后面几个重要模块的移植过程介绍中也会对此详述。
移植的目的在于应用,本移植应用于TD-LTE无线综合测试仪中(该产品采用ARM11架构的S3C6410芯片),为该产品实现协议层的任务调度。很多实验项目中采用手动方式加载启动模块,然而在应用中,实现一个产品不可能像普通的调试程序一样手动加载驱动与操作系统,然后进入任务调度,因此需要实现自动加载而利用到Flash。
另外中断向量表设置必须从内存起始地址0x0000-0000加载[3],否则无法实现正常硬件中断,而在中断产生时使得程序异常终止。在启动时首先要完成两个模块的加载,一是硬件的初始化模块,需要在SROM启动调试模式下烧写到Flash中,Flash启动模式下自动加载到0x0c000000上并自动拷贝到0x00000000运行;第二个模块是操作系统的初始化模块,在启动过程中Flash自动烧写加载到DDR中运行[4],操作系统模块同样需要设置中断向量表。然而这时的起始内存地址0x00000000已经被模块一占用,因此需要设计一种机制在启动过程中动态加载操作系统。
这些限制都是在中断向量表设置与内存分配中需要综合考虑的。下面介绍两种方式来实现上述启动加载,并在后文进行比较测试。
1.1 基于MMU的启动设计
传统的MMU(存储器管理单元)方式,即是在内存上做映射。具体方案是在第一部分的硬件初始化程序段中从0x50000000到0x59000000的DDR物理地址做地址映射,实现中在0x50000000到0x51000000部分存放页表,建立虚拟存储空间,映射地址为0x00000000到0x08000000,这样可以在SROM启动模式和Flash启动模式下将带有中断向量表的操作系统模块从映射过的0x00000000位置加载,完成中断向量表设置[4]。内存分配方式如图2所示。
图2 MMU方式的内存分配模式
但是映射后读写系统数据时会使用到页表查询来计算实际物理地址,影响到系统效率。
1.2 基于重写的启动设计
映射方式虽然设计与加载方面比较简单方便,但是由于采用了MMU会产生页、段等数据换算,同时还要兼顾DDR的运行速度,数据读写速度可能跟不上,因此在设计过程中也设计了第二套方案,考虑如何在不使用MMU的条件下实现启动加载[5]。采用重写方式来实现。由于函数调用会使用到堆栈空间,因此重写部分必须在操作系统模块堆栈空间分配完成后实现,采用memcpy()函数(内存复制函数)将在0x50000000位置的中断向量表复制重写到0x00000000地址。由于系统在0x50000000后面的地址上运行,这种方法在中断发生时会有比较大的内存跨越寻址,也会对系统执行效率有些许影响。此外这种方法还有一个无法避免的缺点,就是在SROM启动的调试模式无法实现,因为S3C6410在该启动模式下0x00000000是只读的(无法重写),因此只能在Flash启动模式加载。
1.3 两种启动方式的性能对比
上述两种方案各有优缺点,因此笔者通过在现实情况比较接近的中断频率条件下写入等量数据到相同内存下,并比较写入时间来确定较优方案。通过在写数据前后拉高拉低电平来统计时间,在0.5 ms一次的中断频率下,写10万个8 bit数据到操作系统中声明的相同数组上,所用时间在示波器上的截图如图3所示。
图中X部分是使用了MMU的映射内存启动模式,10万8 bit数据耗时约2.82 ms,而Y部分所示采用重写方式下耗时约为1.33 ms,可见采用重写方式加载中断向量表具有比较明显的执行效率优势,更能满足实际需求。当然在调试过程中采用MMU方式是比较便于调试修改的,无需每次修改后都进行Flash烧写,而且MMU方式对ARM7以上架构具有普遍实用性,而重写方式仅在本实例中实现,因此MMU方式也有其实用性。
2 中断与定时器
定时器是通过中断来实现的,这里一并介绍。首先在Nucleus的启动代码加载前配置文件存储区域结束地址,通常可采用标示符“|Image$$ZI$$Limit|”作为堆栈起始加载地址,避免加载运行后,破坏代码存储区;其次需要在Nucleus内核初始化区域中对高级中断进行配置并设置堆栈区域,以支持定时器初始化;然后传递堆栈分配结束地址到应用初始化模块,用于动态分配内存池;最后切换到SVC模式运行系统,方便系统设置与模式切换。上述几点是Nucleus内核加载配置的几个关键点。
2.1 硬中断(低级中断)
硬中断是由硬件触发的中断,通过硬件引脚的电平变动触发,有最高的实时性,且可以通过公共引脚来实现外部设备的交互。本文介绍其中3个关键中断,分别对应S3C6410的VIC0、VIC1、VIC28(Vectored Interrupt Controller)寄存器,其中VIC0与VIC1对应外部中断,本文在应用中设计为DSP中断与FPGA中断,VIC28对应PWM定时器,其他功能性中断在这里就不赘述。
在设计中采用IRQ中断模式,中断发生时现场保护比较重要,值得注意的是在低级中断中采用C语言自带的“__irq”做返回值的方法来保护现场是不可取的,Nucleus硬中断需要对寄存器做更有针对性的保护,Nucleus提供了内核级接口对现场做详细保护。首先在IRQ中断入口处对A1到A4寄存器做压栈保护,并保存IRQ模式下的lr寄存器,然后调用Nucleus提供的函数TCT_Interrupt_Context_Save(内核函数)现场保护,并在中断服务处理完成后调用TCT_Interrupt_Context_Restore(内核函数)恢复现场。
2.2 高级中断
高级中断可以有效处理低级中断中需要高效处理或是嵌套处理实时任务的情况。以本应用为例,由于FPGA中断服务中做的数据处理需要消耗一定的时间,而且在系统IRQ中断过程中IRQ中断处于屏蔽状态,因此会出现在中断处理过程中积压后面的中断服务的情况,这里就可以设置高级中断,在低级中断服务中只需将高级中断激活,耗时极短,数据处理由操作系统在高级中断中调度完成。图4中第一行波形高电平段为FPGA中断。
此外在有强时序性的任务调度中,也可以使用高级中断来保障时序同时不影响系统低级中断的实时性。在本应用中DSP中断中的数据处理与协议栈小区激活部分的数据处理都具有强时序性同时由于数据处理量较大会影响系统实时性,导致指针号无法对齐或指针号记录积压等问题,这里也需要使用高级中断来激发任务,加强系统实时性。图4中第二行高电平段为DSP中断数据处理。
从图4中可以看出,采用了高级中断的FPGA子帧中断的时间非常的短,几乎可以忽略不计,第二行的高电平为DSP处理消息时需要耗费的时间长度为465 ?滋s,可见该处理时间较长,若在低级中断中处理很可能影响到FPGA中断的时序,从而影响系统时序。在图中明显可以看到低级中断与任务处理间的调度时间间隔在微秒级,完全满足系统实时性的性能指标。同时在DSP数据处理完成后后续任务的执行在第三行波形中显示出来,运行时序正常。
2.3 定时器设计与中断整体设计
操作系统定时器采用PWM硬件定时器做节拍计时,根据TD-LTE无线综合测试仪的设计要求,采用了0.5 ms一次的节拍频率作为操作系统定时的基本单位。设计中采用Timer4硬件定时器,并开启自动重置(Auto-Reload)模式使计时持续。在每0.5 ms产生一次的定时器硬件中断中调用TMT_Timer_Interrupt()函数(内核函数)来将硬件定时器与Nucleus操作系统关联[6]。整体中断设计如图5所示。
移植应用中可以通过PWM调整定时器单位时间,如果使用了外部设备中断产生单位时间中断,也可作为定时器使用,只需要把TMT_Timer_Interrupt()放在该外部中断中即可。
3 任务调度
根据TD-LTE无线综合测试仪中的设计要求TD-LTE任务流程与触发方式涉及到应用初始化与任务调度设置两个模块。在应用初始化内需要做内存池初始化、任务初始化、队列初始化、时钟设置初始化与高级中断初始化等工作,这些工作比较常规在这里不再详述。任务调度设置需要根据协议栈各层顺序设置,在各层任务中需要设置任务触发方式,任务流程如图6所示。
本文采用队列方式进行任务调度。各任务间采用消息机制触发并支持抢占,操作系统运行时首先在循环调度中按顺序调度任务并将每个任务挂起,在此之后的调度中在每个任务中检查队列中是否有对应消息,需要执行该层任务的时候就在前一个任务中发送该层对应消息到队列中,检测到消息后该层任务从挂起状态进入就绪或执行状态,不需要执行该层任务的时候不发送消息给该层,该层任务在检测不到消息的情况下就会挂起任务等待下一次调用[7],在没有任务的情况下系统进入idle状态等待计时器激活或是硬件中断发生。其中小区激活与DSP任务采用外部硬件中断机制激活,外部中断激活高级中断,任务在高级中断来执行,既可以满足操作系统实时性也可以很好的管理好各层任务。
操作系统移植过程中不仅需要从硬件角度来实现操作系统的正常运作还需要综合考虑系统的管理性能与整个系统的执行效率和实时性。移植后在ARM Workbench IDE v4.0与RealView Debugger v4.0上编译调试,并通过测试板验证和联机验证,运行结果和理论值一致。此移植具有较强的独立性和稳定性,优化了系统资源利用率,实现了任务中断与任务调度的高强度反复稳定运行,符合项目“TD-LTE无线终端综合测试仪表” 调试中对系统实时性与资源调度的要求并应用于其中。
参考文献
[1] 李书根,潘海燕,王培.一种嵌入式实时操作系统高可靠文件系统[J].微电子学与计算机,2014,31(2):14-16.
[2] 徐宇柘,钟锐.Nucleus实时操作系统在继电保护系统中的实时性研究[J].电脑知识与技术,2007(13):3-4.
[3] 杜春雷.ARM体系结构与编程[M].北京:清华大学出版社,2003.
[4] Samsung Electronics.S3C6410X RISC microprocessor user′s manual[Z].2008.
[5] LEE J,PARK J,HONG S.Memory footprint reduction with quasi-static shared libraries in MMU-less embedded systems[C].Real-Time and Embedded Technology and Applications,2006,Proceedings of the 12th IEEE,2006:24-36.
[6] Accelerated Technology,Inc..Nucleus NET reference manual[Z].2005.
[7] NGOLAH C F,Wang Yingxu,Tan Xinming.Implementing task scheduling and event handling in RTOS+[C].Electrical and Computer Engineering,2004,Canadian Conference,2004:1523-1526.