Possible compiler bug.

Hi,

I am having trouble with an ISR for a C++ VDK project, the code of which is shown below. I have found that the code if(*pSIC_ISR & 0x00001800) never resolves to TRUE but if I first save the value of *pSIC_ISR to an intermediate variable and use that instead (as shown) it works fine. The really strange thing is that I have to do this for the UART handler but not for the TWI handler below it. I have tried swapping the order of the code so that the TWI is dealt with first but this makes no difference. I have used the debugger to check that the 0x00001000 flag is being set in the SIC_ISR. Am I missing something obvious or is this a compiler bug? The fact that it works OK when testing the 0x00000200 flag but not the 0x00001000 flag is very strange.

Anyone any ideas,

Thanks,

Peter.

#ifdef VDK_REENTRANT_ISR
EX_REENTRANT_HANDLER(EVT_IVG11_Entry)
#else
EX_INTERRUPT_HANDLER(EVT_IVG11_Entry)
#endif
{
    // Use this value to hold the interrupt flags so we can read the status multiple times without clearing the interrupt.
    int intPending = 0;
   
    // Use this value to hold the SIC_ISR as using it directly doesn't always seem to work.
    unsigned long sic_isr = *pSIC_ISR;


     /************************************************************************
     *                                                                        *
     *                                UART0/1                                    *   
     *                                                                        *
     ************************************************************************/
    
    // Deal with UART0 Rx/Tx.
    intPending = *pUART0_IIR;            // Save contents of IIR (will clear the interrupt).
          if(sic_isr & 0x00001800)               // OK
     //if(*pSIC_ISR & 0x00001800)           // never works

     {
        g_lpUART0->InterruptHandler(intPending);
     }
   
    /************************************************************************
     *                                                                        *
     *                                TWI                                        *   
     *                                                                        *
     ************************************************************************/


     // Don't need to save contents of TWI_INT_STAT as reading it doesn't clear the interrupt.
    if((*pSIC_ISR & 0x00000200) && (*pTWI_INT_STAT & 0xf0) && (g_lpTWIDriver != NULL))
    {
        g_lpTWIDriver->InterruptHandler(*pTWI_INT_STAT);
    }
}

  • I should add that I am developing for the BF534 on a custom board.

    Peter.

  • Hi Peter,

    are you using optimization in your build? My first suspicion is that the pSIC_ISR variable is not being declared as volatile, so the Compiler is not aware that this value can change without its knowledge.

    If you think that may be the case, take a look at this FAQ for more information: FAQ: Why does my code stop working when I enable optimization?

    The TWI "if" contains other conditions, that may reduce the assumptions the compiler is able to make when optimizing that particular section of the routine.

    If the problem persists, could you please provide an example project that we can reproduce the behaviour with, and let us know which version and update of VisualDSP++ you are using. e.g. VisualDSP++ 5.0 Update 10.

    Regards,

    Craig.

  • Hi Craig,

    Thanks for the reply. The variable pSIC_ISR is actually declared as shown below in the ADI supplied header cdefBF534.h.

                        #define pSIC_ISR         ((volatile unsigned long  *)SIC_ISR)

    The project does not have optimization enabled and in fact was created using default project options. I get the same result with both debug and release builds.

    I did try removing the other conditions from the TWI 'if' which had no effect - it still didn't work. When I single-stepped through the code using the debugger I found that the 0x00001000 flag could be set but the execution path still missed out the body of the 'if'.

    As it always works for the 0x0200 flag but not the 0x1000 flag could it be that the compiler is using different assembler commands according to the immediate operand (0x200 or 0x1000) it is being given?

    I am using Visual DSP++ 5.0, update 9.1.

    Thanks,

    Peter.

  • Hi Craig,

    Attached is a stripped-down version of the project. This should transmit a sequence of strings from UART0 which you could monitor using HyperTerminal or similar. This behaves (and misbehaves) in exactly the way I have described earlier. I ran it using the ICE-100B on our custom board.

    Peter.

  • Great, thanks for letting us know that you tracked the issue down.

    Regards,

    Craig.