Multiple Questions...

willywortel wrote on Tuesday, March 31, 2009:


When to use volatile? Is it better to use it always when making a variable global?
Do semaphore and queue’s variables need to be stated volatile?


I’m working on the PIC32 platform, and the pic32 has multivector interrups.
Now in the datasheet they are mentioning that the right ipl (interrupt priority) should be  mentioned in the function call (see below, this part: interrupt(ipl1) )

/* The timer 2 interrupt handler. */
void __attribute__( (interrupt(ipl0), vector(_TIMER_2_VECTOR))) vT2InterruptWrapper( void );

But what is the difference? I only see that ipl7 uses a special, dedicated, stack but for the rest, i don’t know.

I`m asking this for this second question:

This timer2 interrupt is used to count 10uS above max_syscall_priority. So if i`m correctly I may not use any FROM_ISR functions defined by the OS.

But, at sertain times I want that this timer2 calls some FROM_ISR functions. So i thought that i change the interrupt priority "on the fly" to a priority below max_syscall_priority (inside the timer2 ISR) so that the next timer2 ISR may call functions from the OS.

Is this safe to do? I need this timer for my modbus communications used in another task.
So i want to give a semaphore inside the timer2 after a specified time.


Another thing that i’m having now is that the OS, with 6 task and ADC, RS232, timer2 fully interrupt based.
Is freezing after usually a day or so. But it happends only when I`m not using the debugger (RealIce),
only when I set the compiler to “release” the freezes happens. I checked to be sure that no optimizes
are set in the compiler so i think this cannot be the problem.

I don’t know where to search for. I`m pretty sure that it is not a stack problem since I use
an character display that continuesly displays the stack from all the tasks. I’ve never encountered a
stack that reached less than 100 in any of the tasks.

The only thing that i can think off is the predifined DMA functions from microchip
i need to calculate the CRC. I used it on this way:

                for(crcIterationCalculation = 0; crcIterationCalculation != 4; crcIterationCalculation++)
                    mCrcSetSeed(0xffff);        // re-seed the CRC generator to start from exactly the same conditions       
                    res = DmaChnMemCrc(&localCalculatedCrc, &modbusFrame[0], (modbusFrameLength - 2), DMA_CHN, DMA_CHN_PRI2);   
                    // if transfer succeed, break the loop
                    if (res == DMA_TXFER_OK){ break; };

Is this OK to do?


Is it safe to do the following in the RS232 interrupt that is below max_syscall_priority:

setError = 1;

and read it out in a task just like this:

if (setError == 1)
// code

where setError is a volatile portLONG variable

And vice versa (task sets setError, interrupt reads it out)


Another question is about clearing interrupt flags. In a datasheet from the PIC32 they are mentioning to:

You should clear the interrupt request flag as soon as you enter the routine. Handlers
that service more than one interrupt request flag can copy the interrupt request flags into a local
variable, clear the IFS register, and then service the request.

In the demo I never see that this is done. Do I need to do it like mentioned in the datasheet or
doesn’t it really matter?


edwards3 wrote on Tuesday, March 31, 2009:

1/// This is a standard C question. Best look up in your C text book.

2/// The interrupt priority set by the interrupt(ipl0) does not seem to have any meaning as the priority is actually set by configuring a register within the C code. I think you could change the priority on the fly provided you disable the interrupt, change the priority, then re enable it.

3/// Not sure what that code is doing so couldn’t say. Is it waiting for a DMA transfer in the critical section? I would not have thought that would be good.

4/// It is ok for the interrupt to set the variable and the task to read it as its a 32 bit value on a 32 bit machine so the operations will be atomic as far as it matters. I think the other way is also ok for the same reason but you might want to check the generated asm code to be sure.

5/// ? Don’t know, but as long as you clear the flag before the next interrupt comes in I think it should be ok. If you are using interrupt nesting (as it sounds like you are) then not clearing the flag might delay higher priority tasks but that would seem odd if it was the case.

incrediball wrote on Tuesday, March 31, 2009:

1) Volatile is needed when the contents of the variable can change unexpectedly. For example:

static char i = 0;

while (i == 0)

This is obviously an endless loop and the optimizer can exclude i from the program because it is always zero. The compiler can also safely assume that do_something() is never called either. Now if the declaration would be:

static volatile char i = 0;

Then the compiler can make no assumptions since i could be changed by another task, interrupt or hardware.

So there are probably no hard and fast rules for determining if something should be volatile or not. It is up to you to decide if the contents of a variable might be changed by something else and if it is important that a sequence of program code would see the change.

You do not need to declare queues and semaphores as volatile. Firstly xQueueHandle and xSemaphoreHandle are only pointers so declaring them as volatile is just telling the compiler that the address of the queue / semaphore might change unexpectedly, which would be wrong. Secondly if this would be important then xQueueHandle and xSemaphoreHandle would be declared as such (e.g. typedef volatile void * xQueueHandle or whatever).

3) I have found lots of reasons for hanging programs under FreeRTOS. Perhaps there should be a list of common reasons in the FAQ if there isn’t one already. Ones that I have encountered:

*Stack overflows or other corrupted memory.

*Inadequate mutual exclusion protecting shared data causing your program to behave as you would not expect, possibly corrupting memory. These problems are of course very erratic and hard to trace, best to make sure they never happen.

*Blocking FreeRTOS calls in the idle task (such as waiting on a queue or semaphore, delay, etc). This can unintentionally occur if you write a function which has a blocking call somewhere and you use it in various places including in your idle task.

*Critical sections in interrupts. This can happen if you use a non-ISR capable FreeRTOS function such as xTaskGetTickCount.

*Spurious interrupt handlers which are just endless loops.

*Of course there are the obvious ones like endless loops and deadlocks.

If you suspect that your CRC calculation is the problem, find a way of indicating when it is in that section of code (e.g. turn on an LED or something). If it hangs and the LED is on, then you’ll know…

willywortel wrote on Tuesday, March 31, 2009:

So after 3 days of continuously running my program using the REALICE debugger it (finally) stopped working just now.

So i paused the PIC32 to see what the he is still doing.

The strange thing is that the "RTOS viewer plugin" tab "Tasks" at MPLAB is saying that all tasks are gone except the IDLE task witch is still running fine.
Dough at the "System" tab in the RTOS viewer, it says that the uxCurrentNumberOfTasks is still 6, the tick count is still incrementing and the scheduler is running.
The interrupts (UART / Timer2 / ADC) are still running fine too, i checked this with some breakpoints

So I’ve a new question now (mayb. i should post it in a new thread):

What could be a possible reason that all task are removed from the task list?

And thanks for the small FAQ, i`m still learning :)!

rtel wrote on Wednesday, April 01, 2009:

There is this:

but I think you mentioned others too that should be added.


rtel wrote on Wednesday, April 01, 2009:

Either the plug-in is just showing the wrong thing, or alternatively the data structures in the application have been corrupted and the plug-in cannot determine where the task information is.