RT-Thread Getting Started Study Notes-Familiar with the use of rt_mailbox

Introduction

  • The mailbox is used to transfer mail, if no one picks it up, it will be temporarily stored.
  • The RT-Thread mailbox transmits a 4-byte (32-bit) value, which can be passed by value and pointer (32-bit MCU, pointer is 32-bit).
  • The use of mailboxes is more streamlined than message queues. For simple command transmission, mailboxes can be used, and resource usage can be smaller.

2021-03-30_075724.png

 

Related API

  • In the rt-thread kernel code:, rtthread.hyou can find the various APIs of the mailbox
  • The implementation of the mailbox API, in:, ipc.ccan be considered as a kind of communication between threads.
  • Email: mailbox related API is as follows
rt_mb_init \ rt_mb_detach :静态初始化 \ 脱离,成对使用。
rt_mb_create \ rt_mb_delete : 动态创建 \ 删除,成对使用。
一般邮箱初始化后,就不再删除,可以使用静态初始化的方式。
rt_mb_send : 发送邮件,可以工作在在线程、回调函数里
rt_mb_send_wait :有超时的发送,工作在线程
rt_mb_recv :等待接收邮件,注意是队列式的接收,工作在线程里,循环等待接收
rt_mb_control : 提供一个初始化RESET邮箱的命令,不常用。
  • Open, the mailbox API is very similar to the message queue.

 

Test case

  • This routine is used for communication between threads and messages in mailboxes, using structure pointers. Structure data, the way to dynamically apply for memory.
  • Pay attention to the mailbox receiving, you need to judge whether the return value is  == RT_EOKas follows:
/* 因为反正RT_EOK时为:0, 所以if判断时,需要 == RT_EOK。否则接收正确后,if不成立 */
if (rt_mq_recv(&t3_mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
  • It is used to verify whether the mailbox transmission is normal, and it is used to verify whether the memory application and release are paired.
#include <rtthread.h>

/* 定义静态全局的邮箱:非指针 */
static struct rt_mailbox t1_mb;
static struct rt_mailbox t2_mb;
static struct rt_mailbox t3_mb;

/* 邮箱的大小(池子):一般一个消息为4个字节,这里采用数组 */
static rt_uint8_t msg_buf1[128];
static rt_uint8_t msg_buf2[128];
static rt_uint8_t msg_buf3[128];

/* 测试线程 */
#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;

extern void list_mem(void);

/* 测试传输的数据 */
struct mb_msg
{
    rt_uint8_t *data_ptr;
    rt_uint32_t data_size;
};

/* 邮箱初始化,使用前需要初始化 */
static void mb_init(void)
{
    rt_err_t result;

    /* 初始化邮箱1 */
    result = rt_mb_init(&t1_mb,
                        "t1mb",
                        &msg_buf1[0],            /* 内存池指向 msg_pool */
                        sizeof(msg_buf1) / 4,    /* 邮箱中的邮件数目,一封邮件占用4字节 */
                        RT_IPC_FLAG_FIFO);       /* 采用FIFO方式进行线程等待 */

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

    /* 初始化邮箱2 */
    result = rt_mb_init(&t2_mb,
                        "t2mb",
                        &msg_buf2[0],            /* 内存池指向 msg_pool */
                        sizeof(msg_buf2) / 4,    /* 邮箱中的邮件数目,一封邮件占用4字节 */
                        RT_IPC_FLAG_FIFO);       /* 采用FIFO方式进行线程等待 */

    if (result != RT_EOK)
    {
        rt_kprintf("init thread2 mailbox failed.\n");
        return;
    }

    /* 初始化邮箱3 */
    result = rt_mb_init(&t3_mb,
                        "t3mb",
                        &msg_buf3[0],            /* 内存池指向 msg_pool */
                        sizeof(msg_buf3) / 4,    /* 邮箱中的邮件数目,一封邮件占用4字节 */
                        RT_IPC_FLAG_FIFO);       /* 采用FIFO方式进行线程等待 */

    if (result != RT_EOK)
    {
        rt_kprintf("init thread3 mailbox failed.\n");
        return;
    }
    rt_kprintf("mb_init ok.\n");
}

/* 邮箱测试线程,按次序收与发 */
static void thread1_entry(void *param)
{
    struct mb_msg *msg_recv_ptr1;
    struct mb_msg *msg_send_ptr1;
    char sbuf[6] = {'T', 'a', 's', 'k', '1', '.'};

    while(1)
    {
        if (rt_mb_recv(&t1_mb, (rt_ubase_t *)&msg_recv_ptr1, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 1:[recv=%s], print 1.\n", msg_recv_ptr1->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr1->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr1);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr1 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr1->data_size = sizeof(sbuf);
            msg_send_ptr1->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr1->data_size);
            rt_memcpy(msg_send_ptr1->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 1:[send=%s]\n", msg_send_ptr1->data_ptr);
            rt_mb_send(&t2_mb, (rt_uint32_t)msg_send_ptr1);
        }
    }
}

static void thread2_entry(void *param)
{
    struct mb_msg *msg_recv_ptr2;
    struct mb_msg *msg_send_ptr2;

    char sbuf[6] = {'T', 'a', 's', 'k', '2', '.'};

    while(1)
    {
        if (rt_mb_recv(&t2_mb, (rt_ubase_t *)&msg_recv_ptr2, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 2:[recv=%s], print 2.\n", msg_recv_ptr2->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr2->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr2);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr2 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr2->data_size = sizeof(sbuf);
            msg_send_ptr2->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr2->data_size);
            rt_memcpy(msg_send_ptr2->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 2:[send=%s]\n", msg_send_ptr2->data_ptr);
            rt_mb_send(&t3_mb, (rt_uint32_t)msg_send_ptr2);
        }
    }
}

static void thread3_entry(void *param)
{
    struct mb_msg *msg_recv_ptr3;
    struct mb_msg *msg_send_ptr3;
    char sbuf[6] = {'T', 'a', 's', 'k', '3', '.'};

    while(1)
    {
        if (rt_mb_recv(&t3_mb, (rt_ubase_t *)&msg_recv_ptr3, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread 3:[recv=%s], print 3.\n", msg_recv_ptr3->data_ptr);
            rt_thread_mdelay(10);
            rt_free(msg_recv_ptr3->data_ptr);
            list_mem();
            rt_free(msg_recv_ptr3);
            list_mem();
            rt_thread_mdelay(500);
            msg_send_ptr3 = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
            msg_send_ptr3->data_size = sizeof(sbuf);
            msg_send_ptr3->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr3->data_size);
            rt_memcpy(msg_send_ptr3->data_ptr, sbuf, sizeof(sbuf));
            rt_kprintf("thread 3:[send=%s]\n", msg_send_ptr3->data_ptr);
            rt_mb_send(&t1_mb, (rt_uint32_t)msg_send_ptr3);
        }
    }
}

/* 初始化并启动邮箱的测试线程 */
static void task_init(void)
{
    struct mb_msg *msg_send_ptr;
    char sbuf[6] = {'T', 'a', 's', 'k', '1', '.'};
    rt_kprintf("%s: init start!\n", __func__);
    list_mem();
    rt_kprintf("%s: init end!\n", __func__);

    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);

    rt_thread_mdelay(500);
    msg_send_ptr = (struct mb_msg *)rt_malloc(sizeof(struct mb_msg));
    rt_kprintf("%s: rt_malloc 01\n", __func__);
    list_mem();
    rt_kprintf("%s: rt_malloc 01 end\n", __func__);
    msg_send_ptr->data_size = sizeof(sbuf);
    msg_send_ptr->data_ptr = (rt_uint8_t *)rt_malloc(msg_send_ptr->data_size);
    rt_kprintf("%s: rt_malloc 02", __func__);
    list_mem();
    rt_kprintf("%s: rt_malloc 02 end\n", __func__);
    rt_memcpy(msg_send_ptr->data_ptr, sbuf, sizeof(sbuf));
    
    rt_mb_send(&t1_mb, (rt_uint32_t)msg_send_ptr);
    rt_kprintf("task_init ok.\n");
}

/* MSH命令:启动邮箱测试例程 */
int mb_test(void)
{
    mb_init();
    task_init();
    return 1;
}

MSH_CMD_EXPORT(mb_test, mb test);

 

testing method

  • Serial input: mb_test test command, start the test of the mailbox
msh >mb_test
mb_init ok.
task_init: init start!
total memory: 89568
used memory : 10656
maximum allocated memory: 10656
task_init: init end!
task_init: rt_malloc 01
total memory: 89568
used memory : 14208
maximum allocated memory: 14208
task_init: rt_malloc 01 end
task_init: rt_malloc 02total memory: 89568
used memory : 14232
maximum allocated memory: 14232
task_init: rt_malloc 02 end
task_init ok.
msh >thread 1:[recv=Task1.###### ], print 1.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 1:[send=Task1.###### ]
thread 2:[recv=Task1.###### ], print 2.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 2:[send=Task2.###### ]
thread 3:[recv=Task2.###### ], print 3.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 3:[send=Task3.###### ]
thread 1:[recv=Task3.###### ], print 1.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
maximum allocated memory: 14232
thread 1:[send=Task1.###### ]
thread 2:[recv=Task1.###### ], print 2.
total memory: 89568
used memory : 14208
maximum allocated memory: 14232
total memory: 89568
used memory : 14184
  • That the mailbox has been working normally.

 

to sum up

  • Both the mailbox and the message queue can be used for communication between threads. Compared with the message queue, the mailbox itself is more streamlined.
  • Mailbox receiving, similar to the message queue, must be placed in the thread, and the suspend thread is not received, so you can use:RT_WAITING_FOREVER
  • Familiar with the communication between threads such as mailboxes, you need to be familiar with the implementation of the kernel code, and know how to do it.

Guess you like

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