pstepien wrote on Tuesday, February 09, 2016:
Systick interrupt should be at lowest possible level but indeed through its implementation it is at the highest system level by using portSET_INTERRUPT_MASK_FROM_ISR/portCLEAR_INTERRUPT_MASK_FROM_ISR at entry/exit and thus masking interrupts using rtos api for all the systick isr routine execution where only during tasks list manipulation it should mask/unmask interrupts
(FreeRTOS V8.2.3) Source\portable\GCC\ARM_CM4F\port.c:
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. */
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
}
When taking a look into xTaskIncrementTick we see that there is code that does delayed tasks list manipulation, removing woken tasks from blocked state list and event waiting lists, adding to ready list
1. delayed tasks list manipulation may be executed only from thread so does not need to be inside citical section (under masked interrupts) (bad idea, maybe done in isr)
2. only removing woken tasks from blocked state list and event waiting lists and adding to ready list should be inside critical section (under masked interrupts)
(FreeRTOS V8.2.3) tasks.c:
for( ;; )
{
<---- begin critical section here
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{
/* The delayed list is empty. Set xNextTaskUnblockTime
to the maximum possible value so it is extremely
unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass
next time through. */
xNextTaskUnblockTime = portMAX_DELAY;
<---- end critical section here
break;
}
else
{
/* The delayed list is not empty, get the value of the
item at the head of the delayed list. This is the time
at which the task at the head of the delayed list must
be removed from the Blocked state. */
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
if( xConstTickCount < xItemValue )
{
/* It is not time to unblock this item yet, but the
item value is the time at which the task at the head
of the blocked list must be removed from the Blocked
state - so record the item value in
xNextTaskUnblockTime. */
xNextTaskUnblockTime = xItemValue;
break;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* It is time to remove the item from the Blocked state. */
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? If so remove
it from the event list. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Place the unblocked task into the appropriate ready
list. */
prvAddTaskToReadyList( pxTCB );
<---- end critical section here
Please let me know if I am right.
If yes shouldn’t it be considered in next versions of RTOS improve the real time responsiveness ?
Best regards,
Piotr