Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

Problem about xSemaphoreTake()

Posted by brilliantdt on April 30, 2015

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()

Posted by rtel on April 30, 2015

[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()

Posted by brilliantdt on May 1, 2015

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,portMAXDELAY) == pdTRUE) { USARTWrite(AT91CBASEUS0, 0xee, 0); } } }

static void vLED1Task( void *pvParameters )
{
while(1) { if( xSemaphoreTake(xBinarySemaphore2,portMAXDELAY) == pdTRUE) { USARTWrite(AT91CBASEUS0, 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()

Posted by rtel on May 1, 2015

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()

Posted by brilliantdt on May 1, 2015

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()

Posted by rtel on May 1, 2015

...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()

Posted by brilliantdt on May 1, 2015

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()

Posted by brilliantdt on May 1, 2015

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()

Posted by davedoors on May 1, 2015

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()

Posted by brilliantdt on May 1, 2015

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()

Posted by heinbali01 on May 1, 2015

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()

Posted by brilliantdt on May 4, 2015

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


Problem about xSemaphoreTake()

Posted by brilliantdt on May 4, 2015

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


Problem about xSemaphoreTake()

Posted by heinbali01 on May 4, 2015

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()

Posted by brilliantdt on May 8, 2015

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()

Posted by rtel on May 8, 2015

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.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner