首页 > 解决方案 > 从嵌入式板上的驱动程序控制 USART RTS 引脚

问题描述

我正在移植lirc_serial 内核模块以在我们的嵌入式板上工作。我们只需要实现红外发射器功能。

仅对于发送器,自定义驱动程序只需在模块内控制 RTS/dev/ttyS0引脚

在标准硬件上,驱动程序加载:

00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A

新的方法

我还没有弄清楚如何停用当前的串行端口驱动程序,所以与其创建一个新的驱动程序,你将如何使用当前的8250-dw驱动程序来代表我的内核模块更改 RTS 引脚?像这样的东西?

驱动程序堆栈

根据这篇文章在 slip 驱动程序上使用 line 规则看起来很有希望,只需使用slip.c并删除代码的网络端。但它需要一个用户空间程序(slattachdip)来打开/dev/ttyS0并激活线路规则。

在内核模块中这可能(或一个好主意)吗?

来自 https://www.linux.it/~rubini/docs/serial/serial.html

在这个类似的问题中,How do I open/write/read a uart device from a kernel module? , Ian Abbott建议将 serdev 反向移植到内核 4.9。

这有点涉及,我们已经落后于计划。有没有更简单的方法?

原始问题

但是,嵌入式板(基于BayTrail Atom E3845)在内存映射 I/O 中具有串行端口控制器:

80860F0A:00: ttyS0 at MMIO 0x90a0c000 (irq = 39, base_baud = 2764800) is a 16550A
80860F0A:01: ttyS1 at MMIO 0x90a0e000 (irq = 40, base_baud = 2764800) is a 16550A

我是驱动程序开发的新手。我猜0x90a0c000是控制器的物理地址?

为了探测模块,我首先使用重新映射0x90a0c000到虚拟地址ioremap_nocache,然后尝试使用request_mem_region. 那失败了。

ioVirtBase = ioremap_nocache(iommap, 8);

TQTRACE("ecp_serial_probe: devm_ioremap for MMIO 0x%X returned 0x%X\n", (uint32_t)iommap, (uint32_t)ioVirtBase);
if (ioVirtBase != NULL)
{
    tqDumpBuffer(ioVirtBase, 8);
}

tqRes = request_mem_region((uint32_t)ioVirtBase, 8, ECP_DRIVER_NAME);
TQTRACE("ecp_serial_probe: request_mem_region for 0x%X returned 0x%X\n", (uint32_t)ioVirtBase, (uint32_t)tqRes);
if (!tqRes)
{
    TQTRACE("ecp_serial_probe: Cannot request memory at 0x%X\n", (uint32_t)iommap);
    return -ENXIO;
}

这是功能的正确顺序吗?

另外,它似乎request_mem_region失败了,因为设备在控制之下80860F0A??中没有这样的条目,lsmod但 中有一个条目/sys/devices

我是否需要卸载该驱动程序来控制 USART?如何?

# ls -l  /sys/devices/platform/80860F0A\:00
lrwxrwxrwx 1 root root    0 Jul  8 23:30 driver -> ../../../bus/platform/drivers/dw-apb-uart
-rw-r--r-- 1 root root 4096 Jul  9 17:02 driver_override
lrwxrwxrwx 1 root root    0 Jul  9 17:14 firmware_node -> ../../LNXSYSTM:00/LNXSYBUS:00/80860F0A:00
-r--r--r-- 1 root root 4096 Jul  9 17:02 modalias
drwxr-xr-x 2 root root    0 Jul  9 17:02 power
lrwxrwxrwx 1 root root    0 Jul  8 23:30 subsystem -> ../../../bus/platform
drwxr-xr-x 3 root root    0 Jul  8 23:30 tty
-rw-r--r-- 1 root root 4096 Jul  9 17:02 uevent
drwxr-xr-x 3 root root    0 Jul  8 23:30 VCOM0001:00

dmesg 输出如下。将数据转储到重新映射的虚拟地址并不一致。有时全是 0xFF,有时是00 00 00 00 41 02 1C 48. 这个我也看不懂。。。

MARK Tue Jul 9 17:45:35 SGT 2019
ecp_serial: ecp_serial_exit_module()
Spectre V2 : System may be vulnerable to spectre v2
ecp_serial: loading module not compiled with retpoline compiler.
ecp_serial: ecp_serial_init_module()
ecp_serial: ecp_serial_init()
ecp_serial: ecp_serial_probe() iommap=0x90A0C000
ecp_serial: ecp_serial_probe: devm_ioremap for MMIO 0x90A0C000 returned 0xE3296000
ecp_serial: Dump address 0xE3296000:
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
0000  FF FF FF FF FF FF FF FF 
ecp_serial: ecp_serial_probe: request_mem_region for 0xE3296000 returned 0x0
ecp_serial: ecp_serial_probe: Cannot request memory at 0x90A0C000
platform ecp_serial.0: lirc_dev: driver ecp_serial registered at minor = 0

MARK Tue Jul 9 17:46:08 SGT 2019
ecp_serial: ecp_serial_exit_module()
Spectre V2 : System may be vulnerable to spectre v2
ecp_serial: loading module not compiled with retpoline compiler.
ecp_serial: ecp_serial_init_module()
ecp_serial: ecp_serial_init()
ecp_serial: ecp_serial_probe() iommap=0x90A0C000
ecp_serial: ecp_serial_probe: devm_ioremap for MMIO 0x90A0C000 returned 0xE32A2000
ecp_serial: Dump address 0xE32A2000:
      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
0000  00 00 00 00 41 02 1C 48 
ecp_serial: ecp_serial_probe: request_mem_region for 0xE32A2000 returned 0x0
ecp_serial: ecp_serial_probe: Cannot request memory at 0x90A0C000
platform ecp_serial.0: lirc_dev: driver ecp_serial registered at minor = 0

proc/iomem 有什么要说的

90a0c000-90a0cfff : 80860F0A:00
90a0e000-90a0efff : 80860F0A:01

所以确实,内存是由另一个驱动程序控制的......但是如果它没有被列出,如何卸载它lsmod呢?

# rmmod 80860F0A:00
ERROR: Module 80860F0A:00 does not exist in /proc/modules
# rmmod 80860F0A
ERROR: Module 80860F0A does not exist in /proc/modules

操作系统信息

# uname -a
Linux ecp 4.4.127-1.el6.elrepo.i686 #1 SMP Sun Apr 8 09:44:43 EDT 2018 i686 i686 i386 GNU/Linux
# cat /etc/centos-release
CentOS release 6.6 (Final)

标签: linux-device-driveruart

解决方案


推荐阅读