0
\$\begingroup\$

I have board wired up to use ATMega1281's Eternal Memory Interface with a BSI, BS62LV4006STIP55, 512Kx8 SDRAM connected. I am trying to do something similar to this (ATMega128), except my memory is larger and uses ATMega1281:

https://scienceprog.com/adding-external-memory-to-atmega128/

The blog instructs to add a line to the linker option:

-Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x8030ff

I've adapted this to my board with ATMega1281's slightly larger internal SRAM. In the beginning I am happy only to get the external SRAM to work using 8192 bytes. External SRAM should start at 0x2200 and end at 0x41FF:

-Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x8041ff

enter image description here

The linker part of the makefile (I opted to copy the auto-generated make file and modify it) now looks like this:

$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP) $(LIB_DEP) $(LINKER_SCRIPT_DEP)
    @echo Building target: $@
    @echo Invoking: AVR/GNU Linker : 5.4.0
    $(QUOTE)C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -Wl,-Map="XMEM_Mega1281.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mrelax -mmcu=atmega1281 -B "C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega1281" -Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x8041ff
    @echo Finished building target: $@
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "XMEM_Mega1281.elf" "XMEM_Mega1281.hex"
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "XMEM_Mega1281.elf" "XMEM_Mega1281.eep" || exit 0
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "XMEM_Mega1281.elf" > "XMEM_Mega1281.lss"
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "XMEM_Mega1281.elf" "XMEM_Mega1281.srec"
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe" "XMEM_Mega1281.elf"

When compiling using the added linker options I get:

Severity    Code    Description Project File    Line
Error       address 0x802214 of XMEM_Mega1281.elf section `.data' is not within region `data'   XMEM_Mega1281       1
Error       address 0x80221e of XMEM_Mega1281.elf section `.bss' is not within region `data'    XMEM_Mega1281       1
Error       address 0x802214 of XMEM_Mega1281.elf section `.data' is not within region `data'   XMEM_Mega1281       1
Error       address 0x80221e of XMEM_Mega1281.elf section `.bss' is not within region `data'    XMEM_Mega1281       1

Can anyone tell me how to go about to achieve what I want to do, i. e. getting the compiler to take the external SRAM into use? At this point it doesn't matter how much it uses, only that it uses some. I must admit that I have practically no experience modifying memory maps etc.

To my understanding, avr-libs doesn't have a linker. Here's my makefile:

################################################################################
# Automatically-generated file. Do not edit!
################################################################################

SHELL := cmd.exe
RM := rm -rf

USER_OBJS :=

LIBS := 
PROJ := 

O_SRCS := 
C_SRCS := 
S_SRCS := 
S_UPPER_SRCS := 
OBJ_SRCS := 
ASM_SRCS := 
PREPROCESSING_SRCS := 
OBJS := 
OBJS_AS_ARGS := 
C_DEPS := 
C_DEPS_AS_ARGS := 
EXECUTABLES := 
OUTPUT_FILE_PATH :=
OUTPUT_FILE_PATH_AS_ARGS :=
AVR_APP_PATH :=$$$AVR_APP_PATH$$$
QUOTE := "
ADDITIONAL_DEPENDENCIES:=
OUTPUT_FILE_DEP:=
LIB_DEP:=
LINKER_SCRIPT_DEP:=

# Every subdirectory with source files must be described here
SUBDIRS := 


# Add inputs and outputs from these tool invocations to the build variables 
C_SRCS +=  \
../led.c \
../XMEM_Mega1281.c \
../uart.c


PREPROCESSING_SRCS += 


ASM_SRCS += 


OBJS +=  \
led.o \
XMEM_Mega1281.o \
uart.o

OBJS_AS_ARGS +=  \
led.o \
XMEM_Mega1281.o \
uart.o

C_DEPS +=  \
led.d \
XMEM_Mega1281.d \
uart.d

C_DEPS_AS_ARGS +=  \
led.d \
XMEM_Mega1281.d \
uart.d

OUTPUT_FILE_PATH +=XMEM_Mega1281.elf

OUTPUT_FILE_PATH_AS_ARGS +=XMEM_Mega1281.elf

ADDITIONAL_DEPENDENCIES:=

OUTPUT_FILE_DEP:= ./makedep.mk

LIB_DEP+= 

LINKER_SCRIPT_DEP+= 


# AVR32/GNU C Compiler
./led.o: .././led.c
    @echo Building file: $<
    @echo Invoking: AVR/GNU C Compiler : 5.4.0
    $(QUOTE)C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE)  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega1281 -B "C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega1281" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"   -o "$@" "$<" 
    @echo Finished building: $<
    

./XMEM_Mega1281.o: .././XMEM_Mega1281.c
    @echo Building file: $<
    @echo Invoking: AVR/GNU C Compiler : 5.4.0
    $(QUOTE)C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE)  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega1281 -B "C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega1281" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"   -o "$@" "$<" 
    @echo Finished building: $<
    

./uart.o: .././uart.c
    @echo Building file: $<
    @echo Invoking: AVR/GNU C Compiler : 5.4.0
    $(QUOTE)C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE)  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega1281 -B "C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega1281" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"   -o "$@" "$<" 
    @echo Finished building: $<
    




# AVR32/GNU Preprocessing Assembler



# AVR32/GNU Assembler




ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
endif

# Add inputs and outputs from these tool invocations to the build variables 

# All Target
all: $(OUTPUT_FILE_PATH) $(ADDITIONAL_DEPENDENCIES)

$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP) $(LIB_DEP) $(LINKER_SCRIPT_DEP)
    @echo Building target: $@
    @echo Invoking: AVR/GNU Linker : 5.4.0
    $(QUOTE)C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -Wl,-Map="XMEM_Mega1281.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mrelax -mmcu=atmega1281 -B "C:\Program Files (x86)\Atmel Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega1281" -Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x8041ff
    @echo Finished building target: $@
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "XMEM_Mega1281.elf" "XMEM_Mega1281.hex"
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "XMEM_Mega1281.elf" "XMEM_Mega1281.eep" || exit 0
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "XMEM_Mega1281.elf" > "XMEM_Mega1281.lss"
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "XMEM_Mega1281.elf" "XMEM_Mega1281.srec"
    "C:\Program Files (x86)\Atmel Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe" "XMEM_Mega1281.elf"
    
    





# Other Targets
clean:
    -$(RM) $(OBJS_AS_ARGS) $(EXECUTABLES)  
    -$(RM) $(C_DEPS_AS_ARGS)   
    rm -rf "XMEM_Mega1281.elf" "XMEM_Mega1281.a" "XMEM_Mega1281.hex" "XMEM_Mega1281.lss" "XMEM_Mega1281.eep" "XMEM_Mega1281.map" "XMEM_Mega1281.srec" "XMEM_Mega1281.usersignatures"

Linker script and memory map

Address of section .data set to 0x800200
LOAD C:/Program Files (x86)/Atmel Studio/7.0/Packs/atmel/ATmega_DFP/1.7.374/gcc/dev/atmega1281/avr51/crtatmega1281.o
LOAD led.o
LOAD XMEM_Mega1281.o
LOAD uart.o
START GROUP
LOAD c:/program files (x86)/atmel studio/7.0/toolchain/avr8/avr8-gnu-toolchain/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr51\libm.a
END GROUP
Address of section .data set to 0x802200
                0x008041ff                __heap_end = 0x8041ff
START GROUP
LOAD c:/program files (x86)/atmel studio/7.0/toolchain/avr8/avr8-gnu-toolchain/bin/../lib/gcc/avr/5.4.0/avr51\libgcc.a
LOAD c:/program files (x86)/atmel studio/7.0/toolchain/avr8/avr8-gnu-toolchain/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr51\libm.a
LOAD c:/program files (x86)/atmel studio/7.0/toolchain/avr8/avr8-gnu-toolchain/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr51\libc.a
LOAD C:/Program Files (x86)/Atmel Studio/7.0/Packs/atmel/ATmega_DFP/1.7.374/gcc/dev/atmega1281/avr51\libatmega1281.a
END GROUP
                0x00000000                __TEXT_REGION_ORIGIN__ = DEFINED (__TEXT_REGION_ORIGIN__)?__TEXT_REGION_ORIGIN__:0x0
                [0x00800200]                __DATA_REGION_ORIGIN__ = DEFINED (__DATA_REGION_ORIGIN__)?__DATA_REGION_ORIGIN__:0x800100
                [0x00020000]                __TEXT_REGION_LENGTH__ = DEFINED (__TEXT_REGION_LENGTH__)?__TEXT_REGION_LENGTH__:0x20000
                [0x00002000]                __DATA_REGION_LENGTH__ = DEFINED (__DATA_REGION_LENGTH__)?__DATA_REGION_LENGTH__:0xff00
                [0x00001000]                __EEPROM_REGION_LENGTH__ = DEFINED (__EEPROM_REGION_LENGTH__)?__EEPROM_REGION_LENGTH__:0x10000
                [0x00000003]                __FUSE_REGION_LENGTH__ = DEFINED (__FUSE_REGION_LENGTH__)?__FUSE_REGION_LENGTH__:0x400
                0x00000400                __LOCK_REGION_LENGTH__ = DEFINED (__LOCK_REGION_LENGTH__)?__LOCK_REGION_LENGTH__:0x400
                0x00000400                __SIGNATURE_REGION_LENGTH__ = DEFINED (__SIGNATURE_REGION_LENGTH__)?__SIGNATURE_REGION_LENGTH__:0x400
                0x00000400                __USER_SIGNATURE_REGION_LENGTH__ = DEFINED (__USER_SIGNATURE_REGION_LENGTH__)?__USER_SIGNATURE_REGION_LENGTH__:0x400

This caused similar compiler errors:

-Wl,-Tdata,0x802200

I tried following, defining only the heap to reside in external SRAM (adapted from the link above):

-Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x8041ff

SUCCESS! That took the compiler errors away. Since it is writing and reading back the memory contents, the external SRAM now appears to work:

   mem = malloc(BUFFER_SIZE);
   PRINTF("Allocating 256 bytes space in ext ram\n");
   PRINTF("%d Byte buffer (starting at 0x%04X) filled with incrementing numbers:\n",BUFFER_SIZE,mem);
   // Fill memory incrementing values
   for(index = 0; index < BUFFER_SIZE; index++)
   {
       mem[index] = data++;
   }
   // Display memory block
   for(index = 0; index < BUFFER_SIZE; index++)
   {
      PRINTF("%02X ",mem[index]);
      if((index&0x0F) == 0x0F)
      {
         PRINTF("\n");
      }
   }

enter image description here

\$\endgroup\$
10
  • \$\begingroup\$ can you share your linker file? maybe the data and bss section of the linker is not well defined. \$\endgroup\$
    – Rahmany
    Commented Dec 5, 2022 at 12:41
  • \$\begingroup\$ Thanks for the comment, just added the make file. \$\endgroup\$ Commented Dec 5, 2022 at 13:23
  • \$\begingroup\$ The whole .map file made my post too large. I added "Linker script and memory map" from the .map file instead. Hope it was what you asked for. \$\endgroup\$ Commented Dec 5, 2022 at 13:29
  • \$\begingroup\$ in the memory section, the data section starts from 0x00800200 and not from 0x00802200. So, it seems like the linker command wasn't taken into account. \$\endgroup\$
    – Rahmany
    Commented Dec 5, 2022 at 13:37
  • \$\begingroup\$ "It is possible to tell the linker the SRAM address of the beginning of the .data section. This is accomplished by adding -Wl,-Tdata,addr to the avr-gcc command used to the link your program." Try this instead of the command you've written. Source : www-user.tu-chemnitz.de/~heha/hsn/chm/avr-libc.chm/… \$\endgroup\$
    – Rahmany
    Commented Dec 5, 2022 at 13:45

2 Answers 2

1
\$\begingroup\$

ATmega1281 belongs to core family avr51. Hence the default linker script in avr/lib/ldscripts/avr51.x will read something like (depending on Binutils version):

...
__DATA_REGION_ORIGIN__ = DEFINED(__DATA_REGION_ORIGIN__) ? __DATA_REGION_ORIGIN__ : 0x800100;
__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xff00;
...
MEMORY
{
  ...
  data   (rw!x) : ORIGIN = __DATA_REGION_ORIGIN__, LENGTH = __DATA_REGION_LENGTH__
  ...
}
...

Hence if symbols __DATA_REGION_ORIGIN__ and __DATA_REGION_LENGTH__ are not defined, the ld script will assume default values which probably don't fit your memory layout1. So you may want to define these symbols to match your layout. You can define the symbols on command line like linking with:

avr-gcc ... -Wl,--defsym,__DATA_REGION_LENGTH__=8k

If you prefer to define the symbol in a C file, avr-gcc allows this by means of

__attribute__((__address__(8 * 1024)))
char __DATA_REGION_LENGTH__;

As an aside, AVR-LibC's startup code initializes SP from symbol __stack which defaults to RAMEND defined in avr/io.h, so that should work without further adjustments. The specs-atmega1281 however has

*link_data_start:
    %{!Tdata:-Tdata 0x800200}

so you can override that on the command line, too.


1A length of 0xff00 as of the default should be enough though, but the error you are getting indicates that the length is smaller, thus somewhere is defined __DATA_REGION_LENGTH__.

\$\endgroup\$
0
\$\begingroup\$

The error message that you are seeing indicates that the linker is unable to allocate the specified amount of memory for the .data section of your program. This is likely happening because the --section-start option that you are using is specifying a memory address range that is not available on the ATMega1281 microcontroller.

To fix this issue, you will need to specify a valid memory address range for the .data section of your program. The ATMega1281 microcontroller has a total of 8192 bytes of internal SRAM, with the first 64 bytes reserved for the stack, so you will need to specify a memory address range that is within this range and does not overlap with the stack.

For example, you could try specifying a memory address range of 0x0100 to 0x3FFF for the .data section, which would give you 8128 bytes of SRAM for your program to use. The updated linker options would look like this:

-Wl,--section-start,.data=0x0100,--defsym=__heap_end=0x3FFF

You may also need to adjust the __heap_end symbol to ensure that it does not overlap with the stack or any other memory areas that your program is using. You can use the avr-size tool to check the memory usage of your program and determine the appropriate value for this symbol.

Overall, it is important to ensure that you are specifying a valid memory address range for the .data section of your program when using the --section-start option in the linker options. This will ensure that the linker is able to properly allocate the necessary memory for your program, and avoid the kind of error that you are seeing.

\$\endgroup\$
2
  • \$\begingroup\$ the ram addresses should be offset by 0x800000 to be understood by the linker \$\endgroup\$
    – Rahmany
    Commented Dec 5, 2022 at 15:56
  • \$\begingroup\$ Tried your proposal taking into account the Harvard architecture:-Wl,--section-start,.data=0x800100,--defsym=__heap_end=0x803FFF. That provided almost similar compiler error: Error address 0x800114 of XMEM_Mega1281.elf section .data' is not within region data' XMEM_Mega1281 1 Error address 0x80011e of XMEM_Mega1281.elf section .bss' is not within region data' XMEM_Mega1281 1 Error address 0x800114 of XMEM_Mega1281.elf section .data' is not within region data' XMEM_Mega1281 1 Error address 0x80011e of XMEM_Mega1281.elf section .bss' is not within region data' XMEM_Mega1281 1 \$\endgroup\$ Commented Dec 6, 2022 at 8:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.