Problem about xSemaphoreTake()

Hi, After I use xSemaphoreGiveFromISR() in an interrupt handler, I use xSemaphoreTake() with portMAX_DELAY in a task. However, the function xSemaphoreTake() can not take the semaphore. What is the problem? Regaeds

Problem about xSemaphoreTake()

[I deleted your duplicate posts]
What is the problem?
Unfortunately you don’t give enough information to even guess. Please at least post the code that creates the semaphore, gives the semaphore and takes the semaphore, so we can see if the functions are being used correctly. Regards.

Problem about xSemaphoreTake()

void ISRBp1(void) { static portBASETYPE xHigherPriorityTaskWoken1; xHigherPriorityTaskWoken1 = pdFALSE; portBASETYPE isr1 = xSemaphoreGiveFromISR( xBinarySemaphore1, &xHigherPriorityTaskWoken1 ); if(isr1==pdTRUE) { USARTWrite(AT91CBASEUS0, 0xe1, 0); } LED0_ON; } void ISRBp2(void) { static portBASETYPE xHigherPriorityTaskWoken2; xHigherPriorityTaskWoken2 = pdFALSE; portBASETYPE isr2 = xSemaphoreGiveFromISR( xBinarySemaphore2, &xHigherPriorityTaskWoken2 ); if(isr2==pdTRUE) { USARTWrite(AT91CBASEUS0, 0xf1, 0); } LED0_OFF; } static void vLED0Task( void *pvParameters )
{
while(1) { if( xSemaphoreTake(xBinarySemaphore1,portMAX_DELAY) == pdTRUE) { USART_Write(AT91C_BASE_US0, 0xee, 0); } } } static void vLED1Task( void *pvParameters )
{
while(1) { if( xSemaphoreTake(xBinarySemaphore2,portMAX_DELAY) == pdTRUE) { USART_Write(AT91C_BASE_US0, 0xff, 0); } } } int main(void) {
ConfigureUsart0();

PIO_Configure(pins, PIO_LISTSIZE(pins));
USART_Write(AT91C_BASE_US0, 0x11, 0);

ConfigureButtons();
ConfigureLeds();

vSemaphoreCreateBinary( xBinarySemaphore1 );            
vSemaphoreCreateBinary( xBinarySemaphore2 );


portBASE_TYPE flagLED0 = xTaskCreate( vLED0Task, ( signed portCHAR * )"LED0", configMINIMAL_STACK_SIZE, NULL, vLED0Task_PRIORITY, NULL );

if(flagLED0 == pdTRUE)
{ 
  USART_Write(AT91C_BASE_US0, 0x22, 0);
}
USART_Write(AT91C_BASE_US0, 0x12, 0);
portBASE_TYPE flagLED1 = xTaskCreate( vLED1Task, ( signed portCHAR * )"LED1", configMINIMAL_STACK_SIZE, NULL, vLED1Task_PRIORITY, NULL );

if(flagLED1 == pdTRUE)
{ 
  USART_Write(AT91C_BASE_US0, 0x23, 0);
}
USART_Write(AT91C_BASE_US0, 0x13, 0);

vTaskStartScheduler();
// Main loop
while (1) {

}
} As you can see, after I create binary xBinarySemaphore1 and xBinarySemaphore2 in the main function, the two tasks can respectively take these two semaphores. However, after I give semaphores using xSemaphoreGiveFromISR() in the two ISR functions(I am sure that the interrupt handlers respond because LEDO is ON or OFF ,and different byte is transmitted with USART), the task vLED0Task and vLED1Task can not take the semaphores. What is wrong with my codes? Thanks a lot!

Problem about xSemaphoreTake()

Nothing obviously wrong with the code. However, you are not requesting in a context switch in the interrupt (you do not pass the xHigherPriorityTaskWoken variable to call to portYIELDFROMISR() or portENDSWITCHINGISR() at the end of the interrupt). Could it be you are using the co-operative scheduler? What is configUSE_PREEMPTION set to in FreeRTOSConfig.h? Regards.

Problem about xSemaphoreTake()

I only want to see if the task can take the semaphore, so I do not request in a context switch in the interrupt. In my FreeRTOSConfig.h, configUSE_PREEMPTION is set to 1(I copy FreeRTOSConfig.h from the demo of AT91SAM9XE to my project).

Problem about xSemaphoreTake()

…and you are 100% sure that the tick interrupt is running? Can you set a break point in the tick interrupt and/or see xTickCount incrementing in the FreeRTOS/Source/tasks.c file? Regards.

Problem about xSemaphoreTake()

I think the xTickCount is incrementing because 0x00 is always transmitted by USART to my computer.The code is in the following. portBASETYPE xTaskIncrementTick( void ) { tskTCB * pxTCB; portTickType xItemValue; portBASETYPE xSwitchRequired = pdFALSE;
/* Called by the portable layer each time a tick interrupt occurs.
Increments the tick then checks to see if the new tick value will cause any
tasks to be unblocked. */
traceTASK_INCREMENT_TICK( xTickCount );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
    /* Increment the RTOS tick, switching the delayed and overflowed
    delayed lists if it wraps to 0. */
    ++xTickCount;
            USART_Write(AT91C_BASE_US0, 0x00, 0);
    ........................(omited)
}

Problem about xSemaphoreTake()

I think the xTickCount is incrementing beacause 0x00 is transmitted by USART to my computer all the time. The code is in the following: portBASETYPE xTaskIncrementTick( void ) { tskTCB * pxTCB; portTickType xItemValue; portBASETYPE xSwitchRequired = pdFALSE;
/* Called by the portable layer each time a tick interrupt occurs.
Increments the tick then checks to see if the new tick value will cause any
tasks to be unblocked. */
traceTASK_INCREMENT_TICK( xTickCount );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
    /* Increment the RTOS tick, switching the delayed and overflowed
    delayed lists if it wraps to 0. */
    ++xTickCount;
            USART_Write(AT91C_BASE_US0, 0x00, 0);
    (omitted......)
}

Problem about xSemaphoreTake()

This looks very dangerous. You are using USART_Write from multiple tasks so it must have some mutual exclusion mechanism built in, but then you using it in an interrupt to? How does it work? Does it poll the uart for the Tx end? What is your tick frequency? Your processor is probably spending most of its time in the tick interrupt writing to the uart.

Problem about xSemaphoreTake()

Even though I do not use USART_Write in the tick interrupt writing to the uart, xSemaphoreTake() still does not work. It can only run once because I use vSemaphoreCreateBinary to create semaphore. Do you know what is wrong with my code?

Problem about xSemaphoreTake()

Hi Zhang Yi, Just wondering if this will make a change:
void ISR_Bp1(void)
{
/* No need to make variable this static. */
portBASE_TYPE xHigherPriorityTaskWoken1 = pdFALSE;
    ...
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken1 );
}

void ISR_Bp2(void)
{
portBASE_TYPE xHigherPriorityTaskWoken2 = pdFALSE;
    ...
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken2 );
}
In other words, adding the portENDSWITCHINGISR() calls. Like Dave, I also wonder if you can access the USART from within any ISR. Just leave it out and see if it makes a change. Regards.

Problem about xSemaphoreTake()

Hi, Your suggestion is effective! Would you please give me some explaination why it is effective.

Problem about xSemaphoreTake()

Hi, Your suggestion is effective! Would you please give me some explaination why it is effective.

Problem about xSemaphoreTake()

Hi Zhang Yi, Good to hear. Richard (from Real Time Engineers) already suggested to use portYIELDFROMISR() or portENDSWITCHINGISR(), see here above. Calling xSemaphoreGiveFromISR() does not cause a task switch. It does set the semaphore, but your task will keep on waiting eternally because of the time-out portMAX_DELAY:
if( xSemaphoreTake(xBinarySemaphore2, portMAX_DELAY) == pdTRUE)
{
}
Note that the way to ‘initiate’ a task-switch may differ a bit from port to port, in your case you use portENDSWITCHINGISR(). Why does this happen in two steps? First you give to a semaphore and maybe you also write to a queue. The ISR might cause several tasks to get woken-up: ~~~~~ void someisrroutine() { portBASE_TYPE xTaskWoken = pdFALSE;
    /* These are three call that may put tasks in a runnable state.
    The variable xTaskWoken will have an OR'ed value,
    it becomes non-zero if at least one task will be come runnable. */
    xQueueSendFromISR( xQueue, &vItem, &xTaskWoken );
    xSemaphoreGiveFromISR( xSemaphore, &xTaskWoken );
    vTaskNotifyGiveFromISR( pxTask, &xTaskWoken );

    /* Now inform the OS to check if a task-switch is necessary.
    */
    portEND_SWITCHING_ISR( TaskWoken );
}
~~~~~ In the above example, the ISR may wake-up several tasks. The task with the highest priority will start running first. This will happen immediately, after the “iret” instruction of the ISR. I hope the picture is clear now? Regard, Hein

Problem about xSemaphoreTake()

In my previous view, I think if only one task corresponds to one semaphore, it is not necessary to use portENDSWITCHINGISR(). However, even I set the semaphore corresponding to the task with the highest priority, it is still not effective. I think the above situation is a bit different from what you explain. Is it correct? Thanks for your explaination. Regards

Problem about xSemaphoreTake()

To add to what Hein has already said, the portENDSWITCHINGISR()/portYIELDFROMISR() mechanism allows better control over when a context switch is to be performed. For example, if you receive an interrupt each time a character is received on a UART, and the interrupt handler is buffering characters, then you don’t necessarily want to perform a context switch on each character, but only when a complete message is received, so you would call portENDSWITCHINGISR()/portYIELDFROMISR() only when the buffer contained a complete message. …that said, if you omit the call to portENDSWITCHINGISR()/portYIELDFROMISR(), then the task should run on the next tick interrupt anyway, so although in your case it would delay when the task executed, it would not prevent it from executing – so there is something else wrong. Somewhere a task switch is not being performed when it should. Can you set up a test where you have a break point that is hit in vTaskSwitchContext() after the interrupt that gives the semaphore has executed so you can step through the code to see why the task is not selected. Regards.