中国·芯片交易在线
首页 | 供应信息 | 求购信息 | 库存查询 | 新闻中心 | 展会资讯 | IC厂商 | 技术资料 | 自由区域
   新闻首页 |  行业动态 | 新品发布 | 政策法规 | 科技成果 | 模拟技术 | 嵌入系统 | 传感控制 | 存储设计  
当前位置:IC72首页>> IC新闻中心>> 嵌入系统 >>电子行业新闻正文

嵌入式系统中串口驱动概述

时间:2007/6/23 9:49:00  作者:  来源:IC72  浏览人数:1421
 
 

      串口驱动概述

      1. 启动顺序

      在usrConfig.c 中,usrInit()调用sysHwInit(), 对系统硬件进行基本的初始化,使其处于安静状态。sysHwInit()[在sysLib.c 中]调用sysSerial.c 中的sysSerialHwInit()对BSP 串行器件

      进行初始化,使其处于静态;sysSerialHwInit()再通过xxDevInit()复位串行通道。

      在usrInit()函数的最后,产生根任务usrRoot()。usrRoot()调用sysClkConnect()。sysHwInit2()

      主要安装系统中断, 它调用sysSerialHwInit2() 连接串行中断。如果定义了INCLUDE_TTY_DEV,而没有定义INCLUDE_TYCODRV_5_2,在usrRoot()任务中调用 ttyDrv()来初始化串行设备驱动,并通过ttyDevCreate()函数创建串行设备。

      串行驱动是在VxWorks系统开始过程中被初始化的。

      2. 编码步骤

      (1)初始化

      ①定义系统可支持的串行通道数。

      ②初始化驱动的设备描述

      ③写设备初始化代码

      (2)写入口程序

      (3)写中断服务程序管理中断

      (4)使用模板wind/target/src/drv/ssio/templateSio.c

      3.详细步骤介绍

      (1)定义系统可支持的串行通道数

      在config.h 中定义串口通道数NUM_TTY。

      (2)初始化驱动的设备描述

      TEMPLATE_CHAN 例子如下所示:

      typedef struct
      {
      /* SIO_CHAN *MUST* be first */
      SIO_CHAN sio; /* standard SIO_CHAN element */
      UINT32 ioBase;
      UINT32 vecBase;
      UINT32 intLevel;
      /* callbacks */
      STATUS (*getTxChar) (void *, char *);
      void (*putRcvChar) (void *, char);
      void (*errorRtn) (void *, int, void *, int);
      void * getTxArg;
      void * putRcvArg;
      2
      void * errorArg;
      /* misc */
      int intConnect; /* intConnect done flag */
      int baudFreq; /* current baud rate */
      int mode; /* current mode (interrupt or poll) */
      int clkFreq; /* input clock frequency */
      uint_t options; /* Hardware options */
      int scanMode; /* keyboard mapping mode */
      } TEMPLATE_CHAN;

      在XX_DRV 结构中每一个通道有一个XX_CHAN 结构。

      在上面的例子中,TEMPLATE_CHAN 中的SIO_CHAN 必须被第一个定义!

      SIO_CHAN 指向SIO_DRV_FUNCS, SIO_DRV_FUNCS 结构提供驱动的入口函数。

      SIO_DRV_FUNCS 定义在wind/target/h/sioLib.h 中。如下:

      struct sio_drv_funcs /* driver functions */
      {
      int (*ioctl)
      (
      SIO_CHAN * pSioChan,
      int cmd,
      void * arg
      );
      int (*txStartup)
      (
      SIO_CHAN * pSioChan
      );
      int (*callbackInstall)
      (
      SIO_CHAN * pSioChan,
      int callbackType,
      STATUS (*callback)(void *, ...),
      void * callbackArg
      );
      int (*pollInput)
      (
      SIO_CHAN * pSioChan,
      char * inChar
      );
      int (*pollOutput)
      3
      (
      SIO_CHAN * pSioChan,
      char outChar
      );
      };

      xxIoctl(): 支持设备特定的ioctl 命令

      xxTxStartup(): 初始化一个传输循环(transmit cycle)

      xxCallBackInstall(): 安装到高层协议的入口(I/O system,target agent(目标代理),等等)

      xxPollInput() : 轮巡模式输入

      xxPollOutPut() : 轮巡模式输出

      a.启动发送循环

      因为串口发送数据时需要启动,xxTxStartup()就是用来启动串口数据发送,当发送成功后会触发串口中断,中断根据缓存中是否还有数据来决定是否继续发送,当缓存清空后串口将恢复初始状态,并等待下一次传送的启动。

      b.驱动回调安装程序

      回调用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍。

      int xxCallbackInstall (pSioChan,callbackType, callback, callbackArg)


      pSioChan: 指向SIO_CHAN结构的指针

      callbackTyp:SIO_CALLBACK_GET_TX_CHAR or SIO_CALLBACK_PUT_RCV_CHAR

      callback: 指向回调函数的指针

      callbackArg:传给回调函数的参数

      /**************************************************************************
      *
      * templateCallbackInstall - install ISR callbacks to get/put chars
      *
      * This driver allows interrupt callbacks for transmitting characters
      * and receiving characters. In general, drivers may support other
      * types of callbacks too.
      *
      * RETURNS: OK on success, or ENOSYS for an unsupported callback type.
      */
      LOCAL int templateCallbackInstall
      (
      SIO_CHAN * pSioChan, /* channel */
      int callbackType, /* type of callback */
      STATUS (*callback)(void *,...), /* callback */
      4
      void * callbackArg /* parameter to callback */
      ) {
      TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
      {
      case SIO_CALLBACK_GET_TX_CHAR:
      pChan->getTxChar = (STATUS (*)(void *, char *))callback;
      pChan->getTxArg = callbackArg;
      return (OK);
      case SIO_CALLBACK_PUT_RCV_CHAR:
      pChan->putRcvChar = (void (*)(void *, char))callback;
      pChan->putRcvArg = callbackArg;
      return (OK);
      case SIO_CALLBACK_ERROR:
      pChan->errorRtn = (void (*)(void *, int, void *, int))callback;
      pChan->errorArg = callbackArg;
      return (OK);
      default:
      return (ENOSYS);
      } }

      (3)驱动初始化:void xxDevInit (pxxDrv)

      这个函数是用来复位芯片,使芯片处于安静的状态。

      (4)写函数

      用户通过I/O系统的write()操作是调用tyWrite()——在驱动列表中的ttyDrv的写入口函数。tyWrite()把数据拷贝到环形缓冲中,并且调用xxTxStartup( )来初始化一个发送周期。

      当设备输出完毕后,设备就给CPU一个中断表示可以接受下一个字符,然后进入中断xxInTxt( )。函数xxIntTx ( )通过调用回调函数getTxChar从高层协议去字节,把字节写入到设备。如果需要的话清除中断。如果需要的话在没有数据等待发送的时候,复位发送中断。

      (5)读函数

      串口的读操作相对于写操作来说复杂一些。数据的读写有两种方式:查询式和中断式。

      查询方式根据事先设定的时间间隔定时读端口,不论端口是否有数据,操作都要进行。所以查询方式并不能完全适应实时操作系统的及时相应要求,因此在嵌入式实时操作系统中应用的比较少。而中断方式(或者类似中断的机制)则使用比较多。VxWorks提供的Select函数,可以使任务阻塞在一个或者多个I/O设备上,并能制定最多所等待的时间。利用Select函数可以将读串口设备的操作阻塞在设备的读操作上,当有数据可读时,被阻塞的任务就继续向下执行,这是就可以对串口继续读操作,将数据从端口读入。因此可以将读端口的操作单独放在一个任务中,利用Select将任务阻塞在端口读操作,而当端口有数据时继续该任务。Select函数是一种类似于事件触发的机制,利用Select函数可以实现类似于中断的方式的数据读操作。

      下面简单说明一下利用Select实现串口的读操作。

      FOREVER
      {

      /*清除等待设备集合中的读屏蔽位*/

      FD_ZERO(&readFds);

      /*初始化屏蔽位为等待串口状态*/

      (SerialDevFd,& readFds);

      Width = SerialDevFd + 1;

      /*阻塞,等待串口设备变为就绪状态*/

      if(select(width,& readFds,NULL,NULL,NULL) == ERROR)
      return (ERROR);
      if(FD_ISSET(SerialDevFd,&readFds))
      {
      FOREVER
      {
      /*当端口仍有未读数据*/
      If((DataLen = read(SerialDevFd,ComReadBuffer,MAX_IN_DATA)) == ERROR)
      {
      printf(“\nError in read comport”);
      return(ERROR);
      }
      if(DataLen == 0)
      breake;

      /*处理所读出的数据,如将其写到缓存或直接处理*/
      }
      }
      }

      当采用中断方式读数据时,接收中断服务程序void xxIntRcv(pSioChan)实现从设备中读字节,并通过调用回调函数putRcvChar来将字节传给高层协议。

      /**************************************************************************
      *
      * templateSioIntRcv - handle a channel's receive-character interrupt
      *
      * RETURNS: N/A
      */
      LOCAL void templateSioIntRcv
      (
      6
      TEMPLATE_CHAN * pChan /* channel generating the interrupt */
      )
      {
      char inChar; /* rcvr data */
      char crData = 0; /* rcvr status */
      STATUS status = OK;
      /*
      * TODO -
      *
      * Get status and data from the device. Determine if valid data is ready
      * or not.
      *
      * For PCI devices, do an immediate return if device is not asserting
      * an interrupt.
      */
      TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &crData);
      /* Check for error conditions */
      if (crData & TEMPLATE_CR_OKAY)
      {
      TEMPLATE_SIO_READ8(pChan, TEMPLATE_DATA_ID, &inChar);
      #if 0 /* Keyboard emulation code */
      /*
      * TODO - For a keyboard type device we would map the raw scan code
      * to ASCII, or other mapping. Do that here.
      */
      if (pChan->scanMode == SIO_KYBD_MODE_ASCII)
      inChar = templateAsciiTbl[(UINT8)inChar];
      #endif
      }
      else
      {
      /*
      * TODO - Determine precise error condition and perform
      * recovery actions.
      */
      status = ERROR;
      7
      }
      /*
      * TODO - Typically, acknowledge the interrupt as soon as possible.
      * Usually before passing data or error conditions upstream.
      */
      TEMPLATE_SIO_WRITE8(pChan,
      TEMPLATE_CSR_ID, TEMPLATE_RESET_INT); /* ack interrupt*/
      if (status == ERROR)
      {
      /* send error notification upstream */
      (*pChan->errorRtn) (pChan->errorArg, SIO_ERROR_UNKNWN, NULL, 0);
      }
      else
      {
      /* send data character upstream */
      (*pChan->putRcvChar) (pChan->putRcvArg, inChar);
      } }

      (6) I/O控制函数ioctl()

      指向驱动的标准I/O控制接口函数。此函数为任何驱动提供主要的控制接口。为了实现标准的SIO设备的I/O控制,用以下的定义:

      SIO_BAUD_SET 设定一个新的波特率

      SIO_BAUD_GET 得到当前的波特率

      SIO_HW_OPTS_SET 设定一个新的硬件属性

      SIO_HW_OPTS_GET 得到当前的硬件属性

      SIO_MODE_SET 设定一个新的操作模式

      SIO_MODE_GET 得到当前的操作模式

      SIO_AVAIL_MODES_GET 得到可能的模式

      SIO_OPEN 打开一个通道

      SIO_HUP 关闭一个通道

      (7)修改sysSerial.c

      在sysSerial.c中,主要需要修改三个函数,sysSerialHwInit( ),sysSerialHwInit2( ),sysSerialChanGet( )。

      sysSerialHwInit( )主要完成以下功能:初始化和硬件相关的的驱动的XX_CHAN结构(例如寄存器地址);调用xxDevInit()来执行实际的设备初始化;设定标志位来标志ISR仍然没有被安装。此函数是被sysHwInit( )调用的。

      sysSerialHwInit2( )主要是连接中断服务程序。在intConnect()中的第三个参数应该是指向

      8

      xx_CHAN结构的一个指针。此函数是由usrRoot任务在系统启动过程中由sysClkConnect()调用的。它设定标志位标志ISR已经被安装。

      sysSerialChanGet( )主要是把通道号转换成一个SIO_CHAN结构的指针。

 
【相关文章】
·嵌入式系统中串口驱动概述
·基于嵌入式系统的隔离硬件设计
·基于ARM和FPGA的多功能车辆总线嵌入式系统设计
·DVR系统嵌入式Linux解决方案
·嵌入式系统内存管理方案研究
·虚拟系统原型简化嵌入式多内核设计
 
 
IC新闻搜索
 
热点新闻
基于红外超声光电编码器的室内移动小车定位系
基于闪烁存储器的TMS320VC5409DSP并行引导装载方法
非移动市场需求飙升,ARM预计2010年出货量超50亿片
一种快速响应的电容式湿度传感器感湿薄膜设计
利用特殊应用模拟开关改进便携式设计
无线传感器网络跨层通信协议的设计
基于ARM9内核Processor对外部NAND FLASH的控制实现
基于GSM技术的汽车防盗系统的设计
热电阻在烟叶初烤炕房温度控制中的应用
高速数据转换系统对时钟和数据传输的性能要求
友情连接
 关于我们  IC论坛  意见反馈  设置首页  广告服务  用户帮助  联系我们
copyright:(1998-2005) IC72 中国·芯片交易在线
(北京)联系电话:(010)82614113、82614123 传真:(010)82614123 客户服务:service@IC72.com 库存上载:IC72@IC72.com
在线MSN咨询:ic72sale8@hotmail.com 通信地址:北京市西城区西直门内大街2号大厦15层 邮政编码:100013
(深圳)联系方式: 在线MSN咨询:ic72sale6@hotmail.com 在线QQ咨询:191232636 通信地址:深圳市福田区振华路
注 册 号: 1101081318959(1-1)

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9