栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

PX4-6-串口设备驱动

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

PX4-6-串口设备驱动

上一篇我们讲了PX4的SPI/IIC设备驱动,现在讲一下PX4的串口设备。

PX4的串口设备驱动框架比SPI/IIC设备简单不少,使用了两种底层实现方式:

一种是系统自带的标准字符设备接口,一种是直接使用mcu的底层资源通过自行配置中断和DMA的方式实现的串口收发。

使用系统接口

PX4使用Nuttx的标准的字符设备接口,通过标准接口函数open、close、read、write、ioctl等函数操作。

熟悉linux的同学对这个应该不陌生,通过看linux的驱动编程书籍对Nuttx的串口编程也同样有参考意义。

大多数搞飞控的都没有系统性的学习过系统编程,这里分享一个linux的设备驱动编程参考书,里面的知识在Nuttx中也非常适用,可以参考学习一下,对于了解Nuttx非常有参考意义。可以在公众号中回复 驱动编程 获取。

PX4的大多数串口使用的是系统接口,如GPS、数传、以及所有的串口外设等等。PX4的串口驱动在任务调度上分两种情况:

一种是使用task、一种是使用工作队列。

那么都在什么情况下使用呢?

我们回顾前面分享的 PX4-4-任务调度 里面讲到的task与工作队列的区别,具体到串口驱动上。

  • 使用task

使用task的典型应用是gps驱动,gps驱动独立开启了一个线程,串口采用poll阻塞方式读取。以下是gps读取的关键代码:

int GPS::pollOrRead(uint8_t *buf, size_t buf_length, int timeout)
{
    pollfd fds[1];
    fds[0].fd = _serial_fd;
    fds[0].events = POLLIN;

    int ret = poll(fds, sizeof(fds) / sizeof(fds[0]), math::min(max_timeout, timeout));

    if (ret > 0) {
        
        if (fds[0].revents & POLLIN) {
            ...
        }
    }
}

这样的读取的方式的优点是在串口没有数据时任务可以自动挂起,在收到数据时有系统唤醒直接读取数据,这样的方式数据延时可以做到很小。

  • 使用工作队列

大多数的串口任务会使用工作队列的方式,比如距离传感器distance_sensor下的各种串口传感器,这些驱动的串口都采用轮训的方式读取,即非阻塞的定时获取。它的串口读取的关键代码为:

int
XXX::collect()
{
    // Check the number of bytes available in the buffer
    int bytes_available = 0;
    ::ioctl(_fd, FIONREAD, (unsigned long)&bytes_available);

    do {
        // read from the sensor (uart buffer)
        ret = ::read(_fd, &readbuf[0], readlen);

        // bytes left to parse
        bytes_available -= ret;

    } while (bytes_available > 0);
}

可以发现串口只有在周期调度函数collect执行到时尝试读取一次,没有获取到数据则直接返回,这样做的读取延时最大为一个调度周期,如果以100hz调度的话即为10ms。

为什么采用这种方式呢?PX4同时支持非常多的串口设备,而大多数的串口设备的实时性要求不高,采用工作队列非阻塞的方式,可以降低系统的内存、堆栈、调度的消耗,同时也能满足应用的需要。

值得一提的是使用工作队列的方式不能使用阻塞方式的串口读取,否则会影响队列中的其它任务的运行导致严重的故障!

自定义串口驱动

只有一种情况PX4采用的自定义的串口驱动,即板载fmu芯片与io芯片间的串口,这个串口用于两个单片机间的高速数据通信,波特率达到921600,用于传输输出控制信号,遥控输入信号。这个串口的要求是高带宽、低延时,因此PX4选择自己实现这个串口驱动。

我们以pixhawk为例,它的串口驱动底层代码在 platforms/nuttx/src/px4/stm/stm32f4/px4io_serial/px4io_serial.cpp 和 src/drivers/px4io/px4io_serial.cpp 中

这个驱动主要实现了:

  • 使用Nuttx的底层接口(irq_attach()),配置串口中断为自定义的串口中断函数 ArchPX4IOSerial::_interrupt(int irq, void *context, void *arg)

  • 配置了发送和接收数据的dma stm32_dmasetup()

  • 大多操作直接对寄存器操作,效率非常高

这个驱动这里不做详细的分析,感兴趣的同学可以深入的去看看

PX4在使用Nuttx为RTOS的时候,大多接口使用了系统上的API,但在一些高效率的场合还是会直接面向硬件直接编写驱动,比如这里的px4io_serial以及任务调度中提到的hrt。

往期分享:

PX4-5-SPI-IIC设备驱动

AcmeGCS-5-模拟国庆阅兵

Uav开发杂记-2-无人机的RTOS

这个博客转载自我个人的微信公众号,这里会不定期更新一些我整理的无人机相关知识和个人设计,欢迎添加关注。

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/320645.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号