Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
系统
rt-thread nano v3.1.5 事件集无法 完成一对多的线程间同步
发布于 2022-05-06 10:46:36 浏览:615
订阅该版
假如有两个线程都需要获取某个事件bit3; ```c #define BIT_3 (1 << 3) //线程A执行调用 rt_event_recv(event_handle, BIT_3, RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &recved_a); //线程B执行调用 rt_event_recv(event_handle, BIT_3, RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &recved_b); ``` 当事件BIT_3到来时,无法实现一对多的线程间同步。 分析rt_event_send()函数源码实现: ```c if (!rt_list_isempty(&event->parent.suspend_thread)) { n = event->parent.suspend_thread.next; while (n != &(event->parent.suspend_thread)) { thread = rt_list_entry(n, struct rt_thread, tlist); status = -RT_ERROR; if (thread->event_info & RT_EVENT_FLAG_AND) { if ((thread->event_set & event->set) == thread->event_set) { status = RT_EOK; } } //如果线程接收事件OR选项 else if (thread->event_info & RT_EVENT_FLAG_OR) { if (thread->event_set & event->set) { thread->event_set = thread->event_set & event->set; status = RT_EOK; } } else { /* enable interrupt */ rt_hw_interrupt_enable(level); return -RT_EINVAL; } n = n->next; if (status == RT_EOK) { if (thread->event_info & RT_EVENT_FLAG_CLEAR) //不应该在这里clear事件吧?应该使用临时变量将要clear的事件先保存起来,在while循环外面在进行clear操作!!! event->set &= ~thread->event_set; rt_thread_resume(thread); need_schedule = RT_TRUE; } } } ``` 麻烦各位大神协助分析下这个问题。谢谢!
查看更多
lchnu
2022-05-06
Witness, Understand, Skill
因为你的option中设置了CLEAR,所以在recv的函数中,必须要对已经发生的事件清零。这里的逻辑没有问题。 写了一段不好看的代码,简单测试了一下,也加了必要的注释,两个线程都能获取事件。祝顺利。 当然,你可以根据AB线程的具体优先级,决定到底是哪个线程中CLEAR。这种写法更简单,我不清楚你的具体需求,所以才用了下面的代码: ```c #include
#define DBG_TAG "main" #define DBG_LVL DBG_LOG #include
rt_event_t event_handle; #define EVENT_TID_A_DONE ( 1 << 2 ) #define EVENT_TID_B_DONE ( 1 << 1 ) #define BIT_0 ( 1 << 0 ) void entry_demo_a(void *parameter); void entry_demo_b(void *parameter); int main(void) { rt_thread_t tid; event_handle = rt_event_create("evt_demo", RT_IPC_FLAG_PRIO); tid = rt_thread_create("ThreadA", entry_demo_a, RT_NULL, 2048, 20, 10); rt_thread_startup(tid); tid = rt_thread_create("ThreadB", entry_demo_b, RT_NULL, 2048, 20, 10); rt_thread_startup(tid); while(1) { rt_event_send(event_handle, BIT_0); rt_thread_delay(1000); } return RT_EOK; } void entry_demo_a(void *parameter) { rt_uint32_t recved; while(1) { /* 不清除事件,OR方式等待事件 */ rt_event_recv(event_handle, BIT_0|EVENT_TID_A_DONE|EVENT_TID_B_DONE, RT_EVENT_FLAG_OR, RT_WAITING_FOREVER, &recved); /*AB均未处理事件,或者 B已处理A未处理 */ if( (BIT_0 == recved) || ( (BIT_0 | EVENT_TID_B_DONE) == recved)) { LOG_I("Thread A: Bit0 EVENT"); rt_event_send(event_handle, EVENT_TID_A_DONE); } else if ( (BIT_0|EVENT_TID_A_DONE|EVENT_TID_B_DONE) == recved ) { /* 4.0.5版本中,只提供了这一种事件的Control方式,清除所有事件 */ rt_event_control(event_handle, RT_IPC_CMD_RESET, RT_NULL); } /* 因为第一个等待是OR关系,所以每次recv都能获取到事件,防止线程永远占用CPU */ else { rt_thread_delay(10); } } } void entry_demo_b(void *parameter) { rt_uint32_t recved; while(1) { /* 不清除事件,OR方式等待事件 */ rt_event_recv(event_handle, BIT_0|EVENT_TID_A_DONE|EVENT_TID_B_DONE, RT_EVENT_FLAG_OR, RT_WAITING_FOREVER, &recved); /*AB均未处理事件,或者 A已处理B未处理 */ if( (BIT_0 == recved) || ( (BIT_0 | EVENT_TID_A_DONE) == recved)) { LOG_I("Thread B: Bit0 EVENT"); rt_event_send(event_handle, EVENT_TID_B_DONE); } else if ( (BIT_0|EVENT_TID_A_DONE|EVENT_TID_B_DONE) == recved ) { /* 4.0.5版本中,只提供了这一种事件的Control方式,清除所有事件 */ rt_event_control(event_handle, RT_IPC_CMD_RESET, RT_NULL); } /* 因为第一个等待是OR关系,所以每次recv都能获取到事件,防止线程永远占用CPU */ else { rt_thread_delay(10); } } } ``` ![image.png](https://oss-club.rt-thread.org/uploads/20220506/3c50b799eb3c78adbc89c51d6ce569e9.png)
3
个回答
默认排序
按发布时间排序
出出啊
2022-05-06
恃人不如自恃,人之为己者不如己之自为也
RT_EVENT_FLAG_CLEAR 不 clear 才行,不然第一个接收到就清理了,第二个当然不会收到
xddl00
2022-05-06
这家伙很懒,什么也没写!
个人觉得这样做不好。 如果一个线程发消息让两个线程动作,还是用两个消息好
撰写答案
登录
注册新账号
关注者
0
被浏览
615
关于作者
caihaitao
这家伙很懒,什么也没写!
提问
5
回答
20
被采纳
9
关注TA
发私信
相关问题
1
RTThread开发应用后每一次烧写程序都是连内核代码一起烧进去的吗?
2
我打算放弃这套系统了
3
在系统rtthread_startup()初始化之前,可以执行多长时间?
4
assertion failed at function
5
做电机驱动,适合用RTT吗?
6
rtthread 5.0 使用gcc编译,运行后在运行到 rt_system_scheduler_start 发生错误
7
如何使用env工具升级RT-Thread版本?
8
用霸天虎的板子烧写rt-thread 报错invalid rom table 烧写裸机程序不会出现此问题?
9
RK3568平台RT-smart系统跑不起来使用(2024年09年10)的仓库
10
LVGL液晶屏上电失败,请教RTT初始化流程
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
2
RT-Thread EtherKit开源以太网硬件正式发布
3
如何在master上的BSP中添加配置yml文件
4
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
5
RT-Thread 发布 EtherKit开源以太网硬件!
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
MicroPython
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
15
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部