目前在研究一个高精度 IMU ,接口是 GPIO 和 422 串口,数据率每秒 500 帧。现在要读取数据以及数据的精确时刻用来同步,正在用一个 ARM 板读取数据,GPIO 已经写了一个内核模块来抓取同步信号时刻了,运行 Ok ,现在 Uart 这边不知道怎么搞,看了半天内核文档还是有点懵。
初步感觉最简单的是要写一个新的 tty line discipline 模块来接数据帧和时刻,但是考虑 tty 到 ldisc 存在延迟。又不想去重新写 uart driver ,这里都是 dma 和寄存器,而且和芯片强相关。又看到 low level serial api, 但是没什么例子可以参考。所以想问问这样内核模块怎么写?
PS:不要吐槽为啥不用单片机,是真不会单片机。
1
XiaoJSoft 2023-02-16 21:50:22 +08:00 这种需求感觉对接 TTY 的接口不太合适诶,而且也不知道具体是谁家的 SoC ,这种给出具体建议其实有点费劲...
不过既然是 Arm 的话,要不这样,在 UART RX 的 ISR 里面记一下 SysTick 定时器的值,中断优先级看看能不能调高点,DMA 也可以先不管,直接在 RX 中断里面把 FIFO 全读了,和时间戳一起存到自己维护的 Ring Buffer 里面,想办法通知用户空间来取数据( Watch queue?) 要是不想自己搞 ringbuf ,那就参考 TUN/TAP 或者 SocketCAN ,模拟一个网络设备,只不过这样的话就得把数据包分帧的这部分逻辑怼到 ko 里了... |
2
anytk OP @XiaoJSoft 感谢回复。
这样就复杂了,就是不大想涉及 uart 驱动部分,只是想着在内核态把能做的数据分帧打时间戳都做了,然后甩给用户态程序处理。就想知道 tty/uart 这个驱动层面能不能像 gpio 那样,直接写给模块注册 irq 中断,可以在最接近硬件数据到达的时刻,用系统时钟打上时间戳。明天先试试注册 ldisc 的方式试试看。 |
3
Licsber 2023-02-16 22:48:20 +08:00 真实时数据感觉我更喜欢 FPGA 可以看看 GNU Radio 的一些代码 应该有这部分的处理吧 具体没深究过
|
4
duke807 2023-02-17 00:21:46 +08:00 via Android 不会单片机建议学单片机,推荐 stm32g 系列
单片机打好时间戳再发给 linux 不用 mcu 的话,也可以找大小核的 cpu ,小核当 mcu 跑高实时任务,譬如君正 x1600 cpu 另外提一下,我实时 linux 会用 cdbus 这样的数据包(硬件控制器的数据包在内存占用不超过 256 字节),代替 char 型的 tty ,为了实时性整个数据不走 tty 层,驱动直接和用户空间互传数据块。 更高实时性要求,pc 我会接自己的 cdbus 的 pcie 卡,嵌入式会接 spi 接口的 cdbus 控制器,linux 驱动和用户空间直接内存共享,避免数据包重复拷贝。 不改硬件的话,楼主可以自己改串口控制器的驱动,不走 tty 层,驱动直接按块传数据给用户空间,我曾经这么干过,当时内核打过 preemt-rt 补丁。 |
5
XiaoJSoft 2023-02-17 01:50:05 +08:00 @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 的噩梦 ...) |
6
xsen 2023-02-17 08:17:19 +08:00 每秒 500 帧,那就是 20ms ,那也只能都在内核态做,可以定制一个 422 的驱动,把 gpio 的抓取同步信号加进去
类似是 422 接口+额外的 gpio 口,属于一种非标准的 422 接口,要实现就是这么一个驱动 通过别的方式,如楼上提的 gpio 、422 单独设备(驱动)这种复杂,而且 20ms 还不一定能够保证 其实,最简单的方式就是用个 mcu 来做 |
7
anytk OP |
8
villivateur 2023-02-17 08:46:19 +08:00
@anytk
这个用单片机裸写就能解决的事,反正你也得学内核模块编写,不如直接去学一下单片机。会软件开发的人一两天就能上手,很简单的,实在不行先用 Arduino 做。 当然如果要改硬件方案的话,还是死磕内核模块编程吧。 |
9
elmagnificogg 2023-02-17 23:41:22 +08:00
可能我孤陋寡闻,IMU 的接口是 GPIO 和串口?? 不保密的话,能说一下名字吗,很奇怪啊
正常至少也得是一个 SPI 或者 I2C 吧? 如果是串口的话,因为这个比较简单,ARM 上这个驱动应该是开源的,很容易就能看到底层实现了。 串口驱动应该是很简单的,应该就是开了个缓冲器,然后用 DMA 去读串口数据,然后搬运到你的缓冲里,最后被外部驱动或者应用读走数据 如果想要非常准的同步的话,建议直接用中断串口,不用 DMA ,DMA 由于要搬运,其实也要花时间 |
10
anytk OP @elmagnificogg 不是小的 mems ,型号霍尼韦尔 4930 ,一大坨那种。我是考虑要跟 soc uart 实现隔离一下,换 soc 方案源码可以基本不改。最终要求精度在百微秒级就差不多了,再高就得上单片机了。
|