X-018-KERNEL-串口驱动开发之serial console
作者:wowo 发布于:2016-11-18 22:25 分类:X Project
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。
标签: Linux driver serial console aliases

评论:
功能
最新评论
- wangjing
写得太好了 - wangjing
写得太好了! - DRAM
圖面都沒辦法顯示出來好像掛點了。 - Simbr
bus至少是不是还有个subsystem? - troy
@testtest:只要ldrex-modify-strex... - gh
Linux 内核在 sparse 内存模型基础上实现了vme...
文章分类
随机文章
文章存档
- 2025年4月(5)
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2021-03-27 23:21
wowo你好,请问串口加载到这一步就算是加载完成了么?可以通过uart吐出log?我调试时已经加载到这里,但是不知道什么原因仍然没有log吐出emmm,求解答