This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

delay function, use of volatile

Dear Forum,

 

I have implemented a delay function by this:

 

void delay_125us(const UINT32 n)

{                       volatile UINT32 i=66;           // volatile to prevent optimization, value ROUGHLY measured

                        i = i*n;                         

    do i--;

    while (i != 0);

}

 

I now encountered an occasional problem while running the device. Luckily once the problem came up while I had the debugger connected and I found the program stuck in the delay function with

n=8 and

i= 4294880763

 

Since n was 8, i should have been only 528, so must have been changed from outside.

The program uses interrupts which also partly run the delay function.

 

My first guess is that it must be a wrong pointer addressing or array overflow or something like that. Now a colleague brought up that i might get overwritten during interrupt execution because of the fact that it is declared volatile? I learned to improve the delay function by increment i and do i++ while <= max to depend on catching one zero abort condition (or use signed counter), but:

Is there any real error in using such delay function with volatile counter variable, when interrupts are executed in parallel? Or musst this missbehaviour come from wrong use of pointer/arrayoverflow?

 

Thanks in advance

 

Chrishen

  • First it depends on where the debugger stops, on a place where the content of the variable has been expired (not needed anymore) it can already been used for something else.

    But also a previous interrupt which has used this function will have changed the variables, regardless if ‘volatile’ or not.

    A few comments;

    Why const UINT32 n? I would just use UINT32 n, the source of the value can be a constant but for the function it’s just a variable.

    The volatile is unnecessary unless for debugging use.

    Don’t call functions from within an ISR and especially not when the function also can be called from main, if a short delay is necessary use ‘__delay_cycles(n)’.

  • Leo Bosch said:

    Why const UINT32 n? I would just use UINT32 n, the source of the value can be a constant but for the function it’s just a variable.

    There is nothing wrong with "Const UNIT32 n" either. The source of the value can be a variable or an arithmetic expression but for the function it's just a constant. 

    Leo Bosch said:

    The volatile is unnecessary unless for debugging use.

    It is necessary to prevent the compiler to "optimize" and ignore it.

  • Chrishen,

    I do not see anything wrong in your delay function. But this function definitely can be interrupted but may not be re-entrant. Thus if it is interrupted and the ISR calls it again, it may not be able to resume correctly after the ISR finishes.

    Could you show us the compile object code of this function?

    -- OCY

  • Chrishen said:
    The program uses interrupts which also partly run the delay function.

    The problem is with the 32 bit math re-entrancy.

    Just use 2 nested loops for your delay.

    Peter

  • I see but don't understand why this is not reentrant? How to make it reentrant?

    PS: How can I view the object code? .obj-file reads just ...祡浟s⸮䴯偓...

  • I can only guess. One possibility is, the compiler allocated a fix location (rather than in the stack) in RAM for your i. Another possibility is, like what Peter said, when you do i--; a fix location in RAM is used to store an intermediate.

    I do not use c, so I do not know how to view object code of c source. Also, this depends on which compiler you use. I have seen lots of people in this forum posted parts of the object code of their c program.

    Which compiler do you use? May be some else can tell you how to show object code.

     

  • the use of volatile on local variables with auto storage is futile. The compiler knows that only the compiler knows where this variable is stored (register or stack) and that nobody else can access it, and writing to it or reading from it won’t have any side-effects. So depending on compiler implementation, the volatile keyword will be ignored and the compiler will optimize the loop. (regarding the C standard, 'volatile' is just a hint to the compiler)
    Things are different if the variable is a global one (declared outside the function) or if a reference to the local variable is passed to a called function or assigned to a global pointer variable.

    But even if volatile takes effect, it is still unknown how the compiler will translate the C code and therefore how long the delay will be.
    It is better to replace the loop by looping n times over a __delay_cycles() instruction. Here at least the execution time in MCLK cycles is known.

**Attention** This is a public forum