FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [July 2009 Threads] xSemaphoreTake gets blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted 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 blockedPosted by MEdwards on July 20, 2009 Can you post the interrupt code?
RE: xSemaphoreTake gets blockedPosted 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.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|