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 am trying to locate const in a file into a particular bank and access it in the same bank but from a different file. From the map file const is located correctly at the specified address in the bank. However the compiled code to access this const references an address 0 instead of the const address.
Here is a simple banking application...
datafile.c contains
unsigned char const code message0[] = {'a','b','c','\n'};
C_MESS0.c contains
extern unsigned char const code message0[]; unsigned char const code message7[] = {'d','e','f','\n'}; void mess0func() { char x; x = message0[0]; printf("%c", x); x = message7[0]; printf("%c", x); }
Both files are configured for bank 0 in the IDE. Code banking is selected with two banks and starting address 0x8000. User segment in the IDE is set to ?CO?datafile(B0:0x8000), ?CO?C_MESS0(B0:0x82f0).
The map file contains
00808004H CODE/B0 --- mess0func 00808000H CONST/B0 --- message0 008082F3H CODE/B0 --- message7
When I see the .cod file generated by the linker...
21: x = message0[0]; B0:008004 900000 MOV DPTR,#message0 B0:008007 E4 CLR A B0:008008 93 MOVC A,@A+DPTR B0:008009 F508 MOV x,A 22: printf("%c", x); B0:00800B 7BFF MOV R3,#0FFH B0:00800D 7A82 MOV R2,#HIGH 010082F0H B0:00800F 79F0 MOV R1,#LOW 010082F0H B0:008011 85080C MOV ?_printf?BYTE+03H,x B0:008014 1200A3 LCALL _printf 23: x = message7[0]; B0:008017 9082F3 MOV DPTR,#message7 B0:00801A E4 CLR A B0:00801B 93 MOVC A,@A+DPTR B0:00801C F508 MOV x,A 24: printf("%c", x);
Notice that the first assembly line is 900000 instead of 908000
It appears that const is processed correctly in the same file but not in a different file.
I can't figure out what I am missing?
Build parameters: C51 control string: OBJECTADVANCED OPTIMIZE (6,SPEED) BROWSE DEBUG CODE SYMBOLS AX51 : GENONLY SET (SMALL) DEBUG XREF EP LX51: TO "BANK_EX2" BankArea (0x008000, 0x0082FF) CODE IXREF SEGMENTS ( ?CO?datafile(B0:0x8000), ?CO?C_MESS0(B0:0x82f0) )
Here are the tools used..
IDE-Version: µVision3 V3.72 Copyright (c) Keil Elektronik GmbH / Keil Software, Inc. 1995 - 2008
Tool Version Numbers: Toolchain: PK51 Prof. Developers Kit Version: 8.06 Toolchain Path: C:\Keil\C51\BIN\ C Compiler: C51.Exe V8.06 Assembler: AX51.Exe V3.02 Linker/Locator: LX51.Exe V4.10a Librarian: LIBX51.Exe V4.24 Hex Converter: OHX51.Exe V1.36b CPU DLL: S8051.DLL V3.64 Dialog DLL: DP51.DLL V2.48f Target DLL: BIN\MON51.DLL V2.41 Dialog DLL: TP51.DLL V2.48f
The issue here seems to me that the linker cannot tell from the declaration where to locate the const buffer. I would have expected it to end up in the common, unbanked area.
As far as I understand XBANKING.A51 in the Cx51 documentation, "far const" is used to put global constants into the common area. I don't think forcing into a specific bank is actually supported. I.e. banked const should only be accessed from the same .c file, because others may be put into a different bank.
As long as you don't run out of common, unbanked space, it seems to me "far const" is your best bet for working code.
Note that this is purely speculative — I don't have banked code to test this.
From my understanding the linker has located the const (message0) in B0, as it appears from the map file. But is not able to link it correctly.
By moving const data into a particular bank I am trying to ensure space for this data is utilized only when needed. The const data is never used outside the bank, so it would not be ideal to locate it in common area. I can include it in the C file that it is being used in (which solves the problem), but there may be multiple C files in the future and it makes it clunky.
You can find example banking code in Keil\C51\Examples\CodeBanking
I think your only choice is to define your own memory class for each bank in which you want to share globals.