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
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