No context switching after portYIELD_FROM_ISR() cortex M4

emike91 wrote on Monday, November 13, 2017:

hi everyone
I´m using the TM4c123 cortex m4 of TI and i’m trying to use the interrupts in FreeRTOS… here is the situation
I’ve two tasks running, the Task 1 is blocking after attempting to get a binary semaphore(this task has the higher priority) then the Task 2 is running a simple for loop, waiting for an interrupt(the interrupt is the Rx of the UART0) then in the ISR(UARTIntHandler) call the xSemaphoreGiveFromISR and then the portYIELD_FROM_ISR and here comes the problem because i’m expecting the running task will be the Task 1 because of the call to give the semaphore, but the Task 2 is actually running here is the simplified code also i put FreeRTOSconfig.h

void
ConfigureUART(void)
{
    // Configure GPIO Pins for UART mode.
    // Enable the GPIO Peripheral used by the UART.
    //...
    ROM_IntPrioritySet(INT_UART0, 0xA3 );//Here im setting the interrupt priority
    portDISABLE_INTERRUPTS();
    UARTIntDisable(INT_UART0, UART_INT_TX | UART_INT_RI);
    ROM_IntEnable(INT_UART0);
    ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
}
void 
vTask1 (void *pvParamaters)
{
    while(1)
    {
            xSemaphoreTake( xBinarySemaphore, portMAX_DELAY ); //blocking the task
            ROM_UARTCharGetNonBlocking(UART0_BASE)...;
    }
}
void 
vTask2 (void *pvParamaters) 
{
        while(1)
           {
                   for ( u1 = 0; u1 < mainDELAY_LOOP_COUNT; u1++ ){}
            }
}
void 
UARTIntHandler(void)
{
    xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken ); 
    ROM_UARTIntClear(INT_UART0, UART_INT_RX | UART_INT_RT);
    if( xHigherPriorityTaskWoken )
    {
         portYIELD_FROM_ISR( xHigherPriorityTaskWoken );//After this, the context switch to Task 1 never happens
    }
}
int
main(void)
{
  ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_XTAL_16MHZ |SYSCTL_OSC_MAIN);
    ConfigureUART();
    xBinarySemaphore = xSemaphoreCreateBinary();
    xHigherPriorityTaskWoken = pdFALSE;
    xTaskCreate( vTask1, "Task 1", 100, NULL, 2, NULL );
    xTaskCreate( vTask2, "Task 2", 100, NULL, 1, NULL );  
    vTaskStartScheduler();
    while(1)
    {
    }
}
FreeRTOSConfig.h
#define configUSE_PREEMPTION					1
#define configUSE_TIME_SLICING					1
#define configMAX_PRIORITIES					( 5 )
#define configIDLE_SHOULD_YIELD					0
#define configUSE_16_BIT_TICKS					0 /* Only for 8 and 16-bit hardware. */

/* Constants that describe the hardware and memory usage. */
#define configCPU_CLOCK_HZ                  ( ( unsigned long ) 16000000 )
#define configMINIMAL_STACK_SIZE            ( ( unsigned short ) 200 )
#define configMAX_TASK_NAME_LEN					( 12 )
#define configTICK_RATE_HZ                  ( ( portTickType ) 1000 )

#define configTOTAL_HEAP_SIZE               ( ( size_t ) ( 20240 ) )

/* Constants that build features in or out. */
#define configUSE_MUTEXES				     	1
#define configUSE_TICKLESS_IDLE					0
#define configUSE_APPLICATION_TASK_TAG			0
#define configUSE_NEWLIB_REENTRANT 				0
#define configUSE_CO_ROUTINES 					0
#define configUSE_COUNTING_SEMAPHORES 			1
#define configUSE_RECURSIVE_MUTEXES				1
#define configUSE_QUEUE_SETS					0
#define configUSE_TASK_NOTIFICATIONS			1
//-----------------------------------------------------
#define INCLUDE_vTaskPrioritySet				1
#define INCLUDE_uxTaskPriorityGet				1
#define INCLUDE_vTaskDelete					    1
#define INCLUDE_vTaskCleanUpResources			0
#define INCLUDE_vTaskSuspend					1
#define INCLUDE_vTaskDelayUntil					1
#define INCLUDE_vTaskDelay						1
#define INCLUDE_uxTaskGetStackHighWaterMark		0
#define INCLUDE_xTaskGetIdleTaskHandle			0
#define INCLUDE_eTaskGetState					1
#define INCLUDE_xTaskResumeFromISR				0
#define INCLUDE_xTaskGetCurrentTaskHandle		1
#define INCLUDE_xTaskGetSchedulerState			0
#define INCLUDE_xSemaphoreGetMutexHolder		0
#define INCLUDE_xTimerPendFunctionCall			1

/* I'm not understanding the following 2 Macros but i saw this in a demo */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0x07
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

/* Here i set the Kernel interrupt level and the priority level fromISR function calls */
#define configKERNEL_INTERRUPT_PRIORITY         ( 7 << 5 )    /* Priority 7, or 0xE0  */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     ( 5 << 5 )  /* Priority 5, or 0xA0 */

i will appreciate any help or clue to get the code running thanks in advance :)))))

P.S: If anyone knows another technique to deferred an Interrupt in order to receive data from Uart I would appreciate it very much.

rtel wrote on Tuesday, November 14, 2017:

At first glance there is not anything obviously wrong with your code.
There is no need to test xHigherPriorityTaskWoken before passing it to
portYIELD_FROM_ISR, and xHigherPriorityTaskWoken should be initialised
to 0, but neither of those are going to be the source of the problem.

Which version of FreeRTOS are you using and do you have configASSERT
defined? The reason I ask about the version is that the newer the
version the more assert points there are.

You say Task1 should run immediately, implying it does not, but does it
run at all after the semaphore is given?

Task notifications can be used in place of semaphores as they are much
lighter weight.

emike91 wrote on Tuesday, November 14, 2017:

Thanks for the reply!,

Which version of FreeRTOS are you using
I’m using the FreeRTOS V9.0.0


do you have configASSERT defined?
Yes, in FreeRTOSConfig I’ve…

#define configASSERT( x ) if( ( x ) == 0 ) { 
                                   taskDISABLE_INTERRUPTS(); for( ;; ); 
                                   }

You say Task1 should run immediately, implying it does not, but does it
run at all after the semaphore is given?

Task 1 just executes at the first time after vTaskStartScheduler(); then it never runs…
:confused:


Task notifications can be used in place of semaphores as they are much lighter weight.
I also have tried with task notifications but actually when i call vTaskNotifyGiveFromISR() xHigherPriorityTaskWoken never change to pdTRUE(1)

emike91 wrote on Tuesday, November 14, 2017:

Hi there,

I’ve tried a simple modification in the code, specifically, inside the ISR

void UARTIntHandler(void)
{
    xHigherPriorityTaskWoken = pdFALSE;
    while(ROM_UARTCharsAvail(UART0_BASE))
                   {  
                   ROM_UARTCharGetNonBlocking(UART0_BASE);
                    }  
    xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken ); 
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    ROM_UARTIntClear(INT_UART0, UART_INT_RX | UART_INT_RT);
}

If i clean the fifo here, the Task 1 is executed after the end of the ISR but i do not realy want this because of the time spending inside the ISR, does anyone knows a better way to deferred the work of an ISR?

thanks… :slight_smile: