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
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:
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
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:
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
You never check if osMailAlloc() returned NULL.
Same when you in the second code sequence calls osPoolAlloc().