This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Optimization Assembly Problems

Hello everyone,

I am currently having an issue with some code I have that seems to vary based on optimization:


In CommBuff ISR:



if (commData == 0x61)   /* 0x61 = 'a' */
{
        if(DAC1DifVoltn==1)
        {
                DigPressure1 = DiffPressure1;  // Enters this section, problem here
        }
        else
        {
                DigPressure1 = Pressure1>>3;
        }
        COMBUF = DigPressure1>>8;
}
else if (commData == 0x62)      /* 0x62 = 'b' */
{
        COMBUF = DigPressure1;
}

Currently, DAC1DifVoltn is set to 1. When the COMBUF register gets a 0x61, it updates DigPressure1 and puts out the MSB on the COMBUF. When it receives 0x62, it sends out the LSB bits.

The problem I'm having is with the line:

DigPressure1 = DiffPressure1;

DiffPressure1 is set to 0x0FF8. When optimization is set to 4-8, DigPressure1 is set to 0x0097. When it's set to 3, it gets 0x0F97. When it's set to 2-0, it gets the correct value (0x0FF8). Realistically, this has to do with the way my code is written rather than it being an assembly issue but I can't seem to see a better way to handle this.

Does anyone have any explanations as to what I can do? If you need me to post the assembly code, I can do that as well. Any help would be appreciated. Thanks!

Parents
  • The question I have is is this something that was done by Keil (since changing that checkbox fixed it) or is this something that was done/could have been avoided by me and if so, how?

    A bit of both. But it's mostly your fault, for not paying enough attention to the documentation.

    You called a function (the only one you've actually shown here) from another one that assumed a different register bank (your actual __interrrupt function). That is known and documented to cause incorrect program behaviour. So you shouldn't have done that.

Reply
  • The question I have is is this something that was done by Keil (since changing that checkbox fixed it) or is this something that was done/could have been avoided by me and if so, how?

    A bit of both. But it's mostly your fault, for not paying enough attention to the documentation.

    You called a function (the only one you've actually shown here) from another one that assumed a different register bank (your actual __interrrupt function). That is known and documented to cause incorrect program behaviour. So you shouldn't have done that.

Children
  • Bah, rookie mistake on my end! I posted the code I thought was relevant but probably masked the real problem: calling a function from within an ISR (as Eric alluded to). I moved the function call code to within the ISR and the problem seems to have disappeared with me, even with the disable direct addressing box unchecked. I really should know better than to do this!

    Thanks for the insight and links, everyone! I learned a lot from this (like I need to BE MORE CAREFUL). I appreciate the patience and explanations.

  • rookie mistake on my end
    two comments:
    1) you alluded in a previous post that you might have atomicity problems, carefully make sure you do not a)
    2) avoid calling subroutines from an ISR b)

    a) to obtain a variable longer than 8 bits used in an ISR from main

    EAsave =EA;
    EA = 0;
    local variable = shared variable;
    EA= EAsave;
    

    b)calling a subroutine from an ISR is wrong for 3 reasons: 1) it makes the ISR slower; 2) if you need to for clarity purposes, your ISr is already too complex to adhere to KISS and 3) not having a subroutine makes the mistake of calling a subroutine from main and ISr impossible.

    Erik