在 >=3.10.5 中,您所指的“串行 FIFO”称为uart_port
. 这些定义在drivers/tty/serial
.
我假设您想要做的是将 UART 的驱动程序复制到一个新文件中,然后不是使用uart_insert_char
从 UART RX FIFO 插入字符,而是要将字符插入可以从用户空间访问的缓冲区中.
这样做的方法是创建第二个驱动程序,一个misc
具有文件操作的类设备驱动程序,包括mmap
,并分配驱动程序的mmap
文件操作函数与用户空间映射内存相关联的内核内存。Maxime Ripard有一个很好的代码示例。此示例是为 FIQ 处理的设备编写的,但您可以仅使用探测例程的dma_zalloc_coherent
调用和 mmap 例程,通过它的调用来remap_pfn_range
完成这个技巧,即将misc
设备文件上的用户空间 mmap 与的记忆。
您需要misc
使用全局 void 指针或使用导出符号(如果您的misc
驱动程序是模块)将您在驱动程序中分配的内存连接到您在 UART 驱动程序中写入的缓冲区。在 UART 驱动程序中初始化指向一个已知无效值的指针并对其进行测试以确保misc
驱动程序已分配它,然后再尝试将字符插入它指向的地址。
请注意,您不能mmap
直接向 UART 驱动程序添加函数,因为 UART 驱动程序类不支持mmap
文件操作。它只支持include/linux/serial_core.h
struct uart_ops
.
诚然,这是一个麻烦的解决方案 -两个设备驱动程序,但另一种选择是编写一个新的设备类,一个具有mmap
操作的 UART 设备,与上述解决方案相比,这将是很多工作,尽管它会很优雅。迄今为止没有人这样做,因为正如 Jonathan Corbet 所说的“......并非每个设备都适合于 mmap 抽象;例如,对于串行端口和其他面向流的设备来说,这是没有意义的”,尽管这正是你要求。
我根据mxs-auart.c
代码和 Maxime 的示例为轮询模式 UART 驱动程序实现了这个解决方案。这不是微不足道的努力,但主要是因为我正在为轮询计时器使用 FIQ 处理程序。您应该留出两到三周的时间来让整个过程启动并运行。
您问题的 DMA 方面取决于 UART 是否支持 DMA 传输模式。如果是这样,那么您应该可以使用 serial 设置它flags
。i.MX28 的 PrimeCell auarts 支持 DMA 传输,但对于我的应用程序而言,直接从 UART RX FIFO 读取字节并没有优势。