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
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
============================================================ Gary Lynch | To send mail, change no$pam in lynchg@no$pam.com | my domain name to stacoenergy
"this program generates many similar warnings ... which I must ignore." Why must you ignore them? Have you not just proved the folly of ignoring warnings?!
"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.
which I must ignore. Because L1 is only a warning; 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 I can't think of any scenario where I would want the a) build to continue with missing source modules, b) yet I can find no tool that would allow me to make L1 an error instead of a warning. a) the warning is NOT "missing source module" but "missing reference" I often accept a build when that comes up. e.g. in the first stages of a debug, you may have a function that is not called with an unresolved reference. b) such an option might be nice. Erik
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 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.
"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." I'd say that's almost certainly the reason why your application failed in the first place!! You've read the app note, so you know that this is due to a fundamental feature of the 8051 architecture. If you disregard that and and just plough on regardless, you are positively asking for trouble! Yes, tables of function pointers are great for implementing state machines - but you have to weigh this against their cost on the 8051 (ie, having to cope with the Linker's foibles). If getting the tools configured is too much for you, then you need to look for another solution. Personally, I'd have loved to have used my normal function-pointer table approach to FSMs, but found all the manual Linker tweaking far too risky - so I used switches instead. Your call.
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
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: _WAIT MODULE: TestFoo.obj (TESTFOO) ADDRESS: 01BEH
There seems to be two communities of users of the Keil '51 software: There is the "C is C" community that refuse to accept that the '51 is weak in certain respects which makes it advisable to avoid certain constructs. I guess that those also do not use the unique features of the '51 that makes it strong in other respects: I implement a state machine with a table of function pointers Then there is those that adapt to the realities: Personally, I'd have loved to have used my normal function-pointer table approach to FSMs, but found all the manual Linker tweaking far too risky - so I used switches instead. Erik
I think it should be possible to use function pointers in C51 without having to manually tweak the Linker's call tree? On the other hand, I know that the switch approach works. Hence my choice!
I think it should be possible to use function pointers in C51 without having to manually tweak the Linker's call tree? But you have nevertheless accepted reality :) Everyone has something they would like to see different, it may and may not be included in the next release. Do I have 'things', absolutely. Do I sit doen and whine about them? abaolutely not. Now, for a real BUG. I would send 47 e-mails every day till it was fixed. Erik