实现串口SIO驱动(一)
在SylixOS中,不管是调试串口还是通信串口都是以TTY设备的形式注册到内核中使用,每一个串口设备都在/dev/ 目录下有一个对应的ttyS* 设备名的设备:
BSP在启动的过程中也会打开调试串口的tty设备,并且将其文件描述符设置为内核标准输入、标准输出和标准出错这三个文件描述符:
static VOID halStdFileInit (VOID) { INT iFd = open("/dev/ttyS0", O_RDWR, 0); if (iFd >= 0) { ioctl(iFd, FIOBAUDRATE, SIO_BAUD_115200); ioctl(iFd, FIOSETOPTIONS, (OPT_TERMINAL & (~OPT_7_BIT))); /* system terminal 8 bit mode */ ioGlobalStdSet(STD_IN, iFd); ioGlobalStdSet(STD_OUT, iFd); ioGlobalStdSet(STD_ERR, iFd); } }
SylixOS中TTY设备使用的是SIO驱动框架,类似于printf这样的打印最终都需要调用到SIO驱动中的发送回调函数,下面让我们一起来学习下如何开发SylixOS下串口SIO驱动。
在SylixOS中,使用SIO_CHAN 数据结构来表示一个SIO通道:
typedef struct sio_chan { /* a serial channel */ SIO_DRV_FUNCS *pDrvFuncs; } SIO_CHAN;
可以看出这个数据结构很简单,其中只有一个成员,表示SIO驱动操作集。SIO_DRV_FUNCS 数据结构就表示了SIO驱动操作集:
struct sio_drv_funcs { /* driver functions */ INT (*ioctl) ( SIO_CHAN *pSioChan, INT cmd, PVOID arg ); INT (*txStartup) ( SIO_CHAN *pSioChan ); INT (*callbackInstall) ( SIO_CHAN *pSioChan, INT callbackType, VX_SIO_CALLBACK callback, PVOID callbackArg ); INT (*pollInput) ( SIO_CHAN *pSioChan, PCHAR inChar ); INT (*pollOutput) ( SIO_CHAN *pSioChan, CHAR outChar ); }; typedef struct sio_drv_funcs SIO_DRV_FUNCS;
- ioctl:实现对SIO通道的一些控制,比如打开、关闭、设置硬件参数等等。
- txStartup:SIO通道发送数据。
- callbackInstall:SIO驱动中需要通过此回调将系统缓冲区发送和接收数据操作接口记录在驱动中,SylixOS并没有为BSP提供相应的API来直接操作系统数据缓冲区,所以只能通过这种间接的方式来记录内核中操作系统缓冲区的函数指针,然后在驱动中使用。
- pollInput和pollOutput:这两个回调接口当前并没有被内核所使用,是预留接口。
通常在驱动中顶一个SIO通道全局变量:
static SIO_CHAN uartSioChan;
然后再定义一个SIO驱动集全局变量:
static SIO_DRV_FUNCS uartSioDrvFunc;
最后用SIO驱动操作集来初始化SIO通道:
SIO_CHAN *uartSioChanCreate (VOID) { uartSioChan.pDrvFuncs = &uartSioDrvFunc; return &uartSioChan; }
在下一章节我们继续讲解如何实现SIO驱动那3个操作集。
附源码:
sio.c源码:
#define __SYLIXOS_KERNEL #include <SylixOS.h> #include <linux/compat.h> #include "uart.h" static SIO_CHAN uartSioChan; static SIO_DRV_FUNCS uartSioDrvFunc; SIO_CHAN *uartSioChanCreate (VOID) { uartSioChan.pDrvFuncs = &uartSioDrvFunc; return &uartSioChan; }
评论