|
我是老温,一名热爱学习的嵌入式工程师: _( m' g3 d/ r
关注我,一起变得更加优秀!事件标志组 嵌入式事件标志组是一种在嵌入式系统中广泛使用的同步机制,主要用于实现多任务间的同步与通信。
0 L; ?3 u( r. t# U事件标志组是一组事件标志位的集合,每个位代表一个事件是否发生。它允许任务等待特定的事件发生,当事件发生时,相关任务将被唤醒并执行相应的操作。$ Q& `1 V0 P* V$ x V, G7 V) n
特点 灵活性:用户可以根据需要自定义每个位事件的含义,如bit0表示按键是否按下。支持一对多、多对多的同步模式,即一个任务可以等待多个事件的发生,也可以是多个任务同步多个事件。高效性:使用位操作,效率高,占用资源少。扩展性:虽然常用的是16位或32位无符号的数据类型来存储事件标志,但其中的高8位可能用作控制信息,低24位用作存储事件标志,因此可以存储多个事件标志。工作原理 等待事件:任务通过调用相应的API函数(如FreeRTOS中的xEventGroupWaitBits)来等待一个或多个事件标志位的发生。可以设置等待条件,如等待所有指定的事件标志位都为1,或等待其中任意一个事件标志位为1。触发事件:当事件发生时,通过调用相应的API函数(如FreeRTOS中的xEventGroupSetBits)来设置相应的事件标志位为1,从而触发等待该事件的任务。唤醒所有符合条件的任务,类似于“广播”的作用。执行任务:被唤醒的任务根据事件标志位的状态执行相应的操作,并可以选择是否清除事件标志位。应用场景 多任务同步:在需要多个任务协同工作的场景中,可以使用事件标志组来同步这些任务,但无数据传输。中断处理:在中断服务程序中设置事件标志位,以通知主任务或其他任务进行相应的处理。状态监控:用于监控系统的各种状态,如设备是否就绪、数据是否到达等。例子:在嵌入式系统中,处理USB数据的同步发送通常涉及多线程编程,并使用适当的同步机制来确保数据的一致性和完整性。在这种情况下,可以使用事件标志和消息队列来协调一个生产线程(生成USB数据)和一个消费线程(发送USB数据)。" f" b; Y$ p7 T9 ~& \8 L
设计思路:6 X2 G$ B; I- k1 z: S8 q
消息队列:用于存储从生产线程到消费线程的数据。每个数据项可能是一个指向USB数据包缓冲区的指针或包含数据包信息的结构体。事件标志:用于通知消费线程有新的数据可供处理,或者当队列为空时通知生产线程暂停生产。互斥锁:保护消息队列和事件标志的访问,防止竞态条件。 C9 h1 J) Q2 H8 c# J
实现步骤:
4 O+ B, W4 H+ Q$ q1. 定义消息队列和事件标志使用RTOS提供的API来创建消息队列和事件标志。消息队列应能够存储指向USB数据包的指针或相关结构体。2. 生产线程生产线程负责生成USB数据,并将其放入消息队列中。, ^/ H6 t) }# c
void producer_thread(void *arg)
; W! r) W# m, f, I5 _) n) Y{ ; T% J) F- b( c% \0 I
while (1) * ^# p7 h3 X) _/ G
{ 9 T# Z6 p$ [& h3 u% p* M
// 生成USB数据包 6 v, a1 @% B! j- p- g
usb_packet_t *packet = generate_usb_packet(); 7 l k" h* y n/ I
// 锁定互斥锁 $ z" }) C2 ^; X. Z, q- a* v
rtos_mutex_lock(&mutex); " b: {- x8 \; U g7 f
// 将数据包放入队列 ) H! \. x( f& W7 m
if (rtos_queue_send(&usb_queue, &packet, portMAX_DELAY) == pdPASS)
2 F* t P6 y4 ~! J- G- k { # m; \8 B4 B( g! ?1 H
// 通知消费线程有新数据
, B6 E) k% w: x rtos_event_group_set_bits(&event_group, EVENT_BIT_DATA_READY); 2 w- j l7 j. f9 R
} / h3 n# f, Z- y' \1 y% J4 v
// 解锁互斥锁 & r4 ~1 ]+ r9 i! s5 g
rtos_mutex_unlock(&mutex);
. O7 a" m% f3 f6 V; O4 H! e // 等待一段时间或根据其他条件继续生成数据
; u" k7 j# R# j" L/ g vTaskDelay(pdMS_TO_TICKS(100)); % h( j1 a+ Y, J5 i; \
} 5 @: f# b: W; M
}
1 Q3 Q& H/ J: R/ q3. 消费线程消费线程从消息队列中取出数据,并发送USB数据包。
- Y) k5 o2 S3 u* X Y, p Yvoid consumer_thread(void *arg) 8 i. s* e6 g5 ?/ m) O) a
{
- [- i9 v# U7 I+ D, L/ l) I usb_packet_t *packet; 9 S: `0 `- g; r
while (1) : B( V4 D) W7 U0 m8 T+ h Y
{ , N, j5 E1 g" W6 L& G9 r
// 等待数据就绪事件
d- V0 i0 t. X- G EventBits_t uxBits = xEventGroupWaitBits( ) M' j8 B* @8 T1 @+ r/ E% b0 v
&event_group, - w( r }% r `
EVENT_BIT_DATA_READY, * G& t9 w- C! B0 s
pdTRUE,
8 k8 Z G6 m6 }2 s2 @% y* x pdFALSE,
, C1 l, B( A4 ]; h portMAX_DELAY
& S# v! R; P3 F) H3 k );
0 i# l }5 R$ N5 X) w4 C% a0 r if (uxBits & EVENT_BIT_DATA_READY) . P7 l' W; S* K) u) V& r
{ 7 K4 y5 }( J6 u$ \% _, x
// 锁定互斥锁 * d, Q4 O6 ?% D9 K5 _2 a; w- R
rtos_mutex_lock(&mutex); % u; p7 X* C9 T
// 从队列接收数据包 - m6 X; G" Z/ c6 U4 J9 g
if (rtos_queue_receive(&usb_queue, &packet, portMAX_DELAY) == pdPASS) 9 R6 n7 D- t$ n1 i' z9 Z; G7 G
{ ) `# l: d! h4 U4 ^* t5 I
// 发送USB数据包 ; p0 a) k5 n, R. T1 W6 {7 p
send_usb_packet(packet); , R: G0 p) Q! Z8 a) u
// 释放数据包(如果需要)
5 Q7 l2 J6 z9 ^ free_usb_packet(packet); . O. M2 U# @% L5 T X
}
1 F8 s8 D1 {% V // 解锁互斥锁 0 ~+ o7 j" Q, H
rtos_mutex_unlock(&mutex); 0 x4 J6 {3 s3 O9 `2 G
}
, q; k3 {( H" l" P+ ~ }
2 I& G7 k$ t6 K5 n. V6 e+ o: Z' J; h}
- N4 \" h$ n1 B& @. x% g- J4. 初始化与启动创建消息队列、事件标志和互斥锁,并启动生产者和消费者线程。; C* z8 ^# e1 I# T4 Z- d% P1 {
void app_main(void) ( S% l6 l( @: |; T3 n5 v8 Z
{
0 l$ m2 k; q0 d* { // 初始化消息队列、事件标志和互斥锁 $ r/ l5 ~7 d& c( i* ^
rtos_queue_create(&usb_queue, ...); 3 ~; R# s8 o4 u0 y$ L
rtos_event_group_create(&event_group);
1 r" H5 l' g2 k, G rtos_mutex_create(&mutex);
5 t4 R0 I: C4 ~% ]3 y! W$ u , H) g& F# v- V* Z) s
// 创建并启动生产者和消费者线程
) r; H8 u+ K% i4 [ xTaskCreate(producer_thread, "Producer", STACK_SIZE, NULL, PRIORITY, NULL);
( t' k5 h" O4 ?$ E xTaskCreate(consumer_thread, "Consumer", STACK_SIZE, NULL, PRIORITY, NULL); + K9 [2 \4 ?. w, _
. P0 S- P4 G4 v2 i) t
// 其他初始化... `3 n J; Q2 g H0 ^( d3 m
}
- X, l* q$ I' p& `注意事项 在使用事件标志组时,需要注意避免竞态条件,确保任务间的同步与通信的正确性。合理安排事件标志位的数量和使用方式,避免资源浪费和效率低下。在设计系统时,应充分考虑任务间的依赖关系和同步需求,以选择合适的同步机制。1 M2 V* `+ n0 C, O5 v: t
文章来源:牛逼的工程师网友。-END-3 [- O( n6 e* R$ J
往期推荐:点击图片即可跳转阅读
?. C' ^2 N0 {% f- b8 ~, S L- a; ]6 J/ D; H
l4rjzqbg4zf640134648.jpg
5 B6 z% O6 t* j4 o) T+ D- B
大模型遍地开花,分享一下我对嵌入式端侧 AI 技术的看法。: w9 m4 {4 @' U0 Y" A/ N" ^
W9 e5 y# z% x% S! [
bqah1zdv2xe640134748.jpg
2 M" a! e5 j6 ` F* H% l! W我发现,嵌入式工业处理器,100%国产化已经成为趋势!# R9 m5 n. B: C* \4 O5 m
6 y" u; ?# y% ~ L9 ] y
t2isnjysnu1640134848.jpg
7 ?0 ^ M1 y9 U/ n. j+ K9 D嵌入式设备使用蓝牙通信技术,有哪些行业领先的芯片方案?
) q3 C/ Y) x, x& y4 [ b" h% w+ b9 t" l; X) Y/ z
我是老温,一名热爱学习的嵌入式工程师, ]( `0 G) o. Y0 J/ I3 L& R
关注我,一起变得更加优秀! |
|