这里以S3C2440为例说明内核里面的串口驱动结构,这里也是用的虚拟总线,一边设备,一边驱动,两个名字匹配上就调用probe 函数。另外一个uart是tty设备的一种,注册一个uart就是注册一个tty,而一个平台往往对uart有统一抽象的操作,所以uart的驱动都统一了,这里的是uart_ops结构体;所以重点关心tty设备,注册uart设备通过uart_add_one_port 函数。下面看下代码调用分析,我把一个完整的驱动分成了三个部分:
1 虚拟总线驱动端:
s3c2440_serial_probe //与设备端匹配"s3c2440-uart"时调用这个函数uart_add_one_port //s3c24xx_serial_ports : 设备对应的底层信息与操作函数
tty_register_device //注册这个tty设备
2 虚拟总线设备端:
s3c24xx_init_uarts
(cpu->init_uarts)(cfg, no); -> cpu_ids 的 s3c244x_init_uartss3c24xx_init_uartdevs //填充platform_device -> s3c24xx_uart_src 传递给驱动端
3 uart的tty驱动:
s3c24xx_serial_modinit
uart_register_driver
alloc_tty_driver
tty_set_operations //uart_ops :uart操作的抽象,会调用s3c24xx_serial_ports 里面的操作函数
tty_register_driver //注册这个tty设备的驱动
上面这三个部分的数据传递关系:虚拟总线设备端 -> 虚拟总线驱动端 -> uart的tty驱动
解释:
1虚拟总线设备端传递硬件配置信息给驱动端:名称,资源(寄存器地址),平台数据(寄存器配置)
2虚拟总线驱动端传递具体硬件操作函数给uart的tty驱动(UART操作抽象)
——————————————————————————————
打开串口的函数调用过程为:uart_open
uart_startup
uart_port_startup
uport->ops->startup ->s3c24xx_serial_startup
关闭串口的函数调用过程为:uart_close
uart_shutdown
uart_port_shutdown
uport->ops->shutdown ->s3c24xx_serial_shutdown
发送串口数据的函数调用过程为:
uart_write
uart_start
__uart_start
port->ops->start_tx ->s3c24xx_serial_start_tx
其他函数的调用原理是一样的,这里不详解了。