- 串口通信。和网口通信相比,不能一次返回接口协议定义的完整包。需要逐字节解析才能凑齐一包通信协议格式包。为防错,通常采用固定标识、长度校验、校验和的方式保证能够区分开数据。
- 线程调度。Linux线程调度分为实时和分时调度,实时包含SCHED_FIFO(优先级[1,99],越大级别越高)、SCHED_RR、SCHED_DEADLINE(更好的实时性);分时调度SCHED_OTHERS、SCHED_IDLE。默认是SCHED_OTHERS。在以时间戳做图片名称存图调试过程,存在周期不稳定,波动大现象。采图线程通过指定CPU和线程调度方式(设置SCHDE_FIFO)和优先级(设置 80)的方式期望提高实时性能,经过长时间反复测试发现,会出现超过期望的延时和波动(如周期3s,误差能到200ms),通过打印v4l2的buff的时间戳方式,分析42分钟内数据,发现两次buff间的最大误差是-400us 和 60us。因此,确定硬件可靠,数据到内核的延时可忽略,但是图片的名称相减得到延时却存在200ms。翻看8月17日挂飞40分钟的红外相机存图数据,不存在此现象。猜测是因为给线程指定CPU和优先级的方式在xavier这种8核arm结构 (Ubuntu 18.04 内核:4.9.201)不能保证期望的实时性。最终选择不指定CPU和不设置优先级(默认SCHED_OTHERS方式)组合。
设置优先级 | 不设置优先级 | |
指定CPU | 相邻2张照片周期波动大 | 未做测试 |
不指定CPU | 未做测试 | 相邻2张照片周期波动小 |
- V4l2视频框架。这篇很棒v4l2接口解析和摄像头数据采集_liujun3512159的博客-CSDN博客_v4l2视频采集详解。
- Select多路IO复用。此函数可以设置对1个文件句柄最长等待时间,参数有3种情况,NULL(一直阻塞等待,直到有数据);tv=0(调用一次后直接返回结果);tv ! = 0(最长等待时间为设置的值,其中有数据会结束等待、超时导致结束、异常结束)。Xavier是8核Arm的CPU,CPU0-7,由于我在可见光线程当中设置了CPU6运行线程采图且select设置的tv=0,造成CPU6一直进行运算,造成死循环假象。内核日志/var/log/kern.log 中显示BUG: workqueue lockup - pool cpus=6 node=0 flags=0x0 nice=0 stuck for 67s!。stuck是困住的意思。长时间(随机的,试验发现会有1小时、2小时、4小时)运行后,内核重启,造成最后写入硬盘的照片有名称但大小0KB的异常,相片张数大约在10张,每3秒/张。猜测内核发现长时间的CPU6死循环假象,到达某种程度后自己决定重启启动。kern.log日志中计时会从0重新开始计已经证明了这点。后期修改select中tv的值,发现kern.log中无此日志出现。
- 其他。在长时间的运行,发现追加在数据包当中通过 localtime函数获取本地时间,有一包数据记录的时间相差8小时,后改用gettimeofday 获取到的struct timeval 中的秒数自己实现转换年月日的函数方式。