High priority notify processing while in loop and multiple unrelated notifications in queue

I have a task that when it reaches a loop it needs to process that loop few hundreds or sometimes even thousands of times as fast as possible (allowing for some basic notification processing).

To be more specific, I have printing nozzles that need to fire very fast and in a synchronised manner because the drum is rotating at a constant (high) speed and cannot be slowed down. That loop takes care of that and is increased in priority while in the loop (i.e. increased before the loop start and decreased when the loop completes).

While in the loop the task can receive many different types notifications from other tasks. but only one or two emergency notifications are allowed to stop the loop.

  1. What is the best way to implement this with:
    a) minimal time wasting in the loop AND
    b) without having to process and discard (effectively lose) other prior notifications that are in the task queue

  2. Do I have to have a taskNotifyTake() inside the loop every cycle?

  3. how can I check and extract only the “emergency” notification that might be 5 or 10 positions down the queue qithout loosing the previous ones which will need to be processed later on when outside the loop?

Thank you :slight_smile:

Hi Rik,

one thing you need to take into consideration is that even though your task may have highest task priority, it is still subject to being starved by interrupts. If you really need hard real time, you must either disable interrupts during the processing of your loop, or execute the time critical loop in a high priority interrupt itself.

Be aware, also, that you are contradicting yourself. Whatever thread of execution your high pri loop runs in, it can by definition not receive notifications from other tasks because those other tasks, not being able to run while the loop runs under hard real time constrains, can not send those notifications.

Thank you RAc,
you are correct. I will have to then keep the same priority.

Regarding the interrupts, yes that could happen but they are not that frequent. The main thing is while in that loop be able to the process ONLY the “emergency” notification regardless of which position in the queue immediately AND without loosing the other notifications what are in front of such “emergency” notification.

What is the best way to implement that?

Thank you:)

I may not be understanding the entire issue. You mention the taskNotifyTake() which uses the direct task notification system. This is very fast and does not use a queue so there are never any queued notifications. If you are using an event queue then that is certainly slower and will hold a number of outstanding events. If you separate the fast events from the normal events by using direct task notifications (perhaps as an event group) for the high priority events and a queue for the normal events you could choose to ignore the queue during the fast updates.

Another option using only the queue would be to place your important events at the front of a queue using the xQueueSendToFront() and your normal events at the back using xQueueSendToBack(). This makes a simple priority queue with 2 priorities. In stead of using xQueueReceive() you could use xQueuePeek() to just check the front of the queue and see if you care about that message. You know that important stuff will alway be there so you never need to scan the queue.
This has the advantage over my previous suggestion because you only look in one place for all your events. The downside is queue handling is still slower than task notifications.

Thank you Joseph ! :slight_smile:
I’m new to freeRTOS so I might be confusing things.

Perhaps taskNotifyTake() is not the right way to implement it. I just re-read the taskNotifyTake() page and the lowest timeout is obviously 1 tick which in my application is 1ms and way too long to wait.

Also when I mentioned queue I was referring to the task notification queue. My understanding is that every task has a built-in queue of incoming notifications as basic/essential functionality. Or am I missing (or misreading/misunderstanding) something in the way tasks work?

So perhaps there is another way to implement it?

Ideally I want a single line of code that is read every cycle of the loop. And either executing the emergency procedure if such notification is present or, if no emergency notification had been sent to the task, then immediately execute the following instructions (i.e. NOT waiting a whole 1 millisecond tick).

Could you provide me some pointers as I might be misunderstanding either your previous suggestions and/or basic concepts/functionality of freeRTOS.

Thank you again! :slight_smile:

For example:

	    for (i=0; i<10000, i++)
    		//here check if an emergency notification of some sort is present taking only 
			//few instructions to check. If emergency notification is present then can exit the loop
			//and subsequent timing is not an issue because the system is halted

Who sets this emergency notification? What stops you from using an integer?

	    for (i=0; i<10000, i++)
            if( emergencyNotificationPresent != 0 ) break;


Thank you Gaurav,
the notification is sent by another task when a switch is pressed.

What do you mean by “What stops you from using an integer?”?

That line you suggested:

if( emergencyNotificationPresent != 0 ) break;

would need to have way of continuously checking for the notification to set the variable emergencyNotificationPresent. Would it not? And that variable assignment would need to be inside the loop, would it not?

Thank you :slight_smile:

You can also pass 0 to the notificationTake while will not block for any time. It will simply check for a notification and return.

In the case of the emergencyNotificationPresent example, the assumption is an ISR would set the variable. We make that assumption because no other task could post a taskNotification or Queue an event with this task being the highest priority. You are left with an interrupt.

Of course, you could simply poll the GPIO button inputs and directly handle the emergency input without any other task features.

I think the idea of the integer is that this is a global variable, so whoever would send the ‘emergency notification’ could instead just set the variable.

I would NOT use notifications for something that I don’t intend to block for, that is the primary purpose of them. Things you check as you pass are just global flags.

Thank you Richard and Joseph! :slight_smile: