3

我想将数据从内核模块复制到用户空间,内核模块从串口接收数据并将其传输到 DMA,DMA 又将数据转发到 tty 层,最后到用户空间。

当前流程是串行驱动 FIFO--> DMA--> TTY 层 --> 用户空间(到 tty 层的数据在定时器到期时从 DMA 中清空)

我想要实现的是

串行驱动程序 FIFO--> DMA--> 用户空间。(我可以使用计时器将数据发送到用户空间,如果有更好的方法让我知道)

处理 serialFIFO->DMA 的内核模块也不是字符设备。我想完全绕过 tty 层。实现这一目标的最佳方法是什么?

任何指针/代码片段将不胜感激。

4

1 回答 1

3

在 >=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 读取字节并没有优势。

于 2013-10-14T17:33:38.723 回答