-3

I'm writing a module which contains a task with the highest priority and it should be in blocking until it receives a message from an other task the start doing its duty as a highest priority task. It uses mailbox mechanism for signaling .

My problem is I want the task -which send a signal to higher task- gets back message in blocking mode

Here is my question

should I post through mailbox 1 and then fetch from mailbox 2 or there is a better solution?

I use "FreeRTOS" if it helps

EDIT

I think I described the problem very bad

I mean do I need 2 mailbox in order to communicate between task to task or ISR to task or I can use just one mailbox with other implementation!!??

Alireza
  • 47
  • 1
  • 7
  • What are the other options for inter-task communication? – user3386109 Apr 27 '19 at 17:56
  • @user3386109 I don't know ! I'm not familiar with these . That's why I asked – Alireza Apr 27 '19 at 18:08
  • You have three and a half options: Use mailboxes if you need a small amount of data. If no data is require use semaphores. If you need munch data semaphores + shared memory. Signals (which are semaphores only with a different interface) won't work from the high-priority task to the low priority task but will work the other way around. – user6556709 Apr 27 '19 at 18:17
  • @user6556709 `Signals (which are semaphores only with a different interface) won't work from the high-priority task to the low priority task but will work the other way around` this is obviously not the truth. The priorities of the tasks means something completely different in RTOS-es than in "normal" OSes. – 0___________ Apr 27 '19 at 18:20
  • @P__J__ I know how RTOS work. But please explain to me how I'm wrong in this case: low thread: send_message_to_high(); wait_for_signal_from_high(); This won't work cause in FreeRTOS the high priority process will get unblocked immediately after the message is send and before the wait_for_signal_from_high() starts and runs until it gets in a blocking state. So the signal gets lost when the high priority thread didn't enter a blocking before it sends the signal. – user6556709 Apr 27 '19 at 18:25
  • @Alireza Then it's time to Read The Fine Manual. Asking random strangers on the internet to do your design work won't get you very far, because the random strangers don't have all of the details necessary to do the design correctly. – user3386109 Apr 27 '19 at 18:28
  • @user6556709 low priority taks will not be given any execution time before high priority one will enter the inactive mode (blocked, suspended) and vice versa. Only interrupt tasks and timer callbacks can do it but in this case you cant just use simple tasks notifications - you need to have queues for it – 0___________ Apr 27 '19 at 18:33
  • @P__J__ You don't need a queue. xEventGroupWaitBits gets you into a blocking state until the signal is emit (xEventGroupSetBits) and since it is in the backend implemented via the same semaphore mechanism as the queue it blocks and unblocks your tasks in the same way. It works perfectly. – user6556709 Apr 27 '19 at 18:42
  • If you will not in the ISR is OK and if no data is passed. If not queues are needed – 0___________ Apr 27 '19 at 18:45
  • @P__J__ For the ISR there is the exactly matching function to xQueueSendFromISR namely xEventGroupSetBitsFromISR. But I had the wrong signal mechanism in mind. In FreeRTOS the bits are stored. So will not lose the event and work in both directions. – user6556709 Apr 27 '19 at 18:46
  • SORRY GUYS !IT's been completely misunderstood!!! I EDITED it – Alireza Apr 27 '19 at 18:48
  • I advice - use standard RTOS terminology. Mailbox has many meanings. I would use queues and your problem will be sorted out – 0___________ Apr 27 '19 at 19:16

2 Answers2

1

For your edited question:

You have to use two message queues. One for each task otherwise you won't be able to wait correctly. So for your blocking message transfer, the code looks like this:

High priority task:

 while(-1){ 
  xQueueReceive(high_prio_queue, &msg, portMAX_DELAY);
  [your complex code]
  xQueueSend(low_prio_queue, &return_msg, timeout);
 }

Low priority task:

 xQueueSend(high_prio_queue, &msg, timeout);
 //will only wait if your high priority task gets blocked before sending
 xQueueReceive(low_prio_queue, &return_msg, portMAX_DELAY);

From ISR:

 xQueueSendFromISR(high_prio_queue, &msg, &unblocked);
user6556709
  • 1,272
  • 8
  • 13
  • what this anwer adds to my one? – 0___________ Apr 27 '19 at 19:15
  • if other tasks are not blocked this task will not send anything as it will not get the control – 0___________ Apr 27 '19 at 19:17
  • 1
    @P__J__ He wanted to know how many to use and why. If higher priority tasks are not blocked nothing will happen at all. That is the nice thing about RTOS but I didn't get your point. The assumption is that the low priority task will at some point gain control otherwise the whole question is meaningless. – user6556709 Apr 27 '19 at 19:22
  • It does not matter if it higher or lower priority. None of the tasks are preempted in RTOS-es (with one exeption - same prior. tasks and appropriate config definitions) – 0___________ Apr 27 '19 at 20:21
  • 2
    @P__J__ That is wrong. When a higher priority task becomes runable and a lower priority task is running it is preempt. That is a key feature of the priority-based real-time scheduler used in FreeRTOS and co. – user6556709 Apr 27 '19 at 20:30
0

It is very simple. For example queues used and the freeRTOS.

The task waits for the queue. It is in the blocked state

 while(1)
 {  
     xQueueReceive(queue, &object, portMAX_DELAY);
     ....

another task send the data to the queue.

  xQueueSend(queue, &object, timeout);

When the data is received the task is given the control. Then it checks if anything is in the queue. If not it waits in blocked state.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • Thank you for your answer ! Can I use the same object ?? Or I have to declare 2 object! It was my real question which misunderstood by everyone – Alireza Apr 27 '19 at 18:43
  • object is just the generic name. Pass the pointer to the object and queue knows the size from the initialisation. I usually pass only the pointer to avoid copying the actual data to the queue. – 0___________ Apr 27 '19 at 18:47
  • 1
    @Alireza As pointed out in the other answer you need two separate queues - one that stores data that high priority task receives and one that stores data for low priority task. If you had only one, then high priority task pushing a message into it would also later receive it (task sending data to itself). You can however re-use the same message object/struct that you push into those queues. – J_S Apr 28 '19 at 09:48