I am trying to find the best places to save some DATA storage to use it in a more speed sensitive area. Looking at the map, I see the following:
TYPE BASE LENGTH RELOCATION SEGMENT NAME ----------------------------------------------------- * * * * * * * D A T A M E M O R Y * * * * * * * REG 0000H 0008H ABSOLUTE "REG BANK 0" REG 0008H 0008H ABSOLUTE "REG BANK 1" REG 0010H 0008H ABSOLUTE "REG BANK 2" DATA 0018H 0003H UNIT _DATA_GROUP_ IDATA 001BH 0005H UNIT ?ID?AVMAIN BIT 0020H.0 0001H.2 UNIT ?BI?AVMAIN
Jon, all references to "main" in the first post refer to the main MODULE, not the Main function. OOPS I forgot, I have a .h that include all global variables these are defined in the main module. Anyhow, it is wrong/stupid/incorrect (you pick the word) to locate idata variables in the precious space below 0x80. Erik
Anyhow, it is wrong/stupid/incorrect (you pick the word) to locate idata variables in the precious space below 0x80. It is neither wrong, stupid, nor incorrect to locate IDATA variables below 0x80. If that space is not used for anything else, what's wrong with using it for IDATA? Packing DATA, followed by IDATA, followed by the STACK maximizes stack space. The linker uses a well-though-out process for locating variables in on-chip DATA/IDATA memory. This process locates registers, bits, bdata, data, idata, then the stack. The problem with always putting IDATA above 7F is that there are a lot of derivatives that don't have that much memory. Even still, if you locate IDATA variables above 7F, where should the stack start? At the end of the DATA space or at the end of the IDATA space? Linker controls exist that allow you to configure the locations and sizes of all 8051 memory spaces. If you want the IDATA segment to start at 0x80, use the IDATA linker directive. Jon
ok, let me clarify: Idata before the end of data, not necessarily before 0x80 reduces the amount of data space available. Obviously if data is only a few bytes, this makes no difference; however since I am hunting for data space, if this bit of idata were at the end of data it would allow me to increase the use of data by that amount. Can I trick the linker (possibly by defining the data in a separate module) to locate all IDATA at the end OF DATA. Hope this makes it clear Erik
DATA 0018H 0003H UNIT _DATA_GROUP_ IDATA 001BH 0005H UNIT ?ID?AVMAIN BIT 0020H.0 0001H.2 UNIT ?BI?AVMAIN
which seems to imply that the linker has already considered putting data into that area, and decided against it, before moving on and finding an idata segment that would fit. Exactly correct. Jon
In other words: global data is atored by the linker in one chunk that will not be split although that should not be a problem. correct? Erik
I think the C compiler generates one data segment per source file for the global data (if you have data defined, of course). Look for segments with names like ?DT?FILENAME. There's not one single segment for all global data. Take a look at Chapter 9 of the Assembler/Utilities manual. (I don't know why the linker has been banished to a mere "utility" chapter, as it's pretty important. But the poor thing doesn't get its own manual, alas.) A linker can't break segments into pieces. It doesn't know, for example, that your 10-byte segment is really 10 independent unsigned chars, and not a char array[10], so it can't be sure it can safely lop the segment in half and put the two halves in different places. The compiler would have to generate different segments for the linker to independently locate. If you examine the map file, I suspect you'll find that you don't have any ?DT?FILENAME segments that are five bytes or smaller. You've got three register banks. Then there's _DATA_GROUP_, which is assigned to 18H, three bytes long (through 1AH). At this point, you have a five-byte hole at 1BH until 20H, where the bit-addressable memory starts. If there aren't any more data segments that are five bytes or smaller, then nothing can fit into that hole, and the linker would have to assign those segments higher addresses. If you have (hypothetically) an 8-byte segment (call it DT8), then you could argue that perhaps the 3-byte _DATA_GROUP_ should be moved, and DT located at 18H instead. That would leave you with three bytes of data you can't place, instead of an 8 byte segment you can't place and a five-byte hole. Less annoying, maybe, but it doesn't really solve the problem. Can you come up with a manual arrangement of your segments that actually fits in data space that the linker couldn't find? (I assume you only posted a fragment of your map file above, or you wouldn't be worried about running out of space.) I think that what you want is a compiler pragma to let you break up the data segments manually, something like:
#pragma segment ERIK1 char data array1[5]; #pragma segment ERIK2 char data array2[3]; #pragma segment default
erik.c: extern U8 data array1[5]; // was local decl extern U8 data array2[3]; // was local decl erik_seg1.c: U8 data array1[5]; erik_seg1.c: U8 data array2[3];
Does anyone know if there is a way to get the compiler to create separate segments for variables in a single source file as Drew describes? I usually wind up forcing variables into the space below 0x20 using the _at_ keyword - but suffer from the infamous 'can't initialise variables declared with _at_' problem. Stefan