我想从内核模块将数据复制到用户空间,内核模块从串口接收数据并将其传输到DMA,DMA又将数据转发到tty层,最后转发到用户空间。
目前的流量是 串行驱动器FIFO - > DMA - > TTY图层 - >用户空间(计时器到期时从DMA清空数据到tty图层)
我想要实现的是
串行驱动程序FIFO - > DMA - >用户空间。 (我可以使用计时器将数据发送到用户空间,如果有更好的方式让我知道)
处理serialFIFO-> DMA的内核模块也不是字符设备。 我想完全绕过tty层。实现目标的最佳途径是什么?
任何指针/代码段都将不胜感激。
答案 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直接读取字节。