X-018-KERNEL-串口驱动开发之serial console
1. 前言
本文是“X Project”串口驱动开发的第三篇,在第二篇“uart driver框架[1]”的基础上,实现console驱动,并借助这个过程,理解如下知识:
1)从DTS regs字段中获取设备的I/O基址,并map出来供driver访问。这是device tree最基本的使用场景。
2)从DTS aliases中获取串口的索引号。这是device tree aliases功能的一个应用场景。
3)uart port—>line和console—>index之间的关系。
2. 从DTS regs字段中获取设备的I/O基址
大家应该记得我们在移植串口的“early console[2]”的时候,需要使用UART5的寄存器地址,那时直接在代码中用宏定义出来了,如下:
#define UART5_BASE (0xE012a000)
这种做法有一个明显的缺点:driver不具有通用性,如果寄存器地址换了怎么办?如果换个串口呢?如果同时支持多个串口呢?这时device tree的优势就体现出来了,driver可以在probe的时候动态的从dts中获取当前设备的寄存器地址,步骤如下:
1)在dts文件中增加regs字段
serial5: serial@e012a000 {
compatible = “actions,s900-serial”;
- reg = <0 0xe012a000 0 0x2000>; /* UART5_BASE */
};
其格式由dts文件的#address-cells和 #size-cells决定,它们都是2的时候,表示UART5的寄存器从0x00000000e012a000开始,size为0x0000000000002000。
2)在driver probe接口中,以IORESOURCE_MEM为参数,调用platform_get_resource接口,以struct resource的形式,将上面定义的寄存器信息取出来,并保存在uart port的mapbase指针中
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!resource) {
- dev_err(&pdev->dev, “No IO memory resource\n”);
- return -ENODEV;
- }
- port->mapbase = resource->start;
其中“IORESOURCE_MEM”表示要获取的资源类型是memory资源,0表示是第一个(如果有多个,可以以此传入1、2等等)。
3)调用devm_ioremap_resource接口,将资源map出来,driver就可以使用了
- port->membase = devm_ioremap_resource(&pdev->dev, resource);
- if (IS_ERR(port->membase)) {
- dev_err(&pdev->dev, “Failed to map memory resource\n”);
- return PTR_ERR(port->membase);
- }
- port->iotype = UPIO_MEM32;
同样,map出来之后,可以保存在uart port的membase指针中,同时需要把iotype设置为UPIO_MEM32。
3. 从DTS aliases中获取串口的索引号
由于linux serial framework允许一个serial driver支持多个uart port,为了方便,我们会为这些串口编号,具体体现在struct uart_port的line变量中,那用什么方法为port->line赋值呢?最好通过device tree,因为这样灵活啊。下面介绍一种通过aliases的方法。
以本文的UART5为例,dts文件中的节点名为:serial@e012a000,为了方便,我们给它添加了一个别名:serial5,这样就可以在别处引用。为了让driver可以获得该串口的编号(5),我们可以在dts中定义一个aliases,如下:
- aliases {
- serial5 = &serial5;
- };
然后,在driver的probe中,调用of_alias_get_id,就可以获得该编号:
- port->line = of_alias_get_id(pdev->dev.of_node, “serial”);
- if (port->line < 0) {
- dev_err(&pdev->dev, “failed to get alias id, errno %d\n”,
- port->line);
- return port->line;
- }
of_alias_get_id的参数为“serial”,就是上面aliases左边除了数字的部分。
注1:大家可以思考一下这种方法的好处。
4. 完善console driver并测试之
1)把console driver的index也改成5
.flags = CON_PRINTBUFFER,
- .index = -1,
- .index = 5,
.data = &owl_serial_driver,
2)实现console driver的write接口
实现方法和[2]中的类似,只不过寄存器的基址是动态map出来的(具体可参考后面的patch文件[3])。另外需要说明的是,driver中的操作对象都是struct uart_port指针,但console的write接口是个例外,它使用struct console指针。也就是说,我们需要一个办法从struct console指针中得到对应的struct uart_port指针。不着急,有办法(代码如下,大家自行理解即可):
static void owl_console_write(struct console *con, const char *s, unsigned n)
{
struct uart_driver *driver = con->data;
struct uart_port *port = driver->state[con->index].uart_port;
uart_console_write(port, s, n, owl_console_putchar);
}
3)在kernel command line选中我们新增的console
-CONFIG_CMDLINE=“earlycon=owl_serial loglevel=8”
+CONFIG_CMDLINE=“earlycon=owl_serial console=ttyS5 loglevel=8”
4)编译并运行,获得如下打印(early console被禁止了,ttyS5被使能了),console移植成功
[ 0.087281] workingset: timestamp_bits=60 max_order=19 bucket_order=0
[ 0.093281] owl_serial_init
[ 0.096062] owl_serial e012a000.serial: owl_serial_probe
[ 0.101343] e012a000.serial: ttyS5 at MMIO 0xe012a000 (irq = 0, base_baud = 0) is a unknown
[ 0.109656] console [ttyS5] enabled
[ 0.109656] console [ttyS5] enabled
[ 0.116593] bootconsole [owl_serial0] disabled
[ 0.116593] bootconsole [owl_serial0] disabled
[ 0.125468] Failed to find cpu0 device node
[ 0.129593] Unable to detect cache hierarchy from DT for CPU 0
[ 0.135874] Freeing unused kernel memory: 116K (ffffff80081a0000 - ffffff80081bd000)
[ 0.143093] This architecture does not have kernel memory protection.
[ 0.149562] Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
[ 0.162593] Kernel Offset: disabled
[ 0.166062] Memory Limit: none
[ 0.169093] —[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
注2:以上过程可参考[3]中的patch文件。
5. 参考文档
[1] X-017-KERNEL-串口驱动开发之uart driver框架
[2] X-012-KERNEL-serial early console的移植
[3] patch文件,https://github.com/wowotechX/linux/commit/9f4d974605fbc9312333f95a0cd2ae1e4f709941
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
继续讨论
新讨论请用 GitHub 账号在下方发言——评论会保存在本仓库的 Discussions 里,与站点同寿; 再下方的「历史评论」是原站的只读存档。
评论(1 条,只读存档)
以下为原站的历史评论(只读存档);继续讨论请用上方的评论区。

do~best