1 RT-Thread记录(七、IPC机制之邮箱、消息队列)-德赢Vwin官网 网
0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Thread记录(七、IPC机制之邮箱、消息队列)

矜辰所致 来源:矜辰所致 作者:矜辰所致 2022-06-22 10:06 次阅读
讲完了线程同步的机制,我们要开始线程通讯的学习,
线程通讯中的邮箱消息队列也属于 RT-Thread 的IPC机制。

目录

前言
一、邮箱
1.1 邮箱控制块
1.2 邮箱操作
1.2.1 创建和删除
1.2.2 初始化和脱离
1.2.3 发送邮件
1.2.4 接收邮件
1.3 示例(指针传递)
1.3.1 邮箱消息传递
1.3.2 邮箱个数示例
二、消息队列
2.1 消息队列控制块
2.2 消息队列操作
2.2.1 创建和删除
2.2.2 初始化和脱离
2.2.3 发送消息
2.2.4 接收消息
2.3 消息队列原理简析
2.4 示例(消息队列原理理解)
2.4.1 理解消息队列原理
2.4.2 消息传递
结语

前言

与上篇文章的介绍的信号量、互斥量和事件集,邮箱、消息队列同样为 RT-Thread IPC机制。但是信号量它们属于线程同步机制,并不能在线程之间传递消息,我们本文介绍的 邮箱、消息队列就是实现线程间消息传递的机制。

相对于上一篇文章的内容,线程通讯的学习会相对复杂些,因为涉及到消息的传递,消息在实际项目中的可能存在多种不同的情况,所以 邮箱和消息队列的使用场景和方式是关键,尤其是消息队列。基本上实际项目中的所有消息类型都可以使用消息队列的方式。消息队列应用于串口通信我会单独用一篇博文来说明,本文先做基础介绍和基本示例的讲解。

本 RT-Thread 专栏记录的开发环境:
RT-Thread记录(一、RT-Thread 版本、RT-Thread Studio开发环境 及 配合CubeMX开发快速上手)
RT-Thread记录(二、RT-Thread内核启动流程 — 启动文件和源码分析
RT-Thread 内核篇系列博文链接:
RT-Thread记录(三、RT-Thread 线程操作函数及线程管理与FreeRTOS的比较)
RT-Thread记录(四、RT-Thread 时钟节拍和软件定时器
RT-Thread记录(五、RT-Thread 临界区保护)
RT-Thread记录(六、IPC机制之信号量、互斥量和事件集)

一、邮箱

RT-Thread 中的邮件是线程、中断服务、定时器向线程发送消息的有效手段(中断和定时器需要非阻塞方式,不能等待发送,也不能接收)。

邮箱中的每一封邮件只能容纳固定的 4 字节内容(32位内核正好可以传递一个指针)。

邮箱特点 RAM空间占用少,效率较高。

RT-Thread 有点类似 FreeRTOS 的任务通知,同样的只能传递4个字节内容。
但是 FreeRTOS 的任务通知是属于任务自己的,每个任务有且只有一个通知,
而 RT-Thread 的邮箱由邮箱控制块统一管理,新建一个邮箱,可以包含多封邮件(每封4个字节)。

1.1 邮箱控制块

老规矩用源码,解释看注释(使用起来也方便复制 ~ ~!)

#ifdef RT_USING_MAILBOX
/**
 * mailbox structure
 */
struct rt_mailbox
{
    struct rt_ipc_object parent;             /**< inherit from ipc_object */
    rt_ubase_t          *msg_pool;           /**< 邮箱缓冲区的开始地址  */
    rt_uint16_t          size;               /**< 邮箱缓冲区的大小      */
    rt_uint16_t          entry;              /**< 邮箱中邮件的数目 */
    rt_uint16_t          in_offset;          /**< 邮箱缓冲的入口指针 */
    rt_uint16_t          out_offset;         /**< 邮箱缓冲的出口指针 */
    rt_list_t            suspend_sender_thread;   /**< 发送线程的挂起等待队列 */
};
typedef struct rt_mailbox *rt_mailbox_t;
#endif

1.2 邮箱操作

1.2.1 创建和删除

同以前的线程那些一样,动态的方式,先定义一个邮箱结构体的指针变量,接收创建好的句柄。

创建邮箱:

/**
参数的含义:
1、name 		邮箱名称
2、size			邮箱容量(就是多少封邮件,4的倍数)
3、flag 		邮箱标志,它可以取如下数值: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO
返回值:
RT_NULL 		创建失败
邮箱对象的句柄 	创建成功 
 */
rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)

最后的 flag 和信号量一样建议 RT_IPC_FLAG_PRIO

pYYBAGKyeReAI15XAABhZnlz4fA191.png

删除邮箱:

/**
参数的含义:
mb 	邮箱对象的句柄
返回
RT_EOK 	成功
 */
rt_err_t rt_mb_delete(rt_mailbox_t mb)

1.2.2 初始化和脱离

静态的方式,先定义一个邮箱结构体,然后对他进行初始化。

这里要注意,还要定义一个数组,用来做邮箱的内存空间,和静态初始化线程一样。

初始化邮箱:

/**
参数含义:
1、mb	 	邮箱对象的句柄,需要取自定义的结构体地址
2、name	 	邮箱名称
3、msgpool 	缓冲区指针(用户自定义的数组的地址,第一个数组元素的地址)
4、size 	邮箱容量(就是数组的大小/4)
5、flag 	邮箱标志,它可以取如下数值: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO
返回
RT_EOK 	成功
 */
rt_err_t rt_mb_init(rt_mailbox_t mb,
                    const char  *name,
                    void        *msgpool,
                    rt_size_t    size,
                    rt_uint8_t   flag)

脱离邮箱:

/**
参数的含义:
mb 	邮箱对象的句柄
返回
RT_EOK 	成功
 */
rt_err_t rt_mb_detach(rt_mailbox_t mb)

1.2.3 发送邮件

在 RT-Thread 中发送邮件分为 有无等待方式发送邮件,以及发送紧急邮件。

在我建的工程版本中,并没有发送紧急邮件函数了,这里按照工程源码来说明,就不介绍发送紧急邮件的函数了,在一般的 STM32 应用中,个人认为紧急邮件有没有都没有影响!

无等待方式适用于所有的线程和中断,等待方式不能用于中断中!

无等待发送邮件:

/**
参数:
1、mb	 	邮箱对象的句柄
2、value 	邮件内容
返回
RT_EOK 		发送成功
-RT_EFULL 	邮箱已经满了
看函数原型,其实就是把等待方式发送的时间改成了0
 */
rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value)
{
    return rt_mb_send_wait(mb, value, 0);
}

无等待发送其实就是使用等待方式发送邮件,等待时间为0。

等待方式发送邮件:

/**
参数:
1、mb 		邮箱对象的句柄
2、value 	邮件内容
3、timeout 	超时时间
返回:
RT_EOK 			发送成功
-RT_ETIMEOUT 	超时
-RT_ERROR 		失败,返回错误
 */
rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
                         rt_ubase_t   value,
                         rt_int32_t   timeout)

1.2.4 接收邮件

接收邮件时,除了指定接收邮件的邮箱句柄,并指定接收到的邮件存放位置(需要有一个变量来保存接收到的数据)。

/**
参数含义:
1、mb 		邮箱对象的句柄,从哪个邮件控制块取邮件
2、value 	邮件内容,需要用一个变量保存
3、timeout 	超时时间
返回值:
RT_EOK 	接收成功
-RT_ETIMEOUT 	超时
-RT_ERROR 	失败,返回错误
 */
rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)

1.3 示例(指针传递)

2个示例,第一个是正常的消息传递,第二个是与邮箱创建个数有关的引导示例。

1.3.1 邮箱消息传递

前面说到过,邮箱中的每一封邮件只能容纳固定的 4 字节内容,但是4字节可以传递指针,我们分别做个简单的演示。

示例中,我们使用两个不同的按键来发送邮件,通过一个事件来接收邮件,并打印收到的邮件内容。

按键key3,发送4字节的内容,按键Key2,发送一个字符串指针:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

邮件创建:

pYYBAGKyeRiAJ8cRAAAd5J9ja8E495.png

在接收线程中,我们打印出接收到的数值:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

测试结果,两个按键按下,线程不仅能收到直接传过来的4字节数据,还能通过传递的指针发送一个字符串:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_13,color_FFFFFF,t_70,g_se,x_16

1.3.2 邮箱个数示例

在上面的例子中,我们开始创建的邮箱大小就一个,我们测试下,如果没有线程接收,是不是就会打印邮箱满的消息,我们把线程接收邮箱代码注释掉,其他还是和前面测试一样:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

我们再来改一下,使用一个按键测试一下这个 size 是字节呢,还是直接是邮件个数,直接看图说明:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

在静态初始化邮件时候,我们需要注意我们开辟的空间大小,需要是4的倍数,我们一般都是用数组除以4直接表示邮箱的size大小,如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_13,color_FFFFFF,t_70,g_se,x_16

RT-Thread 是通过控制块来管理这些IPC机制,在实际测试中,为了加深对某个对象的理解,比如这里的邮箱,可以直接打印出邮箱的参数来查看当前邮箱的状态。学会测试!!!

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

二、消息队列

消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。

消息队列和邮箱的区别是长度并不限定在 4 个字节以内,但是如果如果把消息队列的每条消息的最大字节规定在4个字节以内,那么消息队列就和邮箱一样了。

典型应用,使用串口接收不定长数据(后期会单独有博文介绍消息队列在串口接收上的应用)。

2.1 消息队列控制块

消息队列控制块的这些属性,我们等会用示例来打印出来看,加深一下对这些属性的认识。

#ifdef RT_USING_MESSAGEQUEUE
/**
 * message queue structure
 */
struct rt_messagequeue
{
    struct rt_ipc_object parent;                        /**< inherit from ipc_object */

    void                *msg_pool;                      /**< 消息队列的开始地址 */

    rt_uint16_t          msg_size;                      /**< 每个消息长度 */
    rt_uint16_t          max_msgs;                      /**< 最大的消息数量 */

    rt_uint16_t          entry;                         /**< 已经有的消息数 */

    void                *msg_queue_head;                /**< list head 链表头 */
    void                *msg_queue_tail;                /**< list tail 链表尾*/
    void                *msg_queue_free;                /**< 空闲消息链表 */

    rt_list_t            suspend_sender_thread;         /**< 挂起的发送线程 */
};
typedef struct rt_messagequeue *rt_mq_t;
#endif

2.2 消息队列操作

2.2.1 创建和删除

先定义一个邮箱结构体的指针变量,接收创建好的句柄。

创建消息队列:

/**
参数:
1、name 		消息队列的名称
2、msg_size 	消息队列中一条消息的最大长度,单位字节
3、max_msgs 	消息队列的最大个数
4、flag 		消息队列采用的等待方式,它可以取如下数值: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO
返回:
RT_EOK 				发送成功
消息队列对象的句柄 	成功
RT_NULL 			失败
 */
rt_mq_t rt_mq_create(const char *name,
                     rt_size_t   msg_size,
                     rt_size_t   max_msgs,
                     rt_uint8_t  flag)

注意!msg_size 单位是字节,在32位系统中 RT-Thread 默认#define RT_ALIGN_SIZE 4 ,所以如果 msg_size 不是4字节对齐,系统会自动补全。

比如用户定义为9,那么系统会自动把消息队列大小设置为 12,定义为1,设置为4。

还有flag的使用,依然得注意一下,和邮箱信号量等一样,注意实时性问题。

删除消息队列:

/**
参数
mq 		消息队列对象的句柄
返回
RT_EOK 	成功
 */
rt_err_t rt_mq_delete(rt_mq_t mq)

2.2.2 初始化和脱离

静态的方式,先定义一个消息队列结构体,然后对他进行初始化。

初始化消息队列:

/**
参数:
1、mq 			消息队列对象的句柄,需要取自定义的结构体地址
2、name 		名称
3、msgpool 		存放消息的地址
4、msg_size 	消息队列中一条消息的最大长度,单位字节
5、pool_size 	存放消息的缓冲区大小
6、flag 		消息队列采用的等待方式,
返回:
RT_EOK 	成功
 */
rt_err_t rt_mq_init(rt_mq_t     mq,
                    const char *name,
                    void       *msgpool,
                    rt_size_t   msg_size,
                    rt_size_t   pool_size,
                    rt_uint8_t  flag)

脱离消息队列:

/**
参数:
mq 		消息队列对象的句柄
返回:
RT_EOK 	成功
 */
rt_err_t rt_mq_detach(rt_mq_t mq)

2.2.3 发送消息

和邮件一样,在 RT-Thread 中发送邮件分为 有无等待方式发送,以及紧急消息发送。

无等待方式适用于所有的线程和中断,等待方式不能用于中断中!

无等待发送消息:

/**
看函数原型,其实就是把等待方式发送的时间改成了0
参数:
1、mq 		消息队列对象的句柄
2、buffer 	消息内容
3、size 	消息大小
返回:
RT_EOK 		成功
-RT_EFULL 	消息队列已满
-RT_ERROR 	失败,表示发送的消息长度大于消息队列中消息的最大长度
 */
rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size)
{
    return rt_mq_send_wait(mq, buffer, size, 0);
}

等待方式发送邮件:

/**
除了最后多一个时间,其他参数,和上面无等待方式一样
timeout 	超时时间(时钟节拍)
*/
rt_err_t rt_mq_send_wait(rt_mq_t     mq,
                         const void *buffer,
                         rt_size_t   size,
                         rt_int32_t  timeout)

发送紧急消息:

/**
参数:
1、mq 		消息队列对象的句柄
2、buffer 	消息内容
3、size 	消息大小
返回:
RT_EOK 		成功
-RT_EFULL 	消息队列已满
-RT_ERROR 	失败
 */
rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size)

2.2.4 接收消息

接收消息时,接收者需指定存储消息的消息队列对象句柄,并且指定一个内存缓冲区,接收到的消息内容将被复制到该缓冲区里。

/**
参数:
mq 				消息队列对象的句柄
buffer 			消息内容
size 			消息大小
timeout 		指定的超时时间
返回:
RT_EOK 			成功收到
-RT_ETIMEOUT 	超时
-RT_ERROR 		失败,返回错误
 */
rt_err_t rt_mq_recv(rt_mq_t    mq,
                    void      *buffer,
                    rt_size_t  size,
                    rt_int32_t timeout)

2.3 消息队列原理简析

消息队列控制块:

要理解 消息队列 的原理,就得从他初始化的状态开始说起:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

发送消息,其实所有的步骤都是在rt_mq_send_wait函数中的,再次强调,学会看源码!

关键的几个地方说明一下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

当然这里没有特意的说明等待时间问题,因为发送和接收都可以阻塞等待,这里不是要理解的重点。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

发送完完成以后如果发现有线程在等待消息队列,会发生一次调度:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

接收消息,其实类似,可以自己查看源码,试着分析。

对于上述过程的理解,我单独写了个例子,结合例子去理解上面的步骤,更加直观!请看下面 理解消息队列原理示例。

2.4 示例(消息队列原理理解)

2个示例,第一个为了更加直观的理解消息队列原理,第二个是简单的消息传递。

对于典型的串口接收不定长度数据的示例,我会单独使用一篇文章来介绍。

2.4.1 理解消息队列原理

我们在上面 《2.3 消息队列原理简析》 分析了一下消息队列的原理,我们再来通过一个例子直观的加深一下理解。

新建一个消息队列(注意新建时候的参数):

pYYBAGKyeRyAXQOeAAAvb5BLk_Q666.png

我们2个按键,通过Key2按键发送消息:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

通过 Key3 打印 消息队列 对应的状态值:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

我们测试的时候,通过观察消息队列初始化以后的状态,然后每次发送以后观察 head,tail,free的变化情况,加深我们对消息队列的理解:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

通过上面的示例再去理解消息队列的原理,就很直观了,如果有消息接收,观察地址的变化,同样的可以分析出接收消息时候的原理。

2.4.2 消息传递

消息传递相对来说,就简单多了,直接在上面的基础上,新建一个任务接收消息(因为没有做长度识别,这里没有做解析):

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

还是通过上面的Key2按键发送消息:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_15,color_FFFFFF,t_70,g_se,x_16

结语

本文虽然只介绍了2个IPC机制,但是在项目中,它们的使用无处不在。

消息队列的应用在我们实际使用中,是很重要的,串口通信接收数据就是使用消息队列来实现。对于消息队列的串口应用,我会单独开一片博文来总结。

本文针对消息队列的实现原理给出了很好的示例,还是那句话,学会多看源码,多动手测试!

我会用心写好每一篇博文,希望大家支持!谢谢!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • IPC
    IPC
    +关注

    关注

    3

    文章

    346

    浏览量

    51897
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19675
  • RT-Thread
    +关注

    关注

    31

    文章

    1285

    浏览量

    40075
  • 消息队列
    +关注

    关注

    0

    文章

    33

    浏览量

    2972
收藏 人收藏

    评论

    相关推荐

    RT-Thread记录(一、版本开发环境及配合CubeMX)

    RT-Thread 学习记录的第一篇文章,RT-Thread记录(一、RT-Thread 版本、RT-T
    的头像 发表于 06-20 00:28 5220次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>记录</b>(一、版本开发环境及配合CubeMX)

    RT-Thread记录(二、RT-Thread内核启动流程)

    在前面我们RT-Thread Studio工程基础之上讲一讲RT-Thread内核启动流程.
    的头像 发表于 06-20 00:30 5025次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>记录</b>(二、<b class='flag-5'>RT-Thread</b>内核启动流程)

    RT-thread内核邮箱

    二、邮箱相关接口:在src/ipc.c中创建邮箱rt_mailbox_t rt_mb_create(const char *name,
    发表于 03-06 17:15

    RT-thread内核消息队列

    的所有内存中的数据就是消息的真正内容。rt-thread采用静态队列的方式来实现消息队列IPC功能的。消息头只是用来做索引功能,通过它可以索引到下一个消息头的位置。如果大家还是有些不
    发表于 03-06 17:17

    一文读懂RT-Thread操作系统的邮箱机制

    RT-Thread操作系统的邮箱有何作用?RT-Thread操作系统的邮箱机制管理数据结构是怎样的?
    发表于 02-28 08:10

    RT-Thread系统消息队列常用的函数接口有哪些

    rt_messagequeue 对象从 rt_ipc_object 中派生,由 IPC 容器所管理。消息队列的操作函数RT-Thread
    发表于 03-31 14:14

    怎样去操作RT-Thread系统的消息邮箱

    rt_ipc_object 中派生,由 IPC 容器管理。结构体 rt_ipc_object 定义如下:结构体定义中,继承关系一目了然,不再赘述。管理邮箱
    发表于 03-31 14:29

    【原创精选】RT-Thread征文精选技术文章合集

    RT-Thread记录(五、RT-Thread 临界区保护)RT-Thread记录(六、IPC
    发表于 07-26 14:56

    rt-thread邮箱-队列区别是什么?

    今天研究了下rt-thread,里面的邮箱队列,除了消息尺寸不同之外还有别的差别吗?怎么感觉像是同一种东西。
    发表于 10-31 08:29

    rt-thread 线程间同步和通信你用对了吗

    系统优化系列先停一停,总对人指指点点会让大家反感的。今天给各位 rt-thread 使用者一些使用信号量、邮箱、消息队列等同步和通信机制的...
    发表于 01-25 14:43 0次下载
    <b class='flag-5'>rt-thread</b> 线程间同步和通信你用对了吗

    RT-Thread隐藏的宝藏completion

    completion 直接翻译过来是完成,所以我更愿意称 rt_completion 为 完成量。在 RT-Thread 的文档中心 中讲线程间通讯(IPC)时,只介绍...
    发表于 01-25 19:27 0次下载
    <b class='flag-5'>RT-Thread</b>隐藏的宝藏<b class='flag-5'>之</b>completion

    RT-Thread全球技术大会:Kconfig在RT-Thread中的工作机制

    RT-Thread全球技术大会:Kconfig在RT-Thread中的工作机制               审核编辑:彭静
    的头像 发表于 05-27 14:49 1532次阅读
    <b class='flag-5'>RT-Thread</b>全球技术大会:Kconfig在<b class='flag-5'>RT-Thread</b>中的工作<b class='flag-5'>机制</b>

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 9次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    RT-Thread v5.0.2 发布

    RT-Thread 代码仓库地址: ●  https://github.com/RT-Thread/rt-thread RT-Thread 5.0.2 版本发布日志详情: ●  htt
    的头像 发表于 10-10 18:45 1464次阅读
    <b class='flag-5'>RT-Thread</b> v5.0.2 发布

    玩转RT-Thread消息队列的应用

    在嵌入式系统开发中,实时处理串口和ADC数据是一项重要的任务。本文将介绍如何在RT-Thread实时操作系统中,利用消息队列来同时处理来自串口和ADC的数据。通过这种方法,我们能够高效地管理和处理
    的头像 发表于 07-23 08:11 605次阅读
    玩转<b class='flag-5'>RT-Thread</b><b class='flag-5'>之</b>消息<b class='flag-5'>队列</b>的应用