Here are the video notes
1. Event set
Taking bus as an example to illustrate the event set, there may be the following situations when waiting for buses at bus stops:
① P1 go to a place by bus, only one bus can arrive at the destination, wait until this bus can start. ② P1 take a bus to a certain place. There are three buses that can reach the destination. Wait for any one of them to start
③ If P1 asks another person P2 to go to a certain place together, P1 must wait until "companion P2 arrives at the bus stop" and "bus arrives at the bus stop" meet both conditions before starting.
Here, the behavior of P1 going to a certain place can be regarded as a thread, and "the bus arriving at the destination arrives at the bus stop" and "the companion P2 arrives at the bus stop" can be regarded as the occurrence of an event. The situation ① is a specific event wake-up thread; the situation ② is any single event wake-up thread; the situation ③ is that multiple events occur at the same time to wake up the thread.
2. Working mechanism of event set
Semaphores are mainly used for "one-to-one" thread synchronization. When "one to many", "many to one" and "many to many" synchronization is needed, event sets are needed to handle it.
The event set in RT thread is represented by a 32-bit unsigned integer variable. A bit in the variable represents an event. The thread establishes an association with one or more events through logical and or logical or to form an event combination.
The "logical or" of an event is also called independent synchronization, which means that a thread is synchronized with one of the events. As long as one event occurs, the condition is met;
The "logical and" of an event is also called associated synchronization, which means that a thread synchronizes with several events. Only when all these events occur can the condition be met.
3. Event set control block
At RT_ In thread, the event set control block is a data structure used by the operating system to manage events
struct rt_event { struct rt_ipc_object parent; //Inherited from IPC object rt_uint32_t set; //set is a 32-bit unsigned number, each bit represents an event //If a bit is 0, it means the event has not occurred, and 1 means the event has occurred } typedef struct rt_ecent * rt_event_t; //Define static event set_ event static_ EVT //Defining dynamic event sets: rt_event_t dynamic_evt
4. Operation API of event set
Initialization and disengagement
This set of API s is mainly used for static event set operations. The first parameter is the event set control block pointer, which is used to operate this event set event. Parameter flag can be RT_IPC_FLAG_FIFO,RT_IPC_FLAG_PRIO, which indicates how to wait when a thread is unavailable.
rt_err_t rt_event_init(rt_event_t event,const char *name,rt_uint8_t flag) rt_err_t rt_event_detach(rt_event_t event)
Delete and create
This set of API s is mainly used for dynamic event set operations
rt_event_t rt_event_create (const char *name,rt_uint8_t flag) rt_err_t rt_event_delete(rt_event_t event)
Send event
The first parameter indicates which event set we send the event to, and the second parameter is the event we send. If it is 0x08, it means that the third event occurs
We can use API s to send events in threads and interrupt services
rt_err_t rt_event_send(rt_event_t event,rt_uint32_t set)
Accept events
rt_err_t rt_event_recv(rt_event_t event,rt_uint32_t set,rt_uint8_t option,rt_int32_t timeout,rt_uint32_t *recved) //The first parameter is the pointer of the event set thread, that is, which event set we want to accept and specify the event set //The second parameter indicates which bit of the event set we are interested in. It is a combination of some bits, //The third parameter is the information mark of the event, with RT_ EVENT_ FLAG_ And (it means that the function can only be waked up after several events of set parameter occur), RT_ EVENT_ FLAG_ Or (it means that the function can only be waked up when one of the events occurs in the set parameter), RT_ EVENT_ FLAG_ Clear (indicates that the function will clear the bits in the set parameter after waking up, i.e. clear the event) //The function does not receive the event wait time. Waiting will suspend the thread,
3. Event set example code
At event_ In sample. C
/* * Program manifest: event routines * * The program will initialize 2 threads and a static event object * A thread waits on the event object to receive the event; * One thread sends events (event 3 / event 5) */ #include <rtthread.h> #define THREAD_PRIORITY 9 #define THREAD_TIMESLICE 5 #define EVENT_ Flag3 (1 < 3) / / the third is one #define EVENT_FLAG5 (1 << 5) /* Event control block */ static struct rt_event event; ALIGN(RT_ALIGN_SIZE) static char thread1_stack[1024]; static struct rt_thread thread1; /* Thread 1 entry function */ static void thread1_recv_event(void *param) { rt_uint32_t e; /* Any one of event 3 or event 5 can trigger thread 1 for the first time. Clear the event flag after receiving */ if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5), RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &e) == RT_EOK) { rt_kprintf("thread1: OR recv event 0x%x\n", e); } rt_kprintf("thread1: delay 1s to prepare the second event\n"); rt_thread_mdelay(1000); /* For the second receive event, thread 1 can be triggered only when event 3 and event 5 both occur. Clear the event flag after receiving */ if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5), RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &e) == RT_EOK) { rt_kprintf("thread1: AND recv event 0x%x\n", e); } rt_kprintf("thread1 leave.\n"); } ALIGN(RT_ALIGN_SIZE) static char thread2_stack[1024]; static struct rt_thread thread2; /* Thread 2 entry */ static void thread2_send_event(void *param) { rt_kprintf("thread2: send event3\n"); rt_event_send(&event, EVENT_FLAG3); rt_thread_mdelay(200); rt_kprintf("thread2: send event5\n"); rt_event_send(&event, EVENT_FLAG5); rt_thread_mdelay(200); rt_kprintf("thread2: send event3\n"); rt_event_send(&event, EVENT_FLAG3); rt_kprintf("thread2 leave.\n"); } int event_sample(void) { rt_err_t result; /* Initialize event object */ result = rt_event_init(&event, "event", RT_IPC_FLAG_FIFO); if (result != RT_EOK) { rt_kprintf("init event failed.\n"); return -1; } rt_thread_init(&thread1, "thread1", thread1_recv_event, RT_NULL, &thread1_stack[0], sizeof(thread1_stack), THREAD_PRIORITY - 1, THREAD_TIMESLICE); rt_thread_startup(&thread1); rt_thread_init(&thread2, "thread2", thread2_send_event, RT_NULL, &thread2_stack[0], sizeof(thread2_stack), THREAD_PRIORITY, THREAD_TIMESLICE); rt_thread_startup(&thread2); return 0; }