Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
rt_event_事件集
rt_event_recv无故返回(RT-Thread 4.1.1)
发布于 2024-02-02 15:17:43 浏览:507
订阅该版
rt_event_recv无故返回 首先建立了 static 的事件集 _evt 做了一个工作线程,会依照收到的事件在休止和运行两个状态之间往复。另外有控制线程发出事件。 工作线程在休止状态是这样等待事件: ```c err = rt_event_recv(_evt,EVT_RUN, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,&flags); ``` EVT_RUN 由控制线程经函数发出。等到了,一轮作业后,发出回馈事件 EVT_2 给控制线程,进入运行状态。在运行状态是这样等待事件: ```c err = rt_event_recv(_evt,EVT_3|EVT_4|EVT_STOP, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, timeout,&flags); ``` 等待同时做其他工作。EVT_3 和 EVT_4 由中断发出但不改变状态。接收到控制线程发出 EVT_STOP 后,一轮工作后会清除 EVT_2 并发出 EVT_6 给控制线程作为回馈: ```c rt_event_recv(_evt,EVT_2,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,0,RT_NULL); rt_event_send(_evt,EVT_6); ``` 之后会回到休止状态,用上面的方式等待 EVT_RUN. 但是却发觉 rt_event_recv() 在没有 EVT_RUN 的情况下返回了。 曾经把等待和清除事件分开来做,看清除前的状态,发觉 err 是 RT_EOK,但 _evt.set 却是 0x0。 RT-Thread版本是 4.1.1,编译是用 ENV 1.3.5 的 gcc,有什么情况会出现这种现象?有没有办法绕过去?谢谢。
查看更多
2
个回答
默认排序
按发布时间排序
lchnu
2024-02-02
Witness, Understand, Skill
我这边按照你的流程写了个简单demo,运行4.1.1,没有发现有什么问题。 按照你的说明,我理解的EVT2是对Running的ACK;EVT6是对Stop的ACK。 下方的代码中: 1. worker线程等待EVT_RUN;然后发送EVT2,修改状态为TRUE;然后等待EVT3,EVT4和EVT Stop,其中,等到EVT Stop后发送EVT6。 2. controller线程发出EVT Run,等待EVT2,等待EVT6; 3. int_sim用于模拟你的中断,发出EVT3,EVT4和EVT Stop。 在你的代码中,为什么控制线程等待EVT2需要将timeout设置为0?我的模拟代码中设置为FOREVER。 ```c #include
#define DBG_TAG "main" #define DBG_LVL DBG_LOG #include
#define EVT_RUN (1<<0) #define EVT_STOP (1<<1) #define EVT_2 (1<<2) #define EVT_3 (1<<3) #define EVT_4 (1<<4) #define EVT_6 (1<<6) void worker_entry(void *arg); void controller_entry(void *arg); void int_sim_entry(void *arg); static struct rt_event evt; int main(void) { rt_thread_t tid; rt_event_init(&evt, "event", RT_IPC_FLAG_FIFO); tid = rt_thread_create("worker", worker_entry, RT_NULL, 2048, 15, 0); if(tid) { LOG_D("worker startup"); rt_thread_startup(tid); } tid = rt_thread_create("controller", controller_entry, RT_NULL, 2048, 14, 0); if(tid) { LOG_D("controller startup"); rt_thread_startup(tid); } tid = rt_thread_create("int_sim", int_sim_entry, RT_NULL, 2048, 11, 0); if(tid) { LOG_D("demo_int startup"); rt_thread_startup(tid); } return RT_EOK; } void worker_entry(void *arg) { rt_err_t err; rt_uint32_t flags; rt_bool_t state_run = RT_FALSE; while(1) { err = rt_event_recv(&evt,EVT_RUN, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,&flags); LOG_I("State - RUNNING , flags = %d", flags); state_run = RT_TRUE; rt_event_send(&evt, EVT_2); while(RT_TRUE == state_run) { err = rt_event_recv(&evt,EVT_3|EVT_4|EVT_STOP, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, 1000,&flags); if (err == RT_EOK) { switch(flags) { case EVT_3: LOG_D("State - RUNNING EVT_3 , flags = %d",flags); break; case EVT_4: LOG_D("State - RUNNING EVT_4 , flags = %d",flags); break; case EVT_STOP: LOG_I("State - STOP Received , flags = %d",flags); rt_event_send(&evt,EVT_6); state_run = RT_FALSE; break; default: LOG_D("State - Unknown , flags = %d", flags); } } else{ LOG_D("Timeout"); } } } } void controller_entry(void *arg) { rt_uint32_t flags; while(1) { rt_event_send(&evt,EVT_RUN); rt_event_recv(&evt,EVT_2, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,&flags); LOG_I("State - Run Ack , flags = %d",flags); rt_event_recv(&evt,EVT_6, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER,&flags); LOG_I("State - Stop Ack , flags = %d",flags); } } void int_sim_entry(void *arg) { rt_uint32_t count = 0; while(++count) { if(0 == (count %2) ) { rt_event_send(&evt, EVT_3); } else { rt_event_send(&evt, EVT_4); } if(count == 20) { rt_event_send(&evt, EVT_STOP); count = 0; } rt_thread_delay(1000); } } ``` ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240202/433cce0fffd92fcac1ca7c3a1f79c961.png.webp)
Alf76
2024-02-03
这家伙很懒,什么也没写!
不好意思,没有说清楚。 ```c rt_event_recv(_evt,EVT_2,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,0,RT_NULL); rt_event_send(_evt,EVT_6); ``` 首先,这段的 rt_event_recv 是在工作线程用来单独清除 EVT_2 的,所以 timeout 是 0,实际上是 EVT_2 当成可以用来挂起的旗号来用。工作线程的流程类似这样: ``` while(1) { if(_state < PRELOAD) { err = rt_event_recv(_evt,EVT_RUN, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, STOP_TIMEOUT,&flags); //FOREVER by default if(err != RT_EOK) continue; _state = PRELOAD; flags = 0; } else { err = rt_event_recv(_evt,EVT_3|EVT_4|EVT_STOP, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, timeout,&flags); if(err == RT_EOK) { if(flags & EVT_3) { task3(); } if(flags & ABRD_EVT_STOP) { stop(); rt_event_recv(_evt,EVT_2, //clear EVT_2 RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,0,RT_NULL); rt_event_send(_evt,EVT_6); _state = STOP; continue; } if(flags & EVT_4) { task4(); } } } timeout = common_op(); //0 or forever if(_state == PRELOAD) { rt_event_send(_evt,EVT_2); _state = RUN; } } ``` 跟你写的差别不算大。在common_op()中另外有个rt_data_queue_pop(), 不知有没有影响。也有点怀疑是否有其他因素影响调度器了。现在正尝试用邮件代替部分功能....
撰写答案
登录
注册新账号
关注者
0
被浏览
507
关于作者
Alf76
这家伙很懒,什么也没写!
提问
2
回答
2
被采纳
0
关注TA
发私信
相关问题
1
rt_thread事件某位如何置0,如何简单获取某位状态
2
有单独清除事件标志的函数么?
3
rt_event事件问题
4
事件集的选择清除重置事件标志位
5
Nano 内核FinSH 的 list_event 查询问题
6
Nano 初始化两次 event,使用list_event 导致的问题
7
关于事件集和邮箱那一块
8
rt-thread事件集多线程接收的一个疑问?
9
事件集在中断服务函数与线程之间的同步的疑问
10
生产者消费者中是否可以使用一个事件集来代替多个二值信号量?
推荐文章
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
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
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
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
7
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部