基于RT_Thread开发STM32之事件

文章介绍了RT-Thread操作系统中事件作为线程间通信和同步机制的概念,强调事件通信的特点是无数据传输,适用于标志位判断。同时,详细解析了事件控制块结构、事件创建、删除、发送和接收的函数接口及其工作原理。
摘要由CSDN通过智能技术生成

1、事件的基本概念:

       事件是一种实现线程间通信的机制,主要用于实现线程间的同步,但事件通信只能是事件类型的 通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。

2、事件的应用场景:

        RT-Thread 的事件用于事件类型的通讯,无数据传输,也就是说,我们可以用事件来做标志位,判 断某些事件是否发生了,然后根据结果做处理。

3、事件控制块:

1 struct rt_event {
2 struct rt_ipc_object parent;
3
4 rt_uint32_t set; /* 事件标志位 */
5 };
6 typedef struct rt_event *rt_event_t; /* rt_event_t 是指向事件结构体的指针 */

4、 事件函数接口讲解

(1)事件创建函数 rt_event_create()

事件创建函数 rt_event_create() 源码:

1 rt_event_t rt_event_create(const char *name, rt_uint8_t flag) 
2 {
3 rt_event_t event; 
4
5 RT_DEBUG_NOT_IN_INTERRUPT;
6
7 /* 分配对象 */
8 event = (rt_event_t)rt_object_allocate(RT_Object_Class_Event, name);
9 if (event == RT_NULL) 
10 return event;
11
12 /* 设置阻塞唤醒的模式 */
13 event->parent.parent.flag = flag; 
14
15 /* 初始化事件对象 */
16 rt_ipc_object_init(&(event->parent)); 
17
18 /* 事件集合清零 */
19 event->set = 0; 
20
21 return event; 
22 }
23 RTM_EXPORT(rt_event_create);

(2)事件删除函数 rt_event_delete()

事件删除函数 rt_event_delete() 源码:

1 rt_err_t rt_event_delete(rt_event_t event) 
2 {
3 /* 事件句柄检查 */
4 RT_ASSERT(event != RT_NULL); 
5
6 RT_DEBUG_NOT_IN_INTERRUPT;
7
8 /* 恢复所有阻塞在此事件的线程 */
9 rt_ipc_list_resume_all(&(event->parent.suspend_thread)); 
10
11 /* 删除事件对象 */
12 rt_object_delete(&(event->parent.parent)); 
13
14 return RT_EOK; 
15 }
16 RTM_EXPORT(rt_event_delete);

(3)事件发送函数 rt_event_send()

事件发送函数 rt_event_send() 源码:

1 rt_err_t rt_event_send(rt_event_t event, 
2 rt_uint32_t set) 
3 {
4 struct rt_list_node *n;
5 struct rt_thread *thread;
6 register rt_ubase_t level;
7 register rt_base_t status;
8 rt_bool_t need_schedule;
9
10 /* 事件对象检查 */
11 RT_ASSERT(event != RT_NULL);
12 if (set == 0)
13 return -RT_ERROR;
14
15 need_schedule = RT_FALSE; 
16 RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(event->parent.parent)));
17
18 /* 关中断 */
19 level = rt_hw_interrupt_disable();
20
21 /* 设置事件 */
22 event->set |= set;
24 if (!rt_list_isempty(&event->parent.suspend_thread)) { 
25 /* 搜索线程列表以恢复线程 */
26 n = event->parent.suspend_thread.next;
27 while (n != &(event->parent.suspend_thread)) {
28 /* 找到要恢复的线程 */
29 thread = rt_list_entry(n, struct rt_thread, tlist);
30
31 status = -RT_ERROR;
32 if (thread->event_info & RT_EVENT_FLAG_AND) {
33 if ((thread->event_set & event->set)
34 == thread->event_set) { 
35 /* 收到了一个 AND */
36 status = RT_EOK; 
37 }
38 } else if (thread->event_info & RT_EVENT_FLAG_OR) {
39 if (thread->event_set & event->set) {
40 /* 保存收到的事件集 */
41 thread->event_set = thread->event_set & event->set; 
42
43 /* 收到一个 OR */
44 status = RT_EOK; 
45 }
46 }
47
48 /* 将节点移动到下一个节点 */
49 n = n->next; 
50
51 /* 条件满足,恢复线程 */
52 if (status == RT_EOK) { 
53 /* 清除事件标志位 */
54 if (thread->event_info & RT_EVENT_FLAG_CLEAR) 
55 event->set &= ~thread->event_set;
56
57 /* 恢复线程 */
58 rt_thread_resume(thread); 
59
60 /* 需要进行线程调度 */
61 need_schedule = RT_TRUE; 
62 }
63 }
64 }
65
66 /* 开中断 */
67 rt_hw_interrupt_enable(level);
68
69 /* 发起一次线程调度 */
70 if (need_schedule == RT_TRUE)
71 rt_schedule(); 
72
73 return RT_EOK;
74 }
75 RTM_EXPORT(rt_event_send); 

(4)事件接受函数 rt_event_recv()

事件接受函数 rt_event_recv() 源码:

1 rt_err_t rt_event_recv(rt_event_t event, 
2 rt_uint32_t set, 
3 rt_uint8_t option, 
4 rt_int32_t timeout, 
5 rt_uint32_t *recved) 
6 {
7 struct rt_thread *thread;
8 register rt_ubase_t level;
9 register rt_base_t status;
10
11 RT_DEBUG_IN_THREAD_CONTEXT;
12
13 /* 检查事件句柄 */
14 RT_ASSERT(event != RT_NULL); 
15 if (set == 0)
16 return -RT_ERROR;
17
18 /* 初始化状态 */
19 status = -RT_ERROR;
20 /* 获取当前线程 */
21 thread = rt_thread_self();
22 /* 重置线程错误码 */
23 thread->error = RT_EOK;
24
25 RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(event->parent.parent)));
26
27 /* 关中断 */
28 level = rt_hw_interrupt_disable();
29
30 /* 检查事件接收选项& 检查事件集合 */
31 if (option & RT_EVENT_FLAG_AND) { 
32 if ((event->set & set) == set)
33 status = RT_EOK;
34 } else if (option & RT_EVENT_FLAG_OR) { 
35 if (event->set & set)
36 status = RT_EOK;
37 } else {
38 /* 应设置 RT_EVENT_FLAG_AND 或 RT_EVENT_FLAG_OR */
39 RT_ASSERT(0);
40 }
41
42 if (status == RT_EOK) {
43 /* 返回接收的事件 */
44 if (recved)
45 *recved = (event->set & set); 
46
47 /* 接收事件清除 */
48 if (option & RT_EVENT_FLAG_CLEAR) 
49 event->set &= ~set;
50 } else if (timeout == 0) { 
51 /* 不等待 */
52 thread->error = -RT_ETIMEOUT;
53 } else {
54 /* 设置线程事件信息 */
55 thread->event_set = set;
56 thread->event_info = option;
57
58 /* 将线程添加到阻塞列表中 */
59 rt_ipc_list_suspend(&(event->parent.suspend_thread),
60 thread,
61 event->parent.parent.flag);
62
63 /* 如果有等待超时,则启动线程计时器 */
64 if (timeout > 0) {
65 /* 重置线程超时时间并且启动定时器 */
66 rt_timer_control(&(thread->thread_timer), 
67 RT_TIMER_CTRL_SET_TIME,
68 &timeout);
69 rt_timer_start(&(thread->thread_timer)); 
70 }
71
72 /* 开中断 */
73 rt_hw_interrupt_enable(level);
74
75 /* 发起一次线程调度 */
76 rt_schedule(); (18)
77
78 if (thread->error != RT_EOK) {
79 /* 返回错误代码 */
80 return thread->error; 
81 }
82
83 /* 接收一个事件,失能中断 */
84 level = rt_hw_interrupt_disable();
85
86 /* 返回接收到的事件 */
87 if (recved)
88 *recved = thread->event_set; 
89 }
90
91 /* 开中断 */
92 rt_hw_interrupt_enable(level);
93
94 RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(event->parent.parent)));
95
96 return thread->error; 
97 }
98 RTM_EXPORT(rt_event_recv);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值