We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I haven't received an answer that fixed my problem, so here is another example.
I have a simple printf statement that causes a L103 error. No variables declared. Includes "stdio.h" and links in C51FPL.LIB. Others LIBs don't seem to link correctly either. Code compiles fine. Anyone know what the linking problem could be?
#include "stdio.h"
main() { printf("12345"); }
BL51 BANKED LINKER/LOCATER V5.12 COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2004
*** ERROR L103: EXTERNAL ATTRIBUT DO NOT MATCH PUBLIC SYMBOL: ?_PRINTF?BYTE MODULE: C51FPL.LIB (PRINTF)
Program Size: data=15.1 xdata=48 code=2562 LINK/LOCATE RUN COMPLETE. 0 WARNING(S), 1 ERROR(S)
So why did you have to start a new thread? Why not continue in the existing thread?
http://www.keil.com/forum/docs/thread9814.asp
C51FPL.LIB is the library for the Large memory model with Floating-Point support.
Is your source compiled for the Large memory model?
Yes, I am using the ROM(Large) option in the compile. I kept it that way for this code snippet, because that is how it is set up in my project code that exhibits the same linker error.
OK. When I used C51S.LIB, the simple file linked fine. Which brings up the question of Why? I can't use the small LIB files, because my project code is about 9K. Using the compact module or the large module doesn't link correctly - same L103 error. I looked in the A51 .pdf from Keil at the Linker section and couldn't find anything on the different LIBs in the Keil LIB folder.
Sutton
Sutton; I don't have a direct answer for your printf problem but I detect a mis-understanding of memory models on your part.
I can't use the small LIB files, because my project code is about 9K
The memory model dialog defines the implicit area for vars storage. Selecting the large memory model gives the compiler/linker permission to place all vars in xdata area. Bad for rapid access of frequently used vars. You should leave the memory model set at small and explicitly define your large vars such as arrays and struct to xdata. Also, define infrequently used vars to xdata and let the tools place locals and autos in data/idata areas. The tools can then over write any vars that go out of scope during program run. This will speed up your code and some what reduce code size but more important, correct libs can be selected by the compiler/linker tools. I know a very indirect answer to your post and I hope I haven't raised another smoke screen for you. Bradford
"You should leave the memory model set at small and explicitly define your large vars such as arrays and struct to xdata."
I understand that. I can't use the small model because of the code restriction < 2K. I get IMPROPER FIXUP linker errors. I have explicitly defined most of my variables to be XDATA long ago, so that's not the issue. I simply want to use printf and sprintf in my code, but all links produce the L103 error. And, I haven't figured it out yet. Compact or large module causes same error.
So, I found a simple snippet that produces the same error, but nobody seems to be able to figure out what the problem is. And, I'm stuck until I do.
Sutton; Just re-read your last post ans I indeed raised a smoke screen.
Yes, I am using the ROM(Large) option in the compile.
Selecting Code Rom Size Large: 64K program is the correct default. This allows the compiler to use both LCALL/LJMP as well as ACALL/AJMP instructions. It does not define a fixed requirement for Large Libs.
Under the drop down dialog Components,Enviorment and Books, select the Folders/Extensions tab and look at how the Tools Base Folder is defined. By default, it should be Using Setting from TOOLS.INI check box and the Base Folder should point to your Keil installation. If you have copied or moved your installations files, the tools.ini file will be corrupted and the tools can't access the correct Lib folders. In this case you can un-check the Settings box and browse each of the folder entries to the correct directories even if they are in the same position as the original installation. The Keil tools can then locate correct lib files. Bradford
Sutton; While I was typing my second post you answered my first post so we are out about 90deg at present. Let's review quickly. Set the Memory Model to Small. Set the Code ROM Size to Large. Review the Extension folder tabs for correct settings. What device type are you using? What On-Chip and/or Off Chip RAM and ROM setting do you have set-up? I will attempt to duplicate you problem. Bradford
I'm using command line for this C51 project. I use uVision for my ARM project. So, what kind of compiles and links do you want me to do from the command line?
Also, I've found out that using either ROM(large) or ROM(compact) does link in the printf and sprintf correctly with the C51S.LIB. So, problem solved temporarily. It does not link, however, with C51L.LIB or C51C.LIB (error L103). Why is that? Where do I find out how those functions are defined in those LIBS. I guess that defines my ultimate question(s).
My simple code compiles and links properly with C51S.LIB (but not with other LIBs - L103 error). Still would like to know why that is.
However, with this code,
#include <stdio.h>
main() { unsigned char idata x, text[15];
x = 12; sprintf(text,"%d Volts",x); }
the value of text is '3072 Volts' in my variable watchbox. The value of x is always 12. There is something going on with the arguments that sprintf has in the Keil LIB. However, there is no source code in the Keil folders to look at. Anybody have any ideas why this simple Keil sprintf is not working? Using V7.50 of the compiler. Thanks.
Do you have ANSI integer promotion enabled?
The format string in your printf is "%d", which is to say an integer, which means 2 bytes for C51. However, you pass it "x", which is declared as char -- 1 byte. This means the actual data passed to printf does not match what the format tells printf() to process, and you will not get the expected results.
Keil introduced a 'b' modifier for 1-byte integers, e.g. "%bd".
The alternative is to enable ANSI integer promotion, which means ALL single-byte parameters to ALL functions will be passed as two-byte integers instead of one byte. This usually means a fair amount of extra, unneeded code.
DOH....That was it. Should have figured that out myself.
"My simple code compiles and links properly with C51S.LIB (but not with other LIBs - L103 error). Still would like to know why that is."
The answer to that is in my very first reply in your original thread.
Hint: The 'S' in C51S.LIB indicates that it is for the Small memory model...
I know what the S,C, and L memory modules stand for. I've been using them for many years. But, that still doesn't answer the question of:
'sprintf' compiles and links fine with a Compact memory module but ONLY with the small libraries (C51S.LIB). It does NOT link properly with the compact or large LIBs (C51C.LIB or C51L.LIB). It gives L103 errors. Why? So, another question is what is the correlation between the memory modules and the LIBS? My first inclination is nothing. Sorry for being so long winded, but none of the postings have answered my question. Please try again.
And actually, if I compile and link a simple 'sprintf' statement with a small memory module with C51FPS.LIB, I get L121 (Invalid Fixup) errors. Why is that? All my variables are explicitly defined as IDATA (or XDATA or whatever). If I link it with C51S.LIB, no problems.
"I know what the S,C, and L memory modules stand for"
NB: It's model - not module.
OK. I was wrong on the terminology.
Also, I am using the command line for compiling and linking, when I get these linker errors. Seems to work OK in uVision. But, I still don't know why the command line linker errors are happening.