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

Why some functions got WARNING L15, while others not!

Hi,
I have several functions called in T0 isr. The outline of call tree like this:

void T0_isr() interrupt 1 {
    getkey();
}

void getkey() {
    char c;
    c = filterGetKeyCode();
}

char filterGetKeyCode() {
    char c;
    c = getKeyCode();
    return c;
}

char getKeyCode() {
    char c;
    char cd;
    // c be assigned somehow
    cd = encodeFlex(c);
    c = decode(cd);
    return c;
}

char encodeFlex(char c) {
    return encode(c);
}

char encode(char);

char decode(char);
Now linker reports (simplified):
Warning 15: multiple call to segment
segment: getKeyCode
caller1: T0_isr
caller2: c_c51stratup

Warning 15: multiple call to segment
segment: encodeFlex
caller1: T0_isr
caller2: c_c51startup

My question is: why getKeyCode and encodeFlex incur warnings, while others, like decode, passed by linker.
When I disoverlay getKeyCode, and declare encodeFlex with reentrant, the warnings all disappear. But I still worry about other functions called in isr. Is it safe now?

Thanks in advance.

d.curie

Parents
  • Warning 15: multiple call to segment
    segment: getKeyCode
    caller1: T0_isr
    caller2: c_c51stratup
    This is telling you that getKeyCode is called from both your main 'C' code (indicated by c51stratup) and from your T0_isr interrupt service routine.

    This is potentially dangerous because C51 functions are inherently non-reentrant; eg,
    If getKeyCode is running (from somewhere called by main) when the interrupt occurs, getKeyCode will be called again - which will corrupt parameters & local variables.

    I you are absolutely certain that this can never occur - you can safely ignore the warning.

    "I have several functions called in T0 isr."

    This is generally not a good idea.
    It's usually better to have the ISR just do very simple stuff - like setting a flag - and then do the real work in the "mainline" code.

Reply
  • Warning 15: multiple call to segment
    segment: getKeyCode
    caller1: T0_isr
    caller2: c_c51stratup
    This is telling you that getKeyCode is called from both your main 'C' code (indicated by c51stratup) and from your T0_isr interrupt service routine.

    This is potentially dangerous because C51 functions are inherently non-reentrant; eg,
    If getKeyCode is running (from somewhere called by main) when the interrupt occurs, getKeyCode will be called again - which will corrupt parameters & local variables.

    I you are absolutely certain that this can never occur - you can safely ignore the warning.

    "I have several functions called in T0 isr."

    This is generally not a good idea.
    It's usually better to have the ISR just do very simple stuff - like setting a flag - and then do the real work in the "mainline" code.

Children
  • Thanks everybody.
    Yes, I must have misused the term call tree in my last post. But the code presented there is exactly the thing I wanted to provide, since that's all that is concerned with my problem (I means the rest of my program never called those functions). The purpose of the code is to show the identical position the function encodeFlex and decode hold. However, the former got warning, while the latter passed.
    Yes, maybe I need to check the manual more carefully.
    I did often employ the framework with " no call in isr" in my program. But in this case, I think it's more natural to scan the keyboard in the timer's isr at regular interval.
    Thanks again.

    d.curie

  • It's not a matter of whether the code is in the same position in the routine that you show. It's a matter of whether either of those routines is called from some other context elsewhere in the program.

    In the snippet posted, the only calling context shown is the ISR.

    T0_isr
        getkey
            filterGetKeyCode
                getKeyCode
                    decode
                    encodeFlex
                        encode
    

    As it stands, that bit of code is fine. There's only one path to call to either decode or encodeFlex.

    But if there's code somewhere else that we can't see -- descended from main(), or another ISR -- that calls encodeFlex() but not decode(), you would get exactly the warnings you reported: a "multiple call to segment" for encodeFlex(), and no warning for decode() since there wasn't a multiple call. The warning means that two independent call trees both call the same routine at some point.

    The map file shows you the call tree for the program (one level at a time, at any rate).

  • "The map file shows you the call tree for the program (one level at a time, at any rate)."

    The uVision Code Browser shows you the full call tree.
    It can also show its converse - the Caller Tree.

    So, just take a look at the Caller Tree (or "Caller Graph") for those functions...

  • Ok, I'll check the map to make sure that the rest of my program did not call those routines mentioned above.

    d.curie

  • "Ok, I'll check the map..."

    I think you'll find the Browser easier!

  • When checking the call map, I eventually found where the multiply calls occurred. There are two callers to _getkey, a function implemented in a project-specific way to override the library function with the same name in stdio.lib. I explicitly called _getkey in T0_isr, and again I implicitly called _getkey in scrollDigit since it calls sscanf, which in turn calls getchar, which then call _getkey. All related call branches are listed as follows.

    ?PR?GETKEYCODE?KEYBOARD_P
      +--> ?PR?_DECODE38?FUNC
      +--> ?PR?_ENCODE83FLEX?FUNC
    
    ?PR?_ENCODE83FLEX?FUNC
      +--> ?PR?_ENCODE83?FUNC
    
    ?PR?FILTERKEYCODE?KEYBOARD_P
      +--> ?PR?GETKEYCODE?KEYBOARD_P
    
    ?PR?_GETKEY?KEYBOARD_P
      +--> ?PR?FILTERKEYCODE?KEYBOARD_P
      +--> ?PR?_TOASCII?KEYBOARD_P
      +--> ?PR?_LOADKEYQUEUE?KEYBOARD_P
    
    ?PR?T0_ISR?T0_ISR
      +--> ?PR?_GETKEY?KEYBOARD_P
    
    ?PR?_SCROLLDIGIT?GUI
      +--> ?CO?GUI
      +--> ?PR?PRINTF?PRINTF
      +--> ?PR?SCANF?SCANF
      +--> ?PR?_TEXTOUT?GUI
    
    ?PR?SCANF?SCANF
      +--> ?PR?GETCHAR?UNGETCHAR
      +--> ?PR?_ISSPACE?ISSPACE
      +--> ?PR?GETCHAR?GETCHAR
      +--> ?PR??C?ATOF??C?ATOF
    
    ?PR?GETCHAR?GETCHAR
      +--> ?PR?_GETKEY?KEYBOARD_P
      +--> ?PR?PUTCHAR?PUTCHAR
    
    But my original question is still there! Why encode83flex get warning, whereas decode38 not?
    And a new question arises: I invoke sscanf in scrollDigit, but the call map above shows scanf is called instead! In my opinion, sscanf should not call getchar (in turn _getkey) even though scanf does.