Fire a lot of Notification from ISR

In my project I have a rotary encoder and every time one of my GPIO pins detect a up or down change it goes to its ISR() function.

//temporarily debounce

xTaskNotifyFromISR( TaskLcdTimerHandle, rotary_tick(), eSetValueWithOverwrite, NULL );
//always clear both flags


The function rotary_tick() returns 0=invalid 1=right turn 2=left turn

I somehow miss a lot of notifications when I turn the knob fast.
This solution might also a bit resource heavy for a 8bit atmega4809

Does my task ignore notifications when it is still busy handling an incoming notification?

Notifications don’t queue up so there won’t be a backlog.

If you use eSetValueWithOverwrite then you will just overwrite the notification value of the receiving task. You could do something different, such as send the values to an array, then use a task notification to unblock the task that will then drain all the values from the array.

Additionally, as you are not using the last parameter the interrupt service routine is not going to return directly to the task you just sent the notification to (assuming that is the highest priority task) - and only switch when the currently executing task blocks or yields - in the worst case the task you sent a notification to won’t run until the next tick interrupt.

So filling a global array inside the ISR()?
But when do you send out the notification?

What I maybe can do is keep collecting ticks inside the ISR() when the ticks are close to each other time wise. If time between ticks is larger, then send out the notification with a eSetValue build like ((leftturn<<7)&amountTicks)

To me this sounds as if you’re better off using mailboxes (queues with payload), that’s a classic use case. You can even put some “intelligence” in the architecture as Richard suggests, ie collate messages if they come in too quickly, might be worth considering in your case (eg if the user turns the knob left and right as a finger stretching excersize, there’s no point in sampling every single movement).

Did you already measure if your MCU is or is not fast enough to cope with the worst case interrupt rate ? You know, if it’s just a knob a human turns, your interrupt rate is rather slow and you could simply just signal a notification and do the rest in the signaled task.
Or maybe use your approach with decoding in the ISR.

Rotary encoders typically suffer from contact bouncing, so they generate lots of interrupts unless the external hardware or MCU provides hardware debouncing. I prefer to poll them either from a timer task, or from the systick ISR, or from a main loop if there is one and it executes predictably enough. The polling routine is short and updates variables that record the movement. The code I use is in the two RotaryEncoder files at RepRapFirmware/src/Display at 3.3-dev · Duet3D/RepRapFirmware · GitHub.

I measured the debounce effect in a earlier prototype and have some hardware filtering for that now.

So it does work, but not fast enough at the moment.
When you fast turn our rotary ring, the timer is updated but not incremented as much as you would expect