PIC32 Core Timer and xTimerCreate()

Hello

I am working on PIC32MZ2064DAB169 and for delay in application I am using Core Timer that is a built-in timer. The delay function is implemented as follows:

void Core::Delay(uint64_t msecs)
{
    uint64_t curTicks;

    curTicks = m_Milliseconds;    
    while ((m_Milliseconds - curTicks) < msecs);
}

The delay function works fine, I have tested it by flashing the LED with the delay of 1 second. The problem arises when I call the xTimerCreate() function to create a software timer, when I call xTimerCreate the delay function stops working and stuck in while loop. It happens right after it, delay works before xTimerCreate() and stop working after it.

m_Milliseconds is a volatile variable to avoid optimization side effect.

I am not able to debug the issue since software timers has nothing to do with hardware timers . Help is greatly appreciated.

Regards
Ahmad Naeem

Is the scheduler started when you call xTimerCreate? If not, the reason may be that the timer ISR is masked and will be unmasked when you start the scheduler. If your timer ISR does not call any FreeRTOS API, you can set its priority higher than configMAX_SYSCALL_INTERRUPT_PRIORITY so that it is not impacted by FreeRTOS critical sections.

You should also look into using vTaskDelay instead of busy waiting to avoid wasting CPU cycles.

Thank you for your reply @aggarg. No the scheduler was not started when this happens. This happens in initialization of my system where I have not started the scheduler yet. Let me confirm if the timer ISR has stopped working…

@aggarg I have checked, the interrupt handler of core timer has stopped working. I have started the Core Timer again but it didn’t work. I have checked its priority as well, it is highest, problem is something else.

what is your mcu’s interrupt mask when the routine is stuck? I suspect some code executed a cpsid, disabling all interrupts.

What is the value of configMAX_SYSCALL_INTERRUPT_PRIORITY?

@aggarg #define configMAX_SYSCALL_INTERRUPT_PRIORITY (3)

@RAc I am checking the values of interrupt mask, I will let you know.

@RAc I couldn’t find interrupt mask register for this particular microcontroller. However when the code gets stuck in delay, my button interrupt doesn’t work.

This only happens when I call delay function after xTimerCreate. If I don’t call delay function after xTimerCreate everything works fine.

How did you check this? Also, are you using this FreeRTOS port - https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/main/portable/MPLAB/PIC32MZ?

I have assigned the highest priority to core timer that is 1, the FreeRTOS port that I am using comes with MPLAB, I have just enabled it as third part libraries and my MPLAB provided me that FreeRTOS port along with other project files.

The following is from the PIC32 FRM -

The user-selectable priority levels range from 1 (the lowest priority) to 7 (the
highest).

So, I think 1 is not the highest priority.

Can you check that the port uses configMAX_SYSCALL_INTERRUPT_PRIORITY to only disable interrupts upto this priority like this - https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/portable/MPLAB/PIC32MZ/portmacro.h#L101?

@aggarg I am sorry that was a typ0, it is 7 the priority of core timer is set to 7.

let me confirm please

hello @aggarg I have checked my portmacro.h Following is the chunk of code you are referring from this file.

#ifdef configASSERT
	#define portDISABLE_INTERRUPTS()											\
	{																			\
	uint32_t ulStatus;															\
																				\
		/* Mask interrupts at and below the kernel interrupt priority. */		\
		ulStatus = _CP0_GET_STATUS();											\
																				\
		/* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */	\
		if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \
		{																		\
			ulStatus &= ~portALL_IPL_BITS;										\
			_CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \
		}																		\
	}
#else /* configASSERT */
	#define portDISABLE_INTERRUPTS()										\
	{																		\
	uint32_t ulStatus;														\
																			\
		/* Mask interrupts at and below the kernel interrupt priority. */	\
		ulStatus = _CP0_GET_STATUS();										\
		ulStatus &= ~portALL_IPL_BITS;										\
		_CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \
	}
#endif /* configASSERT */

Note: configASSERT is not defined in my project.

Hello! The update is, the delay function starts working after the scheduler is started, so some thing happens when the xTimerCreate functions is called which hinders the correct working of delay function, and that thing disappears after the scheduler is started. Now the question is what is that thing!!!

Again, globally disabled interrupts appear to be a hot candidate. When the scheduler starts, interrupts are enabled.

@RAc I have enabled the global interrupts right after calling the xTimeCreate but it didn’t help.

Does your button interrupt work in between the call to xTimerCreate and scheduler start?

@RAc I have put portENABLE_INTERRUPTS(); after xTimerCreate and everything starts working. You were right interrupts was disbaled.

Now that it is working, my question is, is it safe or a good approach to put portENABLE_INTERRUPTS(); right after xTimerCreate is called. I mean manually enabling interrupt with portENABLE_INTERRUPTS() would be ok???

The reason the interrupts are disabled is that it is an error for an ISR to attempt a scheduler operation before it is started, so as a preventive measure, they are disabled in many FreeRTOS functions called before the scheduler is started.

Normally, an application shouldn’t be needing interrupts during this initialization time, things that need interrupts tend to be held off until after the scheduler is started.