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

Selectively disable optimization on macro?

I have a macro:

#define EnterCritical()
  do {     SP++;     *(unsigned char idata *)(SP-1) = IE;     EA = 0;   } while (0);

that I call multiple times (along with its complement, ExitCritical()) in a particular function. With C51's optimization level set at 9, the optimizer is turning these in-line macros into a function and calling them -- this obviously won't work, due to the operations on SP.

Is there a way for me to maintain the OPTIMIZE(9,SIZE) settings for the module but ensure that the macro is left in its original in-line state whenever I invoke it?

Thanks,

Parents Reply Children
  • Opps, I forgot the &ltpre&gt and &lt/pre&gt tags. ( Sure would be nice if the following message was before the message box: "Use &ltpre&gt and &lt/pre&gt tags surrounding any code posted." )

    May I suggest this simpler, faster C code.

    void main()
    {
      //some code ..
      {
        bit ie = IE; IE = 0;
        //critical code ..
        IE = ie;
      }
      //some more code ..
    } 
    


  • Opps, I forgot the &ltpre&gt and &lt/pre&gt tags. ( Sure would be nice if the following message was before the message box: "Use &ltpre&gt and &lt/pre&gt tags surrounding any code posted." )<br>
    <br>
    May I suggest this simpler, faster C code.<br>
    <br>

    void main()
    {
      //some code ..
      {
        bit ie = IE; IE = 0;
        //critical code ..
        IE = ie;
      }
      //some more code ..
    } 
    
    <br>
    <br>

  • (I think the Forum messed up my last post -- it seems to have copied Jon's instead of what I wrote (I previewed it first, and saw after posting it was all wrong ... anyway -- here's what _I_ wrote:)

    Hi Jon.

    That's very elegant. But can I do a bit declaration anywhere in the code (i.e. wherever I insert this macro?). I seem to recall that I can, as long as it's inside a {...} block.

    Typically (but not always) my code looks something like what you've presented. But the problem is that in some instances, the Enter/ExitCritical() macros may be called more than once in a function and the number of each may not be equal (different "exit paths").

    Will your method still work? I have to ponder that a bit. It's a whole lot faster than pushing things on the stack, though ...

  • Why not use the @pragma disable before a function definition. For example:

    #pragma disable
    void function (void)
    {
    // Do non-interruptable stuff in here.
    }
    

    This generates the following code:

                 ; FUNCTION function (BEGIN)
    0000 D3                SETB    C
    0001 10AF01            JBC     EA,?C0002
    0004 C3                CLR     C
    0005         ?C0002:
    0005 C0D0              PUSH    PSW
    
    ; // Do non-interruptable stuff in here.
    
    0007 D0D0              POP     PSW
    0009 92AF              MOV     EA,C
    000B 22                RET     
                 ; FUNCTION function (END)

    As you can see, this routine saves the current state of EA (in the carry), clears EA, and saves the PSW on the stack.

    When the function exits, the PSW is popped from the stack and EA is restored (from the carry).

    The benefit here is that #pragma disable is immune to optimization. It also uses less memory than alternate methods.

    Jon

  • For personal preference I prefer the structured approach where I can clearly see the acquistion & release of this resource. Jon Ward's idea of using "#pragma disable" is even cleaner (but uses 1 byte vs 1 bit of ram and is slightly bigger in code). Of course if you need the speed, just save the IE bit when you acquire the interrupt lock and restore IE when you release the lock.

  • Hi Jon.

    That's an interesting idea.

    I have to see how that fits into the code, and how elegantly I can incorporate it into the preprocessor.

    Off the top of my head, I know of one place where my code requires attention when using this method. Look at this (inside a pragma-disabled function):

    ...
      for (many iterations) {
        do_something_looooooooong;
        enable interrupts;
        disable interrupts;
      }
    ...
    Here, we let interrupts "sneak in" at the end of each iteration, so that we don't have them disabled for the many iterations. Anyway, I had overlooked the disable pragma, and must give it some thought -- thanks. Andrew

  • I agree, your method gives finer-grain control.

    Andrew

  • Maybe you'll want to change that to...

    #pragma disable
    void do_something (void)
    {
    .
    .
    .
    }
    
    void do_something_loop (void)
    {
    .
    .
    .
    //enable interrupts
    .
    .
    .
    for (i = 0; i < ???; i++)
      do_something ();
    .
    .
    .
    }
    

    Jon