RTT-邮箱

本文介绍了RTT-邮箱的基本概念及使用方法,包括邮箱的创建、发送与接收邮件的操作,并通过示例展示了如何在实际应用中实现消息传递。

RTT-邮箱

概念

邮箱是特别的消息队列
邮箱中每个邮件的长度固定,是4个字节
如果是大的buff,直接发送地址

接口

创建静态邮箱

rt_err_t rt_mb_init (rt_mailbox_t mb, const char *name, void *msgpool, rt_size_t size, rt_uint8_t flag)

删除静态邮箱

rt_err_t rt_mb_detach (rt_mailbox_t mb)

创建动态邮箱

rt_mailbox_t rt_mb_create (const char *name, rt_size_t size, rt_uint8_t flag)

删除动态邮箱

rt_err_t rt_mb_delete (rt_mailbox_t mb)

发送邮件

rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value)

接收邮件

rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t *value, rt_int32_t timeout)

用法

  1. 定义邮箱控制块
  2. 创建邮箱对象
  3. 发送邮件
  4. 接收邮件
/* 定义线程控制块指针 */
static rt_thread_t receive0_thread = RT_NULL;
static rt_thread_t receive1_thread = RT_NULL;
static rt_thread_t send_thread = RT_NULL;
/* 定义邮箱控制块 */
static rt_mailbox_t test_mail = RT_NULL;

char test_str1[] = "this is a mail test 1";/* 邮箱消息test1 */
char test_str2[] = "this is a mail test 2";/* 邮箱消息test2 */

/* 创建一个邮箱 */
    test_mail = rt_mb_create("test_mail", /* 邮箱名字 */
                             10,
                             RT_IPC_FLAG_FIFO);/* 信号量模式 FIFO(0x00)*/
if (test_mail != RT_NULL)
	rt_kprintf("creat mb success\n\n");

static void receive0_thread_entry(void *parameter)
{
    rt_err_t uwRet = RT_EOK;
    char *r_str;
    /* 任务都是一个无限循环,不能返回 */
    while (1)
    {
        /* 等待接邮箱消息 */
        uwRet = rt_mb_recv(test_mail, /* 邮箱对象句柄 */
                           (rt_uint32_t *)&r_str, /* 接收邮箱消息 */
                           0);/* 指定超时事件,一直等 */

        if (RT_EOK == uwRet) /* 如果接收完成并且正确 */
        {
            rt_kprintf("rev0:%s\n\n", r_str);
        }
        // else
        //     rt_kprintf("mb0 failed:0x%x\n", uwRet);
        
        rt_thread_delay(10);
    }
}

static void receive1_thread_entry(void *parameter)
{
    rt_err_t uwRet = RT_EOK;
    char *r_str;
    /* 任务都是一个无限循环,不能返回 */
    while (1)
    {
        /* 等待接邮箱消息 */
        uwRet = rt_mb_recv(test_mail, /* 邮箱对象句柄 */
                           (rt_uint32_t *)&r_str, /* 接收邮箱消息 */
                           0);/* 指定超时事件,一直等 */

        if (RT_EOK == uwRet) /* 如果接收完成并且正确 */
        {
            rt_kprintf("rev1:%s\n\n", r_str);
        }
        // else
        //     rt_kprintf("mb1 failed:0x%x\n", uwRet);
        
        rt_thread_delay(10);
    }
}

static void send_thread_entry(void *parameter)
{
    rt_err_t uwRet = RT_EOK;
    /* 任务都是一个无限循环,不能返回 */
    while (1)
    {
        //如果KEY1被单击
        if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON)
        {
            rt_kprintf("KEY0\n");
            /* 发送一个邮箱消息1 */
            uwRet = rt_mb_send(test_mail, (rt_uint32_t)&test_str1);
            if (RT_EOK == uwRet)
                rt_kprintf("mb0 send success\n");
            else
                rt_kprintf("mb0 send failed\n");
        }
        //如果KEY2被单击
        if (Key_Scan(KEY2_GPIO_PORT, KEY2_GPIO_PIN) == KEY_ON)
        {
            rt_kprintf("KEY1\n");
            /* 发送一个邮箱2 */
            uwRet = rt_mb_send(test_mail, (rt_uint32_t)&test_str2);
            if (RT_EOK == uwRet)
                rt_kprintf("mb1 send success\n");
            else
                rt_kprintf("mb1 send failed\n");
        }
        rt_thread_delay(20);     //每20ms扫描一次
    }
}

### RT-Thread 邮箱队列的配置与状态解决方案 RT-Thread 是一个实时嵌入式操作系统,其内核提供了多种同步和通信机制,其中包括邮箱队列。邮箱队列是一种用于线程间通信的消息传递方式,允许发送方将消息放入队列中,接收方从中取出并处理[^4]。 #### 1. **邮箱队列的基础概念** 在 RT-Thread 中,邮箱队列是一个存储固定大小数据项的容器,通常用来在线程之间传输少量的数据或指针。它的主要特点是轻量化、高效以及适合小型嵌入式系统的资源约束条件。通过 `rt_mq_t` 类型定义邮箱队列对象,并利用一系列 API 进行初始化、控制和销毁操作。 #### 2. **邮箱队列的配置方法** 为了正确使用邮箱队列,需要完成以下几个方面的配置: ##### (1) 初始化邮箱队列 可以通过调用函数 `rt_mq_init()` 或者宏 `RT_MQ_INIT()` 完成邮箱队列的初始化工作。以下是具体的参数说明: - 参数一:指向邮箱队列结构体实例; - 参数二:指定名称字符串; - 参数三:缓冲区起始地址; - 参数四:每条消息长度(单位字节); - 参数五:最大消息数目; - 参数六:标志位集合(如 FIFO 模式或其他特殊选项)。 示例代码如下所示: ```c #include <rtthread.h> #define MQ_NAME "testmq" #define MSG_SIZE sizeof(int) #define MSG_COUNT 5 static struct rt_messagequeue mq; char msg_pool[MSG_SIZE * MSG_COUNT]; int init_mailbox_queue(void){ /* Initialize the message queue */ if(rt_mq_init(&mq, MQ_NAME, msg_pool, MSG_SIZE, MSG_COUNT, RT_IPC_FLAG_FIFO)){ rt_kprintf("Message Queue initialization failed.\n"); return -1; } rt_kprintf("Message Queue initialized successfully.\n"); return 0; } INIT_APP_EXPORT(init_mailbox_queue); ``` ##### (2) 发送消息至邮箱队列 使用 `rt_mq_send()` 函数向目标邮箱队列发送一条新消息。如果当前没有足够的空间容纳新的消息,则可以选择阻塞或者立即返回错误码。 ```c /* Send a integer value to mailbox queue */ int send_value_to_mq(){ int data = 123; if(rt_mq_send(&mq, &data, sizeof(data)) != RT_EOK){ rt_kprintf("Failed to send data into Message Queue\n"); return -1; } rt_kprintf("Data sent to Message Queue successfully.\n"); return 0; } ``` ##### (3) 接收来自邮箱队列的消息 同样地,可以借助 `rt_mq_recv()` 方法从已有的邮箱队列里提取待处理的信息。如果没有可用的消息存在,默认情况下会进入等待状态直到超时时间到达为止。 ```c /* Receive an integer from mailbox queue */ void receive_data_from_mq(){ int received_data; if(rt_mq_recv(&mq,&received_data,sizeof(received_data),RT_WAITING_FOREVER)!=RT_EOK){ rt_kprintf("Error occurred while receiving data from Message Queue!\n"); return ; }else{ rt_kprintf("Received Data:%d \n",received_data ); } } ``` #### 3. **常见问题及解决方案** **(a)** 如果发现无法正常创建邮箱队列,请确认系统堆栈是否有足够剩余容量来满足需求。此外还需要注意是否重复命名引起冲突等问题^。 **(b)** 当频繁发生丢弃现象时,可能是因为生产速度远高于消费速率造成的积压情况。此时建议适当增加缓存池尺寸或是优化业务逻辑减少不必要的交互频率^. **(c)** 对于某些特定应用场景下要求严格顺序保障的话,则应该选用具备FIFO特性的实现版本而非其他变种形式^.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tangYi0_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值