2012-01-22 5 views
6

Краткая история. Я хочу узнать, как создать хороший сценарий компоновщика, чтобы я мог менять платформы/архитектуры/поставщиков, я снова не зацикливаюсь на ноль земли, не зная, что делать. Меня не интересует сложность задачи, так же как и понимание этого.Консультации по созданию и верификации сценариев компоновщика

Я начал своего рода project, как это было, чтобы создать базу или скелет для программирования и разработки на 32-битных Cortex-M3 чипов СТМ. С помощью jsiei97 Начиная с STM32F103RB (у меня также есть TI Stellaris LM3S828, но это еще одна проблема), без необходимости лицензированной среды IDE. Поскольку я студент, и большинство студентов не могут позволить себе такие вещи.

Я понимаю, что есть плагины ODev и Eclipse, а что нет, и читали разные блоги, вики, документы/man-страницы, а большинство проектов предоставляют вам скрипт-компоновщик, который мало знает, почему и где были определены.

Я скомпилировал инструментальную цепочку arm-none-eabi для STM32, но там, где я повесил трубку, находится в скрипте компоновщика. CodeSourcery также требует его. У меня есть базовая концепция создания и синтаксиса после прочтения страниц gnu man, но я просто не знаю, с чего начать, добавляя различные дополнительные разделы, помимо очевидных .text, .bss и .data ,

Я создал rudimentary version, но я получаю ошибки связи, требующие определения разделов, и вот где я застрял. Я знаю, как их определить, но знать, что то, что я делаю, даже близко к делу, является проблемой.

+0

gnu linker скрипты в лучшем случае весьма болезненны. И от gcc 3.x до 4.x вещи, которые раньше работали, больше не работали, поэтому я предполагаю, что это будет продолжаться, независимо от того, насколько хорошо вы его получите, когда-нибудь они вырвут коврик из-под ваших ног. –

+0

Это правда. Я могу только ожидать этого. Однако с 4.x до 5.x я мог бы получить прочную работу, и это будет вопрос следования журналу изменений. должно произойти какое-либо существенное изменение. – Crewe

ответ

2

Вот рабочий компоновщик скрипт для STM32F105RB (существуют также версии для R8 и RC):

https://github.com/anrope/stm-arp/blob/github/arp.rb.ld (текст ниже)

Мой топ-оф-головка кажется, что вы не будете должны что-то изменить. Возможно, это происхождение регионов, определенных в инструкции MEMORY {}. Надеемся, что комментарии будут вам полезны.

Я использовал это с кросс-компилятором GNU/GCC, который я катался. После компиляции полезно запустить nm в коде, чтобы убедиться, что разделы размещены по правильным адресам.

Edit: Я кусочки этого линкера сценарий вместе с помощью ЛД документации GNU:

http://sourceware.org/binutils/docs/ld/

и пути анализа выходных данных GCC кросс-компиляции со стандартным сценарием компоновщика, используя nm. Я в основном определил все разделы, которые были выводятся, и выяснил, какие из них действительно полезны, и где в памяти они должны идти на STM32F105.

Я сделал заметки в сценарии компоновщика для каждого раздела.

/* 
arp.{r8,rb,rc}.ld : 
These linker scripts (one for each memory density of the stm32f105) are used by 
the linker to arrange program symbols and sections in memory. This is especially 
important for sections like the interrupt vector, which must be placed where the 
processor is hard-coded to look for it. 
*/ 

/*stm32f105 dev board linker script*/ 

/* 
OUTPUT_FORMAT() defines the BFD (binary file descriptor) format 
OUTPUT_FORMAT(default, big, little) 
*/ 
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 
/* ENTRY() defines the symbol at which to begin executing code */ 
ENTRY(_start) 
/* tell ld where to look for archive libraries */ 
/*SEARCH_DIR("/home/arp/stm/ctc/arm-eabi/lib")*/ 
/*SEARCH_DIR("/home/arp/stm/ccbuild/method2/install/arm-eabi/lib")*/ 
SEARCH_DIR("/home/arp/stm32dev-root/usrlol/arm-eabi/lib") 

/* 
MEMORY{} defines the memory regions of the target device, 
and gives them an alias for use later in the linker script. 
*/ 

/* stm32f105rb */ 
MEMORY 
{ 
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32k 
    flash (rx) : ORIGIN = 0x08000000, LENGTH = 128k 
    option_bytes_rom (rx) : ORIGIN = 0x1FFFF800, LENGTH = 16 
} 

_sheap = _ebss + 4; 
_sstack = _ebss + 4; 
/*placed __stack_base__ trying to figure out 
global variable overwrite issue 
__stack_base__ = _ebss + 4;*/ 

_eheap = ORIGIN(ram) + LENGTH(ram) - 1; 
_estack = ORIGIN(ram) + LENGTH(ram) - 1; 

/* SECTIONS{} defines all the ELF sections we want to create */ 
SECTIONS 
{ 
    /* 
    set . to an initial value (0 here). 
    . (dot) is the location counter. New sections are placed at the 
    location pointed to by the location counter, and the location counter 
    is automatically moved ahead the length of the new section. It is important 
    to maintain alignment (not handled automatically by the location counter). 
    */ 
    . = SEGMENT_START("text-segment", 0); 



    /*isr_vector contains the interrupt vector. 

    isr_vector is read only (could be write too?). 

    isr_vector must appear at start of flash (USR), 
    address 0x0800 0000*/ 
    .isr_vector : 
    { 
     . = ALIGN(4); 
     _sisr_vector = .; 

     *(.isr_vector) 

     _eisr_vector = .; 
    } >flash 

    /*text contains executable code. 

    text is read and execute.*/ 
    .text : 
    { 
     . = ALIGN(4); 
     *(.text) 
     . = ALIGN(4); 
     *(.text.*) 
    } >flash 

    /*init contains constructor functions 
    called before entering main. used by crt (?).*/ 
    .init : 
    { 
     . = ALIGN(4); 
     KEEP(*(.init)) 
    } >flash 

    /*fini contains destructor functions 
    called after leaving main. used by crt (?).*/ 
    .fini : 
    { 
     . = ALIGN(4); 
     KEEP(*(.fini)) 
    } >flash 

    /* rodata contains read only data.*/ 
    .rodata : 
    { 
     . = ALIGN(4); 
     *(.rodata) 

     /* sidata contains the initial values 
     for variables in the data section. 

     sidata is read only.*/ 
     . = ALIGN(4); 
     _sidata = .; 
    } >flash 

    /*data contains all initalized variables. 

    data is read and write. 
    .data (NOLOAD) : AT(_sidata)*/ 
    .data : AT(_sidata) 
    { 
     . = ALIGN(4); 
     _sdata = .; 

     *(.data) 

     _edata = .; 
    } >ram 

    /*bss contains unintialized variables. 

    bss is read and write. 
    .bss (NOLOAD) :*/ 
    .bss : 
    { 
     . = ALIGN(4); 
     _sbss = .; 
     __bss_start__ = .; 

     *(.bss) 
     . = ALIGN(4); 

     /*COMMON is a special section containing 
     uninitialized data. 

     Example: (declared globally) 
     int temp; //this will appear in COMMON */ 
     *(COMMON) 

     _ebss = .; 
     __bss_end__ = .; 
    } >ram AT>flash 

    . = ALIGN(4); 
    end = .; 

     /* remove the debugging information from the standard libraries */ 
    DISCARD : 
    { 
    libc.a (*) 
    libm.a (*) 
    libgcc.a (*) 
    } 

    /* 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) } 
    /* 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_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) } 
} 
+0

Мне сказали, что мы не можем просто указывать ссылки в ответах, поскольку они могут меняться, но привносят информацию в ответ, о котором мы говорим. Я добавил файл, указанный вами для ответа. –

+1

Где вы приобрели информацию, необходимую для создания этого скрипта? Как вы узнали, что вам нужно ** _ sheap **, ** _ sidata ** и ** _stack ** и что им назначать. Это тип информации, которую я ищу. – Crewe

+1

Я отредактировал свой ответ. Каждый из этих разделов (и более) появился в компиляции с использованием стандартного сценария компоновщика. Проверьте комментарии в скрипте. _sheap - это начало кучи, _sstack - это начало стека. – anrope

8

У меня есть простой скрипт компоновщика, который я регулярно использую на разных платформах, просто изменяю некоторые адреса по мере необходимости.

http://github.com/dwelch67/

Есть целый ряд образцов многих с ССАГПЗОМ образцами и большинство из них имеет компоновщик сценарии.

MEMORY 
{ 
    rom : ORIGIN = 0x00000000, LENGTH = 0x40000 
    ram : ORIGIN = 0x10000000, LENGTH = 30K 
} 

SECTIONS 
{ 
    .text : { *(.text*) } > rom 
    .bss : { *(.bss*) } > ram 
} 
+3

+1 для удобства использования. Абсолютно любой мог прочитать это и понять. Так много людей пытаются напрямую помещать регистры с памятью и т. Д. В сценарий компоновщика, и довольно скоро он взят на свою собственную жизнь. Не говоря уже о том, что он неспособен. – Dan

+1

Не хватает ли этого, по крайней мере, раздела данных? (Где ваши инициализированные глобалы?) – dbrank0