V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
anytk
V2EX  ›  Linux

内核模块读取 uart 数据

  •  
  •   anytk · 2023-02-16 21:08:04 +08:00 via Android · 2138 次点击
    这是一个创建于 679 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前在研究一个高精度 IMU ,接口是 GPIO 和 422 串口,数据率每秒 500 帧。现在要读取数据以及数据的精确时刻用来同步,正在用一个 ARM 板读取数据,GPIO 已经写了一个内核模块来抓取同步信号时刻了,运行 Ok ,现在 Uart 这边不知道怎么搞,看了半天内核文档还是有点懵。

    初步感觉最简单的是要写一个新的 tty line discipline 模块来接数据帧和时刻,但是考虑 tty 到 ldisc 存在延迟。又不想去重新写 uart driver ,这里都是 dma 和寄存器,而且和芯片强相关。又看到 low level serial api, 但是没什么例子可以参考。所以想问问这样内核模块怎么写?

    PS:不要吐槽为啥不用单片机,是真不会单片机。

    10 条回复    2023-02-18 09:42:12 +08:00
    XiaoJSoft
        1
    XiaoJSoft  
       2023-02-16 21:50:22 +08:00   ❤️ 1
    这种需求感觉对接 TTY 的接口不太合适诶,而且也不知道具体是谁家的 SoC ,这种给出具体建议其实有点费劲...
    不过既然是 Arm 的话,要不这样,在 UART RX 的 ISR 里面记一下 SysTick 定时器的值,中断优先级看看能不能调高点,DMA 也可以先不管,直接在 RX 中断里面把 FIFO 全读了,和时间戳一起存到自己维护的 Ring Buffer 里面,想办法通知用户空间来取数据( Watch queue?)
    要是不想自己搞 ringbuf ,那就参考 TUN/TAP 或者 SocketCAN ,模拟一个网络设备,只不过这样的话就得把数据包分帧的这部分逻辑怼到 ko 里了...
    anytk
        2
    anytk  
    OP
       2023-02-16 22:24:45 +08:00 via Android
    @XiaoJSoft 感谢回复。
    这样就复杂了,就是不大想涉及 uart 驱动部分,只是想着在内核态把能做的数据分帧打时间戳都做了,然后甩给用户态程序处理。就想知道 tty/uart 这个驱动层面能不能像 gpio 那样,直接写给模块注册 irq 中断,可以在最接近硬件数据到达的时刻,用系统时钟打上时间戳。明天先试试注册 ldisc 的方式试试看。
    Licsber
        3
    Licsber  
       2023-02-16 22:48:20 +08:00   ❤️ 1
    真实时数据感觉我更喜欢 FPGA 可以看看 GNU Radio 的一些代码 应该有这部分的处理吧 具体没深究过
    duke807
        4
    duke807  
       2023-02-17 00:21:46 +08:00 via Android   ❤️ 1
    不会单片机建议学单片机,推荐 stm32g 系列

    单片机打好时间戳再发给 linux

    不用 mcu 的话,也可以找大小核的 cpu ,小核当 mcu 跑高实时任务,譬如君正 x1600 cpu

    另外提一下,我实时 linux 会用 cdbus 这样的数据包(硬件控制器的数据包在内存占用不超过 256 字节),代替 char 型的 tty ,为了实时性整个数据不走 tty 层,驱动直接和用户空间互传数据块。
    更高实时性要求,pc 我会接自己的 cdbus 的 pcie 卡,嵌入式会接 spi 接口的 cdbus 控制器,linux 驱动和用户空间直接内存共享,避免数据包重复拷贝。

    不改硬件的话,楼主可以自己改串口控制器的驱动,不走 tty 层,驱动直接按块传数据给用户空间,我曾经这么干过,当时内核打过 preemt-rt 补丁。
    XiaoJSoft
        5
    XiaoJSoft  
       2023-02-17 01:50:05 +08:00   ❤️ 1
    @duke807
    其实仔细说来 OP 的要求确实有点很难全方位达到
    比如加个 MCU 当下位机这事,确实是理论上最好的解决方案了,但 MCU 也得算钱啊,而且还得改 Layout 、BOM ,除非一开始做硬件的时候就想到了。
    我是觉得 UART 这类 Peripheral 的控制器接口基本上没啥太复杂的,自己重新按照芯片手册写个驱动大概不会特别耗费时间,不过 OP 看起来确实不想碰这些鬼东西。当然做得再好一点可以直接 Map 一块空间让 Peripheral 直接 DMA 数据过去,做 zero copy ,不过这个就更复杂了,大概可以不用考虑了。
    ----
    不过话说回来... OP 只是想要个 422 物理层上的通信协议啊,这玩意儿撑死 10M ,搞个便宜点的 MCU 来弄这事看起来还是更合适的...
    (... 回想起了做 Modbus RTU 时那 1.5/3.5 char time 的噩梦 ...)
    xsen
        6
    xsen  
       2023-02-17 08:17:19 +08:00   ❤️ 1
    每秒 500 帧,那就是 20ms ,那也只能都在内核态做,可以定制一个 422 的驱动,把 gpio 的抓取同步信号加进去
    类似是 422 接口+额外的 gpio 口,属于一种非标准的 422 接口,要实现就是这么一个驱动

    通过别的方式,如楼上提的 gpio 、422 单独设备(驱动)这种复杂,而且 20ms 还不一定能够保证

    其实,最简单的方式就是用个 mcu 来做
    anytk
        7
    anytk  
    OP
       2023-02-17 08:34:59 +08:00
    最简单的确是 MCU 来做,但是不大想去碰了,本来我也一直以来都做 Linux 应用开发,偶尔需要才小改改 BSP 而已。

    不想去重写 uart driver,一部分是硬件 /寄存器 /DMA 这些的确一点经验没有,另外一方面是这部分跟 SOC 强绑定,后面再移植到其他 SOC 又需要改动。我的设想是在 uart driver 和 tty driver/ tty core 这两层,有没有办法获取到数据中断,在这里面处理数据。

    今天先试试看,感谢楼上各位回复。
    @xsen @duke807 @Licsber @XiaoJSoft
    villivateur
        8
    villivateur  
       2023-02-17 08:46:19 +08:00
    @anytk
    这个用单片机裸写就能解决的事,反正你也得学内核模块编写,不如直接去学一下单片机。会软件开发的人一两天就能上手,很简单的,实在不行先用 Arduino 做。
    当然如果要改硬件方案的话,还是死磕内核模块编程吧。
    elmagnificogg
        9
    elmagnificogg  
       2023-02-17 23:41:22 +08:00
    可能我孤陋寡闻,IMU 的接口是 GPIO 和串口?? 不保密的话,能说一下名字吗,很奇怪啊
    正常至少也得是一个 SPI 或者 I2C 吧?
    如果是串口的话,因为这个比较简单,ARM 上这个驱动应该是开源的,很容易就能看到底层实现了。
    串口驱动应该是很简单的,应该就是开了个缓冲器,然后用 DMA 去读串口数据,然后搬运到你的缓冲里,最后被外部驱动或者应用读走数据
    如果想要非常准的同步的话,建议直接用中断串口,不用 DMA ,DMA 由于要搬运,其实也要花时间
    anytk
        10
    anytk  
    OP
       2023-02-18 09:42:12 +08:00 via Android
    @elmagnificogg 不是小的 mems ,型号霍尼韦尔 4930 ,一大坨那种。我是考虑要跟 soc uart 实现隔离一下,换 soc 方案源码可以基本不改。最终要求精度在百微秒级就差不多了,再高就得上单片机了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1614 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:51 · PVG 00:51 · LAX 08:51 · JFK 11:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.