Dear all,
I am using Keil Microvision IDE v5.16 and CMSIS Keil RTX RTOS. Our microcontroller is STM32F4xx. In the CMSIS RTOS API, message queue and mail queue inter-thread communication mechanisms are mentioned. Even after reading the documentation, we are still confused of its differences / benefits of one over other / usage scenarios of both.
Only difference we feel are:-
1. In message queue, 32 bit integer or a pointer value is being transferred. Message queue make use of Memory pool APIs to allocate and free memory inside message queue.
2. In mail queue, instead of using memory pool APIs, memory blocks can be created directly using mail APIs.
Both message queue and mail queue seems to have queueing property. But in mail queue, we didn't find any error code corresponding to mail queue full or mail queue empty state while trying to put a mail to the queue.
Can anyone differentiate mail queue and message queue, its benefits and usage scenario in detail as CMSIS Keil RTX documentation / CMSIS RTOS API documentation seems to create severe confusion in developers regarding the same. Also it is very difficult to simulate an exact feasibility study for this selection as only in our final application actual factors can be simulated such as CPU load, OS scheduling times etc.
Is it possible to mix and use mail queue and message queue in a single application?
Thank you, Lullaby Dayal
You can use both in an app.
If you have a queue of linked - allocated - memory bloks then the queue itself can't go full. You can only fail to allocate more blocks to enqueue.
If you have a queue of 32-bit values, then the queue is an array of a fixed size. And you decide if the 32-bit value is an integer (event number or maybe received UART character) or if it is a 32-bit pointer to a memory block that the sender somehow allocated.
Thank you for the reply.
But I still have some queries in my mind.. Trying to understand what exactly is the difference among mail queue and a message queue. Reiterating my understanding with excerpts from CMSIS Keil page examples....
[Lullaby] >> By this queue, you mean a mail queue, right? If that is the case, both message queue and mail queue can allocate more blocks even though in their definition, we need to give a queue size.
My understanding as per the CMSIS Keil RTX example page for mail queue is:-
typedef struct { // Mail object structure float voltage; // AD result of measured voltage float current; // AD result of measured current int counter; // A counter value } T_MEAS; osMailQDef(mail, 16, T_MEAS); // Define mail queue
Here 16 is the queue size of mail queue, right?
Then from one thread, we will do a mail alloc, set mail content and put the mail to queue. From another thread, we will get the mail, process it and free the mail allocated. This process can happen any number of times.
Thread 1:-
mptr = osMailAlloc(mail, osWaitForever); // Allocate memory mptr->voltage = 223.72; // Set the mail content mptr->current = 17.54; mptr->counter = 120786; osMailPut(mail, mptr); // Send Mail
Thread 2:-
evt = osMailGet(mail, osWaitForever); // wait for mail if (evt.status == osEventMail) { rptr = evt.value.p; osMailFree(mail, rptr); // free memory allocated for mail
So my query regarding Mail queue is:-
1. When this mail queue becomes full? What is the significance of queue size value in a mail queue? As I am allocating block from a mail queue itself, and if my only error expected is the mail alloc failure, then what is the usage of queue size?
2. There is no mention about mail queue getting full in the documentation of any of these mail related APIs.. Please share your thoughts on this..
[Lullaby] >> My understanding as per the CMSIS Keil RTX example page for message queue is:-
typedef struct { // Message object structure float voltage; // AD result of measured voltage float current; // AD result of measured current int counter; // A counter value } T_MEAS; osPoolDef(mpool, 16, T_MEAS); // Define memory pool
Here 16 is the queue size of message queue, right?
Then from one thread, we will do a pool alloc, assign values and put the message to queue. From another thread, we will get the message from queue, process it and free the pool. This process can happen any number of times.
mptr = osPoolAlloc(mpool); // Allocate memory for the message mptr->voltage = 223.72; // Set the message content mptr->current = 17.54; mptr->counter = 120786; osMessagePut(MsgBox, (uint32_t)mptr, osWaitForever); // Send Message
evt = osMessageGet(MsgBox, osWaitForever); // wait for message if (evt.status == osEventMessage) { rptr = evt.value.p; osPoolFree(mpool, rptr);
So my query regarding Message queue is:-
1. When this message queue becomes full? What is the significance of queue size value in a message queue? As I am allocating memory from a pool, and if my only error expected is the pool alloc failure, then what is the usage of queue size?
2. In the documentation of osMessagePut(), it is mentioned "When the message queue is full, the system retries for a specified time with millisec." Does it mean:- message queue can be full in some cases.. When it will be full? When no memory available for allocation or when queue size is crossed?
2. Now could you please explain what is the real difference between a mail queue and message queue?
Thank you, Lullaby
Your mail queue can get full - it's just that it gets full in a different way.
From osMailAlloc() documentation: "A NULL pointer is returned when no memory slot can be obtained or queue specifies an illegal parameter. "
So with mails, you allocate a mail, and that allocation can fail.
But if osMailAlloc() didn't fail, then osMailPut() should be able to handle this mail - assuming you haven't some other parameter errors, or maybe have sneaked in a osMailFree() or similar.
From documentation:
typedef struct { // Mail object structure float voltage; // AD result of measured voltage float current; // AD result of measured current int counter; // A counter value } T_MEAS; osMailQDef(mail, 16, T_MEAS); // Define mail queue osMailQId mail;
The above code does allocate 16 measurement objects - so before you can get the 17:th call to osMailAlloc() to give back a new T_MEAS object, you need to first release at least one of the previous 16 with a call to osMailFree().
With a message box, the message box itself does not allocate any actual objects. You need to decide for yourself if you are just going to insert integers or if you are going to create some different means to allocate objects, allowing you to insert memory pointers into the message queue.
This means that there is no osMessageAlloc() function that will decide if there is room for one more message. It's the actual osMessagePut() function that will have to return osErrorResource if the message queue is full.
So the important thing is that with mailboxes, it's the allocation of a mail that is the operation that reports if you have reached the limit. With message boxes it's the attempt to insert the message that will report if the queue is full.
So back to the code you posted:
The osPoolAlloc() function could potentiall allow the allocation of 100 objects - that depends on the osPoolDef(). While your code might have put a limit of 10 entries for the osMessagePut() function - controlled by the separate osMessageQDef().
With a mail queue, you don't get a chance to specify 2 different sizes for queue and for memory pool, since the mail queue owns the memory pool. Hence, the need for error reporting is different - you have a different call sequence to add entries for the two queue types.
Just one more thing - you posted the code:
You never check if osMailAlloc() returned NULL.
Same when you in the second code sequence calls osPoolAlloc().