Das Makefile beginnt mit diesen Zeilen:

Code:
PROJECT				= XRAMtest
MCU_TARGET			= atmega162
DEFINITIONS			= -DF_CPU=8000000UL
LIBRARIES			= -lm
EXTRA_CLEAN_FILES	= *.hex *.bin *.srec
EXTRA_CLEAN_FILES	+= *.gch
#OPTIMIZE			= -Os -mcall-prologues
OPTIMIZE			= -O2


COMPILER	= avr-gcc
LINKER		= avr-gcc
OBJCOPY		= avr-objcopy
OBJDUMP		= avr-objdump


TO_COMPILER	= -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFINITIONS)
TO_LINKER	= $(TO_COMPILER) -Wl,--section-start=.data=0x800500,--defsym=__heap_start=0x806000,--defsym=__heap_end=0x807fff,-Map,$(PROJECT).map -o
#TO_LINKER	= $(TO_COMPILER) -Wl,-Tdata=0x800500,--defsym=__heap_end=0x807fff,-Map,$(PROJECT).map -o
#TO_LINKER	= $(TO_COMPILER) -Wl,-Map,$(PROJECT).map -o
TO_OBJCOPY	= -j .text -j .data -O


# Override is only needed by avr-lib build system.
override CFLAGS	= $(TO_COMPILER)
override LFLAGS	= $(TO_LINKER)
Und daraus "zaubert" der Linker dann dieses hier:

Code:
Memory Configuration

Name             Origin             Length             Attributes
text             0x00000000         0x00020000         xr
data             0x00800060         0x0000ffa0         rw !x
eeprom           0x00810000         0x00010000         rw !x
*default*        0x00000000         0xffffffff

Linker script and memory map

Address of section .data set to 0x800100
LOAD c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr5/crtm162.o
Address of section .data set to 0x800500
                0x00806000                __heap_start = 0x806000
                0x00807fff                __heap_end = 0x807fff
LOAD main.o
LOAD c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr5\libm.a
LOAD c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/avr5\libgcc.a
LOAD c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr5\libc.a
LOAD c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/avr5\libgcc.a
...[das Gemüse hier ist wohl uninteressant]...
               0x00000294                _etext = .

.data           0x00800500        0x0 load address 0x00000294
                0x00800500                PROVIDE (__data_start, .)
 *(.data)
 .data          0x00800500        0x0 c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr5/crtm162.o
 .data          0x00800500        0x0 main.o
 .data          0x00800500        0x0 c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/avr5\libgcc.a(_copy_data.o)
 .data          0x00800500        0x0 c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/avr5\libgcc.a(_clear_bss.o)
 *(.data*)
 *(.rodata)
 *(.rodata*)
 *(.gnu.linkonce.d*)
                0x00800500                . = ALIGN (0x2)
                0x00800500                _edata = .
                0x00800500                PROVIDE (__data_end, .)

.bss            0x00800500        0x0
                0x00800500                PROVIDE (__bss_start, .)
 *(.bss)
 .bss           0x00800500        0x0 c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr5/crtm162.o
 .bss           0x00800500        0x0 main.o
 .bss           0x00800500        0x0 c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/avr5\libgcc.a(_copy_data.o)
 .bss           0x00800500        0x0 c:/programme/atmel/winavr/bin/../lib/gcc/avr/4.1.1/avr5\libgcc.a(_clear_bss.o)
 *(.bss*)
 *(COMMON)
                0x00800500                PROVIDE (__bss_end, .)
                0x00000294                __data_load_start = LOADADDR (.data)
                0x00000294                __data_load_end = (__data_load_start + SIZEOF (.data))

.noinit         0x00800500        0x0
                0x00800500                PROVIDE (__noinit_start, .)
 *(.noinit*)
                0x00800500                PROVIDE (__noinit_end, .)
                0x00800500                _end = .
                0x00800500                PROVIDE (__heap_start, .)
Das sieht ja auch soweit gut aus. Mein Problem ist weniger der Linker sondern der Compiler! Der kommt ja bekanntlich vor dem Linker dran und weiß daher (noch) nix von den neuen Einstellungen für das RAM. Ergo nimmt er brav die Default-Werte des Controllers und manipuliert schön den Stackpointer (gekürzter Auszug aus dem Disassembler-Fenster des Simulators, verziert mit einigen Kommentaren meinerseits):

Code:
+00000000:   940C0038    JMP     0x00000038       Jump
...
@00000038: early_XRAM_on
---- main.c ---------------------------------------------------------------------------------------
34:       {
+00000038:   E880        LDI     R24,0x80         Load immediate
=> das geht also schon mal

+00000039:   BF85        OUT     0x35,R24         Out to I/O location
+0000003A:   2411        CLR     R1               Clear Register
+0000003B:   BE1F        OUT     0x3F,R1          Out to I/O location
+0000003C:   EFCF        SER     R28              Set Register
=> mit diesem Vorgeplänkel geht es um SP
+0000003D:   E0D4        LDI     R29,0x04         Load immediate
+0000003E:   BFDE        OUT     0x3E,R29         Out to I/O location
+0000003F:   BFCD        OUT     0x3D,R28         Out to I/O location
=> Aha, der steht jetzt auf 0x04ff - paßt also auch
=> bis hierher sieht es also tatsächlich gut aus

=> jetzt kommt ein ganzer Schwung mögliche Initialisierungen von Speicherbereichen, der eigentlich nicht weiter relevant ist....
+00000040:   E015        LDI     R17,0x05         Load immediate
+00000041:   E0A0        LDI     R26,0x00         Load immediate
+00000042:   E0B5        LDI     R27,0x05         Load immediate
+00000043:   E9E4        LDI     R30,0x94         Load immediate
+00000044:   E0F2        LDI     R31,0x02         Load immediate
+00000045:   C002        RJMP    PC+0x0003        Relative jump
+00000046:   9005        LPM     R0,Z+            Load program memory and postincrement
+00000047:   920D        ST      X+,R0            Store indirect and postincrement
+00000048:   30A0        CPI     R26,0x00         Compare with immediate
+00000049:   07B1        CPC     R27,R17          Compare with carry
+0000004A:   F7D9        BRNE    PC-0x04          Branch if not equal
+0000004B:   E015        LDI     R17,0x05         Load immediate
+0000004C:   E0A0        LDI     R26,0x00         Load immediate
+0000004D:   E0B5        LDI     R27,0x05         Load immediate
+0000004E:   C001        RJMP    PC+0x0002        Relative jump
+0000004F:   921D        ST      X+,R1            Store indirect and postincrement
+00000050:   30A0        CPI     R26,0x00         Compare with immediate
+00000051:   07B1        CPC     R27,R17          Compare with carry
+00000052:   F7E1        BRNE    PC-0x03          Branch if not equal
+00000053:   940C0098    JMP     0x00000098       Jump
=> und weiter gehts es
@00000098: main
---- main.c ---------------------------------------------------------------------------------------
41:       {
+00000098:   930F        PUSH    R16              Push register on stack
+00000099:   931F        PUSH    R17              Push register on stack
+0000009A:   93CF        PUSH    R28              Push register on stack
+0000009B:   93DF        PUSH    R29              Push register on stack

=> SP abholen
+0000009C:   B7CD        IN      R28,0x3D         In from I/O location
+0000009D:   B7DE        IN      R29,0x3E         In from I/O location

=> um 240Bytes verringern
+0000009E:   5FC0        SUBI    R28,0xF0         Subtract immediate
+0000009F:   40D0        SBCI    R29,0x00         Subtract immediate with carry

=> und den neuen Wert retour schreiben (unter optimierter IRQ-Sperre!)
+000000A0:   B60F        IN      R0,0x3F          In from I/O location
+000000A1:   94F8        CLI                      Global Interrupt Disable
+000000A2:   BFDE        OUT     0x3E,R29         Out to I/O location
+000000A3:   BE0F        OUT     0x3F,R0          Out to I/O location
+000000A4:   BFCD        OUT     0x3D,R28         Out to I/O location
=> damit ist SP=0x040b
Und damit auch klar ist, wieso der Compiler den SP um 240 runterdreht:
Code:
int main (void)
{
	unsigned char buffer[240];
	char *storagePtr;			// ext. RAM is located RAMEND..0x7FFF
	char check, temp;
	unsigned char i;
Dabei kommt mir so eine vage Vermutung: das Array ist bei dieser Deklaration eine private Variable von main() und wird deshalb im Stack platziert?!? - Natürlich !!!

Die Deklaration als GLOBALES Array läßt den SP brav auf 0x04ff - AHA. Und wo liegt das globale Array nun? Im externen RAM ab 0x0500 - AHA.
War das Ganze also - wie vermutet - ein Verständnisproblem meinerseits.

Das heißt also nun, Stack und private Variablen (sofern nicht in Register passend) landen hier im internen RAM, alles GLOBALE im externen RAM => die großen (statischen) Arrays deklariere ich also erstmal global um den gewünschten Effekt zu erzielen.

@SprinterSB:
Danke für die Hilfsbereitschaft.

Gruß René