This article is a continuation of the Series on RT-Thread STM32 Tutorials and carries the discussion on RT-Thread RTOS and implementation with STM32. The aim of this series is to provide easy and practical examples that anyone can understand. In our last post, we have seen Mailbox in the RT-Thread RTOS. In this post, we will see the Message Queue in RT-Thread RTOS.
You can see the video explanation of Getting started with the RT-Thread RTOS.
Prerequisites
This is the continuation of the below tutorials. If you don’t read it, please read that also before this.
- RT-Thread RTOS Introduction
- Getting started with RT-Thread RTOS – Part 1
- Thread management of RT-Thread RTOS – Part 2
- Timer management of RT-Thread RTOS – Part 3
- Semaphore in RT-Thread RTOS – Part 4
- Mutex and Event in RT-Thread RTOS – Part 5
- Mailbox in RT-Thread RTOS – Part 6
Tools and Components Required
- STM32F411 Dev Board (You can use any STM32F4 controller)
- RT-Thread Studio
Inter-thread Communication in RT-Thread RTOS
If we are working in a multithreaded environment, we need to send data from one thread to another thread. There are many ways to do that. Normally we use global variables or some memory segment for that purpose. Sometimes it is hard to use global data. Because it is difficult to keep track of the messages. To make our lives easier, RTOSs are will support a few inter-thread communication methods. RT-Thread RTOS supports the below inter-thread communication methods.
- Mailbox
- Message Queues
- Signals
Message Queue in RT-Thread RTOS – RT-Thread Tutorial Part 7
Message Queue
Message Queuing is another commonly used inter-thread communication method, which is an extension of the mailbox. A queue is a FIFO (First In First Out) type buffer where data is written to the end (tail) of the queue and removed from the front (head) of the queue. A queue can either hold the data or a pointer to the data. A message queue can receive messages with unfixed lengths from threads or ISR and cache messages in their own memory space. So, the thread can put one or many messages to the queue.
Management of Message Queue
In RT-Thread RTOS, the queue supports the below operations.
- Creating/initiating a queue,
- Sending messages to the queue,
- Receive the message from the queue, and
- Deleting/detaching a queue
Creating/initiating a queue
To dynamically create a message queue object, call the following function interface:
rt_mq_t rt_mq_create(const char* name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag);
The size of this memory = [message size + message header (for linked list connection) Size] X the number of messages in the message queue.
Input parameters and return values for rt_mq_create()
Parameters | Description |
---|---|
name | The name of the message queue |
msg_size | The maximum length of a message in the message queue, in bytes |
max_msgs | The number of messages in the message queue |
flag | The waiting method took by the message queue, which can take the following values: RT_IPC_FLAG_FIFO or RT_IPC_FLAG_PRIO |
Return | —— |
RT_EOK | Sent successfully |
The handle of the message queue object | Successful |
RT_NULL | Fail |
You can use the below API to create the Static message queue.
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);
Input parameters and return values of rt_mq_init()
Parameters | Description |
---|---|
mq | The handle of the message queue object |
name | The name of the message queue |
msgpool | Pointer pointing to the buffer storing the messages |
msg_size | The maximum length of a message in the message queue, in bytes |
pool_size | The buffer size for storing messages |
flag | The waiting method is taken by the message queue, which can take the following values: RT_IPC_FLAG_FIFO or RT_IPC_FLAG_PRIO |
Return | —— |
RT_EOK | Successful |
Deleting/detaching a queue
You can use the below API to delete the dynamically created message queue (message queue which has been created using the rt_mq_create()
).
rt_err_t rt_mq_delete(rt_mq_t mq);
If you have used a static message queue (message queue which has been initialized using rt_mq_init()
), then you can use the below API to detach the message queue.
rt_err_t rt_mq_detach(rt_mq_t mq);
When deleting/detaching a message queue, if a thread is suspended on the message queue object, the kernel first wakes up all threads suspended on the queue (the thread return value is –RT_ERROR
), then releases the memory used by the queue and finally deletes/detaches the queue object.
Sending messages to the queue
We can send messages in three ways.
Send a message without waiting
The below API is used to send a message without waiting.
rt_err_t rt_mq_send (rt_mq_t mq, void* buffer, rt_size_t size);
Input parameters and return values of rt_mq_send()
Parameter | Description |
---|---|
mq | The handle of the message queue object |
buffer | Message content |
size | Message size |
Return | —— |
RT_EOK | Successful |
-RT_EFULL | A message queue is full |
-RT_ERROR | Failed, indicating that the length of the sent message is greater than the maximum length of the message in the message queue. |
If the queue is full, then this function will return an error code (-RT_EFULL
). So, we can use this function in the thread as well as in the ISR.
Send a message with waiting
Users can also send messages to specified message queues through the following function interface:
rt_err_t rt_mq_send_wait(rt_mq_t mq, const void *buffer, rt_size_t size, rt_int32_t timeout);
Input parameters and return values of rt_mb_send_wait()
Parameter | Description |
---|---|
mq | The handle of the message queue object |
buffer | Message content |
size | Message size |
timeout | Timeout |
Return | —— |
RT_EOK | Successful |
-RT_EFULL | A message queue is full |
-RT_ERROR | Failed, indicating that the length of the sent message is greater than the maximum length of the message in the message queue. |
If the queue is full, then this function will wait based on the timeout value. If the timeout expires, then it will return -RT_EFULL
. So, we cannot use this function in the ISR.
Send an emergency message
We know that Queue is a FIFO. But we can put the message also in the front. So that, the message will be delivered ASAP without waiting in the back. The below function is used to put the message into the front.
rt_err_t rt_mq_urgent(rt_mq_t mq, void* buffer, rt_size_t size);
The process of sending an emergency message is almost the same as sending a message. The only difference is that when an emergency message is sent, the message block taken from the idle message list is not put at the end of the message queue, but at the head of the queue.
Input parameters and return values of rt_mq_urgent()
Parameters | Description |
---|---|
mq | The handle of the message queue object |
buffer | Message content |
size | Message size |
Return | —— |
RT_EOK | Successful |
-RT_EFULL | A message queue is full |
-RT_ERROR | Fail |
Receive the message from the queue
To receive messages from the queue, we can use the below function. If the queue is empty, it will wait till the timeout. If the timeout expires, then it will return an error.
rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeout);
Input parameters and return values of rt_mq_recv()
Parameters | Description |
---|---|
mq | The handle of the message queue object |
buffer | Message content |
size | Message size |
timeout | Specified timeout |
Return | —— |
RT_EOK | Received successfully |
-RT_ETIMEOUT | Timeout |
-RT_ERROR | Fail, return error |
Message Queue in RT-Thread Example
In the below example, we have created the two threads. Thread 1 is incrementing the count and sending the count value to the queue. Thread 2 will be waiting for the messages in the queue. Once the message is posted by thread 1, then thread 2 will wake up and read the data, and prints it.
Source code
You can get this entire project’s source code from GitHub.
#include <rtthread.h> #define DBG_TAG "main" #define DBG_LVL DBG_LOG #include <rtdbg.h> #include <drv_common.h> #include <rtdevice.h> /* Message queue control block */ static struct rt_messagequeue *mq; static rt_thread_t threadId1 = RT_NULL; static rt_thread_t threadId2 = RT_NULL; /* Thread 1 */ static void thread1_function(void *parameter) { uint32_t count = 0; while (1) { count++; LOG_D("Thread 1: count = %d\n", count); rt_mq_send(mq, (void*)&count, sizeof(uint32_t)); rt_thread_mdelay(1000); } } /* Thread 2 */ static void thread2_function(void *parameter) { uint32_t received_message = 0; while (1) { /* Receive message from the queue */ if (rt_mq_recv(mq, &received_message, sizeof(uint32_t), RT_WAITING_FOREVER) == RT_EOK) { LOG_D("Thread2: Got a message, the message:%u\n", received_message); } } } int main(void) { /* create queue object */ mq = rt_mq_create("etx_mq", sizeof(uint32_t), 10, RT_IPC_FLAG_FIFO); if( mq == RT_NULL ) { LOG_D("Queue init failed.\n"); return -1; } /* Create thread 1 */ threadId1 = rt_thread_create("thread1_fn", //Name thread1_function, //Function address RT_NULL, //Thread function parameter 1024, //Stack Size 1, //Thread priority 2000); //Time slice in ticks /* Create thread 2 */ threadId2 = rt_thread_create("thread2_fn", //Name thread2_function, //Function address RT_NULL, //Thread function parameter 1024, //Stack Size 1, //Thread priority 2000); //Time slice in ticks /* Start both threads */ rt_thread_startup(threadId1); rt_thread_startup(threadId2); while(1); return RT_EOK; }
Queue in RT-Thread – Output
\ | / - RT - Thread Operating System / | \ 4.1.1 build Mar 8 2023 09:55:56 2006 - 2022 Copyright by RT-Thread team ←[0m[D/main] Thread 1: count = 1 ←[0m ←[0m[D/main] Thread2: Got a message, the message:1 ←[0m ←[0m[D/main] Thread 1: count = 2 ←[0m ←[0m[D/main] Thread2: Got a message, the message:2 ←[0m ←[0m[D/main] Thread 1: count = 3 ←[0m ←[0m[D/main] Thread2: Got a message, the message:3 ←[0m ←[0m[D/main] Thread 1: count = 4 ←[0m ←[0m[D/main] Thread2: Got a message, the message:4 ←[0m ←[0m[D/main] Thread 1: count = 5 ←[0m ←[0m[D/main] Thread2: Got a message, the message:5 ←[0m ←[0m[D/main] Thread 1: count = 6 ←[0m ←[0m[D/main] Thread2: Got a message, the message:6 ←[0m ←[0m[D/main] Thread 1: count = 7 ←[0m ←[0m[D/main] Thread2: Got a message, the message:7 ←[0m
In our next tutorial, we will see the signals in RT-Thread RTOS.
You can also read the below tutorials.

Embedded Software | Firmware | Linux Devic Deriver | RTOS
Hi, I’m SLR. I am a tech blogger and an Embedded Engineer. I am always eager to learn and explore tech-related concepts. And also, I wanted to share my knowledge with everyone in a more straightforward way with easy practical examples. I strongly believe that learning by doing is more powerful than just learning by reading. I love to do experiments. If you want to help or support me on my journey, consider sharing my articles, or Buy me a Coffee! Thank you for reading my blog! Happy learning!