PX4模块设计之二十一:uORB消息管理模块

本文详细介绍了PX4飞行控制系统中uORB消息管理模块的工作原理,包括不同构建模式下的实现差异,消息管理函数的功能及实现方式,以及消息接口的具体定义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面主要给出uORB消息API接口自定义消息的使用。这里主要来看下uORB消息管理模块是如何对uORB消息进行管理的。

1. uORB模块构建模式

鉴于Nuttx系统有两种构建模式:不同构建模式使用的源文件也有差异。

  • Flat Build
    uORB:${SRCS_COMMON} + ${SRCS_KERNEL}
  • Protected Build
    uORB_kernel:${SRCS_COMMON} + S R C S K E R N E L = = > 内核态 u O R B : {SRCS_KERNEL} ==> 内核态 uORB: SRCSKERNEL==>内核态uORB{SRCS_COMMON} + ${SRCS_USER} ==> 用户态

参考CMakeLists.txt主要差异在于:

  1. 总体声明定义:${SRCS_COMMON}下的uORBManager.hpp
  2. 内核态实现: ${SRCS_KERNEL}下的uORBDeviceMaster.cppuORBDeviceNode.cppuORBManager.cpp
  3. 用户态实现: ${SRCS_USER} 下的uORBManagerUsr.cpp
  4. Flat编译模式:鉴于全地址访问,所以不需要使用用户态实现
39 set(SRCS_COMMON
40 	ORBSet.hpp
41 	Publication.hpp
42 	PublicationMulti.hpp
43 	Subscription.cpp
44 	Subscription.hpp
45 	SubscriptionCallback.hpp
46 	SubscriptionInterval.hpp
47 	SubscriptionMultiArray.hpp
48 	uORB.cpp
49 	uORB.h
50 	uORBCommon.hpp
51 	uORBCommunicator.hpp
52 	uORBManager.hpp
53 	uORBUtils.cpp
54 	uORBUtils.hpp
55 	uORBDeviceMaster.hpp
56 	uORBDeviceNode.hpp
57 	)
58 
59 set(SRCS_KERNEL
60 	uORBDeviceMaster.cpp
61 	uORBDeviceNode.cpp
62 	uORBManager.cpp
63 	)
64 
65 set(SRCS_USER
66 	uORBManagerUsr.cpp
67 	)
68 
69 if (NOT DEFINED CONFIG_BUILD_FLAT AND "${PX4_PLATFORM}" MATCHES "nuttx")
70 	# Kernel side library in nuttx kernel/protected build
71 	px4_add_library(uORB_kernel
72 		${SRCS_COMMON}
73 		${SRCS_KERNEL}
74 		)
75 	target_link_libraries(uORB_kernel PRIVATE cdev uorb_msgs)
76 	target_compile_options(uORB_kernel PRIVATE ${MAX_CUSTOM_OPT_LEVEL} -D__KERNEL__)
77 
78 	# User side library in nuttx kernel/protected build
79 	px4_add_library(uORB
80 		${SRCS_COMMON}
81 		${SRCS_USER}
82 		)
83 else()
84 
85 	# Library for all other targets (flat build, posix...)
86 	px4_add_library(uORB
87 		${SRCS_COMMON}
88 		${SRCS_KERNEL}
89 		)
90 	target_link_libraries(uORB PRIVATE cdev)
91 endif()

2. uORB消息管理函数

2.1 状态查询

uorb_status
 ├──> [Flat Build]
 │   ├──> <g_dev != nullptr>
 │   │   └──> g_dev->printStatistics();
 │   └──> PX4_INFO("uorb is not running");
 └──> [Protected Build]
     └──> boardctl(ORBIOCDEVMASTERCMD, ORB_DEVMASTER_STATUS);

2.2 资源利用

uorb_top
 ├──> [Flat Build]
 │   ├──> <g_dev != nullptr>
 │   │   └──> g_dev->showTop(topic_filter, num_filters);
 │   └──> <g_dev == nullptr>
 │       └──> PX4_INFO("uorb is not running");
 └──> [Protected Build]
     └──> boardctl(ORBIOCDEVMASTERCMD, ORB_DEVMASTER_TOP);

2.3 模块启动

uorb_start
 ├──> <g_dev != nullptr>
 │   ├──> PX4_WARN("already loaded");
 │   └──> return OK;
 ├──> <!uORB::Manager::initialize()>
 │   ├──> PX4_ERR("uorb manager alloc failed");
 │   └──> return -ENOMEM;
 ├──> [Flat Build]
 │   ├──> g_dev = uORB::Manager::get_instance()->get_device_master();
 │   └──> <g_dev == nullptr>
 │       └──> return -errno;
 └──> return OK;
uORB::Manager::initialize
 ├──> <_Instance == nullptr)>
 │   └──> _Instance = new uORB::Manager();
 ├──> [Protected Build]
 │   └──> _px4_register_boardct_ioctl(_ORBIOCDEVBASE, orb_ioctl);  // boardctl
 └──> return _Instance != nullptr;

注:uORB_kernel+uORB两套实现代码。代码差异px4_register_boardct_ioctl。

2.4 模块停止

该函数实际上在PX4系统内部并未使用。

uORB::Manager::terminate
 ├──> <_Instance != nullptr>
 │   ├──> delete _Instance
 │   ├──> _Instance = nullptr
 │   └──> return true
 └──> return false

注:uORB_kernel+uORB两套实现代码。代码一致。

3. uORB消息接口

注:这里根据uORBManager.hpp列出接口定义(部分在uORBManager.cpp实现,部分在uORBManagerUsr.cpp实现),这里不做代码展开。

3.1 消息主题注册

uORB::Manager::orb_advertise_multi

注:orb_advertise是orb_advertise_multi的精简版本API

3.2 消息主题去注册

uORB::Manager::orb_unadvertise

3.3 消息主题发布

uORB::Manager::orb_publish

3.4 消息主题订阅

uORB::Manager::orb_subscribe
uORB::Manager::orb_subscribe_multi

3.5 消息主题去订阅

uORB::Manager::orb_unsubscribe

3.6 设置/获取间隔时间

uORB::Manager::orb_set_interval
uORB::Manager::orb_get_interval

3.7 获取订阅消息

uORB::Manager::orb_copy

3.8 主题消费检查

uORB::Manager::orb_check

3.9 主题存在性检查

uORB::Manager::orb_exists

4. uORB消息辅助接口

注:这里根据uORBManager.hpp列出接口定义(部分在uORBManager.cpp实现,部分在uORBManagerUsr.cpp实现),这里不做代码展开。

4.1 设备节点存在性检查

uORB::Manager::orb_device_node_exists

4.2 消息主题内部订阅

uORB::Manager::orb_add_internal_subscriber

4.3 消息主题内部去订阅

uORB::Manager::orb_remove_internal_subscriber

4.4 获取队列长度

uORB::Manager::orb_get_queue_size

4.5 获取ORB数据

uORB::Manager::orb_data_copy

4.6 设备节点注册回调

uORB::Manager::register_callback

4.7 设备节点去注册回调

uORB::Manager::unregister_callback

4.8 获取ORB实例

uORB::Manager::orb_get_instance

4.9 主题消息更新检查

uORB::Manager::updates_available

4.10 主题注册检查

uORB::Manager::is_advertised

5. uORB类继承关系

Subscription
 └──> SubscriptionData


SubscriptionMultiArray


SubscriptionInterval, ListNode<SubscriptionCallback *>
 └──> SubscriptionCallback
     ├──> SubscriptionCallbackWorkItem
     └──> SubscriptionBlocking

PublicationBase
 ├──> Publication
 │   └──> PublicationData
 └──> PublicationMulti
     └──> PublicationMultiData

6. 参考资料

【1】PX4开源软件框架简明简介
【2】PX4模块设计之二:uORB消息代理
【3】PX4模块设计之三:自定义uORB消息

### STM32CubeMX FreeRTOS CAN Queue Read Example #### 配置项目环境 为了实现基于FreeRTOS的CAN消息队列读取,在STM32CubeMX环境中需完成以下设置: - 使用STM32CubeMX创建新工程并选择目标MCU型号。 - 启用CAN外设支持,并通过RTE(Run-Time Environment)配置其参数,如波特率等。 - 添加对FreeRTOS的支持,这会自动引入必要的库文件和初始化代码。 #### 初始化FreeRTOS与CAN模块 确保已正确设置了`FreeRTOSConfig.h`中的各项参数以适应应用需求[^1]。对于CAN通信部分,则要依据具体硬件平台调整相应的初始化函数调用,通常位于`main.c`或其他由开发者指定的位置。 ```c // main.c or other designated file #include "cmsis_os.h" #include "can.h" osThreadId canReceiveTaskHandle; osMessageQueueId canMsgQueue; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_CAN1_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_CAN1_Init(); osKernelInitialize(); // Initialize CMSIS-OS V2 RTX Kernel // Create the message queue capable of holding up to 10 messages. canMsgQueue = osMessageQueueNew(10, sizeof(CAN_RxHeaderTypeDef), NULL); // Start thread as specified. canReceiveTaskHandle = osThreadNew(can_receive_task, NULL, NULL); osKernelStart(); } ``` #### 创建接收任务处理程序 定义一个专门的任务用于监听来自CAN总线的数据包并通过预先建立的消息队列传递给其他组件进一步解析或响应。 ```c #define MSG_QUEUE_TIMEOUT (10) void can_receive_task(void *argument) { uint8_t rxData[8]; CAN_RxHeaderTypeDef RxHeader; while (true) { if(HAL_CAN_GetRxMessage(&hcan1,&RxHeader,rxData)==HAL_OK){ // Put received data into a queue for processing by another task. osMessageQueuePut(canMsgQueue, &RxHeader, 0, MSG_QUEUE_TIMEOUT); /* Process Data Here */ } osDelay(1); // Short delay between checks } } ``` 上述代码片段展示了如何利用FreeRTOS提供的APIs构建一个多线程应用程序框架下的CAN报文接收机制。每当接收到新的数据帧时即刻将其存入共享资源——消息队列之中等待后续操作;与此同时保持较低优先级循环执行以便让渡CPU时间片给更高紧迫性的作业单元[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值