SysTick ISR getting pended by Timer ISR (Not getting disabled)

I have configured my Timer ISR with priority 1 which also equal to configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY value so that I can notify a task every time timer ISR gets hit. But I have noticed that timer ISR was able pend when the control was inside SysTick ISR. Should I reduce my timer ISR logical prioroty in this case?

You should not need to reduce your timer priority. Can you share the code snippet of your tick handler and timer isr?

void xPortSysTickHandler( void )
{
	/* The SysTick runs at the lowest interrupt priority, so when this interrupt
	executes all interrupts must be unmasked.  There is therefore no need to
	save and then restore the interrupt mask value as its value is already
	known. */
	portDISABLE_INTERRUPTS();
  traceISR_ENTER();
	{
		/* Increment the RTOS tick. */
		if( xTaskIncrementTick() != pdFALSE )
		{
			traceISR_EXIT_TO_SCHEDULER();
			/* A context switch is required.  Context switching is performed in
			the PendSV interrupt.  Pend the PendSV interrupt. */
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
		else
		{
			traceISR_EXIT();
		}
	}
	portENABLE_INTERRUPTS();
}

void HWT_TIM0_OVF_ISR(void)
{
	xTaskNotifyFromISR(task_10ms_handler, 0U, eSetValueWithOverwrite, NULL);
    FTM_DRV_ClearStatusFlags(INST_HWT_TIM0, (uint32_t)FTM_TIME_OVER_FLOW_FLAG);
}

The trace functions are added as a patch to use it with SystemView tool to view events since this is a debug configuration of the code. In Release configuration this will be removed.

StdRetType_t HWT_TIM0_Init(void)
{
    StdRetType_t ret = FAIL;

    ftm_state_t FTM_State;
    
    /* Init FTM 0 */
    if(STATUS_SUCCESS != FTM_DRV_Init(INST_HWT_TIM0, &HWT_TIM0_InitConfig_0, &FTM_State))
    {
        return ret;
    }

    /* Init FTM 0 Counter */
    if(STATUS_SUCCESS != FTM_DRV_InitCounter(INST_HWT_TIM0, &HWT_TIM0_TimerConfig_0))
    {
        return ret;
    }

    /* Init FTM 0 Start Counter */
    if(STATUS_SUCCESS != FTM_DRV_CounterStart(INST_HWT_TIM0))
    {
        return ret;
    }

    /* Installing Interrupt Handler */
    INT_SYS_InstallHandler(FTM0_Ovf_Reload_IRQn, HWT_TIM0_OVF_ISR, 0);
    INT_SYS_SetPriority(FTM0_Ovf_Reload_IRQn, 1U);
    INT_SYS_EnableIRQ(FTM0_Ovf_Reload_IRQn);

    ret = PASS;

    return ret;
}

This is my Timer Init func. I’m assigning it a priority of 1 because,
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ( 1 )

Nothing here seems unexpected. Which hardware are you using? Which FreeRTOS version and port are you using?

S32K144 - ARM Cortex-M4F Core
FreeRTOS 10.2.1

I’m not sure I understand the question. Sounds like you noticed your high-priority timer ISR being delayed (interrupt pending) while the SysTick ISR executes, even though the SysTick has a lower priority. If so, that behavior is expected because the SysTick ISR masks higher-priority interrupts.

Once the SysTick ISR unmasks interrupts (near the end of the ISR), your high-priority timer ISR will execute, and FreeRTOS will give control to your notified task upon return from all the interrupts (assuming your notified task is the highest priority task ready to execute and preemption is enabled etc.) So potentially everything is OK here.

Sorry if I have posed the question wrongly… I meant that my Systick was overrun by my timer ISR which should not have happened because Systick disables all interrupts. I found this by adding small trace functions inside critical sections of the kernel such as places where the tasks are inserted and removed out of lists (both ready task list and delayed task list). So during Systick execution xtaskincrementTick() Api found out that my Task timeout got expired and removed it from the delayed task list. But before it could place the task onto ready task list, it was overrun by my Timer ISR which notifies the task which in turn tried to remove the task from Delayed list but only this time the task is not there on any list hence imprecise exception got raised.

Oh I see.

Do you have configASSERT defined? If so, the port layer should automatically catch any misconfiguration related to configMAX_SYSCALL_INTERRUPT_PRIORITY. See this function, which is called from inside the …FromISR() API functions.

Yes I have configASSERT defined in Config header. It did not throw error because I have configured my interrupt priority to be equal to
configLIBRARYMAXSYSCALLINTERRUPTPRIORITY which is 1

Can you share your definition of configMAX_SYSCALL_INTERRUPT_PRIORITY (not the one with ‘LIBRARY’ in it).

Also can you check in the debugger what happens here? What is the value assigned to ucMaxSysCallPriority?

Hi, sorry for the late reply.
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8-configPRIO_BITS))

configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY = 1
configPRIO_BITS = 4

ucMaxSysCallPriority = 240 (Decimal)

Could you kindly explain me the difference between configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY and configMAX_SYSCALL_INTERRUPT_PRIORITY

I wonder if maybe you mistakenly looked at the value of ucMaxPriorityValue instead of ucMaxSysCallPriority. 240 (0xF0) is the expected value for ucMaxPriorityValue if your S32K MCU implements 4 priority bits.

Based on the above, we should expect a value of 0x10 (decimal 16) for ucMaxSysCallPriority. Can you double check?

Yes you are right, ucMaxSysCallPriority is 16 (decimal)
S32K144 uses only 4bits for priority. No sub-priority is used.

Finally the issue was solved with the help of @aggarg. It was due trace APIs trying to modify the BASEPRI register which made the timer interrupt to fire when inside the SysTick ISR.
This was solved by setting SEGGER_RTT_MAX_INTERRUPT_PRIORITY to configMAX_SYSCALL_INTERRUPT_PRIORITY

1 Like