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

BL51: '*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL'

I am designing an application to run on the Si Labs
C8051F046 MCU with uVision 3. Yesterday I created a new
project, but forgot to include one of the source modules.
This produced a line during the link in the Output Window:

  *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL

I missed it, as this program generates many similar warnings:
  *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS

(in that tiny, little output window) which I must ignore.
Because L1 is only a warning; BL51 completed the build and
gave me a load module, which I attempted to debug. (It came
fairly close to working). I wasted an hour tracking the
cause back to this source.

I can't think of any scenario where I would want the build
to continue with missing source modules, yet I can find no
tool that would allow me to make L1 an error instead of a
warning. As best I can tell, this topic has never appeared
in the knowledge base or on this forum.

Does anybody have a differing opinion? A workaround?

Advance thanks for any insight.
============================================================
Gary Lynch            |     To send mail, change no$pam in
lynchg@no$pam.com     |     my domain name to stacoenergy

Parents Reply Children
  • "I can't think of any scenario where I would want the build to continue with missing source modules"

    How about If you were doing some sort of "incremental build", or you were building a Library that required some call-backs to be provided by the user?

    Anyhow, if the functions in those modules are never called, and the data is never accessed, what difference does it make!

    "yet I can find no tool that would allow me to make L1 an error instead of a warning."

    As soon as you actually try to reference one of the undefined symbols, that most certainly will give you an error.

  • On 5/10/06 8:16:52; A.W. Neil wrote:
    >
    > Why must you ignore them?
    >
    > Have you not just proved the folly of ignoring warnings?!
    >
    Several reasons:

    • This board is one of 5 using the same MCU. I frequently
      borrow a driver from one board to use on the other. The
      old driver may contain multiple functions which I have not
      yet implemented on the new hardware, and aren't called by
      my test suite.
    • I have developed a suite of functions I find extremely
      useful in debugging, but are not a part of the final
      application, which I keep in a separate source file. I
      don't call all of them when I need help debugging.
    • I implement a state machine with a table of function
      pointers. This interacts with an idiosyncracy of BL51
      to make it jump to the (erroneous) conclusion my
      functions are calling themselves recursively. Keil has
      an app note detailing a workaround for this, but it is
      such a hassle to get the syntax right, I frequently let
      BL51 whine.

    So although I don't expect to have any warnings in my final
    release, the debug process is not that simple.

    I also find it extremely difficult to review the list of
    warnings (accurately) in that little slit that passes for an
    output window. If anyone has found a way to pass the build
    output to a text file I could open with my text editor, that
    might make it worth the trouble.
    ============================================================
    Gary Lynch            |     To send mail, change no$pam in
    lynchg@no$pam.com     |     my domain name to stacoenergy

  • This interacts with an idiosyncracy of BL51
    to make it jump to the (erroneous) conclusion my
    functions are calling themselves recursively.


    The linker is not making any erroneus conclusions. It tries to construct a calling tree for your functions, but fails as soon as function pointers come into play since the Linker has absolutely no idea what values the function pointers will have during run-time. It therefore makes the right decision by not considering those functions for overlaying.

    Don't blame the linker for perfectly expected behavior.

  • I also find it extremely difficult to review the list of
    warnings (accurately) in that little slit that passes for an
    output window.


    Have you tried resizing the output window ? Works fine for me ...

  • "Have you tried resizing the output window ? Works fine for me ... "

    All the Linker messages are saved in the Linker Listing file (the "Map" file).

    Just as the compiler messages are in the compiler listing files.

    I think the build window content is also saved to a file - maybe .plg ?

    You can also copy-&-paste from the output window.

    With Windows XP, you could probably even get it to read the warnings to you out loud...

  • With Windows XP, you could probably even get it to read the warnings to you out loud...

    Doing this at your workplace without headphones would amount to severe Wally-esque behavior.

  • I think the build window content is also saved to a file - maybe .plg ?

    Yep. In HTML, no less.

  • On 5/10/06 8:24:01; erik malund wrote:
    >
    > Many decide to ignore warnings, that may be OK during
    > development, but there is a difference between "ignore" and
    > "not read"
    >
    > I may ignore warnings during development, but I ALWAYS read
    > them
    >
    Ok, so oversimplified my process. I read ALL the warnings
    the first time I link a new module and take action as
    indicated. But some of them are not eliminatable.

    Thereafter I only read the body of the warnings if the
    NUMBER of warnings changes from the prior build. In the
    case cited, I went too fast and confused "UNRESOLVED" with
    "UNCALLED".

    Then at 5/10/06 8:23:07; A.W. Neil wrote:
    >
    > How about If you were doing some sort of "incremental
    > build", or you were building a Library that required some
    > call-backs to be provided by the user?
    >
    Ok, I'll grant you that scenario. It's just that I've never
    used it.

    >
    > Anyhow, if the functions in those modules are never called,
    > and the data is never accessed, what difference does it
    > make!
    >
    <snip>
    >
    > As soon as you actually try to reference one of the
    > undefined symbols, that most certainly will give you an
    > error.
    >
    Well, you want the dirty details, here they are. The source
    containing the main() function looks like (names have been
    changed to protect the guilty):

    while(1) {
      for(j=0; j<6; j++) {   | ?C0001: CLR     A        ;  1
                             |         MOV     j,A      ;  2
                             |         MOV     j+01H,A  ;  3
                             | ?C0003: CLR     C        ;  4
                             |         MOV     A,j+01H  ;  5
                             |         SUBB    A,#06H   ;  6
                             |         MOV     A,j      ;  7
                             |         SUBB    A,#00H   ;  8
                             |         JNC     ?C0001   ;  9
        doFoo(2, j);         |         MOV     R5,j+01H ; 10
                             |         MOV     R7,#02H  ; 11
                             |         LCALL   _doFoo   ; 12
        wait(4473);          |         MOV     R7,#079H ; 13
                             |         MOV     R6,#011H ; 14
                             |         LCALL   _wait    ; 15
      }                      |         INC     j+01H    ; 16
                             |         MOV     A,j+01H  ; 17
                             |         JNZ     ?C0007   ; 18
                             |         INC     j        ; 19
                             | ?C0007: SJMP    ?C0003   ; 20
                             |         RET              ; 21
    } /* END while(1) */     |                          ; 22
    

    I tacked the assembly produced by C51 onto the right side
    for reasons that will become apparent later. I also added
    line numbers to facilitate discussion. Variable j is an
    unsigned int.

    The module I forgot to add holds function wait() (which is a
    thumb-twiddling loop whose execution time I can control with
    the argument shown). The object module produced by the
    compiler sets wait()'s address to dummy value c:0x0000
    (a.k.a. your friendly neighborhood power-up vector).

    The linker issues its warning:

    *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
        SYMBOL:  _WAIT
        MODULE:  TestFoo.obj (TESTFOO)
        ADDRESS: 01BEH
    

    and the execution module gets built, assuming wait() is
    still at 0000.

    As compiled, the "j=0" part of the for-loop consists of the 3
    instructions beginning at line 1; the "j<6" code is in
    lines 4-9, while the "j++" term resides in lines 16-19.

    This baby executes exactly as I intended until we get to the
    call to wait(). At this point, it performs the moral
    equivalent of a power-on reset, putting control back at the
    top of the loop with j=0. Thus my program executes the
    infinite loop I had wanted, but j never deviates from 0.

    This is the scenario that prompted this post.
    ============================================================
    Gary Lynch            |     To send mail, change no$pam in
    lynchg@no$pam.com     |     my domain name to stacoenergy