C 建设个人网站,wordpress优惠券自动使用,网上做兼职网站有哪些,什么软件可以做dj视频网站串口驱动的整体框架实际上和显示驱动类似
驱动程序是一个字符设备#xff0c;驱动的实质内容都是在一个平台总线设备驱动程序里 1. 串口驱动的分析#xff0c;从drivers/tty/serial/8250/8250.c开始 serial8250_init为入口函数#xff0c;从这个函数一路分析下…串口驱动的整体框架实际上和显示驱动类似
驱动程序是一个字符设备驱动的实质内容都是在一个平台总线设备驱动程序里 1. 串口驱动的分析从drivers/tty/serial/8250/8250.c开始 serial8250_init为入口函数从这个函数一路分析下去下面列出主要代码 serial8250_reg.nr UART_NR; UART_NR为8查看datasheet可知A20支持8个uart ret uart_register_driver(serial8250_reg); uart_register_driver在”drivers/tty/serial/serial_core.c“中可以找到 normal-type TTY_DRIVER_TYPE_SERIAL; normal-flags TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_register_driver tty_register_driver 在drivers/tty/tty_io.c这个文件中找到如下函数 alloc_chrdev_region register_chrdev_region cdev_init cdev_add if (!(driver-flags TTY_DRIVER_DYNAMIC_DEV)) { for (i 0; i driver-num; i) { d tty_register_device(driver, i, NULL); if (IS_ERR(d)) { error PTR_ERR(d); goto err; } } } 前四个函数是创建一个字符设备驱动程序的典型函数后面那段if语句之所以拿出来说一下是因为 tty_register_device这个函数是用来创建设备文件的但是这个if语句是不会执行因为从上面的分析可 知道这个驱动的flags里有TTY_DRIVER_DYNAMIC_DEV。那么什么时候创建了设备文件呢。实际上上面几个文件只是一个框架性的东西。 2. 接下来分析另一路主线 ”drivers/tty/serial/8250/8250_sunxi.c sw_serial_init 这里注册了一个平台总线驱动和平台总线设备 script_get_item(uart_para, uart_used, val); 从配置文件中得到某一个串口是否可用如果可用的话在调用如下函数 platform_device_register platform_driver_register 来完成平台总线驱动和平台总线设备的匹配 分析device和driver 如下 static struct platform_driver sw_serial_driver { .probe sw_serial_probe, .remove sw_serial_remove, .suspend sw_serial_suspend, .resume sw_serial_resume, .driver { .name sunxi-uart, .owner THIS_MODULE, }, }; struct platform_device sw_uart_dev[] { [0] {.name sunxi-uart, .id 0, .num_resources ARRAY_SIZE(sw_uart_res[0]), .resource sw_uart_res[0][0], .dev.release sunxi_serial_release}, [1] {.name sunxi-uart, .id 1, .num_resources ARRAY_SIZE(sw_uart_res[1]), .resource sw_uart_res[1][0], .dev.release sunxi_serial_release}, [2] {.name sunxi-uart, .id 2, .num_resources ARRAY_SIZE(sw_uart_res[2]), .resource sw_uart_res[2][0], .dev.release sunxi_serial_release}, [3] {.name sunxi-uart, .id 3, .num_resources ARRAY_SIZE(sw_uart_res[3]), .resource sw_uart_res[3][0], .dev.release sunxi_serial_release}, [4] {.name sunxi-uart, .id 4, .num_resources ARRAY_SIZE(sw_uart_res[4]), .resource sw_uart_res[4][0], .dev.release sunxi_serial_release}, [5] {.name sunxi-uart, .id 5, .num_resources ARRAY_SIZE(sw_uart_res[5]), .resource sw_uart_res[5][0], .dev.release sunxi_serial_release}, [6] {.name sunxi-uart, .id 6, .num_resources ARRAY_SIZE(sw_uart_res[6]), .resource sw_uart_res[6][0], .dev.release sunxi_serial_release}, [7] {.name sunxi-uart, .id 7, .num_resources ARRAY_SIZE(sw_uart_res[7]), .resource sw_uart_res[7][0], .dev.release sunxi_serial_release}, }; 从上面两个结构体可以看出8个平台总线设备匹配了1个平台总线驱动。 那么接下来我们看看平台总线驱动的probe函数实现了什么。
3. sw_serial_probe函数分析 sw_serial_get_config这个函数从配置文件中得到type和port两个参数type应该是管脚数目比如基本的串口使用了tx,rx那个type就是2加两个流控type就是4全串口type就是8. sw_serial_get_resource这个函数从配置文件中得到管脚的定义并从平台设备的resources中得到内存和中断资源。 serial8250_register_port serial8250_register_port定义8250.c中 uart_add_one_port 定义在serial_core.c中 tty_register_device 定义在tty_io.c中 下面主要分析这个函数
4. struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) { char name[64]; 这句构造主次设备号 dev_t dev MKDEV(driver-major, driver-minor_start) index; if (index driver-num) { printk(KERN_ERR Attempt to register invalid tty line number (%d).\n, index); return ERR_PTR(-EINVAL); } if (driver-type TTY_DRIVER_TYPE_PTY) pty_line_name(driver, index, name); else 这句构造串口设备文件 tty_line_name(driver, index, name); 这句用name来创建一个设备文件 return device_create(tty_class, device, dev, NULL, name); } 最终在这里创建了串口的设备文件实际这个串口真正硬件资源相关的东西都是在这个平台总线设备和平台总线驱动里来管理的。 最上面的那个串口字符设备驱动只是一个框架性的东西。实际和显示驱动类似2.6内核以后的很多驱动程序都是这种分层的方式用平台总线驱动程序来实现。