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
  • 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

Reply
  • 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

Children
  • 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

  • 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