资讯详情

vxWorks下基于TTY中间件的串口驱动开发

很久没有更新博客了,最近基于TTY串口驱动中间件,在这里分享经验,做笔记。

首先,定义结构体

typedef struct m8313_Uart_Chan {  SIO_CHAN sio;  STATUS (*getChar)();  STATUS (*putChar)();  void * getCharArg;  void * putCharArg;  unsigned int intLevel;  unsigned int baund;  unsigned int errorCount;  int intrMode; }M8313_UART_ChAN;

第二步是实现驱动函数的挂接

static SIO_DRV_FUNCS TL16C550C_DrvFuncs = {   TL16C550C_Ioctrl,  TL16C550C_StartUp,  TL16C550C_CallbackInstall,  TL16C550C_PollInput,  TL16C550C_PollOutput }; 

第三步,实现TTY从中间层到驱动层接口函数的挂接

static int TL16C550C_CallbackInstall(SIO_CHAN * pSioChan,                                int callbackType,                                STATUS (*callback)(void *, ...),                                void * callbackArg) {  M8313_UART_ChAN *pChan = (M8313_UART_ChAN*)pSioChan;  switch(callbackType)  {  case SIO_CALLBACK_GET_TX_CHAR:   pChan->getChar = callback;   pChan->getCharArg = callbackArg;   return OK;  case SIO_CALLBACK_PUT_RCV_CHAR:   pChan->putChar = callback;   pChan->putCharArg = callbackArg;   return OK;  case SIO_CALLBACK_ERROR:  default:   return ENOSYS;  } }

这个函数主要是接收数据后如何将数据交给TTY中间件接口putChar,还有如何从tty获取需要发送的数据接口的中间件接口getChar

第四步是发送函数TL16C550C_StartUp,该函数是驱动层的数据发送函数

static void TL16C550C_SendByte(char byte) {  int LocalBusAddr = 0;  char value = 0;  int errorCount = 0;    do  {   LocalBusAddr = Get_LocalBus_Addr(LSR_REGISTER);   value = *(unsigned short *)LocalBusAddr;   errorCount  ;   if(errorCount > 100)   {    TL16C550C_Config();    return;   }  }while(!(value&LSR_THRE_MASK));    LocalBusAddr = Get_LocalBus_Addr(LCR_REGISTER);  value = *(unsigned short *)LocalBusAddr;  value &= ~LCR_DLAB_MASK;  *(unsigned short *)LocalBusAddr = value;  LocalBusAddr = Get_LocalBus_Addr(THR_REGISTER);   *(unsigned short *)LocalBusAddr = byte;  }

第五步是实现配置函数TL16C550C_Ioctrl,该函数主要设置串口波特率、模式、缓冲区、验证位、数据位、停止位,并根据不同的芯片配置

static int TL16C550C_Ioctrl(SIO_CHAN *pSioChan,int cmd,void *arg) {  M8313_UART_ChAN* pChan = (M8313_UART_ChAN*)pSioChan;  int setArg = (int)arg;   switch (cmd)  {  case SIO_BAUD_SET:   if(setArg != 0)   {    if(setArg < TL16C550C_MIN_BAUD || setArg > TL16C550C_MAX_BAUD)    {     return ERROR;    }    switch(setArg)    {    case 600:    case 1200:    case 2400:    case 4800:    case 9600:    case 19200:    case 38400:    case 56000:     pChan->baund = setArg;     TL16C550C_SetBaund(setArg);     break;    default:     break;    }   }   break;  case SIO_BAUD_GET:   *(int *)arg = pChan->baund;   break;  case SIO_MODE_SET:   if(setArg == SIO_MODE_INT) ///中断模式   {    TL16c550cSio.intrMode = TRUE;    TL16C550C_ModeSet(SIO_MODE_INT);   }   else if(setArg == SIO_MODE_POLL)///查询模式   {    TL16c550cSio.intrMode = FALSE;    TL16C550C_ModeSet(SIO_MODE_POLL);    }   break;  case SIO_MODE_GET:   if(TL16c550cSio.intrMode)   {    *(int *)arg = SIO_MODE_INT;   }   else   {    *(int *)arg = SIO_MODE_POLL;   }   break;  case SIO_AVAIL_MODES_GET:   *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;    break;  case SIO_HW_OPTS_SET:   TL16C550C_LCR(setArg);   break;  default:   break;  }  return OK; }

由于查询模式的效率较低,因此很少使用查询模式,这里不再描述

第六步是挂接驱动程序

static void TL16C550C_Init() {  TL16c550cSio.sio.pDrvFuncs = &TL16C550C_DrvFuncs;  TL16c550cSio.errorCount = 0;  TL16c550cSio.getChar = dummyCallBack;  TL16c550cSio.putChar = dummyCallBack;  TL16c550cSio.intLevel = INUM_IRQ2;  //配置串口芯片  TL16C550C_Config();  TL16c550cSio.intrMode = FALSE; } 

第七步,创建tty设备使能接收中断

void TL16C550C_Open(void) {  char devName[16] = {0};   TL16C550C_Init();  sprintf(devName, "%s", SERIAL_NAME);  /*驱动设备注册tty驱动*/   ttyDevCreate(devName, &TL16c550cSio.sio,RECV_BUF_SIZE, SEND_BUF_SIZE);  //中断串口  intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(TL16c550cSio.intLevel), (VOIDFUNCPTR)TL16C550C_IntIsr, (int)0);  intEnable(TL16c550cSio.intLevel);  }

第八步是中断接收数据tty中间层

static void TL16C550C_IntIsr(void) {  int LocalBusAddr = 0;  char status= 0;  char Value = 0;    LocalBusAddr = Get_LocalBus_Addr(LSR_REGISTER);  status = *(unsigned short *)LocalBusAddr;  if(status & (LSR_OE_MASK | LSR_PE_MASK |LSR_FE_MASK))//错误  {   //复位串口   TL16c550cSio.errorCount  ;      TL16C550C_Config();  }  else if(status & LSR_DR_MASK)  {   LocalBusAddr = Get_LocalBus_Addr(LCR_REGISTER);   Value = *(unsigned short *)LocalBusAddr;   Value &= ~LCR_DLAB_MASK;   *(unsigned short *)LocalBusAddr = Value;   LocalBusAddr = Get_LocalBus_Addr(RBR_REGISTER);   Value = *(unsignedshort *)LocalBusAddr;
		TL16c550cSio.putChar(TL16c550cSio.putCharArg,Value);
	}
}

标签: 16c热过载继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台