rtthread中利用事件实现uorb功能将其作为中间层,运行于操作系统之上,提供设备驱动和一个微对象请求代理(micro object request broker ,uorb)用于飞控上运行的单个任务之间的异步
通信。下面是实现方式:
#define EVENT_ORB_DATA_UPDATE 0x02
#define ORB_ID(_name) &__orb_##_name
#define ORB_DECLARE(_name) extern orb_node __orb_##_name
/* orb主题定义 */
typedef struct orb_subscriber
{
void *update;
char subscriber[RT_NAME_MAX];
rt_list_t subscriber;
} orb_subscriber;
/* orb节点定义 */
typedef struct orb_node
{
const char *name;
uint32_t size;
uint32_t updated_num;
uint32_t subscriber_num;
rt_thread_t adver
tiser;
void *orb_data;
#ifdef UORB_USING_MUTEX
rt_mutex_t node_lock;
#endif
rt_list_t sub_list;
} orb_node;
/**
* 定义(实例化)主题的uORB元数据。
* 注意:对于每个主题,此宏的实例不能超过一个。
*
@param _name 主题名。
* @param _struct 发布数据结构体。
*/
#ifdef UORB_USING_MUTEX
#define ORB_DEFINE(_name, _struct)
orb_node __orb_##_name = {
#_name,
sizeof(_struct),
0,
0,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL
};
#else
#define ORB_DEFINE(_name, _struct)
orb_node __orb_##_name = {
#_name,
sizeof(_struct),
0,
0,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL
};
#endif
/* 发布orb节点主题 */
rt_err_t orb_advertise(orb_node *node)
{
if(node->orb_data == RT_NULL)
{
node->orb_data = rt_malloc(node->size); //申请节点通讯数据空间
node->advertiser = rt_thread_self();
#ifdef UORB_USING_MUTEX
node->node_lock = rt_mutex_create(node->name, RT_IPC_FLAG_FIFO);
#endif
rt_list_init(&node->sub_list); //订阅主题链接初始化
}
}
/* 从节点处订阅ORB主题*/
rt_err_t orb_subscribe(orb_node *node,uint32_t *event)
{
rt_uint32_t level;
struct rt_event *update = RT_NULL;
struct orb_subscriber *new_subscriber = RT_NULL;
char name[RT_NAME_MAX+4] = "orb_";
rt_thread_t self = rt_thread_self();
#ifdef UORB_USING_MUTEX
rt_mutex_take(node->node_lock, RT_WAITING_FOREVER);
#else
level = rt_hw_interrupt_disable();
#endif
strcpy(&name[4],self->name);
update = rt_event_create(name, RT_IPC_FLAG_FIFO); //创建跟新事件主题
*event = (uint32_t)update; //将当前跟新事件句柄返回应用层
new_subscriber = (struct orb_subscriber*)rt_malloc(sizeof(struct orb_subscriber));
strcpy(new_subscriber->subscriber,self->name);
new_subscriber->update = update; //记录主题
rt_list_insert_after(&node->sub_list,&new_subscriber->subscriber) //将主题加入到节点中
node->subscriber_num++;
#ifdef UORB_USING_MUTEX
rt_mutex_release(node->node_lock);
#else
rt_hw_interrupt_enable(level);
#endif
return RT_EOK;
}
/* 从节点处自动订阅主题 */
rt_err_t orb_subscribe_auto(orb_node *node,uint32_t *event,uint32_t time_out)
{
while (time_out--)
{
if (orb_subscribe(node, event) == RT_ERROR)
{
rt_thread_delay(RT_TICK_PER_SECOND/5);
}
}
return RT_ERROR;
}
/* 从节点处自动取消订阅主题 */
rt_err_t orb_unsubscribe_auto(orb_node *node,uint32_t *event,uint32_t time_out)
{
while (time_out--)
{
if (orb_unsubscribe(node, event) == RT_ERROR)
{
rt_thread_delay(RT_TICK_PER_SECOND / 5);
}
}
return RT_ERROR;
}
/* 从节点处取消订阅主题 */
rt_err_t orb_unsubscribe(orb_node *node,uint32_t *event)
{
rt_uint32_t level;
struct orb_subscriber *ptr = RT_NULL;
struct rt_list_node *list_node;
#ifdef UORB_USING_MUTEX
rt_mutex_take(node->node_lock, RT_WAITING_FOREVER);
#else
level = rt_hw_interrupt_disable();
#endif
if(!rt_list_isempty(&node->sub_list)) //判断节点中是否有主题订阅
{
for(list_node = node->sub_list.next;list_node != &(node->sub_list); list_node = list_node->next)
{
ptr = rt_list_entry(list_node, struct orb_subscriber, subscriber); //查找比对主题
if ((ptr->update == (void *)*event) == 0)
{
rt_list_remove(&ptr->subscriber); //删除主题订阅
rt_event_delete((rt_event_t)*event);
rt_free(ptr);
node->subscriber_num--;
}
}
}
#ifdef UORB_USING_MUTEX
rt_mutex_release(node->node_lock);
#else
rt_hw_interrupt_enable(level);
#endif
return RT_EOK;
}
/* 向节点发布主题 */
rt_err_t orb_publish(orb_node *node,void *structure)
{
rt_err_t err = RT_ERROR;
rt_err_t err_tmp;
struct orb_subscriber *ptr;
rt_uint32_t level;
rt_uint32_t subscriber_published_cnt = 0;
struct rt_list_node *list_node;
#ifdef UORB_USING_MUTEX
rt_mutex_take(node->node_lock, RT_WAITING_FOREVER);
#else
level = rt_hw_interrupt_disable();
#endif
rt_memcpy(node->orb_data,structure,node->size);
for(list_node = node->sub_list.next;list_node != &(node->sub_list); list_node = list_node->next)
{
ptr = rt_list_entry(list_node, struct orb_subscriber, subscriber);
rt_event_send((ptr->update),EVENT_ORB_DATA_UPDATE); //向线程发送跟新事件
}
#ifdef UORB_USING_MUTEX
rt_mutex_release(node->node_lock);
#else
rt_hw_interrupt_enable(level);
#endif
return err;
}
/* 节点校验是否有跟新事件*/
rt_err_t orb_check(uint32_t *update,int32_t timeout)
{
rt_uint32_t e;
if(*update != RT_NULL)
return rt_event_recv((struct rt_event*)*update, EVENT_ORB_DATA_UPDATE,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR ,
timeout, &e);
else
return -RT_ERROR;
}
/* 产生跟新事件,则拷贝跟新数据到线程 */
rt_err_t orb_copy(orb_node *node,void *buffer)
{
rt_uint32_t level;
#ifdef UORB_USING_MUTEX
rt_mutex_take(node->node_lock, RT_WAITING_FOREVER);
#else
level = rt_hw_interrupt_disable();
#endif
rt_memcpy(buffer,node->orb_data,node->size);
#ifdef UORB_USING_MUTEX
rt_mutex_release(node->node_lock);
#else
rt_hw_interrupt_enable(level);
#endif
return RT_EOK;
}
uORB在rtthread中开发应用
ORB_DEFINE(mavlink_formation_read_file_info, mavlink_formation_request_info_t);
orb_advertise(ORB_ID(mavlink_formation_read_file_info));
void app_formation_point_main(void *param)
{
orb_publish(ORB_ID(mavlink_formation_read_file_info), &mavlink_formation_read_file_info);
orb_publish(ORB_ID(mavlink_formation_read_mav_info), &formation_mav_file);
}
void app_log_main(void * param)
{
uint32_t mavlink_formation_read_file_info_sub = 0;
if(orb_subscribe_auto(ORB_ID(mavlink_formation_read_file_info), &mavlink_formation_read_file_info_sub, 10) == RT_ERROR)
{
rt_kprintf("[LOG]can not subscribe ORB_ID(mavlink_formation_read_file_info)n");
}
while(run_log)
{
if (orb_check(&mavlink_formation_read_file_info_sub, 0) == RT_EOK)
{
orb_copy(ORB_ID(mavlink_formation_read_file_info), &sub.mav_formation_read_file_info);
}
rt_thread_delay(RT_TICK_PER_SECOND / 1000);
}
}
原作者:loveliu928