linux-device-driver - 从嵌入式板上的驱动程序控制 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并删除代码的网络端。但它需要一个用户空间程序(slattach
或dip
)来打开/dev/ttyS0并激活线路规则。
在内核模块中这可能(或一个好主意)吗?
在这个类似的问题中,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)
解决方案
推荐阅读
- erlang - 如何遍历 Erlang 中的目录以仅获取文件夹?
- php - PHP 和 HTML 中的 Br 标签 - 为什么我们需要引号
- python - Python OverflowError 从 32 位系统中的时间戳创建日期
- javascript - 如何在谷歌表格应用程序脚本中对以逗号分隔的多个数据进行 vlookup?
- gtsummary - 更改 gtsummary 汇总表中“add_p()”函数执行的默认统计测试
- python - 创建一个计算 + 清除按钮 Tkinter
- docker - 如何在 ArangoDB docker 映像中指定配置文件?
- php - Reactjs - 导出到以编码格式显示的 csv
- python - 仅适用于实数的 Lambdifying Sympy 函数
- javascript - 地图框JS未加载