OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » [转帖]串口驱动编写实例解读(一)

共4条 1/1 1 跳转至

[转帖]串口驱动编写实例解读(一)

菜鸟
2003-01-15 21:04:00    评分
串口驱动(Serial Drivers)编写实例解读(连载:一) <--- 〖回复该帖子〗 串口驱动(Serial Drivers)编写实例解读(连载:一) [代码步骤:Code Steps] 。初始化 。定义支持的串口通道数 。初始化驱动的设备描述 。写你的设备初始化代码 。写入口程序(entry point routines) 。写ISRs(中断服务程序)来管理设备 。使用模板 wind/target/src/drv/ssio/templateSio.c 注意:串口驱动在VxWorks系统开始的代码里初始化 [设备描述:The Device Descriptor] 。XX_DRV结构每个通道有一个XX_CHAN 。每个XX_CHAN指向SIO_DRV_FUNCS 。SIO_DRV_FUNCS引诱驱动的入口(entry point) 。XX_DRV是xxDrv使用的中心数据结构 。xx_CHAN包括: 。xxDrv需要的通道特定信息 。指向驱动SIO_DRV_FUNCS结构的指针 。例: /* device and channel structures */ typedef struct { /* must be first */ SIO_CHAN sio; /* standard SIO_CHAN element */ /* callbacks */ STATUS (*getTxChar) (); STATUS (*putRcvChar) (); void * getTxArg; void * putRcvArg; /* register addresses */ volatile char * cr; /* channel control register */ volatile char * dr; /* channel data register */ volatile char * sr; /* channel status register */ volatile char * ms; /* channel modem status register */ volatile char * mc; /* channel modem control register */ volatile short * br; /* channel baud constant register */ /* misc */ int mode; /* current mode (interrupt or poll) */ int baudFreq; /* input clock frequency */ int options; /* Hardware options */ } TEMPLATE_CHAN; typedef struct { TEMPLATE_CHAN portA; /* DUSRAT has two channels */ TEMPLATE_CHAN portB; volatile char * masterCr; /* master control register */ } TEMPLATE_DUSART; [SIO_CHAN结构] 。对一般字符驱动,一个指向DEV_FDR的指针被用来在驱动和I/O system 之间通讯 。对一个串口驱动,一个指向SIO_CHAN的指针用来在驱动和高层协议之间通讯 在 wind/target/h/sioLib.h;里,SIO_CHAN如下定义: typedef struct sio_chan/* a serial channel */ { SIO_DRV_FUNCS * pDrvFuncs; /* device data */ } SIO_CHAN; .由于高层协议不知道驱动的XX_CHAN结构,SIO_CHAN被用来允许一个精心定义的数据类型在协议间交换数据 .ttyDrv通过SIO_DRV_FUNCS里的入口向xxDrv发送信息,而xxDrv通过回调向ttyDrv发送信息 [入口:Entry Points] xxCallBackInstall() 安装到高层协议的入口(I/O system,target agent(目标代理),等等) xxPollOutPut() 轮巡模式输出 xxPollInput() 轮巡模式输入 xxIoctl() 支持设备特定的ioctl命令 xxTxStaartup() 初始化一个传输循环(transmit cycle) [驱动回调安装程序] int xxCallbackInstall(pSsioChan,callbackType,callback,callbbackArg) pSioChan 指向SIO_CHAN的指针 callbackType SIO_CALLBACK_GET_TX_CHAR 或 SIO_CALLBACK_PUT_RCV_CHAR callback 指向回调程序的指针 callbackArg 回调的参数 。初始化SIO_CHAN结构里的特定成员 。返回OK 或 ENOSYS(当callbackType不是上两种中的一种) /******************************************************************************** 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)(), /* callback */ void * callbackArg /* parameter to callback */ ) { TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = callback; pChan->putRcvArg = callbackArg; return (OK); default: return (ENOSYS); } } [驱动初始化] 。参数是没一个指向XX_DRV的指针 。初始化XX_CHAN 。带你的程序的SIO_DRV_FUNCS 。傀儡回调 。所有设备特定 。重启芯片 /* local variables */ LOCAL SIO_DRV_FUNCS templateSioDrvFuncs = { templateIoctl, templateTxStartup, templateCallbackInstall, templatePollInput, templatePollOutput }; void templateDevInit ( TEMPLATE_DUSART * pDusart ) { /* initialize each channel"s driver function pointers */ pDusart->portA.sio.pDrvFuncs = &templateSioDrvFuncs; pDusart->portB.sio.pDrvFuncs = &templateSioDrvFuncs; /* install dummy driver callbacks */ pDusart->portA.getTxChar = dummyCallback; pDusart->portA.putRcvChar = dummyCallback; pDusart->portB.getTxChar = dummyCallback; pDusart->portB.putRcvChar = dummyCallback; /* reset the chip */ TEMPLATE_REG_WRITE(pDusart, masterCr, TEMPLATE_RESET_CHIP); /* setting polled mode is one way to make the device quiet */ templateIoctl ((SIO_CHAN *)&pDusart->portA, SIO_MODE_SET, (void *)SIO_MODE_POLL); templateIoctl ((SIO_CHAN *)&pDusart->portB, SIO_MODE_SET, (void *)SIO_MODE_POLL); } /******************************************************************************* * * dummyCallback - dummy callback routine * * RETURNS: ERROR. */ LOCAL STATUS dummyCallback (void) { return (ERROR); } ※ 作 者: 自由妹妹 01-5-22 下午 05:10:58 ※



关键词: 转帖     串口     驱动     编写     实例     解读    

菜鸟
2003-01-15 21:09:00    评分
2楼
已拜读,请教! <--- 〖回复该帖子〗 我发现在usrSerial.c中定义了TY_NAME_BASE "/tyCo/" 如果我使用scc3做uart串口,设备名是否只能为"/tyCo/x"形式? 还是任意取名tty 设备名,然后该设备名通过一个SIO_CHAN,在xxCallbackInstall函数中传给上层协议, 上层在通过SIO_CHAN调用IOCTL来控制串口驱动. 请你指教,谢谢! ※ 作 者: little 01-5-23 下午 02:31:59 ※ reply little <--- 〖回复该帖子〗 Little: 设备名只要是唯一的就可以了... 另,你用scc3做uart一定使用st16c552或者st16c554吧? 我现有st16c552(可扩展两个串口)的完全驱动程序.正开发st16c554(带4个 ACE,可扩展4个串口)的驱动, 欢迎多多交流... ※ 作 者: 自由妹妹 01-5-23 下午 02:59:45 ※

菜鸟
2003-01-15 21:11:00    评分
3楼
Re:串口驱动(Serial Drivers)编写实例解读(连载:一) <--- 〖回复该帖子〗 自由妹妹: 拜读了您的程序,受益良多,我想问如果是用1655X系列作的扩展串口卡,可不可以将Vxworks的标准串中驱动直接扩展到自己卡上用呢? ※ 作 者: 化民 01-5-28 上午 07:39:13 ※ Re:Re:串口驱动(Serial Drivers)编写实例解读(连载:一) <--- 〖回复该帖子〗 化民: VXworks标准的串口驱动是采用SMC(串口通讯控制器)的两个通道,1655x的机制与之不同,故虽然其驱动程序架构相同,但实现起来差异较大. 我现在在把SMC和16c554整合到一起,而且现在已经有阶段性成果,希望我们可以多交流... 另外,我很快会推出一篇关于这个的文章(顺便回击一下论坛上某些人对我的指责),请期待... 自由妹妹 ※ 作 者: 自由妹妹 01-5-28 下午 10:23:03 ※

菜鸟
2003-01-15 21:12:00    评分
4楼
串口驱动(Serial Drivers)编写实例解读(连载:一) <--- 〖回复该帖子〗 大家好,看了大家的高作,有找到亲人的感觉,我现在正在vxworks下进行协议开发,但是对vxworks的机制很是不熟,在对串口驱动的开发中,我扩展了12个串口(用3片16c554),利用epld进行地址译码(地址0x1000开始),中断的合并(把16c554的12个中断合成一个x86的中断),完全按照汇编的方式对串口进行编程。我想做成标准的驱动程序的方式,请大家多多指导。 我的程序如下,有些语句是调试用的,没有一一去掉,请多包涵: /*初始化函数,iosign为第几个串口,0--11)*/ void comini(int iosign) { /*清空原来状态*/ sysInByte(0x1000*iosign+0x1100+lsr);/*read LSR*/ sysInByte(0x1000*iosign+0x1100+msr);/*READ MSR*/ sysInByte(0x1000*iosign+0x1100+iir);/*READ IIR*/ sysInByte(0x1000*iosign+0x1100+rbr);/*READ RBR*/ sysOutByte(0x1000*iosign+0x1100+lcr,0); /* DLAB=0 */ sysOutByte(0x1000*iosign+0x1100+ier,0); /* CLOSE INT */ sysInByte(0x1000*iosign+0x1100+lsr);/*read LSR*/ sysInByte(0x1000*iosign+0x1100+msr);/*READ MSR*/ sysInByte(0x1000*iosign+0x1100+iir);/*READ IIR*/ sysInByte(0x1000*iosign+0x1100+rbr);/*READ RBR*/ sysOutByte(0x1000*iosign+0x1100+lcr,0x80);/*set DLAB=1*/ sysOutByte(0x1000*iosign+0x1100+dlm,0);/*DLM=0*/ sysOutByte(0x1000*iosign+0x1100+dll,0x30);/*DLL=0x0c,set 9600*/ sysOutByte(0x1000*iosign+0x1100+lcr,0x03);/*set n,8,1*/ sysOutByte(0x1000*iosign+0x1100+mcr,0x0b);/*mcr=0x0b,P527*/ sysInByte(0x1000*iosign+0x1100+lsr);/*read LSR*/ sysInByte(0x1000*iosign+0x1100+msr);/*READ MSR*/ sysInByte(0x1000*iosign+0x1100+iir);/*READ IIR*/ sysInByte(0x1000*iosign+0x1100+rbr);/*READ RBR*/ #ifndef ENABLE_FOLLOW sysOutByte(0x1000*iosign+0x1100+ier,0x03); #else sysOutByte(0x1000*iosign+0x1100+ier,0x0b); #endif } 再在初始化中循环调用12次,12个串口的初始化就能完成。 用 vectot7 = INUM_TO_IVEC((INT_NUM_IRQ0)+7); intConnect(vectot7,FunIRQ7,0); 把中断7定向到函数FunIRQ7(),这个函数处理8个串口,另外4个类似 void FunIRQ7() /*com0--7*/ { unsigned char temp; #ifdef ENABLE_FOLLOW unsigned char mymsr; #endif int mycnt; int ionumber; int i; unsigned char _flag[8]; for(i=0;i<=7;i++) _flag[i]=sysInByte(0x1000*i+0x1100+iir); do { for(ionumber=0;ionumber<=7;ionumber++) { if((_flag[ionumber]&0x01)==0) { do { switch(_flag[ionumber]&0x0f) { #ifdef ENABLE_FOLLOW case 0: /*处理流控*/ break; #endif case 4: case 12: /*接收数据*/ break; case 2: /*发送数据*/ break; default: break; } }while(((_flag[ionumber]=sysInByte(0x1000*ionumber+0x1100+iir))&0x01)==0); } } for(i=0;i<=7;i++) _flag[i]=sysInByte(0x1000*i+0x1100+iir); }while(((_flag[0]&0x01)==0)||((_flag[1]&0x01)==0)||((_flag[2]&0x01)==0)\||((_flag[3]&0x01)==0)||((_flag[4]&0x01)==0)||((_flag[5]&0x01)==0)\||((_flag[6]&0x01)==0)||((_flag[7]&0x01)==0)); } 希望大家多联系,freedom_zj@163.com ※ 作 者: freedomzj 01-6-27 上午 11:18:38 ※

共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]