绕过tty层并复制到用户

时间:2013-09-26 16:08:50

标签: linux-kernel serial-port linux-device-driver mamp dma

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

目前的流量是 串行驱动器FIFO - > DMA - > TTY图层 - >用户空间(计时器到期时从DMA清空数据到tty图层)

我想要实现的是

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

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

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

1 个答案:

答案 0 :(得分:2)

在> = 3.10.5中,您引用的“串行FIFO”称为uart_port。这些在drivers/tty/serial中定义。

我假设您要做的是将UART的驱动程序复制到一个新文件,然后不是使用uart_insert_char从UART RX FIFO插入字符,而是要将字符插入到您可以从用户空间访问的缓冲区。

这样做的方法是创建第二个驱动程序,misc类设备驱动程序,它具有文件操作,包括mmap,并分配驱动程序mmap文件的内核内存操作函数与用户空间映射的内存相关联。 Maxime Ripard写的代码有good example。这个例子是为FIQ处理的设备编写的,但是你可以只使用探测例程的dma_zalloc_coherent调用和mmap例程,并调用remap_pfn_range来完成这个操作,即关联一个带有alloc'ed内存的misc设备文件上的用户空间mmap。

您需要使用全局void指针将您在misc驱动程序中分配的内存连接到UART驱动程序中写入的缓冲区,或者使用导出的符号将misc驱动程序中的内存连接到misc驱动程序中。 1}}驱动程序是一个模块。将指针初始化为UART驱动程序中的已知无效值,并在尝试将字符插入其指向的地址之前对其进行测试,以确保mmap驱动程序已将其分配。

请注意,您无法直接向UART驱动程序添加mmap函数,因为UART驱动程序类不支持include/linux/serial_core.h文件操作。它仅支持struct uart_ops mmap中定义的操作。

不可否认,这是一个麻烦的解决方案 - 两个设备驱动程序,但另一种方法是编写一个新的设备类,一个具有mxs-auart.c操作的UART设备,这将是一个与上述解决方案相比,大量的工作虽然很优雅。迄今为止没有人这样做过,因为Jonathan Corbet说"...not every device lends itself to the mmap abstraction; it makes no sense, for instance, for serial ports and other stream-oriented devices",尽管这正是你所要求的。

我基于flags代码和Maxime的示例为轮询模式UART驱动程序实现了此解决方案。这是非常重要的努力,但主要是因为我使用FIQ处理程序进行轮询计时器。您应该允许两到三周的时间来完成所有事情。

您问题的DMA方面取决于UART是否支持DMA传输模式。如果是这样,那么您应该能够使用序列{{1}}进行设置。 i.MX28的PrimeCell auart支持DMA传输,但对于我的应用,没有优势直接从UART RX FIFO直接读取字节。