参考链接:MSM8937-MSM8953 UART配置调试指南
uart驱动是使用内核驱动,无需自己编写,一般只需修改设备树。
设备树的配置有三部分:
设备树配置完成后,编译bootimage,刷机,重启。
# user2 @ user2-HP-280-Pro-G2-MT-Legacy in ~/work/dujuan/out/target/product/msm8953_64 [14:13:25] $ adb reboot bootloader # user2 @ user2-HP-280-Pro-G2-MT-Legacy in ~/work/dujuan/out/target/product/msm8953_64 [14:13:30] $ fastboot flash boot boot.img target reported max download size of 536870912 bytes sending 'boot' (24775 KB)... OKAY [ 0.710s] writing 'boot'... OKAY [ 0.358s] finished. total time: 1.068s # user2 @ user2-HP-280-Pro-G2-MT-Legacy in ~/work/dujuan/out/target/product/msm8953_64 [14:13:35] $ fastboot reboot设备启动后,却没有找到预期的/dev/ttyHSL3的设备节点。 这里想到的是先确认设备树是否修改正确。
参考资料: 设备树学习(十、在根文件系统中查看设备树) 在根文件系统中查看设备树(有助于调试) 以下内核属于转载
进入/sys/firmware目录后便可看到二个文件,一个是devicetree文件夹,另一个是fdt(原始dtb文件,可以用hexdump -C fdt 将其打印出来查看就会发现里面的数据和dtb文件是一致的)。
以目录结构呈现的dtb文件。 根节点对应base目录, 每一个节点对应一个目录, 每一个属性对应一个文件
系统中所有的platform_device, 有来自设备树的, 也有来有.c文件中注册的 对于来自设备树的platform_device,可以进入 /sys/devices/platform/<设备名>/of_node 查看它的设备树属性(例如进入/sys/devices/platform/led/后若发现该目录下有of_node节点,就表明该platform_device来自设备树)
是链接文件, 指向 /sys/firmware/devicetree/base
查看dump的fdt文件,发现里面是有uart6的配置信息,且配置是正确的。 然后到网络上寻找资料。
在网络找到参考资料中发现是需要修改驱动文件,在我这里的uart是配置的第4路uart,需要到kernel/msm-3.18/drivers/tty/serial路径下修改msm_serial_hs_lite.c文件。 修改如下,添加一路uart
static struct msm_hsl_port msm_hsl_uart_ports[] = { { .uart = { .iotype = UPIO_MEM, .ops = &msm_hsl_uart_pops, .flags = UPF_BOOT_AUTOCONF, .fifosize = 64, .line = 0, }, }, { .uart = { .iotype = UPIO_MEM, .ops = &msm_hsl_uart_pops, .flags = UPF_BOOT_AUTOCONF, .fifosize = 64, .line = 1, }, }, { .uart = { .iotype = UPIO_MEM, .ops = &msm_hsl_uart_pops, .flags = UPF_BOOT_AUTOCONF, .fifosize = 64, .line = 2, }, }, { .uart = { .iotype = UPIO_MEM, .ops = &msm_hsl_uart_pops, .flags = UPF_BOOT_AUTOCONF, .fifosize = 64, .line = 3, }, }, };查看log,有正确加载驱动会打印出detected port #%d (ttyHSL%d) 的log,分析probe函数。 probe函数代码如下:
static int msm_serial_hsl_probe(struct platform_device *pdev) { struct msm_hsl_port *msm_hsl_port; struct resource *uart_resource; struct resource *gsbi_resource; struct uart_port *port; struct msm_serial_hslite_platform_data *pdata; const struct of_device_id *match; u32 line; int ret; if (pdev->id == -1) pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1; /* Use line (ttyHSLx) number from pdata or device tree if specified */ pdata = pdev->dev.platform_data; if (pdata) line = pdata->line; else line = pdev->id; /* Use line number from device tree alias if present */ if (pdev->dev.of_node) { dev_dbg(&pdev->dev, "device tree enabled\n"); ret = of_alias_get_id(pdev->dev.of_node, "serial"); if (ret >= 0) line = ret; pdata = msm_hsl_dt_to_pdata(pdev); if (IS_ERR(pdata)) return PTR_ERR(pdata); pdev->dev.platform_data = pdata; } if (unlikely(line < 0 || line >= UART_NR)) return -ENXIO; pr_info("detected port #%d (ttyHSL%d)\n", pdev->id, line); ......在probe函数代码中关于line的判断处理如下:
// 这里 UART_NR的值是预处理的时候根据结构体msm_hsl_uart_ports元素个数确定的 #define UART_NR ARRAY_SIZE(msm_hsl_uart_ports) static int msm_serial_hsl_probe(struct platform_device *pdev) { /* Use line (ttyHSLx) number from pdata or device tree if specified */ pdata = pdev->dev.platform_data; if (pdata) line = pdata->line; // 这里有个疑问,这个pdata结构体中的line是谁来更新的? else line = pdev->id; /* Use line number from device tree alias if present */ ...... if (unlikely(line < 0 || line >= UART_NR)) return -ENXIO; // 这里 UART_NR的值是预处理的时候就确定的综上:msm_hsl_uart_ports的元素个数是3的话,设备树中配置第四个uart会直接结束probe函数,不会打印相关log。 在msm_hsl_uart_ports中添加一个元素即可解决我遇到的问题。