Why scheduler does wokr in FreeRTOS from 7.5 version

juvf wrote on Sunday, December 15, 2013:

I make only one task with priority 3.

#define configUSE_PREEMPTION 1

My task is bloked by waiting byte from queue.

xQueueReceive(uart485Queue, &byte, portMAX_DELAY);

Byte is sending to queue from ISR

void USART1_IRQHandler(void)
{
static uint8_t byte;
static portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
if(USART1_SR_bit.RXNE == 1)
{
byte = USART1_DR;
xQueueSendToBackFromISR(uart485Queue, &byte, &xHigherPriorityTaskWoken);
}
//portEND_SWITCHING_ISR(xHigherPriorityTaskWoken == pdTRUE );
}

After calling xQueueSendToBackFromISR() my task changes state and gets READY.
If i call portEND_SWITCHING_ISR() in the end of the USART1_IRQHandler, that my task gives CPU, changes state and gets RUNNING. My task continue works.
But if i don’t call portEND_SWITCHING_ISR(), my task must gets CPU in the end of system tick. In the hendler of the system timer must call scheduler. But scheduler does call and switch context no occur. Why? My singular task is ready and only IDLE running all times. Why?
Where in the hendler of the system timer calling scheduler and where checking for tasks ready?

The same code works with FreeRTOS v7.2.0 and early.

ps FreeRTOS 7.6.0, port Cortex-M3, IAR.

rtel wrote on Sunday, December 15, 2013:

Please confirm that all the RTOS code you are running is from the V7.6.0 distribution. What I think you are describing could be the case if you updated the core files found in FreeRTOS/source from V7.2.0 to V7.6.0, but left the port layer files found in FreeRTOS/source/portable/IAR/ARM_CM3 at V7.2.0.

Please ensure you report back even if that is your problem so we can be assured there are no issues.

Regards.

juvf wrote on Monday, December 16, 2013:

I am sure the files from V7.2.0 use in project with V7.2.0, and the files from V7.6.0 use in project with V7.6.0.
Initially, i was doing project with V7.6.0. By accident i detected that one of my task with highest priority didn’t work. Its state was READY. I studied of rtos source code and found out that the scheduler isn’t calling from the hendler of the system timer.
Then i downdated FreeRTOS/source from V7.6.0 to V7.2.0 and my task worked.

You can see and compare hendler V7.6.0 ( FreeRTOSV7.6.0\FreeRTOS\Source\portable\IAR\ARM_CM3\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 );
}

…compare with hendler V7.2.0 ( FreeRTOSV7.2.0\FreeRTOS\Source\portable\IAR\ARM_CM3\port.c )

void xPortSysTickHandler( void )
{
unsigned long ulDummy;

/* If using preemption, also force a context switch. */
#if configUSE_PREEMPTION == 1
	*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;	
#endif

ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
{
	vTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );

}

Where calling scheduler in V7.6.0?
Also i studied of rtos source code another ports. For example ATMega323:
V7.2.0
vPortYieldFromTick:
portSAVE_CONTEXT ; Save the context of the current task.
call vTaskIncrementTick ; Call the timer tick function.
call vTaskSwitchContext ; Call the scheduler.
portRESTORE_CONTEXT ; Restore the context of whichever task the …
ret ; … scheduler decided should run.

V7.6.0
vPortYieldFromTick:
portSAVE_CONTEXT ; Save the context of the current task.
call xTaskIncrementTick ; Call the timer tick function.
tst r16
breq SkipTaskSwitch
call vTaskSwitchContext ; Call the scheduler.
SkipTaskSwitch:
portRESTORE_CONTEXT ; Restore the context of whichever task the …
ret ; … scheduler decided should run.

Why in the V7.6.0 is SkipTaskSwitch?

rtel wrote on Monday, December 16, 2013:

Please try the following sequence when you build with portEND_SWITCHING_ISR() commented out, and report back where you think the problem occurs.

  1. Put a break point on your call to xQueueSendToBackFromISR(), then run the code until the break point is hit.
  2. In the debugger, step into the xQueueSendToBackFromISR() function, you should enter the xQueueGenericSendFromISR() function, from which xTaskRemoveFromEventList() is called. Step into xTaskRemoveFromEventList().
  3. Inside cTaskRemoveFromEventList() there is the line of code:
    if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
    which, if there is a task waiting on the queue, and the task's priority is above the idle priority, should evaluate to true, which in turn will cause xYieldPending to be set to pdTRUE.
  4. When you get to the line that sets xYieldPending to pdTRUE, put a break point on the first line of xTaskIncrementTick() which is in tasks.c. Run the code again until the new break point is hit.
  5. At the very end of xTaskIncrementTick() you will find the following lines of code:
    if( xYieldPending != pdFALSE )
    {
        xSwitchRequired = pdTRUE;
    }
    
    xSwitchRequired is the functions return value.
  6. Step out of xTaskIncrementTick() and you will end up in the code you posted in your previous post.
    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;
    }
    

    As xTaskIncrementTick() returns pdTRUE (because xSwitchRequired equaled pdTRUE) the PendSV interrupt is pended to request a context switch.

So the logic shows a context switch should happen. At which point do you see the actual behaviour deviate from this sequence? Please ensure to report back as it is very important to know if you think there is an error somewhere.

Regards.

juvf wrote on Monday, December 16, 2013:

Hello. Thank you for replay and help.
I try you steps in the debbug mode and … and make several screenshort… step-by-step. You can see them in attach.
I don’t understand… where and when xYieldPending must be set to pdTRUE?

ps if you need I can send my project

rtel wrote on Monday, December 16, 2013:

Thanks for such detailed screen shots. I can see in image 9 that this is not FreeRTOS V7.6.0, as V7.6.0 contains the following code:

if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
    /* Return true if the task removed from the event list has
    a higher priority than the calling task.  This allows
    the calling task to know if it should force a context
    switch now. */
    xReturn = pdTRUE;

    /* Mark that a yield is pending in case the user is not using the
    "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
    xYieldPending = pdTRUE;
}
else
{
    xReturn = pdFALSE;
}

The lines in red are missing in your code.

Regards.

[edit the red didn’t come out - but it is the code with the comment “mark that a yield…” that is missing in your code - this forum is hard to post code too!]

juvf wrote on Monday, December 16, 2013:

Thank you for you help. I deleted all source of FreeRTOS and load V7.6.0 again. My task works. Thank yo very match and i’m sorry for my mistake made through lack of attention.

But happiness was short. I was sending bytes whit period 1 sec to my programm. For the short haul my task worked, than it hang.
I stoped running and begin step in the debag mode. My task was READY, queue was full and xYieldPending == 0. Something was wrong, and context doesn’t switch to my task. In the handler of system timer no check tasks for ready. Why?

edwards3 wrote on Monday, December 16, 2013:

If this happened after it has been running for a while then the most likely cause is a bad interrupt priority assignment. Do you have configASSERT() defined?

juvf wrote on Monday, December 16, 2013:

No. I don’t have configASSERT() defined. I copy-past FreeRTOSConfig.h from FreeRTOSV7.6.0\FreeRTOS\Demo\CORTEX_STM32F103_IAR

edwards3 wrote on Monday, December 16, 2013:

I will rephrase that. If you don’t have configASSERT() defined then define it because it will help trap bad interrupt priority assignments. http://www.freertos.org/FAQHelp.html

juvf wrote on Tuesday, December 17, 2013:

You are right. configASSERT() shows that I made mistakes with assignt peripheries priority.

Freertos works excellent.

Thank you for your help.