6.1.1Drv/Serial(Character Device Drv)
来源:互联网 发布:java邮箱格式验证方法 编辑:程序博客网 时间:2024/06/05 05:11
转载请注明出处http://blog.csdn.net/alvin_jack/article/details/70665371
在Nuttx中,字符型设备具有以下的属性(以串口为例):
文章均出自个人理解,错误之处敬请指出;
Nuttx的驱动主要分为两层,向上为抽象为文件的接口层,具体接口如下,向下为驱动接口层,通过dev、ops实现对底层寄存器的操作,以及对驱动模块的配置;
1)include/nuttx/fs/fs.h所有的结构和API接口需要以字符型设备正常运行,具体的定义在该头文件中;每个设备驱动必须实现struct file_operations这个数据结构的实例,具体如下:
struct file_operations{ int open (FAR struct file *filep); int close (FAR struct file *filep); ssize_t read(FAR struct file *filep, FAR char *buffer, size_t buflen); ssize_t write(FAR struct file *filep, FAR const char *buffer, size_t buflen); off_t seek(FAR struct file *filep, off_t offset, int whence); int ioctl(FAR struct file *filep,int cmd, unsigned long arg); int poll(FAR struct file *filep, struct pollfd *fds, bool setup);}
2)drivers/serial/serial.c,这里就是用来填充之前已经定义的file_operations结构,换句话说就是对该结构的实现;
而实现函数,例如uart_open(FAR struct file *filep):
static int uart_open(FAR struct file *filep){ //获取设备的路径,并根据路径在虚拟文件系统中找到该设备驱动结构体变量(即dev) FAR struct inode *inode = filep->f_inode; FAR uart_dev_t *dev = inode->i_private; uint8_t tmp; int ret; /* If the port is the middle of closing, wait until the close is finished. * If a signal is received while we are waiting, then return EINTR. */ ret = uart_takesem(&dev->closesem, true); if (ret < 0) { /* A signal received while waiting for the last close operation. */ return ret; }#ifdef CONFIG_SERIAL_REMOVABLE /* If the removable device is no longer connected, refuse to open the * device. We check this after obtaining the close semaphore because * we might have been waiting when the device was disconnected. */ if (dev->disconnected) { ret = -ENOTCONN; goto errout_with_sem; }#endif /* Start up serial port */ /* Increment the count of references to the device. */ tmp = dev->open_count + 1; if (tmp == 0) { /* More than 255 opens; uint8_t overflows to zero */ ret = -EMFILE; goto errout_with_sem; } /* Check if this is the first time that the driver has been opened. */ if (tmp == 1) { irqstate_t flags = enter_critical_section(); /* If this is the console, then the UART has already been initialized. */ if (!dev->isconsole) { /* Perform one time hardware initialization */ ret = uart_setup(dev); if (ret < 0) { leave_critical_section(flags); goto errout_with_sem; } } /* In any event, we do have to configure for interrupt driven mode of * operation. Attach the hardware IRQ(s). Hmm.. should shutdown() the * the device in the rare case that uart_attach() fails, tmp==1, and * this is not the console. */ ret = uart_attach(dev); if (ret < 0) { uart_shutdown(dev); leave_critical_section(flags); goto errout_with_sem; } /* Mark the io buffers empty */ dev->xmit.head = 0; dev->xmit.tail = 0; dev->recv.head = 0; dev->recv.tail = 0; /* Initialize termios state */#ifdef CONFIG_SERIAL_TERMIOS dev->tc_iflag = 0; if (dev->isconsole) { /* Enable \n -> \r\n translation for the console */ dev->tc_oflag = OPOST | ONLCR; } else { dev->tc_oflag = 0; }#endif#ifdef CONFIG_SERIAL_DMA /* Notify DMA that there is free space in the RX buffer */ uart_dmarxfree(dev);#endif /* Enable the RX interrupt */ uart_enablerxint(dev); leave_critical_section(flags); } /* Save the new open count on success */ dev->open_count = tmp;errout_with_sem: uart_givesem(&dev->closesem); return ret;}
里面调用的函数例如uart_setup、uart_givesem、uart_dmarxfree都是来自于uart_ops_s的数据结构中的,而uart_ops_s中的数据结构则是对uart的外设寄存器组进行操作,从而实现串口的功能;
#define uart_setup(dev) dev->ops->setup(dev)#define uart_shutdown(dev) dev->ops->shutdown(dev)#define uart_attach(dev) dev->ops->attach(dev)#define uart_detach(dev) dev->ops->detach(dev)#define uart_enabletxint(dev) dev->ops->txint(dev, true)#define uart_disabletxint(dev) dev->ops->txint(dev, false)#define uart_enablerxint(dev) dev->ops->rxint(dev, true)#define uart_disablerxint(dev) dev->ops->rxint(dev, false)#define uart_rxavailable(dev) dev->ops->rxavailable(dev)#define uart_txready(dev) dev->ops->txready(dev)#define uart_txempty(dev) dev->ops->txempty(dev)#define uart_send(dev,ch) dev->ops->send(dev,ch)#define uart_receive(dev,s) dev->ops->receive(dev,s)
3)uart_dev_s,包含了uart_ops_s以及串口的状态值(如中断信号量、传输标志位...),uart_dev_s是需要被系统的驱动调用的,也就是说在初始化的时候会通过(uart_register())进行注册,将之前的填充好的数据结构与虚拟文件系统进行关联;
struct uart_dev_s{ /* State data */ uint8_t open_count; /* Number of times the device has been opened */ volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */ volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */#ifdef CONFIG_SERIAL_REMOVABLE volatile bool disconnected; /* true: Removable device is not connected */#endif bool isconsole; /* true: This is the serial console */#ifdef CONFIG_SERIAL_TERMIOS /* Terminal control flags */ tcflag_t tc_iflag; /* Input modes */ tcflag_t tc_oflag; /* Output modes */ tcflag_t tc_lflag; /* Local modes */#endif /* Semaphores */ sem_t closesem; /* Locks out new open while close is in progress */ sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */ sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */#ifndef CONFIG_DISABLE_POLL sem_t pollsem; /* Manages exclusive access to fds[] */#endif /* I/O buffers */ struct uart_buffer_s xmit; /* Describes transmit buffer */ struct uart_buffer_s recv; /* Describes receive buffer */#ifdef CONFIG_SERIAL_DMA /* DMA transfers */ struct uart_dmaxfer_s dmatx; /* Describes transmit DMA transfer */ struct uart_dmaxfer_s dmarx; /* Describes receive DMA transfer */#endif /* Driver interface */ FAR const struct uart_ops_s *ops; /* Arch-specific operations */ FAR void *priv; /* Used by the arch-specific logic */ /* The following is a list if poll structures of threads waiting for * driver events. The 'struct pollfd' reference for each open is also * retained in the f_priv field of the 'struct file'. */#ifndef CONFIG_DISABLE_POLL struct pollfd *fds[CONFIG_SERIAL_NPOLLWAITERS];#endif};
4)register_driver,串口注册函数,完成之前所填充的数据结构uart_dev_s和uart_ops_s与虚拟文件系统关联
int register_driver( FAR const char *path, \ FAR const struct file_operations *fops,\ mode_t mode,\ FAR void *priv);eg:register_driver(/dev/ttyS0, \注册到系统虚拟文件系统的地址 &g_serialops,\填充的file_operations数据结构 0666,\端口的权限 dev);\填充的uart_dev_s数据结构
到这里一个串口的驱动就算完成了,对应用层来说,所调用file_operations中的函数去驱动的硬件,是已经在初始化的时候就做好了的;基于串口的应用开发也就不需要再去关心硬件驱动层面的开发了;
一般来说,file_operations和dev(uart_dev_s)之间的关系也就是从注册开始建立起联系的,一般的板卡会存在多个dev(uart_dev_s),而file_operations针对同一类设备来说只会是存在一个实例,这些驱动一般OS都会事先写好,然后用户通过配置文件进行选择;
0 0
- 6.1.1Drv/Serial(Character Device Drv)
- 6.1.4.Drv/PWM(Character Device Drv)
- 6.3.3Drv/I2C(Specialized Device Drivers)
- Drv总结
- IPCAM?还是DRV?
- xorg-x11-drv-vmware
- experiment : thread on drv
- drv experiment : FOLLOW_JMP parse
- GD25Q32C FLASH DRV
- experiment : 字符串分解 on drv
- int platform_driver_register(struct platform_driver *drv)
- int driver_register(struct device_driver *drv)
- int uart_register_driver(struct uart_driver *drv)
- alg : 单向链表逆序 on drv
- alg : 单向链表排序 on drv
- src/hwif和src/drv的区别
- linux 内核专题— drv术语
- DDI DEV DRV 之间的关系
- 前端学HTTP之实体和编码
- 参照MyEclipse/eclipse设置notepad++的快捷键
- LauchMode(Activity的启动模式)
- Libevent编程-捕获 signal
- Android The specified child already has a parent.解决方法
- 6.1.1Drv/Serial(Character Device Drv)
- Android System Server进程源码分析 上
- 机器视觉
- 从零写一个线程切换工具
- Non-overlapping Intervals
- springBoot上传文件大小设置
- 一起Talk Android吧(第十八回:Java常用类String VS StringBuffer)
- 个人博客页面
- HashMap底层源码分析