xTaskNotifyFromISR Causing Interrupt Jitter

Hi All,

I’m currently experiencing some undesirable behaviour that I wouldn’t expect when using xTaskNotifyFromISR. Hoping someone might be able to explain why.

I have some hardware based timers on a XMC4800 generating interrupts that I’m using to control the state of some other hardware. These interrupts are time critical and must have low jitter (<1us). Therefore they have a high priority below the configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY.

I also have a lot of ADC data to process on the same device. Four ADC’s that are storing their results in their conversion complete interrupts and then I am using xTaskNotifyFromISR as an events group to hand over to a FreeRTOS task to average and convert the results. It’s worth mentioning that these interrupts have a priority lower than the configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY.

Since using xTaskNotifyFromISR to process the ADC results I have noticed considerable jitter on my high priority interrupts (5 - 10us). Removing the call from ADC result interrupt causes it to go away.

I chose to use xTaskNotifyFromISR as an events group as from what I understand it’s considerably quicker than using an actual event group. And from what I have read and understand of configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, the scheduler should not affect the interrupts with a priority greater than it. So why when I use xTaskNotifyFromISR in my ADC interrupts am I seeing my high priority interrupts performance affected.

I would like to avoid having to do all of my ADC processing in the interrupt as this is generally discouraged. Although unless I can get to the bottom of the scheduler causing the jitter I am going to be left with no choice.

Kind Regards,
Ryan

Are nested interrupts supported / used ?

Hi,

Yes nested interrupts are supported. It’s a ARM Cortex M4 based device (Infineon XMC4800).

Well, if nesting is used and the INT prios are right (which might be confusing for Cortex-M3/4) along with FreeRTOS config like configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, there should be no jitter caused by lower prio ISRs …
Maybe double check the INT related config/ NVIC config to be sure things are setup as you need.

Hi,

Thanks for the response. Just had another read of the document you suggested. I’m prity confident things are configured correctly.

I have the high priority time critical interrupts currently configured between 7 - 11.

The ADC result interrupts are between 50 - 54.

#define configPRIO_BITS 6 /* 63 priority levels */

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x3f

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x0c

#define configKERNEL_INTERRUPT_PRIORITY
( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

#define configMAX_SYSCALL_INTERRUPT_PRIORITY
( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

Hmm … looks fine.
Just to be sure: NVIC_SetPriorityGrouping is set to 0 as as recommended ?
Otherwise to be honest I’ve no idea what the problem might be :frowning:
Some guys had issues with multiple FreeRTOSConfig.h files in their project space including a wrong one, but I assume that’s not the problem in your case.

Priority grouping was set to 1. Setting it to 0 hasn’t improved things though. Is that a FreeRTOS recommendation on ensuring it is set to 0? Wasn’t aware of that.
Yes definitely only the one FreeRTOSConfig.h file included in the project.

… found it … it’s probably also documented somewhere.
in CM3/CM4F port.c - vPortValidateInterruptPriority():

...
		/* Priority grouping:  The interrupt controller (NVIC) allows the bits
		that define each interrupt's priority to be split between bits that
		define the interrupt's pre-emption priority bits and bits that define
		the interrupt's sub-priority.  For simplicity all bits must be defined
		to be pre-emption priority bits.  The following assertion will fail if
		this is not the case (if some bits represent a sub-priority).

		If the application only uses CMSIS libraries for interrupt
		configuration then the correct setting can be achieved on all Cortex-M
		devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
		scheduler.  Note however that some vendor specific peripheral libraries
		assume a non-zero priority group setting, in which cases using a value
		of zero will result in unpredictable behaviour. */
		configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );

While we’re at it. You’re using a decent FreeRTOS version with or w/o a 3rd party SDK (like ST HAL) ?

So setting the priority grouping to 0 just ensures no sub priorities can be used then? All my sub priorities are set to 0.

I using FreeRTOS V10.3.1 with the Infineon DAVE libraries.

Sorry, I didn’t use sub-priorities yet and had also no need to do so. I just followed the default route :wink:
No idea what’s going on. If the interrupt prio partitioning and FreeRTOS configuration is right, the high prio interrupts outside the FreeRTOS world/range are not affected by FreeRTOS in any way.
This could be verified the simple way by using portDISABLE_INTERRUPTS() for testing and checking if the timers are still serviced.
Are you sure that nowhere in your ADC post processing code global __disable_irq/__enable_irq are used (disable/enable ALL interrupts) ?

No worries. I also have never made use of the sub priorities, just thought it was worth mentioning that they weren’t being used in this case.
I have just run some tests using taskENTER_CRITICAL(), effectively disabling all of the interrupts lower than the MAX_SYSCALL_INTERRUPT_PRIORITY. I placed it just after where I start the timers. The timers continued to be serviced but ADC interrupts and scheduler stopped as expected. Confirming MAX_SYSCALL_INTERRUPT_PRIORITY is working as I would expect.

At the moment I have commented out all of the post processing code in the task, so the ADC result interrupts are just notifying an empty task at the moment. So defiantly no __disable_irq/__enable_irq being used in any of my code, unless the task notification itself makes use of them?

FreeRTOS code at least for CortexM3/4F/7 doesn’t globally disable interrupts and make use of the MAX_SYSCALL_INTERRUPT_PRIORITY based interrupt (BASEPRI) masking.

Turns out the jitter isn’t being caused by FreeRTOS and is actually due to the Segger Systemview source code that was in my project. I haven’t figured out yet why the Systemview integration is causing it, although removing it from the project has sorted the problem.

Thanks for reporting Ryan ! Good to know … and being warned :slight_smile:

No worries, will update if I ever get to the bottom of why. Thanks for your help.

If you think how these debuggers work on Cortex parts, a very high priority interrupt switches into firm code embedded in the processor to send the needed information out the debug port, there actions will necessarily cause some timing jitter.