您好,  [请登录] [QQ登录]  [支付宝登录[免费注册]

商品分类

分享到: 百度搜藏 搜狐微博 新浪微博 腾讯微博 QQ收藏 人人网 Facebook Twitter

利用RTLinux开辟嵌入式应用步调

发布日期:2011-04-22


    敷衍中国工程师来说,利用及时Linux开辟嵌入式应用步调是他们面对的困难之一,本文以RTLinux为例,并连合最为业界存眷的是RTAI举行讨论,只管这两种实现要领在句法细节上存在差别,但变乱要领底子一样,因此所报告的内容对两者都实用。


  在及时任务与用户进程相互通讯的进程中,有些及时应用步调无需恣意用户界面即可在背景沉寂地运行,然而,越来越多的及时应用步调确实须要一个用户界面及别的体系结果,如文件利用或联网等,全部这些结果都必须在用户空间内运行。标题是,用户空间利用好坏确定性的,并且与及时利用不兼容。

  荣幸的是及时Linux具有一种可在时间上减弱及时与非及时利用的机制,这种机制表现为一种称为及时FIFO的驱动步调。当insmod将rtl_fifo.o驱动步调插入Linux内核时,该驱动步调将本身注册为RTLinux的一部分,并成为Linux驱动步调。一旦插入Linux内核,用户空间进程和及时任务都可利用及时Linux FIFO。
在深入探究及时FIFO的细节之前,还要回顾一下及时应用步调布局的某些部分(图1)。有效的嵌入式应用步调筹划要领是将及时部分与固有的非及时结果疏散开来(表1)。要是应用步调的任一部分,如用户界面、图形、数据库或网络仅需软及时性能,最好是将该部分写入用户空间。然后,仅将必须餍足时序恳求的那部分写成及时任务。

  过细,RTLinux(PSC,便携式信号编码)和RTAI(LXRT,Linux及时扩展)的最新版本已采取了一种可在用户空间实行软和硬及时任务的要领。

  恣意硬及时任务都是在RTLinux的控制下运行的,该任务一样通常可实行周期性任务、处理惩罚处罚克制并与I/O配置驱动步调通讯,以征求或输出仿照和数字信息。当及时任务须要报告用户进程有一个变乱将孕育产生时,它便将这一消息送给及时FIFO。每一个FIFO都是在一个方向上发送数据:从及时任务到用户空间,或反之。因此,双向通讯须要利用两个FIFO。恣意读出或写入及时任务一侧的利用都好坏模块利用,因此rtf_put()和rtf_get()都立即返回,而不管FIFO状态是什么。

  从应用步调一侧来看,FIFO就像一个惯例文件。缺省环境下,RTLinux摆设步调将在/dev目次下创建64个及时FIFO节点;要是须要,还必须本身创建新的节点。比喻,要创建/dev/rtf80,需采取如下下令:
=========================
mknod c 150 80;
chmod 0666 /dev/rtf80
=========================

  此中,150是及时FIFO主数,而80是rtf80的次数。

  从用户进程的角度看,及时FIFO可实行标准文件利用。从及时任务来看,FIFO有两种通讯要领:直接调用RTLinux FIFO结果,或将FIFO作为一个RTLinux配置驱动步调,并利用open()、close()、read()和write()利用。要想将FIFO作为一个配置驱动步调,就必须将rtl_conf.h中的配置变量ONFIG_RTL_POSIX_IO设置为1。

  rtf_create_handler()可设置处理惩罚处罚步调结果。每次Linux进程读或写FIFO时,rtl_fifo驱动步调都要调用该处理惩罚处罚步调。应过细的是,该处理惩罚处罚步调驻留在Linux内核,因此当Linux须要调用时,从该处理惩罚处罚步调举行恣意内核调用都是沉寂的。从该处理惩罚处罚步调到及时任务间的最好通讯要领是利用旗语或线程同步结果。着末,FIFO驱动步调还必须对内核存储器举行配置。因此,及时线程内的rtf_create()不该调用。相反,可调用init_module()中的rtf_create()结果及cleanup_module()中的rtf_destroy()结果。

  比喻,列表1给出了一个采取两个FIFO的大抵数据征求应用步调的及时部分。两个FIFO都是在init_module()创建,并付与minor numbers 为1和2。在调用rtf_create(minor, size)之前,该步调在已创建该FIFO的环境下调用rtf_destroy(minor)。这种环境便是另一个模块在开辟进程中未被调用。然后,调用rtf_create_handler(ID, &pd_do_aout)以注册带该及时FIFO的数据征求仿照输出结果pd_do_aout()。过细,创建及时线程pp_thread_ep()是由于它是周期性的,其隔绝为1/100秒。

  每次周期性线程得到体系控制权后,它就调用rtf_put(ID,dataptr,size)以便将数据插入minor number为2的FIFO。Linux进程打开/dev/rtf2,从及时FIFO中读取并表现所征求的数据。该进程还打开/dev/rtf1,将数据写入别的及时FIFO。当用户移动屏幕滑动器以变革仿照输出电压时,进程就向该FIFO写入一个新的值。RTLinux便调用pd_do_aout()处理惩罚处罚步调,随后pd_do_aout()利用rtf_get()从FIFO得到值,并调用实际的硬件驱动步调以设置仿照输出的电压。可以看到,及时任务和用户进程是异步利用FIFO的。

  任务间的存储器共享
  FIFO为用户进程和及时任务的连接提供了一种方便的机制,但将它们作为消息行列步队更切合。比如,一个及时线程可利用FIFO记录测试结果,然后用户进程就可读取该结果,并将之存入数据库文件。

  很多数据征求应用步调涉及到内核及用户空间之间的大量数据。Linux内核v. 2.2.x并没有为这些空间的数据共享提供恣意机制,但v. 2.4.0版本预计会包括kiobuf布局。为办理现有稳固内核的这个缺点,RTLinux包括mbuff驱动步调。该驱动步调可利用vmalloc()分派假造内核存储器的已定名存储器地区,它采取的存储器分派和页面锁定本领跟大多数Linux中bttv帧抓取器(frame-grabber)驱动步调所用的一样。

  更细致地说,mbuff一页一页地将假造内存锁定到实际的物理内存页面。恣意及时或内核任务,或用户进程在恣意时间都可访问该存储器。通过将假造内存页面锁定到物理内存页面,mbuff可确保所分派的页面永世驻留在物理内存,并且不会孕育产生页面错误。换言之,当及时或内核进程访问所分派的存储器时,它可确保VMM不被调用。过细:由于及时任务实行时期及时Linux冻结标准内核的实行,恣意对VMM的调用都市引起体系停息。要是它要访问并不位于物理RAM内的假造存储页面,那么纵然正常的Linux内核驱动步调也会引起体系妨碍。

由于mbuff是一种Linux驱动步调,其结果可通过配置节点/dev/mbuff实现。该节点可表现几个录入点,此中包括可将内核空间地点映射到用户空间的mmap()。它还可以利用录入点ioctl()来控制。然而,并不须要巨大的布局及直接
调用ioctl。相反,mbuff可为ioctl()调用提供一个包裹,并且仅仅调用两个大抵的结果即可配置和开释共享的存储缓冲器。

  固然,不克不及从及时任务调用mbuff驱动步调,由于该驱动步调所调用的假造存储器分派结果本身是不确定性利用。分派共享存储器所需的时间依赖于主体系的存储器容量以及CPU速率、磁盘驱动器性能和存储器分派的现有状态。因此,只能从模块的Linux内核一侧来分派共享存储器,比如从init_module()或一个ioctl()恳求开始。

  那么,一个共享缓冲器到底能分派多少存储器呢?要是不是任务綦重沉重的办事器或图形应用,提倡至少为Linux生存8MB存储空间。为了得到优化的配置,可在限定存储器大小的同时丈量及时应用步调的性能,以确定须要多少存储空间。

  列表2给出了怎样从及时任务和用户进程方面访问共享的存储器。内核模块和用户任务采取同样的结果集。固然,要想利用insmod mbuff.o,还必须将之置于Linux内核中。比喻,mbuff_alloc("buf_name", size)可将标记名buf_name分派给一个缓冲器,而mbuff_free("buf_name", mbuf)可将之开释。

  当第一次调用带有标记缓冲器名的mbuff_alloc()时,mbuff实行实际的存储器分派。而当从内核模块或用户进程再次调用该结果时,它只是大抵地增长利用数(usage count)及将指针返回现有的缓冲器。每次调用mbuff_free()都市淘汰利用数,直至为零,这时mbuff就去分派带标记名的缓冲器。这种要领从多个内核模块和用户进程得到一个指向同一共享缓冲器的指针,从而办理了标题。它还可确保共享缓冲器不绝有效,直到着末的应用步调开释它。请过细,是及时内核还是用户进程实行实际的buf1配置依赖于谁先得到控制权。

  另有一个“笨”要领可在及时应用步调、内核模块和用户应用步调间共享存储器。敷衍嵌入式应用,该要领还是可以承继的。比喻,要是PC带有128MB RAM,可将线搜刮路径="mem=120m"添加进lilo.conf文件(列表3)。当启动带有Linux内核和RTLinux 2.3的体系时,Linux仅利用120MB内存。OS也不消剩下的8MB内存(物理地点为0x7F00000到0x7FFFFFF),而是留给在OS下运行的种种任务共享。要想从用户进程获取存储器地点并访问预留的存储器,必须用O_RDWR访问模式来打开/dev/mem驱动步调,然后利用mmap()生存存储器(列表4)。而从及时模块或内核驱动步调一侧举行,则必须利用ioremap(0x7F00000, 0x100000)才华获取这8MB (0x100000字节)预留内存。

  这种要领有利有弊。既不克不及通过预留内存的全部权,也不克不及通过读或写来获取控制权。正确地配置和开释大量内存的机制尚未问世。别的,无论及时进程是否须要,该内存都不克不及为Linux所用。

  大概存储器共享笨要领的唯一实用场合是专为特定应用而定制的小型嵌入式体系,由于此时可为小型化而放弃利用mbuff驱动步调。

  克制
  RTLinux有两种克制:硬克制和软克制。软克制便是惯例Linux内核克制,它的长处在于可无穷制地利用Linux内核调用。这类克制作为硬克制处理惩罚处罚的第二部分还是相称有效的(由参考文献5可得到更多有关Linux环境下克制处理惩罚处罚的细节)。

  硬(及时)克制是摆设及时Linux的条件。要摆设克制处理惩罚处罚步调,先调用rtl_request_irq(...),然后调用rtl_free_irq()开释它。依赖于差别的体系,及时Linux下硬(或及时)克制的扩展是15μs的数量级。较快的处理惩罚处罚用具有较好的扩展。要是想在及时处理惩罚处罚步调和惯例Linux驱动步调中处理惩罚处罚同一配置IRQ,必须为每一个硬克制单独设置IRQ。

  列表5给出了摆设及时克制处理惩罚处罚步调的进程。RTLinux在实行及时克制处理惩罚处罚步调时将克制IRQ。应过细,该代码须在退出及时克制处理惩罚处罚步调前调用rtl_hard_enable_irq()才华重新使能克制。

  有两个标题影响直接从及时克制处理惩罚处罚步调调用Linux内核结果:内核克制全部克制及不定义实行内容。还应过细的是,这里也不克不及实行浮点利用。利用及时克制处理惩罚处罚步调来控制线程实行是克制出现这些标题标好步调。本例采取pthread_wakeup_np()结果来唤醒一个及时线程。克制处理惩罚处罚步调可处理惩罚处罚及时的变乱,余下的由该线程办理。

  SMP布局的长处
  及时Linux都支持多处理惩罚处罚器架构。对称多处理惩罚处罚器(SMP)布局采取了高级可编程克制控制器(APIC),奔驰级处理惩罚处罚器都有片上本地APIC,可为本地处理惩罚处罚器发送克制。SMP(以致单处理惩罚处罚器母板)都有I/O APIC,可网络来自外设的克制恳求,并将它们发送给本地APIC。旧的8259 PIC速率很慢,所处理惩罚处罚的克制向量数不充分,迫使配置共享克制,使得克制处理惩罚处罚更慢。但是,APIC可办理这些标题。通过为每个配置恳求设置一个特定的IRQ,体系可淘汰克制扩展,APIC还可加快同步代码。

  及时Linux可充分利用APIC。在SMP体系中,及时调理步调利用APIC,而不是采取逾期的8254芯片来完成时序分派。由于PC的兼容性,8254位于每一个ISA总线上,并且每一个再编程配置的调用都要占用处理惩罚处罚器周期。一个千兆赫CPU要浪费数百个处理惩罚处罚器周期来等待8MHz定时器(约莫2.5μs)。APIC变乱在总线频率,并且可立即实行全部的定时器利用,这意味着必须利用本地APIC时钟在AMP呆板上获取更高的周期性频率(双P-III-500 CPU可在100kHz运行周期性及时线程,而无明显的性能丧失)。

  及时Linux能很好地实行多处理惩罚处罚任务,它为每个CPU实行单独的进程。调用pthread_create()可创建一个在现有CPU上运行的线程。还可用pthread_attr_setcpu_np()将该线程分派给一个特定的CPU,以变革线程属性。在调用这一结果之前,必须起首初始化线程属性。

  RTLinux v. 3包括reserve_cpu结果,可预留SMP平台上的一个CPU,专供RTLinux利用。它可运行于2.4x内核,RTAI也具有险些同样的结果。

要是想将任务分给某一特定的CPU,请当心“pset”方案(http://isunix.it.ilstu.edu/thockin/pset/)。利用该
0869;核可将一个SMP处理惩罚处罚器专门分派给一个用户应用步调,以致可从Linux处理惩罚处罚器组中调用一个处理惩罚处罚器专用于及时任务。

  同步基元
  早期的及时Linux没有同步基元。如今,POSIX型的旗语、互斥和信号在最新的及时Linux版本中都已出现。固然在及时筹划中采取这些同步基元还存在标题,但同步或用信号表现及时任务和用户应用步调很存心义,然而,这恳求软件开辟者具有高超的技能,这一标题已超过跨过本文的讨论范畴。
快速学习pthread_mutex_init()、pthread_mutex_lock()、pthread_mutex_trylock()、pthread_mutex_unlock()和pthread_mutex_destroy()等同步结果的最好要领是查察./examples/mutex/mutex.c。分外要提示的是./examples/mutex/sema_test.c文件是学习旗语的很好出发点。

  及时Linux生长方向
  及时Linux与Linux一样仍旧处于不绝生长之中。每一个新的版本都添加了更多的特性和结果。及时Linux正朝着更好的POSIX 1003.x实现方向生长,最新的特性包括用户空间进程的及时支持、互斥、信号、旗语、及时存储器办理和扩展的SMP支持等。要是还未确定下一个项目采取哪个及时体系,可下载一种及时Linux版原形识一下。着实,Linux已经是一种成熟的OS,并且具备及时扩展版本,它是嵌入式应用的最佳选择之一。

  Alex Ivchenko博士是连合电子实业公司的研发工程经理,也是该公司PowerDAQ II系列PCI数据征求板的紧张开辟者之一。近来,他正为该系列卡编写Linux驱动步调。可通过电子邮件aivchenko@ueidaq.com与他讨论。