Synchronizing task w/interrupt and semaphore

danielwlewis wrote on Wednesday, August 08, 2007:

I’ve run into a problem that I can’t resolve: As long as I don’t call any FreeRTOS API’s from within an interrupt routine, everything worksfine. But when I try to use xSemaphoreGiveFromISR/xSemaphoreTake to synchronize a task using an interrupt, I begin to have problems.

FYI: I’m using the Luminary Micro LM3S811 evaluation board, their driver library version 1427, FreeRTOS V4.3.1, and the free evaluation version (V4.42A) of IAR’s Embedded Workbench.

I’ve simplified the application down to the minimal code that demonstrates the problem: The CPU is running at the default 6Mhz rate. A hardware timer is configured to interrupt 100 times per second. THe ISR merely clears the interrupt and calls xSemaphoreGiveFromISR. The task pends on the semaphore; when released, it increments an integer and sends it to the onboard display. Thus the application should display a continuously incrementing number on the onboard display. It does so for a while (up to 487) and then hangs. Where it hangs changes if I change the stack size or the interrupt rate, but it always hangs.

The code is attached. Any help would be most appreciated!


#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "timer.h"
#include "interrupt.h"
#include "sysctl.h"
#include "osram96x16x1.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

xSemaphoreHandle TimerSemaphore = NULL ;

void Timer0IntHandler(void)
        xSemaphoreGiveFromISR(TimerSemaphore, pdFALSE) ;

char *Convert(unsigned long int n, char *bfr)
        if (n >= 10) bfr = Convert(n / 10, bfr) ;
        *bfr++ = (n % 10) + ‘0’ ;
        *bfr = ‘\0’ ;
        return bfr ;

void TimerTask(void *pvParameters)
    unsigned long int count = 0 ;
    char bfr[30] ;

    for (;:wink:
        xSemaphoreTake(TimerSemaphore, portMAX_DELAY) ;
        Convert(count++, bfr) ;
        OSRAM96x16x1StringDraw(bfr, 0, 0) ;

#define PRIORITY ((tskIDLE_PRIORITY) + 1)

int main(void)
    OSRAM96x16x1Init(true) ;

    vSemaphoreCreateBinary(TimerSemaphore) ;

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0) ;
    // Configure timer 0 to generate periodic interrupts
    TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER) ;
    TimerLoadSet(TIMER0_BASE, TIMER_A, 60000) ; // interrupt 100 times/second
    TimerEnable(TIMER0_BASE, TIMER_A);

    xTaskCreate(TimerTask, "TimerTask", 128, NULL, PRIORITY, NULL) ;

    // Should never arrive here …
    OSRAM96x16x1StringDraw("Failed!", 0, 1) ;
    for (;:wink: ;

sotd wrote on Wednesday, August 08, 2007:

I cannot see anything wrong but am not familiar with the port.  A couple of questions.

Could it simply be a stack problem.  Try making bfr static to see if that helps.  Also, some demos use FreeRTOS calls in the LCD initialization routines.  This means you have to call them from a task after the scheduler has been started.  COuld this be a problem?

You say everything works ok, other than this.  Odd.  The docs say you don’t need any special syntax for ISRs with is unlike most port, so it should be easy.

Do any of the Cortex demos demonstrate this being done, where you could copy code from.  I suspect the USRT demo will show a queue being used, which is basically the same thing.

danielwlewis wrote on Wednesday, August 08, 2007:

Thanks for the suggestions. I made bfr static, but it made no difference at all.

The LCD initialization code is from Luminary Micro’s driver lib, which has no FreeRTOS reference within it. But just for kicks, I then moved the call to vSemaphoreCreateBinary into the task, and moved the call to IntEnable just after it so that the interrupt routine would not access the semaphore before it had been created. However, other than changing the point where the application hangs (from a count of 487 to 490), there was no significant change.

The demo that comes with the LM3S811 port of FreeRTOS uses a similar interrupt routine (vGPIO_ISR) for a push button on the board and uses it to synchronize a task (vButtonHandlerTask). The only difference I can think of is that most users are not likely to push that button 500 times. :slight_smile:


fkln wrote on Wednesday, August 08, 2007:


I am also working with FreeRTOS and the chips from Luminary Micro.

Which compiler do you use ?

If you use gcc, I recommend to try the IAR compiler.
I have got a similar problem with nested interrupts, after I switch to IAR the problem was solved.


danielwlewis wrote on Wednesday, August 08, 2007:


As mentioned in my original post, I too am using IAR. And I just solved my problem: I upgraded to version 4.4.0 of FreeRTOS and the problem went away! :slight_smile:


danielwlewis wrote on Thursday, August 09, 2007:

Well, I spoke too soon. :frowning:

The simplified test case given in my original post works fine now with version 4.4.0 of FreeRTOS. However, the larger application from which it was extracted still runs for a while and then suddenly hangs. It contains a task that uses vTaskDelayUntil; if I replace it with the older vTaskDelay, then everything works great. Apparently there are still problems in vTaskDelayUntil.


rtel wrote on Thursday, August 09, 2007:

While I can offer no guarantees, I would be very suprised if there was a problem with vTaskDelayUntil() considering the amount of testing it has undergone.  Did you read the conclusion to this thread?

It was been raised a couple of times that there is a problem with the function, but in all cases it turns out that it does exactly what you tell it to do.

I should look somewhere else.  I’m away from the office for a while at the moment, but if you zip up the smallest application you can write that exhibits the problem and send it to me then I can take a look when I get back.  Use the r (dot) barry[ @ ] address, not the sourceforge address, otherwise the attachment will get removed.

I won’t be able to try it until probably middle of next week.


danielwlewis wrote on Friday, August 10, 2007:


I think I may have found my problem. I made a naive assumption that Luminary Micro’s driver library was reentrant. I have two tasks which each call their TimerMatchSet API. After protecting these calls with a semaphore, my application seems to run ok. So for now please assume that it was “user error”. I’ll continue to test the application; if I find otherwise, I’ll let you know.

Thanks for your help!


jcwren wrote on Friday, August 10, 2007:

Dude… A *real* programmer would have blamed the hardware, then claimed to have fixed it in software!