On Thu, Oct 09, 2014 at 08:49:27AM +0200, Alistair Gadd wrote: > > On 2014/10/09 08:29 AM, Senthil Kumar Selvaraj wrote: > >On Thu, Oct 09, 2014 at 07:32:51AM +0200, Alistair Gadd wrote: > >>Hi Everybody, > >> > >>I'm hoping this is an easy one for someone out there. > >> > >>I'm putting together a bootloader for an ATmega328P using Atmel Studio 6.2 > >>and I would just like to ask if there is an easy way configure the IDE so > >>that I can have separate sections that I can allocate code to. I have been > >>using "-Ttext 0x7000" as a linker flag in "Configuration > >>Manager->Toolchain->AVR/GNU Linker->Miscellaneous", which places all the > >>code starting with reset vector at 0x3800 onwards, but I would like to have > >>another section in the application section where I can place an SD card > >>library that will be accessible by the bootloader and by future > >>applications. > >> > >>I have defined another "FLASH segment" - ".sdlib=0x2000" in "Configuration > >>Manager->Toolchain->AVR/GNU Linker->Memory Settings, but I don't know how to > >>configure .c source files and assembler .s files so that their code is > >>allocated to this segment. > >> > >>Can anybody give me some ideas on how I could achieve this? > >There are a couple of ways. > > > >1. Create a linker script that groups code from specific object > >files into custom output sections. Something like > > > >.sdlib : > >{ > > foo.o(*.text) > >} > > > >where foo.o is the object file containing the code to go into the > >section. > > > >2. Use attributes in C code and .section directives in assembler code to > >specify the section. > > > >void __attribute__((section(".sdlib"))) my_function() {} > >int main() { return 0; } > > > >This makes the place the my_function's code in a .sdlib section. main's > >code still goes into .text. > > > >Hope this helps. > > > >Regards > >Senthil > Thanks very much Senthil, > > I have tried the __attribute__((section(".sdlib"))) directive which works > but I'm having problems trying to define variables in flash by using: > > const unsigned char __attribute__((section(".sdlib"))) array[5] PROGMEM = > {1,2,3,4,5}; > or: > const unsigned char array[5] __attribute__((section(".sdlib"))) PROGMEM = > {1,2,3,4,5};
The PROGMEM macro expands to a section attribute as well, which is probably why you're running into problems. > > I think I prefer your first option though because it would put everything in > that module into the .sdlib section, but my problem is I don't know how to > create and use the linker script. Can you maybe point me to some > documentation that would show me how it is used. https://sourceware.org/binutils/docs/ld/Scripts.html. For atmega328p, the default linker script is at <install_prefix>/avr/lib/ldscripts/avr5.xn. With a custom .sdlib section, it looks like this /* Script for -n: mix text and data on same page */ OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") OUTPUT_ARCH(avr:5) MEMORY { text (rx) : ORIGIN = 0, LENGTH = 128K data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K } SECTIONS { /* Read-only sections, merged into text segment: */ .hash : { *(.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } .rel.init : { *(.rel.init) } .rela.init : { *(.rela.init) } .rel.text : { *(.rel.text) *(.rel.text.*) *(.rel.gnu.linkonce.t*) } .rela.text : { *(.rela.text) *(.rela.text.*) *(.rela.gnu.linkonce.t*) } .rel.fini : { *(.rel.fini) } .rela.fini : { *(.rela.fini) } .rel.rodata : { *(.rel.rodata) *(.rel.rodata.*) *(.rel.gnu.linkonce.r*) } .rela.rodata : { *(.rela.rodata) *(.rela.rodata.*) *(.rela.gnu.linkonce.r*) } .rel.data : { *(.rel.data) *(.rel.data.*) *(.rel.gnu.linkonce.d*) } .rela.data : { *(.rela.data) *(.rela.data.*) *(.rela.gnu.linkonce.d*) } .rel.ctors : { *(.rel.ctors) } .rela.ctors : { *(.rela.ctors) } .rel.dtors : { *(.rel.dtors) } .rela.dtors : { *(.rela.dtors) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.bss : { *(.rel.bss) } .rela.bss : { *(.rela.bss) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .sdlib : 0x2000 { foo.o(*.text) foo.o(*.text.*) /* Other object files to go into sdlib */ } /* Internal text space or external memory. */ .text : { *(.vectors) KEEP(*(.vectors)) /* For data that needs to reside in the lower 64k of progmem. */ *(.progmem.gcc*) /* PR 13812: Placing the trampolines here gives a better chance that they will be in range of the code that uses them. */ . = ALIGN(2); __trampolines_start = . ; /* The jump trampolines for the 16-bit limited relocs will reside here. */ *(.trampolines) *(.trampolines*) __trampolines_end = . ; *(.progmem*) . = ALIGN(2); /* For future tablejump instruction arrays for 3 byte pc devices. We don't relax jump/call instructions within these sections. */ *(.jumptables) *(.jumptables*) /* For code that needs to reside in the lower 128k progmem. */ *(.lowtext) *(.lowtext*) __ctors_start = . ; *(.ctors) __ctors_end = . ; __dtors_start = . ; *(.dtors) __dtors_end = . ; KEEP(SORT(*)(.ctors)) KEEP(SORT(*)(.dtors)) /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary. */ *(.init0) /* Start here after reset. */ KEEP (*(.init0)) *(.init1) KEEP (*(.init1)) *(.init2) /* Clear __zero_reg__, set up stack pointer. */ KEEP (*(.init2)) *(.init3) KEEP (*(.init3)) *(.init4) /* Initialize data and BSS. */ KEEP (*(.init4)) *(.init5) KEEP (*(.init5)) *(.init6) /* C++ constructors. */ KEEP (*(.init6)) *(.init7) KEEP (*(.init7)) *(.init8) KEEP (*(.init8)) *(.init9) /* Call main(). */ KEEP (*(.init9)) *(.text) . = ALIGN(2); *(.text.*) . = ALIGN(2); *(.fini9) /* _exit() starts here. */ KEEP (*(.fini9)) *(.fini8) KEEP (*(.fini8)) *(.fini7) KEEP (*(.fini7)) *(.fini6) /* C++ destructors. */ KEEP (*(.fini6)) *(.fini5) KEEP (*(.fini5)) *(.fini4) KEEP (*(.fini4)) *(.fini3) KEEP (*(.fini3)) *(.fini2) KEEP (*(.fini2)) *(.fini1) KEEP (*(.fini1)) *(.fini0) /* Infinite loop after program termination. */ KEEP (*(.fini0)) _etext = . ; } > text .data : { PROVIDE (__data_start = .) ; *(.data) *(.data*) *(.rodata) /* We need to include .rodata here if gcc is used */ *(.rodata*) /* with -fdata-sections. */ *(.gnu.linkonce.d*) . = ALIGN(2); _edata = . ; PROVIDE (__data_end = .) ; } > data AT> text .bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss)) { PROVIDE (__bss_start = .) ; *(.bss) *(.bss*) *(COMMON) PROVIDE (__bss_end = .) ; } > data __data_load_start = LOADADDR(.data); __data_load_end = __data_load_start + SIZEOF(.data); /* Global data not cleared after reset. */ .noinit : { PROVIDE (__noinit_start = .) ; *(.noinit*) PROVIDE (__noinit_end = .) ; _end = . ; PROVIDE (__heap_start = .) ; } > data .eeprom : { /* See .data above... */ KEEP(*(.eeprom*)) __eeprom_end = . ; } > eeprom .fuse : { KEEP(*(.fuse)) KEEP(*(.lfuse)) KEEP(*(.hfuse)) KEEP(*(.efuse)) } > fuse .lock : { KEEP(*(.lock*)) } > lock .signature : { KEEP(*(.signature*)) } > signature .user_signatures : { KEEP(*(.user_signatures*)) } > user_signatures /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } .note.gnu.build-id : { *(.note.gnu.build-id) } /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } /* DWARF 3 */ .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } /* DWARF Extension. */ .debug_macro 0 : { *(.debug_macro) } } Regards Senthil _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-gcc-list