diff --git a/IMX6ULL/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.md b/IMX6ULL/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.md new file mode 100644 index 0000000..ecb6f6c --- /dev/null +++ b/IMX6ULL/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.md @@ -0,0 +1,77 @@ +## 编写虚拟UART驱动程序_框架 + +* 参考代码 + + ```shell + 硬件相关: + drivers/tty/serial/imx.c + drivers/tty/serial/stm32-usart.c + + 串口核心层: + drivers/tty/serial/serial_core.c + + TTY层: + drivers/tty/tty_io.c + ``` + + + +* 本节课程源码在GIT仓库里 + + ```shell + doc_and_source_for_drivers\IMX6ULL\source\09_UART + 04_virtual_uart_driver + doc_and_source_for_drivers\STM32MP157\source\A7\09_UART + 04_virtual_uart_driver + ``` + + + +### 1. 框架回顾 + +![image-20210724153515059](pic/09_UART/24_tty_driver_level_2.png) + + + +### 2. 编写UART驱动要做的事 + +![image-20210730142813809](pic/09_UART/39_uart_driver.png) + + + +* 注册一个uart_driver:它里面有名字、主次设备号等 +* 对于每一个port,调用uart_add_one_port,里面的核心是uart_ops,提供了硬件操作函数 + * uart_add_one_port由platform_driver的probe函数调用 + * 所以: + * 编写设备树节点 + * 注册platform_driver + + + +### 3. 虚拟的UART + +![image-20210730150445225](pic/09_UART/40_virtual_uart.png) + +为了做实验,我们还要创建一个虚拟文件:/proc/virt_uart_buf + +* 要发数据给虚拟串口时,执行:echo "xxx" > /proc/virt_uart_buf +* 要读取虚拟串口的数据时,执行:cat /proc/virt_uart_buf + + + + + +### 4. 编程 + +#### 4.1 编写设备树 + +#### 4.2 编写uart_driver + +#### 4.3 编写platform_driver + +#### 4.4 实现uart_ops + +#### 4.5 实现/proc/virt_uart_buf + + + diff --git a/IMX6ULL/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.tif b/IMX6ULL/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.tif new file mode 100644 index 0000000..dfe18f1 Binary files /dev/null and b/IMX6ULL/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.tif differ diff --git a/IMX6ULL/doc_pic/09_UART/pic/09_UART/39_uart_driver.png b/IMX6ULL/doc_pic/09_UART/pic/09_UART/39_uart_driver.png new file mode 100644 index 0000000..6bab838 Binary files /dev/null and b/IMX6ULL/doc_pic/09_UART/pic/09_UART/39_uart_driver.png differ diff --git a/IMX6ULL/doc_pic/09_UART/pic/09_UART/40_virtual_uart.png b/IMX6ULL/doc_pic/09_UART/pic/09_UART/40_virtual_uart.png new file mode 100644 index 0000000..6fce702 Binary files /dev/null and b/IMX6ULL/doc_pic/09_UART/pic/09_UART/40_virtual_uart.png differ diff --git a/IMX6ULL/source/09_UART/04_virtual_uart_driver/virtual_uart.c b/IMX6ULL/source/09_UART/04_virtual_uart_driver/virtual_uart.c new file mode 100644 index 0000000..9fa3d7c --- /dev/null +++ b/IMX6ULL/source/09_UART/04_virtual_uart_driver/virtual_uart.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct uart_driver virt_uart_drv = { + .owner = THIS_MODULE, + .driver_name = "VIRT_UART", + .dev_name = "ttyVIRT", + .major = 0, + .minor = 0, + .nr = 1, +}; + + +static int virtual_uart_probe(struct platform_device *pdev) +{ + uart_add_one_port(struct uart_driver * drv, struct uart_port * uport); + + return 0; +} +static int virtual_uart_remove(struct platform_device *pdev) +{ + + return 0; +} + + + +static const struct of_device_id virtual_uart_of_match[] = { + { .compatible = "100ask,virtual_uart", }, + { }, +}; + + +static struct platform_driver virtual_uart_driver = { + .probe = virtual_uart_probe, + .remove = virtual_uart_remove, + .driver = { + .name = "100ask_virtual_uart", + .of_match_table = of_match_ptr(virtual_uart_of_match), + } +}; + + +/* 1. 入口函数 */ +static int __init virtual_uart_init(void) +{ + printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + + int ret = uart_register_driver(&virt_uart_drv); + + if (ret) + return ret; + + /* 1.1 注册一个platform_driver */ + return platform_driver_register(&virtual_uart_driver); +} + + +/* 2. 出口函数 */ +static void __exit virtual_uart_exit(void) +{ + printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + /* 2.1 反注册platform_driver */ + platform_driver_unregister(&virtual_uart_driver); +} + +module_init(virtual_uart_init); +module_exit(virtual_uart_exit); + +MODULE_LICENSE("GPL"); + + diff --git a/IMX6ULL/source/09_UART/04_virtual_uart_driver/virtual_uart.dts b/IMX6ULL/source/09_UART/04_virtual_uart_driver/virtual_uart.dts new file mode 100644 index 0000000..50b380a --- /dev/null +++ b/IMX6ULL/source/09_UART/04_virtual_uart_driver/virtual_uart.dts @@ -0,0 +1,13 @@ + + +/{ + virtual_uart: virtual_uart_100ask { + compatible = "100ask,virtual_uart"; + + interrupt-parent = <&intc>; + interrupts = ; + + }; + + +}; diff --git a/README.md b/README.md index 47fec27..05c7135 100644 --- a/README.md +++ b/README.md @@ -358,6 +358,7 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git ```shell 12_UART驱动调试方法 + 13_编写虚拟UART驱动程序_框架 ``` ## 6. 联系方式 diff --git a/STM32MP157/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.md b/STM32MP157/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.md new file mode 100644 index 0000000..ecb6f6c --- /dev/null +++ b/STM32MP157/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.md @@ -0,0 +1,77 @@ +## 编写虚拟UART驱动程序_框架 + +* 参考代码 + + ```shell + 硬件相关: + drivers/tty/serial/imx.c + drivers/tty/serial/stm32-usart.c + + 串口核心层: + drivers/tty/serial/serial_core.c + + TTY层: + drivers/tty/tty_io.c + ``` + + + +* 本节课程源码在GIT仓库里 + + ```shell + doc_and_source_for_drivers\IMX6ULL\source\09_UART + 04_virtual_uart_driver + doc_and_source_for_drivers\STM32MP157\source\A7\09_UART + 04_virtual_uart_driver + ``` + + + +### 1. 框架回顾 + +![image-20210724153515059](pic/09_UART/24_tty_driver_level_2.png) + + + +### 2. 编写UART驱动要做的事 + +![image-20210730142813809](pic/09_UART/39_uart_driver.png) + + + +* 注册一个uart_driver:它里面有名字、主次设备号等 +* 对于每一个port,调用uart_add_one_port,里面的核心是uart_ops,提供了硬件操作函数 + * uart_add_one_port由platform_driver的probe函数调用 + * 所以: + * 编写设备树节点 + * 注册platform_driver + + + +### 3. 虚拟的UART + +![image-20210730150445225](pic/09_UART/40_virtual_uart.png) + +为了做实验,我们还要创建一个虚拟文件:/proc/virt_uart_buf + +* 要发数据给虚拟串口时,执行:echo "xxx" > /proc/virt_uart_buf +* 要读取虚拟串口的数据时,执行:cat /proc/virt_uart_buf + + + + + +### 4. 编程 + +#### 4.1 编写设备树 + +#### 4.2 编写uart_driver + +#### 4.3 编写platform_driver + +#### 4.4 实现uart_ops + +#### 4.5 实现/proc/virt_uart_buf + + + diff --git a/STM32MP157/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.tif b/STM32MP157/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.tif new file mode 100644 index 0000000..dfe18f1 Binary files /dev/null and b/STM32MP157/doc_pic/09_UART/13_编写虚拟UART驱动程序_框架.tif differ diff --git a/STM32MP157/doc_pic/09_UART/pic/09_UART/39_uart_driver.png b/STM32MP157/doc_pic/09_UART/pic/09_UART/39_uart_driver.png new file mode 100644 index 0000000..6bab838 Binary files /dev/null and b/STM32MP157/doc_pic/09_UART/pic/09_UART/39_uart_driver.png differ diff --git a/STM32MP157/doc_pic/09_UART/pic/09_UART/40_virtual_uart.png b/STM32MP157/doc_pic/09_UART/pic/09_UART/40_virtual_uart.png new file mode 100644 index 0000000..6fce702 Binary files /dev/null and b/STM32MP157/doc_pic/09_UART/pic/09_UART/40_virtual_uart.png differ diff --git a/STM32MP157/source/A7/09_UART/04_virtual_uart_driver/virtual_uart.c b/STM32MP157/source/A7/09_UART/04_virtual_uart_driver/virtual_uart.c new file mode 100644 index 0000000..9fa3d7c --- /dev/null +++ b/STM32MP157/source/A7/09_UART/04_virtual_uart_driver/virtual_uart.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct uart_driver virt_uart_drv = { + .owner = THIS_MODULE, + .driver_name = "VIRT_UART", + .dev_name = "ttyVIRT", + .major = 0, + .minor = 0, + .nr = 1, +}; + + +static int virtual_uart_probe(struct platform_device *pdev) +{ + uart_add_one_port(struct uart_driver * drv, struct uart_port * uport); + + return 0; +} +static int virtual_uart_remove(struct platform_device *pdev) +{ + + return 0; +} + + + +static const struct of_device_id virtual_uart_of_match[] = { + { .compatible = "100ask,virtual_uart", }, + { }, +}; + + +static struct platform_driver virtual_uart_driver = { + .probe = virtual_uart_probe, + .remove = virtual_uart_remove, + .driver = { + .name = "100ask_virtual_uart", + .of_match_table = of_match_ptr(virtual_uart_of_match), + } +}; + + +/* 1. 入口函数 */ +static int __init virtual_uart_init(void) +{ + printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + + int ret = uart_register_driver(&virt_uart_drv); + + if (ret) + return ret; + + /* 1.1 注册一个platform_driver */ + return platform_driver_register(&virtual_uart_driver); +} + + +/* 2. 出口函数 */ +static void __exit virtual_uart_exit(void) +{ + printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + /* 2.1 反注册platform_driver */ + platform_driver_unregister(&virtual_uart_driver); +} + +module_init(virtual_uart_init); +module_exit(virtual_uart_exit); + +MODULE_LICENSE("GPL"); + + diff --git a/STM32MP157/source/A7/09_UART/04_virtual_uart_driver/virtual_uart.dts b/STM32MP157/source/A7/09_UART/04_virtual_uart_driver/virtual_uart.dts new file mode 100644 index 0000000..50b380a --- /dev/null +++ b/STM32MP157/source/A7/09_UART/04_virtual_uart_driver/virtual_uart.dts @@ -0,0 +1,13 @@ + + +/{ + virtual_uart: virtual_uart_100ask { + compatible = "100ask,virtual_uart"; + + interrupt-parent = <&intc>; + interrupts = ; + + }; + + +};