玩转RT-Thread系列教程(3)--消息邮箱的使用

16 篇文章 6 订阅
14 篇文章 6 订阅

玩转RT-Thread系列教程(3)–消息邮箱的使用

一、什么是消息邮箱

邮箱服务是实时操作系统中一种典型的线程间通信方法。

RT-Thread 操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的 4 字节内容

(针对 32 位处理系统,指针的大小即为 4 个字节,所以一封邮件恰好能够容纳一个指针)。

通常来说,邮件收取过程可能是阻塞的,这取决于邮箱中是否有邮件,以及收取邮件时设置的超时时间。


1.发送邮件

当一个线程向邮箱发送邮件时,如果邮箱没满,将把邮件复制到邮箱中。如果邮箱已经满了,发送线程可以设置超时时间,

选择等待挂起或直接返回 - RT_EFULL。如果发送线程选择挂起等待,那么当邮箱中的邮件被收取而空出空间来时,等待挂起的发送线程将被唤醒继续发送。


2.接收邮件

当一个线程从邮箱中接收邮件时,如果邮箱是空的,接收线程可以选择是否等待挂起直到收到新的邮件而唤醒,或可以设置超时时间。

当达到设置的超时时间,邮箱依然未收到邮件时,这个选择超时等待的线程将被唤醒并返回 - RT_ETIMEOUT。如果邮箱中存在邮件,

那么接收线程将复制邮箱中的 4 个字节邮件到接收缓存中。


二、消息邮箱的使用

介绍完了消息邮箱,那么消息邮箱的使用场合是什么呢?邮箱是一种简单的线程间消息传递方式,特点是开销比较低,效率较高。邮箱具备一定的存储功能,能够缓存一定数量的邮件数。

接下来让我们用一段示例代码演示以下消息邮箱的使用:

1.功能设计

线程1会向线程2发送消息,线程2接收到消息存放到邮箱中并串口输出该消息,同时发送消息给线程1,线程1接收到消息存放到邮箱中并串口输出该消息。当运行完2次发送任务时,删除二者邮箱,并串口输出“Mailboxes demo finsh”。

2.代码设计
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

/* defined the LED0 pin: PB5 */
#define LED0_PIN    GET_PIN(B, 5)
/* defined the LED1 pin: PE5 */
#define LED1_PIN    GET_PIN(E, 5)

/* 邮箱控制块 */
static struct rt_mailbox mb1;
/* 用于放邮件的内存池 */
static char mb_pool1[128];

/* 邮箱控制块 */
static struct rt_mailbox mb2;
/* 用于放邮件的内存池 */
static char mb_pool2[128];

static rt_uint8_t thread2_stack[512];   					//线程栈
static struct rt_thread static_thread;			 			//线程控制块

static char mb_str1[] = "thread1 send information";
static char mb_str2[] = "thread2 send information";

int main(void)
{
    /* set LED0 pin mode to output */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    /* set LED1 pin mode to output */
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    rt_pin_mode(KEY0_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);
}

//thread1
static void dynamic_entry(void *param)
{
    char *str;
    static rt_uint8_t cnt;

    while (cnt < 2)
    {
        cnt++;

        /* 发送 mb_str1 地址到邮箱中 */
        rt_mb_send(&mb2, (rt_uint32_t)&mb_str1);
        rt_kprintf("@thread1 send mb to thread2\r\n");

        /* 从邮箱中收取邮件 */
        if (rt_mb_recv(&mb1, (rt_ubase_t *)&str, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread1: get a mail from mailbox1, the content:%s\r\n", str);
            rt_thread_mdelay(50);
        }

        rt_thread_mdelay(50);
    }

    /* 执行邮箱对象脱离 */
    if(rt_mb_detach(&mb1) != RT_EOK)
        rt_kprintf("mb1 detach fail\r\n");
}

//thread2
static void static_entry(void *param)
{
    char *str;
    static rt_uint8_t cnt;

    while (cnt < 2)
    {
        cnt++;

        /* 从邮箱中收取邮件 */
        if (rt_mb_recv(&mb2, (rt_ubase_t *)&str, RT_WAITING_FOREVER) == RT_EOK)
        {
            rt_kprintf("thread2: get a mail from mailbox2, the content:%s\r\n", str);
            rt_thread_mdelay(50);
            rt_kprintf("@thread2 send mb to thread1\r\n");

            /* 发送 mb_str2 地址到邮箱中 */
            rt_mb_send(&mb1, (rt_uint32_t)&mb_str2);
        }

        rt_thread_mdelay(50);
    }

    if(rt_mb_detach(&mb2) != RT_EOK)
        rt_kprintf("mb2 detach fail\r\n");

    rt_kprintf("Mailboxes demo finsh\r\n");
}

int MailBox_demo(void)
{

    rt_err_t result1, result2;

    /* 初始化一个 mailbox */
    result1 = rt_mb_init(&mb1,
                         "mbt1",                      /* 名称是 mbt */
                         &mb_pool1[0],                /* 邮箱用到的内存池是 mb_pool */
                         sizeof(mb_pool1) / 4,        /* 邮箱中的邮件数目,因为一封邮件占 4 字节 */
                         RT_IPC_FLAG_FIFO);           /* 采用 FIFO 方式进行线程等待 */

    if (result1 != RT_EOK)
    {
        rt_kprintf("init mailbox1 failed.\r\n");
        return -1;
    }

    /* 初始化一个 mailbox */
    result2 = rt_mb_init(&mb2,
                         "mbt2",                      /* 名称是 mbt */
                         &mb_pool2[0],                /* 邮箱用到的内存池是 mb_pool */
                         sizeof(mb_pool2) / 4,        /* 邮箱中的邮件数目,因为一封邮件占 4 字节 */
                         RT_IPC_FLAG_FIFO);           /* 采用 FIFO 方式进行线程等待 */

    if (result2 != RT_EOK)
    {
        rt_kprintf("init mailbox2 failed.\r\n");
        return -1;
    }

    //
    static rt_thread_t thread_id = RT_NULL;
    thread_id = rt_thread_create("thread1",    		//名称
                                 dynamic_entry,   //线程代码
                                 RT_NULL,         //参数
                                 512,            	//栈大小
                                 14,              //优先级
                                 20);             //时间片

    if (thread_id != RT_NULL)
        rt_thread_startup(thread_id);					 	  //线程进入就绪态
    else
        rt_kprintf("dynamic_thread create failure\r\n");

    //
    rt_thread_init(&static_thread,							//线程handle
                   "thread2",										//线程名称
                   static_entry,					  		//线程入口函数
                   RT_NULL,							    		//线程入口参数
                   &thread2_stack[0],       		//线程栈地址
                   sizeof(thread2_stack),	  		//线程栈大小
                   15, 	 								    		//线程优先级
                   10);			 							  		//线程时间片
    rt_thread_startup(&static_thread);					//线程进入就绪态

    return RT_EOK;
}

MSH_CMD_EXPORT(MailBox_demo, MailBox_demo);
3.编译、下载、查看结果

​ 通过串口数据我们不难发现,消息邮箱的运行机制,一方发送一方接收。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RT-Thread Studio是一款基于Eclipse的RT-Thread开发环境,它提供了一整套的开发工具,包括代码编辑器、编译器、调试器等,用于开发实时操作系统RTOS)上的嵌入式软件。使用RT-Thread Studio,开发者可以更高效地进行实时系统的开发和调试。以下是关于RT-Thread Studio使用的一些主要特点和介绍: 1. 集成开发环境(IDE):RT-Thread Studio提供了直观的图形界面,使开发者能够轻松地创建、编辑、编译和调试RT-Thread应用程序。 2. 代码编辑器:RT-Thread Studio的代码编辑器支持多种语言,包括C/C++,开发者可以在其中编写和编辑代码。 3. 编译器:RT-Thread Studio集成了RT-Thread的编译器,可以将编写好的代码编译成可在嵌入式设备上运行的二进制文件。 4. 调试器:RT-Thread Studio提供了强大的调试工具,允许开发者在嵌入式设备上实时观察和修改代码的运行状态,以便进行调试和优化。 5. 集成工具链:RT-Thread Studio集成了RT-Thread的开发工具链,包括交叉编译工具、下载工具、性能分析工具等,方便开发者进行整个开发流程。 6. 代码版本管理:RT-Thread Studio支持代码版本管理,如Git,方便团队进行协作开发和版本控制。 7. 实时更新和文档:RT-Thread Studio提供了实时更新的RT-Thread版本和相关文档,方便开发者获取最新的功能和信息。 8. 集成仿真器:RT-Thread Studio支持多种仿真器,如QEMU、STM32CubeMX等,方便开发者在开发过程中进行模拟和调试。 使用RT-Thread Studio进行实时系统开发的一般步骤如下: 1. 安装和配置RT-Thread Studio:根据官方文档或教程,安装并配置RT-Thread Studio环境。 2. 创建新项目:使用RT-Thread Studio创建新的实时系统项目。 3. 编写代码:在代码编辑器中编写C/C++代码,实现所需的功能。 4. 编译代码:使用RT-Thread编译器将代码编译成可在嵌入式设备上运行的二进制文件。 5. 下载和部署:使用RT-Thread Studio提供的下载工具将二进制文件部署到嵌入式设备上。 6. 调试和优化:使用RT-Thread Studio的调试工具进行实时调试和性能优化。 7. 测试和发布:对部署到嵌入式设备上的软件进行测试,确保功能正常,然后进行发布。 总的来说,使用RT-Thread Studio进行实时系统开发可以提高开发效率,简化开发流程,并有助于提高软件的质量和性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值