Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->嵌入式系统 ->正文

RTOS设备驱动向嵌人式Linux的移植

来源: 作者: 时间:2007-04-11 点击: [收藏] [投稿]

RTOS 中断服务例程

在 Linux里, 中断服务属于内核层; 在一个 RTOS里, 中断服务例程代码没有特殊规定且常与应用程序代码没什么区别(不外乎返回序列异同)。很多 RTOS提供系统调用或者宏来让代码自己检测它自己的切换状态(比如 Wind River VxWorks的 intContext())。中断服务例程通常也使用标准的库函数,随之而来也有可重入性和移植性等问题。

大多数RTOS支持注册中断服务例程代码、中断判断和中断服务调用。一些简单的嵌入式程序,仅仅支持在硬件矢量表里插入中断服务例程的起始地址。

如果试图直接在用户程序空间执行读和写操作,你不得不把Linux中断服务例程放入内核程序空间。

RTOS I/O 子系统

大多数RTOS会提供一个定制的标准C运行库 (比如 pSOS 的pREPC),或者修改编译器提供商的C库(libc)或修改glibc。在尽量最小化情况下,多数的 RTOS支持标准C的I/O子集(open/close/read/write/ioctl). 大多数情况下,这些调用和从衍生出来的调用转化为基本I/O简单封装.有趣的是,因为大多数的 RTOS不支持文件系统,这些平台不提供针对flash和其他存储介质的文件存储,常采用完全不同的代码实现或者其他应用程序接口(API) (比如 pSOS 的pHILE).

Wind River VxWorks 在这方面比其它RTOS做得好些,它提供功能丰富的I/O子集,有效广泛集成网络接口及网络媒体。

延时处理

很多RTOS也支持一种叫”下半部 “("bottom half" )的机制, 把I/O处理放到可中断或者可抢占切换上下文中执行。其他RTOS提供类似机制比如中断嵌套来获得同样的效果.

典型RTOS应用的I/O架构

下面描述一个典型的I/O图解(仅输入)和它向主应用程序传递数据的路径,处理过程如下:

· 一个硬件中断触发一个中断服务例程执行。

· 中断服务例程做基本处理,完成本地输入操作,或者让RTOS调度延时处理。在一些情况下,延时处理过程由Linux里的用户进程来处理,在这里就是普通的RTOS任务。

· 当获取到数据(中断服务例程或者延时切换),准备好的数据被放进队列(RTOS中断服务例程能够访问应用程序队列通过应用程序接口(API)和其它进程间通信 ( IPC),请看下面的API表)。

· 一个或者多个应用任务从队列读消息取出数据

传统的RTOS和Linux的典型I/O比较

输出常常由类似的机制来完成-代替write()或者相似的系统调用,一个或者多个RTOS任务,把数据放进队列.队列中的数据由以下几种过程取出:一个I/O程序或者响应“准备好发送”中断的中断服务例程,一个系统时钟,或者其它阻塞在取数据队列中的应用任务,然后执行I/O操作(可以是轮询,也可以是通过 DMA).

把RTOS I/O 映射到 Linux中

上面描述的基于队列的生产者/消费者I/O模型,仅仅是传统多种设计中所采用的特别方法的一种。让我们继续用这个直接的例子,来讨论几种在嵌入式Linux下的实现方法:

大规模移植到用户空间

对于只是初步了解Linux设备驱动设计,或者没有经验的开发者,可能把大多数这种基于队列的程序原封不动地移植到用户空间。在这种驱动程序映射中,内存映射通过函数mmap()提供的指针可以在用户空间操作物理I/O接口。

#include <sys/mman.h>
#define REG_SIZE 0x4 /* device register size */
#define REG_OFFSET 0xFA400000
/* physical address of device */
void *mem_ptr; /* de-reference for memory-mapped access */
int fd;
fd=open("/dev/mem",O_RDWR); /* open physical memory (must be root) */
mem_ptr = mmap((void *)0x0, REG_AREA_SIZE, PROT_READ+PROT_WRITE,
MAP_SHARED, fd, REG_OFFSET);
/* actual call to mmap() */

一个进程下的用户线程运行类似RTOS的中断服务例程或延时任务一样的操作,然后使用SVR4进程间通信函数msgsnd()把消息放进队列,等待被另一个本地线程或者另一个进程利用函数msgrcv()获取。

这种快速缺乏技巧的处理方法是一种较好的原型,但同时给代码模型建立带来了巨大的挑战。首先重要的是要在用户空间扫描中断.象DOSEMU项目提供基于信号 的I/O中断方式,但用户空间的中断处理过程非常慢(一般毫秒级中断延时相较内核中断服务例程数十微秒中断延时).进一步讲,即使采用可抢占Linux内核,和实时调度策略,用户空间的切换调度不能保证I/O 线程100%的及时得到执行。

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:Linux操作系统的嵌入式领域面临新挑战   下一篇:Linux嵌入式系统与硬件平台的关系

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号