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.
Hello all, My goal is to get some variables placed in EEPROM without hardcoding it to a fixed address (using the _at_ keyword is unfortunately not an option). The variable shall be assigned to a certain segment and then the linker should take care of the rest. The problem is that the RAM of the chip is within the same address-range (xdata) as the EEPROM and Keil seems to make use of xdata in a linear structure so that it will first use up all the RAM (0-0x03FF) before it starts placing variables in EEPROM (0x03FF-0xFFFF). I know that theres a USERCLASS-directive which the kind people here at Keil pointed out to me, but I cannot get it working. I tried every possible combination I can think of and also all the tips I got from Keil-support but no luck yet. Do you have any suggestions as to what I might change or what Im doing wrong ? Ive posted a small program that demonstrates the problem. The challenge is to get variable B placed inside the XDATA_DANSCLASS area of the xdata, that is between 0x3000 and 0x4000 of xdata. If you can do that please let me know !!! As the project is now it will compile but not without a linker-error (L107) "Address Space Overflow" Why this problem ??? If you look at the map-file theres lots of space left, - I cant see why the linker complaints about this ? Please dont hesitate to post a message if you need more info in order to help. Heres the source:
#pragma userclass (xdata = DansClass) #define DansClass xdata void main() { unsigned char A; DansClass unsigned char B[0x80]; A=0; B[0]=A; }
CPU MODE: 8051 MODE MEMORY MODEL: LARGE ACTIVE MEMORY CLASSES OF MODULE: Test (MAIN) BASE START END USED MEMORY CLASS ========================================================== X:000000H X:003000H X:004000H XDATA_DANSCLASS C:000000H C:000000H C:00FFFFH 000015H CODE I:000000H I:000000H I:0000FFH 000001H IDATA I:000000H I:000000H I:00007FH 000008H DATA X:000000H X:000000H X:00FFFFH 000080H XDATA MEMORY MAP OF MODULE: Test (MAIN) START STOP LENGTH ALIGN RELOC MEMORY CLASS SEGMENT NAME ========================================================================= * * * * * * * * * * * D A T A M E M O R Y * * * * * * * * * * * * * 000000H 000007H 000008H --- AT.. DATA "REG BANK 0" 000008H 000008H 000001H BYTE UNIT IDATA ?STACK * * * * * * * * * * * C O D E M E M O R Y * * * * * * * * * * * * * 000000H 000002H 000003H --- OFFS.. CODE ?CO??C_STARTUP?0 000003H 00000EH 00000CH BYTE UNIT CODE ?C_C51STARTUP 00000FH 000014H 000006H BYTE UNIT CODE ?PR?MAIN?MAIN * * * * * * * * * * * X D A T A M E M O R Y * * * * * * * * * * * * * 000000H 00007FH 000080H BYTE UNIT XDATA _XDATA_GROUP_ OVERLAY MAP OF MODULE: Test (MAIN) FUNCTION/MODULE XDATA_GROUP --> CALLED FUNCTION/MODULE START STOP ======================================= ?C_C51STARTUP ----- ----- +--> ?PR?MAIN?MAIN MAIN/MAIN ----- ----- PUBLIC SYMBOLS OF MODULE: Test (MAIN) VALUE CLASS TYPE PUBLIC SYMBOL NAME ================================================= 00000000H NUMBER --- ?C?CODESEG 00000000H NUMBER --- ?C?XDATASEG LX51 LINKER/LOCATER V3.58 0100000FH CODE --- ?C_START 01000000H CODE --- ?C_STARTUP 0100000FH CODE --- main SYMBOL TABLE OF MODULE: Test (MAIN) VALUE REP CLASS TYPE SYMBOL NAME ==================================================== --- MODULE --- --- MAIN 0100000FH PUBLIC CODE --- main 0100000FH BLOCK CODE --- LVL=0 0100000FH BLOCK CODE NEAR LAB LVL=1 00000007H SYMBOL DATA BYTE A 02000000H SYMBOL XDATA --- B --- BLOCKEND --- --- LVL=1 0100000FH LINE CODE --- #4 0100000FH LINE CODE --- #5 0100000FH LINE CODE --- #10 01000010H LINE CODE --- #11 01000014H LINE CODE --- #12 --- BLOCKEND --- --- LVL=0 --- MODULE --- --- ?C_STARTUP 01000000H PUBLIC CODE --- ?C_STARTUP Program Size: data=9.0 xdata=128 const=0 code=21 LX51 RUN COMPLETE. 0 WARNING(S), 0 ERROR(S)
This was stated in the C51 User's Guide under the USERCLASS Directive: "The USERCLASS directive renames the basic class name for a complete module, but not overlayable segments." I have updated this manual page to be more explicit: "The USERCLASS directive renames the basic class name for an entire module. Overlayable segments (typically local variables in C functions) are not renamed. To rename a local variable, you must change its allocation type to static by including the static keyword in the variable definition." Jon
Thankyou very much Mr. Ward That helped a lot, in fact it seems to me that this will solve my problem. I fully support the update of the manual page and its a very good idea. Regarding userclasses and the use of hereof the manual could be more descriptive as you mention it yourself and in my opinion the example is not self-explanatory, its quite difficult to see the logic in the example. Thanks again ! I really appreciate your help :) Best regards, Dan Eckberg
The solution works, however it only works for local variables (inside the module). Let me explain. We have a key word "_EEPROM" which we use throughout our code for creating EEPROM variables. When using the Keil compiler we define this key word to "static xdata" in order to place variables with this key word in EEPROM. But this gives us a problem when we reference the variables from other scopes, as we then have "extern _EEPROM bTest" which equals to "extern static xdata bTest" - and that doesn't make sense! We want to keep a high level of portability, which is why we need to keep the _EEPROM key word. Is there an other way to define and place variables in an user defined eeprom segment, than using the static key word? Regards, Dan Eckberg
Is there an other way to define and place variables in an user defined eeprom segment, than using the static key word? Uhh, I never said you had to use static on your global variables. And, local variables (those declared inside a function) cannot have global scope no matter what. The only reason static is required is because local variables are local and do not have continuous lifetime. By default, local variables are overlayed. Since overlayable segments can't be renamed using user classes, you need to change them from overlayable to non-overlayable. The static keyword is one way to do this. Take a look at USERCLASS in the C51 User's Guide. I added an example that may clarify this a bit. http://www.keil.com/support/man/docs/c51/c51_userclass.htm Jon