Quality RTOS & Embedded Software

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




Loading

xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 20, 2009
I've created a simple semaphore mutex into one of the tasks in order to avoid silmultaneous access to a global variable. The code is identical to the one explained in the online tutorial:

xSemaphoreHandle xSemaphore = NULL;

void myTask(void *pvParameters)
{
xSemaphore = xSemaphoreCreateMutex();
...
}

void myfunction(void)
{
...
if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
{
// Access to the global resource
xSemaphoreGive(epSemaphore);
}
...
}
...

I've verified that the semaphore is correctly created. During the first accesses, it's even "taken" and "released" without problems. However, after some successful accesses, myfunction gets blocked at xSemaphoreTake. Doing xBlockTime = 0 solves the problem but I'd like myfunction to wait at least some ticks before abandoning the semaphore. I'm thinking that maybe FreeRTOS doesn't know what a tick is in my system so that it waits indefinitely. I've maybe missed some definition elsewhere...

I understand that my descriptions are quite vague but... has anyone an idea about what could be happening with my setup?

Thank you very much,

Daniel.

RE: xSemaphoreTake gets blocked

Posted by Dave on July 20, 2009
First, put a break point in vTaskIncrementTick() in tasks.c. If the break point is triggered repeatedly then your tick interrupt is working ok.

Also do the usual things like checking for stack overflows, things like that.

RE: xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 20, 2009
Thanks Dave for your help.

vTaskIncrementTick() is called several times at the beginning of the execution. Then, it's not called again, matching with the blockage at xSemaphoreTake in myfunction() . I've also verified that there is no stack overflow through the use of the vApplicationStackOverflowHook function.

Something curious IMO, If I add an instruction in vTaskIncrementTick() that prints a text message on my Dev Board's OLED display, then vTaskIncrementTick gets called without problems all the time and my program works smoothly. This is not a valid solution though but I wanted to explain this behavior, just in case this is a symptom about what's happening.

My hardware platform is a Luminary LM3S8962 Eval board.

Thanks again!

Daniel.

RE: xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 20, 2009
I've found the source of the problem. I was using a timer interrupt in order to run ADC conversions on my Stellaris platform. The trigger of this interrupt was hanging the task I think. I now know that custom interrupts have to be avoided under FreeRTOS :-)

RE: xSemaphoreTake gets blocked

Posted by dave m on July 20, 2009
I've written several FreeRTOS programs that run on Luminary chips. Interrupts work correctly, but you have to be careful about priority. Specifically, in the NVIC, lower-numbered priorities are higher. Also, there's an intermediate priority level (configMAX_SYSCALL_INTERRUPT_PRIORITY) above which you can't call FreeRTOS routines. There's a lot more information on the FreeRTOS website, but it's slightly difficult to find. (It would be nice if there was a FAQ about it, or a more-prominent link in a section talking about Cortex procs.) Here's where to start reading:

http://www.freertos.org/index.html?http://www.freertos.org/portcortexgcc.html

Near the bottom of the main frame, under the heading "RTOS Port specific configuration"

RE: xSemaphoreTake gets blocked

Posted by Richard on July 20, 2009
I'm not sure what you mean by "custom interrupts have to be avoided". Its fine to have any interrupts you want provided there are no resource conflicts.

Was your interrupt using the FreeRTOS API? If so then ensure only API functions that end in FromISR were being used and that the interrupt priority was less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY (remembering that low number mean high priorities on the Cortex M3).

Regards.

RE: xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 20, 2009
Thanks both for your remarks. I'm quite new in FreeRTOS and have still a lot to learn... and I'm really happy to know that I can use interrupts together with RfeeRTOS.

My custom interrupt (the one currently triggering the ADC reads) has now the lowest priority (255) but it still makes the system crash. I'm now thinking that maybe the problem is in the timer used to trigger these ADC conversions periodically. I did verify that this timer was not used anywhere by the Os but maybe I should do a second check (I'm not the author of the FreeRTOS port)

More news tomorrow...

Daniel.

RE: xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 20, 2009
My application no longer uses a timer to trigger ADC conversions... and the problem persists.

RE: xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 20, 2009
I forgot to say that the interrupt is not calling any function from the FreeRTOS API. It just reads the ADC values.

RE: xSemaphoreTake gets blocked

Posted by MEdwards on July 20, 2009
Can you post the interrupt code?

RE: xSemaphoreTake gets blocked

Posted by Daniel Berenguer on July 21, 2009
Of course!

TaskIO.c runs in a separate task, all the routines regarding the IO management. setup_analog_inps() is the function that sets up the ADC sequencer (sequencer 0) and programs Timer1 to trigger the sequencer every 0.1 sec:

static void setup_analog_inps(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC);// Enable ADC
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);// Enable Timer 1

ADCSequenceDisable(ADC_BASE, 1);// Disable ADC sequencer 1

// Configure the ADC to sample when the timer expires
// After sampling, the ADC will interrupt the processor
ADCSequenceConfigure(ADC_BASE, 0, ADC_TRIGGER_TIMER, 255);
ADCSequenceStepConfigure(ADC_BASE, 0, 0,ADC_CTL_CH0 );
ADCSequenceStepConfigure(ADC_BASE, 0, 1,ADC_CTL_CH1 );
ADCSequenceStepConfigure(ADC_BASE, 0, 2,ADC_CTL_CH2 );
ADCSequenceStepConfigure(ADC_BASE, 0, 3,ADC_CTL_CH3 | ADC_CTL_IE | ADC_CTL_END);

ADCSequenceEnable(ADC_BASE, 0);

ADCIntEnable(ADC_BASE, 0);
IntEnable(INT_ADC0);

// Configure Timer 1 to generate triggers to the ADC
TimerConfigure(TIMER1_BASE, TIMER_CFG_32_BIT_PER);
TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet()/10);// Trigger every 0.1 secs
TimerControlStall(TIMER1_BASE, TIMER_A, true);
TimerControlTrigger(TIMER1_BASE, TIMER_A, true);
TimerEnable(TIMER1_BASE, TIMER_A);
}

ADCIntHandler is a callback function called whenever the ADC Sequencer 0 reads new analog data (once every 0.1 sec)

void ADCIntHandler(void)
{
unsigned long ulData[8];
unsigned long ulmVolt;
unsigned long ulValue;

BYTE bState;
int i;

// Clear the ADC interrupt.
ADCIntClear(ADC_BASE, 0);

// Read the data from the ADC.
ADCSequenceDataGet(ADC_BASE, 0, ulData);

// For every analog input
for(i=0 ; i<NBOF_INPANA ; i++)
{
// Get ADC value in voltage (mV) format
ulmVolt = (ADC_VOLT_RANGE * 1000 * ulData) / 1024;// Milivolts
// Apply factor and offset for each ADC endpoint
ulValue = ulmVolt * aEndpoint[0].factor + aEndpoint[0].offset;
// Set state
if (ulValue < 10)
bState = 0;
else
bState = 1;

epUpdateValue(i, 'a', ulValue, bState);// Update value in the array of binary endpoints
}
}

Apart from here, there is no other place where a timer or interrupt is set.

Thanks again,

Daniel.


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




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

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

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