积分规则 网站地图 帮助中心    
嵌入式软件 单 片 机 DSP 存储器 传感控制 光电显示
嵌入式硬件 CPLD/FPGA SOPC AD/DA 接口电路 模拟设计
I C设计 通信产品 汽车电子 电源产品 消费电子 数控系统
工业控制 军工/航天 安防产品 医疗电子 计算机外设 测试测量
供应 I C
求购 公司库

  IC 求购 销售 公司 论文 DATASHEET 参考设计 论坛
当前位置: 电子技术 >> 嵌入式软件 >> VXWORKS
  相关分类: LINUX | WINCE | UC/OS | Bootloader | 下载 | VXWORKS | 网络协议 | JAVA | 汇编 | 驱动设计 | Symbian | XP Embedded | Nucleus | 新产品 | 相关文章 | 综合技术 |
vxworks嵌入式操作系统串行设备驱动程序的编写
 
作者:赵文栋 张 磊   来源:本站原创    点击数:384   更新时间:2007-11-23
您可以添加到网摘 让更多人关注此文章:

    摘要:目前,基于嵌入式操作系统的软件开发是国内外研究的热点,vxworks嵌入式操作系统又是目前最流行的嵌入式操作系统之一。本文的目的在于通过分析vxworks操作系统下串行通信设备驱动程序的运行机制,提出在此操作系统下开发串行设备驱动程序开发的基本思路。

  关键词:vxworks 串行设备 驱动

  1. 概  述
       
  我们在基于vxworks嵌入式操作系统开发产品时,经常会根据自行设计的硬件电路开发专用的驱动程序。Vxworks下的驱动程序根据设备的不同特性,,大体可分为:char driver、serial driver、block driver、end driver、scsi driver等类型,其中以char driver最简单,最基础,以serial driver最常用。掌握驱动程序的基本工作流程,无论对我们开发上层的应用还是自己编写相应的驱动程序,都很有帮助。本文主要以i8250串口驱动程序为例,介绍一下串行驱动程序编写的基本思路。
       
  驱动程序,简而言之就是对具体的硬件设备进行管理和服务的程序。为了提高代码的可移植性,vxworks将所有的输入/输出设备都看成是一个文件,我们对设备的输入/输出操作,都可以看作是对指定文件的读写操作。例如,我们用c 标准库函数open()打开一个文件,可以是打开一个传统意义上的文本文件,也可以是指定一个输入/输出设备,如指定对某一个串口的输入/输出操作。在vxworks操作系统中,驱动程序的主要作用是完成对相关设备的读、写、打开、建立、关闭及控制等功能中的一项或几项,具体情况视具体的设备及设计要求而定。

  概括的说,驱动程序主要完成以下几项工作:

  (1)相关设备的初始化。 
  (2)底层输入/输出函数与上层标准输入/输出函数的挂接。
  (3)相关设备与对应驱动程序的挂接。

  我们就按照这个思路,以I8250串口为例,分析一下串行设备驱动程序的编写及加载流程。首先,给出串行设备驱动的结构框图:


图(一)

  需要说明的是,ttyDrv是一个虚拟的设备驱动,与tylib一起,用于处理I/O系统与底层实际设备之间的通信。主要完成以下工作:

  (1)处理I/O系统的各种需求,如在driver talbe 中添加相应的驱动条目、创建设备标识符(devise  descriptor)。
  (2)实现与上层标准I/O函数及实际驱动程序的无缝连接。其中,ttyDrv完成open和ioctl两项功能(ttyopen()和ttyioctl())。Tylib完成read和write两项功能(tyRead()和tyWrite())。
  (3)管理输入/输出数据缓冲区。

  下面,我们结合图(一)给出的框图,以i8250为例,开始分析串行设备驱动的设计流程。用户在编写自己的驱动程序时,可以不按照系统函数命名的方法命名,也可以不按照系统给定的方法进行函数功能的划分,但其初始化及实现流程却不能改变。

  2. 驱动程序设计流程分析

  ⑴ i8250相关硬件设备的初始化。
      
  编写驱动程序的第一步是完成相关硬件的初始化。与I8250相关的硬件初始化函数主要有以下三个:sysSerialHwInit()、i8250HrdInit()、i8250InitChannel(),其调用顺序是:sysSerialHwInit()i8250HrdInit()i8250InitChannel(),这条工作链的主要作用是,完成对I8250_CHAN数据结构的初始化。

  下面对分别这几个函数的功能介绍一下:

  sysSerialHwInit()

  本函数完成的主要任务是初始化设备的中断向量、串口的通信模式及相关存贮器,在函数的最后调用i8250HrdInit()对I8250_CHAN结构进一步初始化。

  void sysSerialHwInit (void)
   {
     int i;
     for (i=0;i<N_UART_CHANNELS;i++)
     {
   i8250Chan[i].int_vec = devParas[i].vector; /*初始化中断向量*/
   i8250Chan[i].channelMode = 0; /*初始化SIO_MODE 可以是INT或POLL*/
   i8250Chan[i].lcr =  UART_REG(UART_LCR,i); /*初始化line control register*/
   ………………………
  i8250Chan[i].outByte = sysOutByte; /*挂接输出函数,此函数向指定的I/O地址写入1bye*/
  i8250Chan[i].inByte  = sysInByte; /*挂接输出函数,此函数从指定的I/O地址读出1byte*/

   i8250HrdInit(&i8250Chan[i]);/*调用i8250HrdInit()进一步完成初始化*/
     }
  }
   i8250HrdInit()

  本函数完成的主要工作是挂接相应的入口函数,具体说明如下:

  void i8250HrdInit
  (
    I8250_CHAN *  pChan  /* 指向相应设备的指针*/
  )
  {
      if (i8250SioDrvFuncs.ioctl == NULL)
   {
   i8250SioDrvFuncs.ioctl = (int (*)())i8250Ioctl;/*挂接用于处理控制I8250相关输入
  输出命令的函数*/
   i8250SioDrvFuncs.txStartup = (int (*)())i8250Startup;/*如果设备工作于中断模式下,
  启用此函数用于打开中断,使设备开始工作*/
   i8250SioDrvFuncs.callbackInstall = i8250CallbackInstall;/*安装上层提供的回调函数,
  本例中是安装的tyIRd()、tyITx()*/
   i8250SioDrvFuncs.pollInput = (int (*)())i8250PRxChar;/*挂接输入轮询函数*/
   i8250SioDrvFuncs.pollOutput = (int (*)(SIO_CHAN *,char))i8250PTxChar;/*挂接输出轮询函数*/
   }
      pChan->pDrvFuncs = &i8250SioDrvFuncs;/*初始化CHAN结构,挂接接口函数列表*/
      i8250InitChannel(pChan); /* reset the channel */
  }

  由上面挂接的函数可以看出,i8250驱动主要实现了三个功能:read、write、ioctl,而并没有实现所有和七项功能。同时,值的注意的是,对同一种设备的驱动只需挂接一次。

  同时ttyDrv通过SIO_DRV_FUNCS使用xxDrv(i8250Drv)提供的服务,而xxDrv通过回调函数(本例中是由i8250CallbackInstall()安装的tyIRd()、tyITx())完成ttyDrv提出的请求。原理如下图示:


图(二)

  i8250InitChannel()

  本函数的主要作用是初始化特定的CHAN所描述的信道。具体分析如下。

  static void i8250InitChannel
   (
      I8250_CHAN *  pChan  /* pointer to device */
    )
  {
   int oldLevel;
   oldLevel = intLock (); /*关中断进入临界区*
   (void) i8250BaudSet(pChan, I8250_DEFAULT_BAUD);/*设置信道的波特率*/
  …………………………………
  intUnlock (oldLevel); /*开中断响应,出临界区*/
  }

  ⑵ 挂接中断服务程序

        对i8250的硬件初始化完成后,接着挂接相关的中断服务程序。主要有sysSerialHwinit2()函数完成。需要注意的是,挂接中断应放在系统初始化的最后,主要是因为中断挂接函数intConnect()需要调用malloc()函数,如果在系统的内存分配还未初始化前调用,则会出错。下面请看源代码:

  void sysSerialHwInit2 (void)
      {
      int i;
      for (i=0;i<N_UART_CHANNELS; i++)
      if (i8250Chan[i].int_vec)
        {
           (void) intConnect (INUM_TO_IVEC (i8250Chan[i].int_vec), i8250Int, (int)&i8250Chan[i] );
           sysIntEnablePIC (devParas[i].intLevel);
        }
      }

  其中,宏INUM_TO_IVEC的作用是把中断号转为中断向量。i8250Int是指向输入/输出中断处理函数的指针。描述相应硬件的结构i8250Chan为函数i8250int()的入口参数。

  至此,设备硬件的初始化、相关的低层函数的挂接、中断初始化基本完成。开始进行下一步,将设备的驱动函数安装在Driver Table 中。

  ⑶ 与上层标准输入/输出函数的挂接

  在此处I/O系统通过调用ttyDrv()(在没有定义INCLUDE_TYCODRV_5_2的情况下)将相应驱动函数添加到Driver Table中,从而完成与上层标准输入/输出函数的挂接。

 
图(三)

  由上图知,iosDrvInstall()函数在Driver Table中挂接的函数是tyWrite()和tyRead(),而不是我们实际编写的输入/输出函数。其具体的调用过程是:

  ① 当用户调用write函数进行写操作时,根据相应的fd调用在Driver Table中注册的函数tyWrite(),此函数的作用是将用户缓冲区的内容写入相应的输出ring buffer,当发现缓冲区内有内容时,开始调用回调函数tyITX(),从ring buffer读取字符,由I8250Startup()启动中断输出,最后由设备的输出中断服务程序(在本例中调用的是sysOutbyte())将字符发往指定的串口。

  ② 当串口接收到数据时会调用输入中断服务程序(在本例中是sysInbyte()),将输入的字符写入指定的缓冲区。然后由回调函数tyIRd()将缓冲区的内容读入ring buffer,当用户调用read函数进行写操作时,会根据相应的fd调用在Driver Table中注册的函数tyRead(),此函数会将ring buffer中的内容读入用户缓冲区。

       关于具体的中断输入/输出函数如何调用,本文不做详细分析,请参阅i8250int()及i8250Startup()。

       对于输入/输出控制函数ioctl()的挂接,则是直接将命令传到由用户编写的i8250ioctl()函数,其具体的实现代码与驱动的设计思路无紧密的联系,本文也不做具体分析。

  ⑷ 具体设备与相关驱动的挂接

       当Driver Table中相应的驱动函数挂接完成,开始编写驱动程序的最后一步:在Device Table中加入设备,完成具体设备与相关驱动的挂接。此项工作是由ttyDevCreat()函数完成的。本函数主要实现以下功能:

  ① 分配并初始化一个device descriptor。
  ② 通过调用tyDevInit()初始化tyLib。此处主要完成输入/输出ring buffer的创建、建立用与相关函数的信号量、初始化selectLib。
  ③ 调用iosDevAdd()将串口设备加入Device Table。对于设备特性的描述信息是由sysSerialChanGet()函数得到,并以参数形式传入的。
  ④ 为底层设备安装回调函数,在本例中是为i8250CHAN 安装tyIRd()、tyITx()两处回调函数。
  ⑤ 开中断,设备开始以中断方式工作。
至此,驱动程序的分析全部完成。与挂接驱动函数不同,在安装设备的过程中,无论设备相同与否,有几个设备则上述过程需调用几次。以上各函数的加载主要在usrinit()函数中完成。

  3. 结束语

  需要说明的是,在VxWorks下,设备驱动程序既可以嵌入内核随系统一起启动,也可以作为可加载模块在系统启动之后运行。相比之下,后一种方式比较简单,不用修改系统内核,引入错误的可能性小。但是无论采取哪种方式,其基本思路及需要完成的工作是相同的。本文没有按照系统的调用过程进行一步步分析,主要基于上述考虑。用户在编写相关驱动程序时,中心任务是按步骤完成上述功能,而没有必要去死搬系统的加载步骤。

  参考文献:

  [1] tornado device driver workshop wind river
  [2] tornado Bsp Developer’s kit for vxworks  wind river
  [3] VxWorks 5.4 Programmer's Guide wind river
  [4]《嵌入式实时操作系统vxworks及其开发环境Tornado》 孔祥营 柏桂枝 编著 2002年第一版



相关文章
· VxWorks基于AT91RM9200处理器的中断处理[4]
· VxWorks下消息、信号量的使用和任务创建[3]
· VxWorks下MPC860的中断处理机制及其应用[180]
· VxWorks下实时多任务程序的实现[207]
· VxWorks下的USB驱动程序原理与分析[303]
热门评论排行
·VHDL设计中电路简化问题的
·江苏嵌入式Linux教育培训
·锐极LINUX驱动培训班定于
·基于实时操作系统μC/OS-
·ARM处理器应用开发4步骤

文章评论
    没有任何评论
*只显示最新10条评论。评论内容只代表网友观点,与本站立场无关。更多评论
发表评论
  * 请先[登陆]再进行评论,谢谢。
评分: 1分 2分 3分 4分 5分
内容: *
发帖须知:
一.所发文章必须遵守《互联网电子公告服务管理规定》;
二.严禁发布供求代理信息,公司介绍,产品信息等广告宣传信息;
三.严禁恶意重复发帖;
四.严禁对个人,实体,民族,国家等进行漫骂,污蔑,诽谤。
 
热点新闻 [更多]
 
ARM联手IBM等三家公司开发32n
Hitachi Elect
中国芯片供需缺口达七成
西班牙研发出视觉鼠标 眨眼
首条OLED生产线昆山投产 
宇航服电子元器件:航天员的“生命保护
美研发出可卷曲太阳能电池
美国研发嗅觉感受器获新进展 
首尔半导体就日亚(NICHIA)专利
MIPS 科技授权国家集成
 
热门下载 [更多]
 
[ PCB设计] Protel99教程下载
[ ] 手把手学单片机20个例
[ ] 单片机做的智能台灯
[ ] 单片机入门书
[ ] linux系统移植开发文档
[ ] IC卡的读写程序
[ ] 8051单片机C语言彻底应用
[ 常用软件] 555定时器电路设计软件V1.2
[ 常用软件] 51定时器计算软件
[ ] ARM处理器应用开发4步骤
 
论坛新帖 [更多]
 
写给迷茫中的嵌入式新手...
Arm/DSP/FPGA的比较...
Arm/DSP/FPGA的比较...
Arm/DSP/FPGA的比较...
[分享]逆变器的买与用...
[分享]电力系统直流电源装置的...
单片机如何控制TFT真彩色LC...
请教:2051的C程序...
中国为何没有世界级的企业和企业...
AVR的EEPROM,到底怎么...

 
赞助商 [更多]
 

ICP许可证号:[粤 05056597]
联系电话:010-82517432 82517615 传真: 010-82517615

版权所有 Copyright © 2006 嵌入式技术网