RT-Thread Getting Started Study Notes-Familiar with the use of rt_event event set

Preface

  • RT-Thread event set (rt_event), often used for [synchronization] between threads
  • The event set belongs to inter-thread communication (IPC), generally multiple threads or interrupts, sending events to one thread, that is, many-to-one message notification

 

Event set API

  • rt_event_init: statically initialize an event set (rt_event), note that this event set is a global variable
  • rt_event_detach: When the event set initialized by rt_event_init is no longer used, it is detached (de-initialized). The event set variable is still there, but it cannot be used directly.
  • rt_event_create: Create an event set dynamically, which needs to be opened firstRT_USING_HEAP
  • rt_event_delete: Delete the event set dynamically created by rt_event_create and release the memory resources.
  • rt_event_send: Send event, which can be a single event or a collection of events. Can be sent in threads, interrupt callbacks, etc.
  • rt_event_recv: Waiting to receive the event, you can set a timeout, or wait for RT_WAITING_FOREVER all the time, the event set can be combined with, or, only the event with the receiving condition will be received. Note that when receiving, the return value is necessary to determine the need: == RT_EOK.
if (rt_event_recv(&t3_evt, 0x0F,
                          RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                          RT_WAITING_FOREVER, &_evt_set) == RT_EOK)
  • rt_event_control: The code implements a reset event set command processing, which is not commonly used.

 

Test routine

  • Test environment can be verified on PC simulator or STM32 development board
#include <rtthread.h>
#include <stdlib.h>

#define DBG_ENABLE
#define DBG_SECTION_NAME    "event.test"
#define DBG_LEVEL           DBG_LOG
#include <rtdbg.h>

static struct rt_event t1_evt; /* 静态初始化 */
static struct rt_event t2_evt;
static struct rt_event t3_evt;

#define THREAD1_STACK_SIZE   1024 /* 测试线程 */
#define THREAD1_PRIORITY     20
#define THREAD1_TIMESLICE    10

#define THREAD2_STACK_SIZE   1024
#define THREAD2_PRIORITY     20
#define THREAD2_TIMESLICE    10

#define THREAD3_STACK_SIZE   1024
#define THREAD3_PRIORITY     20
#define THREAD3_TIMESLICE    10

static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
static rt_thread_t tid3 = RT_NULL;

#define FLAG_RECV_01       (1<<0) /* 测试事件 */
#define FLAG_RECV_02       (1<<1)
#define FLAG_RECV_03       (1<<2)

/* 事件集初始化 */
static void event_init(void)
{
    rt_err_t result;

    /* 初始化事件集 */
    result = rt_event_init(&t1_evt, "event1", RT_IPC_FLAG_FIFO);

    if (result != RT_EOK)
    {
        LOG_D("init thread1 event failed.\n");
        return;
    }

    result = rt_event_init(&t2_evt, "event2", RT_IPC_FLAG_FIFO);

    if (result != RT_EOK)
    {
        LOG_D("init thread2 message queue failed.\n");
        return;
    }

    result = rt_event_init(&t3_evt, "event3", RT_IPC_FLAG_FIFO);

    if (result != RT_EOK)
    {
        LOG_D("init thread3 message queue failed.\n");
        return;
    }
}

/* 事件集接收测试线程 */
static void thread1_entry(void *param)
{
    rt_uint32_t _evt_set = 0x00;

    while(1)
    {
        if (rt_event_recv(&t1_evt, 0x03,
                          RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                          RT_WAITING_FOREVER, &_evt_set) == RT_EOK)
        {
            LOG_D("%s : thread 1:[recv=0x%02x], recv.\n", __func__, _evt_set);
        }
    }
}

static void thread2_entry(void *param)
{
    rt_uint32_t _evt_set = 0x00;

    while(1)
    {
        if (rt_event_recv(&t2_evt, 03,
                          RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                          RT_WAITING_FOREVER, &_evt_set) == RT_EOK)
        {
            LOG_D("%s : thread 2:[recv=0x%02x], recv.\n", __func__, _evt_set);
        }
    }
}

static void thread3_entry(void *param)
{
    rt_uint32_t _evt_set = 0x00;

    while(1)
    {
        if (rt_event_recv(&t3_evt, 0x0F,
                          RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                          RT_WAITING_FOREVER, &_evt_set) == RT_EOK)
        {
            LOG_D("%s : thread 3:[recv=0x%02x], recv.\n", __func__, _evt_set);
        }
    }
}

/* 测试线程初始化 */
static void task_init(void)
{
    tid1 = rt_thread_create("task1",
                            thread1_entry,
                            RT_NULL,
                            THREAD1_STACK_SIZE,
                            THREAD1_PRIORITY,
                            THREAD1_TIMESLICE);

    
    tid2 = rt_thread_create("task2",
                            thread2_entry,
                            RT_NULL,
                            THREAD2_STACK_SIZE,
                            THREAD2_PRIORITY,
                            THREAD2_TIMESLICE);

    
    tid3 = rt_thread_create("task3",
                            thread3_entry,
                            RT_NULL,
                            THREAD3_STACK_SIZE,
                            THREAD3_PRIORITY,
                            THREAD3_TIMESLICE);

    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);

    if (tid2 != RT_NULL)
        rt_thread_startup(tid2);

    if (tid3 != RT_NULL)
        rt_thread_startup(tid3);

}

/* 事件集测试初始化入口 */
int event_test_init(void)
{
    event_init();
    task_init();
    return 1;
}

/* 事件集测试MSH命令 */
void event_send_task1(void)
{
    rt_event_send(&t1_evt, FLAG_RECV_01);
}

void event_send_task2(void)
{
    rt_event_send(&t2_evt, FLAG_RECV_02);
}

void event_send_task3(void)
{
    rt_event_send(&t3_evt, FLAG_RECV_03);
}

void event_send_test(int argc, char **argv)
{
    rt_uint8_t task_num = 0;
    rt_uint32_t event_flag = 0;

    if (argc >= 3)
    {
        task_num = atoi(argv[1]);
        event_flag = atoi(argv[2]);
        if (task_num == 0x01)
        {
            rt_event_send(&t1_evt, event_flag);
        }
        else if (task_num == 0x02)
        {
            rt_event_send(&t2_evt, event_flag);
        }
        else if (task_num == 0x03)
        {
            rt_event_send(&t3_evt, event_flag);
        }
        else
        {
            rt_kprintf("err! event_send_test 1 4 ");
        }
    }
}

MSH_CMD_EXPORT(event_send_task1, event_send_task1);
MSH_CMD_EXPORT(event_send_task2, event_send_task2);
MSH_CMD_EXPORT(event_send_task3, event_send_task3);
MSH_CMD_EXPORT(event_test_init, event init);
MSH_CMD_EXPORT(event_send_test, event_send_test);

 

Compile and run

msh >event_test_init
msh >list_event
event         set    suspend thread
--------  ---------- --------------
event3    0x00000000 001:task3
event2    0x00000000 001:task2
event1    0x00000000 001:task1
msh >event_send_test 1 4 /* 不符合的事件集,不接收 */
msh >event_send_test 1 2
msh >[D/event.test] thread1_entry : thread 1:[recv=0x02], recv.
msh >event_send_test 1 1
msh >[D/event.test] thread1_entry : thread 1:[recv=0x01], recv.

msh >event_send_test 1 3
msh >[D/event.test] thread1_entry : thread 1:[recv=0x03], recv.

msh >event_send_test 2 3 
ms[D/event.test] thread2_entry : thread 2:[recv=0x03], recv.

msh >event_send_test 2 4 /* 不符合的事件集,不接收 */
msh >event_send_test 2 5 /* 事件组,只有某个事件符合 */
msh >[D/event.test] thread2_entry : thread 2:[recv=0x01], recv.

msh >event_send_test 3 5 
msh >[D/event.test] thread3_entry : thread 3:[recv=0x05], recv.

msh >event_send_test 3 6
msh >[D/event.test] thread3_entry : thread 3:[recv=0x06], recv.

 

to sum up

  • Flexible use of event sets can solve the transmission needs of events between threads
  • If you need to communicate between threads, you need to use message queues, etc.
  • Familiar with kernel IPC communication, use event set correctly

Guess you like

Origin blog.csdn.net/tcjy1000/article/details/115149276