目录
1、PX4模块运行方式2、PX任务启动方式Task工作队列
参考文献
1、PX4模块运行方式
PX4项目采用两种方式运行:
Tasks Work queue tasks Tasks: 模块在自己的任务中运行,具有自己的堆栈和进程优先级。
Work queue tasks:多个任务在同一堆栈上运行,与队列中的其他模块共享相同的堆栈和工作队列线程优先级。
工作队列的优点是 RAM 占用更少,减少任务切换,缺点是队列任务不能休眠,也不能轮询消息。对于运行时间比较长的任务应该使用Tasks或者在一个独立的工作队列中
工作队列(work Queue)用于执行周期性任务,如传感器驱动程序。
2、PX任务启动方式
px4_task_spawn_cmd() 用来启动任务:
independent_task = px4_task_spawn_cmd(
"commander", // Process name
SCHED_DEFAULT, // Scheduling type (RR or FIFO)
SCHED_PRIORITY_DEFAULT + 40, // Scheduling priority
3600, // Stack size of the new task or thread
commander_thread_main, // Task (or thread) main function
(char * const *)&argv[0] // Void pointer to pass to the new task
// (here the commandline arguments).
);
Task
使用工作队列功能需要使用任务队列的任务需要继承ModuleBase,这个类提供了队列需要的方法,其继承关系如图所示:
由上图我们可以知道:
任务模块通过xxx_main()函数启动,这个函数是系统执行该任务的入口函数ModuleBase类封装了任务管理所需要的基础功能,如:start、stop、status、help、info等ModuleBase通过px4_task_spawn_cmd函数启动任务,这个函数封装了pthread的接口Task模块通过Run函数运行任务,这里需要一个while循环,用于周期性执行
工作队列
使用工作队列功能需要继承ScheduledWorkItem,这个类提供了队列需要的方法,其继承关系如图所示:
队列执行时序图:
PX4的任务队列调用稍微复杂一些,由上述时序图,工作队列的调度设计一个高精度定时中断hrt和一个队列管理线程WorkQueueManager,它的设计目的是提供一个高精度的周期性任务调度方法。
在hrt定时器中对插入周期任务的队列检测是否到达执行时间,如果需要运行则将需要执行的周期任务添加进WorkQueue中,在高优先级线程WorkQueueRunner检测是否有插入需要运行的任务,在该线程中执行该任务。
这样设计的优点:
使用hrt的高精度定时中断可以确保周期调度的精度,这个中断运行周期为1MHz,理论最小调度分辨率为1us,远高于使用rtos的调度分辨率,它取决于rtos的时间片轮长度,一般情况是1ms多个工作队列共享一个WorkQueueRunner线程,因此队列任务是共享堆栈的,可以减小RAM的使用多个工作队列在一个线程中是顺序执行的,可以减少任务切换的次数工作队列任务时间过长可能会造成线程中其他队列任务延时,因此队列任务不能运行执行时间过长的任务
参考文献
PX4-4-任务调度_AcmeUav的博客-CSDN博客 PX4模块设计之十三:WorkQueue设计 Nuttx WorkQueue
好文链接
发表评论