功能分析
Linux 内核中灵活的模块化机制在 RTAI 中得到完美发挥。按照实现功能的不
同,RTAI 将系统划分为多个不同的模块,比如:硬件抽象层模块、实时任务调度
模块、管道机制模块、内存共享机制模块、邮箱机制模块和信号量机制模块等。
接下来对 RTAI 的几个主要功能模块进行简单介绍。
硬件抽象层模块(rtai_hal.ko)是 RTAI 最重要的模块之一。该模块主要实现
与 ADEOS 之间进行交互的功能,比如:分配虚拟中断、初始化 RTAI 域和向 ADEOS
注册 RTAI 域的中断处理函数等。
按照运行空间的不同,RTAI 的实时任务分为两类:内核空间的实时任务和用
户空间的实时任务。两种实时任务对应的任务调度模块有所区别。因此,实时任
务调度模块分为内核空间的 rtai_sched.ko 和用户空间的 rtai_lxrt.ko。rtai_sched.ko
主要实现的内核空间的实时任务的调度执行,满足系统的硬实时要求。rtai_lxrt.ko
模块是 RTAI 实现的用户空间实时任务调度模块,RTAI 支持 LXRT 机制允许在用
户空间创建软实时任务,满足系统的软实时要求。目前,RTAI 支持 SCHED_FIFO
和 SCHED_RR 两种调度策略,支持 RM 和 EDF 两种调度算法。RTAI 的默认调度
策略和默认调度算法分别是 SCHED_FIFO 和 RM。RTAI 实现的调度器支持两种定
时器工作模式:period 和 one-shot。
RTAI 支持多种进程间通信方式。管道机制模块(rtai_fifos.ko)和共享内存机
制模块(rtai_shm.ko)分别是 RTAI 域的实时任务和 Linux 域的非实时任务之间通
过管道和共享内存的方式进行交互的接口。
当嵌入式 Linux 中实现了 ADEOS 之后,RTAI 的各功能模块就可以通过 insmod
命令以动态模块的形式加载到系统中。
RTAI的关键技术
RTAI 的实现主要包含两个关键技术:中断虚拟器和细粒度时钟。
中断虚拟器:
在分析标准 Linux 实时性受限的原因时,其中有一条是中断机制的问题,针对该问题,RTAI 在内核与硬件之间引入了中断虚拟器。
中断虚拟器与内核的交互主要表现为:接收到硬件中断后,先向内核通知中断的产生,并将中断置于中断管道中,再沿着管道通过某种中断分发机制将接收到的中断依次进行传递。
中断虚拟器对硬件的控制主要体现为:系统向硬件发出的控制命令(如开/关中断等)后,并不像 Linux 系统一样直接操作硬件,而是先被中断虚拟器接收,再由它进行相应的处理。
引入中断虚拟器之后,RTAI 的中断处理流程是:系统接收到中断后,先试着执行与该中断对应的 RTAI 域的中断处理程序,如果系统发现它并没有注册该中断处理程序,则通过 ADEOS 的 IPIPE 将该中断传播给 Linux 域。
细粒度时钟:
针对 Linux 实时性受限的另一原因:时钟粒度过于粗糙,RTAI 引入了细粒度
时钟机制。细粒度时钟机制主要利用处理器的定时器来实现,其核心思想是使用
硬件平台的定时器来实现系统对实时任务的高精度计时。在本课题实现 RTAI 之前,
必须先熟悉 S3C2440 的系统时钟和定时器的工作原理。
** S3C2440 的系统时钟**
微处理器的主时钟源一般是外部晶振或外部时钟。外部时钟源一般无法满足
系统所需的频率要求,常采用锁相环(PLL:Phase-locked loops)技术进行倍频处理。
S3C2440 有两个不同的 PLL:UPLLL 和 MPLL。其中,跟定时器相关的是 MPLL。
S3C2440 的外部时钟源经过 MPLL 处理后得到三个系统时钟:1. FCLK 主频时钟,
用于 ARM920T core;2. HCLK,用于 AHB 总线设备;3. PCLK,用于 APB 总线设
备。这三个时钟存在比例关系,比例值通过 S3C2440 内部寄存器 CLKDIVN 的
HDIVN 位([2:1])和 PDIVN 位([0])来设置。
因此,S3C2440 处理器的系统时钟产生过程是:外部时钟源经过 MPLL 处理
先得到 FCLK 的值,再通过设置 CLKDIVN 寄存器确定 HCLK 和 PCLK 的值。
本课题采用的主时钟源是 12MHz 的外部晶振,经过 MPLL 倍频处理后得到
400MHz 的 FCLK,而 FCLK/HCLK/PCLK 之间的比例关系是 1/4/8。因此,HCLK
为 100MHz,PCLK 为 50MHz。这三个值在 Linux 系统启动信息(图 3-8)中可以
看到。三个系统时钟中,与定时器相关的是 PCLK。
S3C2440 定时器的工作原理
S3C24100 提供 5 个 16 位的定时器(timer0~timer4)。图 4-7 给出了其工作原
理图。从图中可知,定时器的信号源是 PCLK,通过设置与定时器对应的 Prescaler
和 Clock Divider,PCLK 转换为输入时钟信号,传送给定时器的逻辑控制单元。每
个定时器都有一个输入时钟频率,这是定时器逻辑控制单元的工作频率。
定时器的输入时钟频率计算公式如下:
{PCLK} = 50MHz (从上文分析可知)
{prescaler} = 0 ~ 255, {divider} = 2,4,8,16
根据公式 4-1 可知,当 prescaler = 0,divider = 2 时,S3C2440 定时器的精度
最高可达到 0.04us。而 prescaler 和 divider 的值可以通过 S3C2440 的寄存器 TCFG0
和 TCFG1 来设置。
与 X86 的 tsc 时间戳计数器在每个时钟信号到来时加 1 不同,S3C2440 中的定
时器是预先设置一个计数值,每个时钟信号到来时值减 1。
S3C2440 定时器的工作原理大致如下:
- 通过配置寄存器 TCFG0 和 TCFG1 来设置定时器的输入时钟频率;
- 通过配置寄存器 TCNTB 和 TCMPB 来设置定时器周期;
- 载入 TCNTB 中设置的初始值,该值按照步骤 1 中设置的时钟频率自动减 1;
- 将递减后的数值与 TCMPB 设置的值进行比较;
- 当两个数值相等时,触发定时器中断。