2014-11-18 4 views
9

Ich hoffe, der Titel ist beschreibend genug. Also hier ist was ich machen möchte und womit ich gespielt habe.Schreiben von Daten auf bestimmte Adresse während der Kompilierung

Warten Sie, zuerst ist dies eine eingebettete Anwendung. Atmel SAM4L-Mikrocontroller, der die Atmel Studio IDE und den GCC Compiler/Linker verwendet.

Richtig, ich schreibe einen Bootloader, aber möchte die Bootloader-Version im Programmspeicher bis zum Ende des zugewiesenen Speicherplatzes für den Bootloader speichern (sagen wir 0x3FF0). Auf diese Weise kann die App auch die Bootloader-Version überprüfen, indem sie nur die spezifische Adresse anschaut. In diesem Moment bin ich beschäftigt mit einem Dienstprogramm für die App, um den Bootloader selbst zu aktualisieren, aber ich möchte nicht, dass die App oder der Bootloader die Version bei 0x3FF0 mit einem Befehl oder Code aktualisieren, ich will es als Teil der .bin/.hex Datei, wenn ich also den Bootloader auflee, wird die Version mit geblinkt. Also habe ich derzeit eine #define für den Bootloader-Typ, Hauptversion und Nebenversion, die alle in einer Datei globals.h im Projekt sind. Im Grunde möchte ich nur diese 3 Bytes zu 0x3FF0 schreiben, wenn ich kompiliere.

Wie ich es verstehe, gibt es ziemlich viele Tricks, die ich mit dem Linker ziehen kann, aber noch nie mit Linker-Skripten bis gestern gespielt habe und einige Dinge damit machen konnte, aber nicht, was ich noch will. Das Projekt erzeugt auch ein ziemlich intensives Linker-Skript, also bin ich auch ein wenig vorsichtig, wo ich hineinspringen und meine drei Bytes ausgeben kann. Ich weiß, dass Sie den Adresszeiger nicht zurück bewegen dürfen.

Hier ist die Linker-Skript durch das Projekt erzeugt

/** 
* \file 
* 
* \brief Flash Linker script for SAM. 
* 
* Copyright (c) 2013 Atmel Corporation. All rights reserved. 
* 
* \asf_license_start 
* 
* \page License 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions are met: 
* 
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer. 
* 
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation 
* and/or other materials provided with the distribution. 
* 
* 3. The name of Atmel may not be used to endorse or promote products derived 
* from this software without specific prior written permission. 
* 
* 4. This software may only be redistributed and used in connection with an 
* Atmel microcontroller product. 
* 
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR 
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE. 
* 
* \asf_license_stop 
* 
*/ 

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 
OUTPUT_ARCH(arm) 
SEARCH_DIR(.) 

/* 
* NOTE: to keep binary compatibility with SAM4L4 device on SAM4L Xplained Pro, 
* we use SAM4L4 memory space here instead SAM4L8. You may change it if you are 
* using SAM4L8 device. 
*/ 
/* Memory Spaces Definitions */ 
MEMORY 
{ 
    rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* flash, 256K */ 
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */ 
    /* rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000 */ /* flash, 512K */ 
    /* ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000 */ /* sram, 64K */ 
} 

/* The stack size used by the application. NOTE: you need to adjust according to your application. */ 
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x1000; 
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4; 

/* Section Definitions */ 
SECTIONS 
{ 
    .text : 
    { 
     . = ALIGN(4); 
     _sfixed = .; 
     KEEP(*(.vectors .vectors.*)) 
     *(.text .text.* .gnu.linkonce.t.*) 
     *(.glue_7t) *(.glue_7) 
     *(.rodata .rodata* .gnu.linkonce.r.*) 
     *(.ARM.extab* .gnu.linkonce.armextab.*) 

     /* Support C constructors, and C destructors in both user code 
      and the C library. This also provides support for C++ code. */ 
     . = ALIGN(4); 
     KEEP(*(.init)) 
     . = ALIGN(4); 
     __preinit_array_start = .; 
     KEEP (*(.preinit_array)) 
     __preinit_array_end = .; 

     . = ALIGN(4); 
     __init_array_start = .; 
     KEEP (*(SORT(.init_array.*))) 
     KEEP (*(.init_array)) 
     __init_array_end = .; 

     . = ALIGN(0x4); 
     KEEP (*crtbegin.o(.ctors)) 
     KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 
     KEEP (*(SORT(.ctors.*))) 
     KEEP (*crtend.o(.ctors)) 

     . = ALIGN(4); 
     KEEP(*(.fini)) 

     . = ALIGN(4); 
     __fini_array_start = .; 
     KEEP (*(.fini_array)) 
     KEEP (*(SORT(.fini_array.*))) 
     __fini_array_end = .; 

     KEEP (*crtbegin.o(.dtors)) 
     KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 
     KEEP (*(SORT(.dtors.*))) 
     KEEP (*crtend.o(.dtors)) 

     . = ALIGN(4); 
     _efixed = .;   /* End of text section */ 
    } > rom 

    /* .ARM.exidx is sorted, so has to go in its own output section. */ 
    PROVIDE_HIDDEN (__exidx_start = .); 
    .ARM.exidx : 
    { 
     *(.ARM.exidx* .gnu.linkonce.armexidx.*) 
    } > rom 
    PROVIDE_HIDDEN (__exidx_end = .); 

    . = ALIGN(4); 
    _etext = .; 

    .relocate : AT (_etext) 
    { 
     . = ALIGN(4); 
     _srelocate = .; 
     *(.ramfunc .ramfunc.*); 
     *(.data .data.*); 
     . = ALIGN(4); 
     _erelocate = .; 
    } > ram 

    /* .bss section which is used for uninitialized data */ 
    .bss (NOLOAD) : 
    { 
     . = ALIGN(4); 
     _sbss = . ; 
     _szero = .; 
     *(.bss .bss.*) 
     *(COMMON) 
     . = ALIGN(4); 
     _ebss = . ; 
     _ezero = .; 
    } > ram 

    /* stack section */ 
    .stack (NOLOAD): 
    { 
     . = ALIGN(8); 
     _sstack = .; 
     . = . + __stack_size__; 
     . = ALIGN(8); 
     _estack = .; 
    } > ram 

    . = ALIGN(4); 
    _end = . ; 
} 

So so weit wie ich es verstehe, ist .ARM.exidx der letzte Abschnitt in ROM platziert und .relocate wird (von 0x20000000 weiter in RAM platziert wird) basierend auf den Regionen und MEMORY-Deklarationen, so dass meine drei Bytes irgendwo zwischen diesen beiden liegen sollten.

Dann, wie habe ich dieses Beispiel versucht http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0803a/BABDJCAA.html aber ich sehe es nicht in meinem .bin oder .hex Dateien wider. Ich nehme an, dass es nur den Speicher zuweist und tatsächlich nichts lädt, da es nur eine Variable ist. Ich habe auch Dinge wie diese gefunden gcc linker description file force symbol to be at specific address , aber ich nicht, da es nicht wirklich Code ich versuche, auf eine bestimmte Adresse zu laden, sehe ich nicht, wie ich diese Methode verwenden kann.

Ich spiele immer noch damit herum, das Linker-Skript zu manipulieren und zu sehen, was ich erreichen kann, aber jede Hilfe wäre sehr willkommen.

Wenn weitere Informationen erforderlich sind, fragen Sie bitte und ich werde zur Verfügung stellen. (Oder wenn ich den Titel oder die Tags für bessere Treffer ändern muss.)

+0

Ich weiß nicht, wie gcc damit umgeht, aber mit anderen Toolchains gab es keinen großen Unterschied zwischen Funktionen und Variablen. Normalerweise wird die Platzierung auf die gleiche Weise durchgeführt. – user694733

+0

Die beste Referenz für diese Information ist [** The ld Manual (sourceware) **] (https://sourceware.org/binutils/docs/ld/index.html). In Ihrem Fall mit eingebetteten Systemen oder mit Assembly selbst ist das Wissen um "ld" genauso wichtig wie die Kenntnis des Compilers selbst. Sieh dir an, ob du deine Frage etwas eingrenzen kannst. –

+0

Danke, ich werde mich dort umsehen. – kowalski5233

Antwort

0

Also, für diejenigen, die hier landen, auf der Suche nach Antworten, dies ist das detailliertere Beispiel von dem, was ich getan habe.

In main.c I definierte einen Prototyp, zuerst das Beispiel erhalten arbeiten, nach dem ich versuchte, ein Array in Gang zu bringen:

void jver(void) __attribute__((section(".jver"))); 

static uint8_t jvar[10] __attribute__((section(".jvar"))) = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 

void jver(void) 
{ 
    //static uint8_t sbuf[10] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; 
    jamba_TxBuff(jvar, 10); 

} 

Dann wurde in der Linker-Skript, nachdem der letzte Abschnitt in dem platziert ‚rom‘ Region, füge ich meine Sachen, die ich in der ‚rom‘ Region hinzufügen möge:

_jverstart = 0x3FF0; 
.jver : AT (_jverstart) 
{ 
    *(.jver) 
} > rom 


_jvarstart = 0x4100; 
.jvar : AT (_jvarstart) 
{ 
    *(.jvar) 
} > rom 

Hinweis hier hatte ich das Beispiel zu optimieren, so dass nur der Zeiger gleich einen Wert hat nicht funktioniert. Ich musste eine Variable erstellen und die AT-Funktion verwenden. Während meiner Tests habe ich die Region 'rom' hinzugefügt und nicht überprüft, ob sie immer noch funktioniert, wenn ich sie entferne.

Wenn ich kompilieren, erhalte ich folgendes Ergebnis:

:103FF00008B502480A21024B984708BDA02D0000D1 
:04400000310D00007E 
:0C410000303132333435363738390000A6 
:0400000300001A657A 
:00000001FF 

Vom letzten Code 0x3FF0 die .bin-Datei mit 0x00 füllt, dann wird das Paar von Bytes Code für meine jver (void) Funktion (was wahrscheinlich nur ein Aufruf der jamba_TxBuff-Funktion ist), dann füllt 0x00 den ganzen Weg zu 0x4100, wo "" befindet. BOOM!!! Alles, was ich jetzt hinzufügen werde, ist die 'FILL' -Funktion im Linker-Skript, die mit 0xFF anstelle von 0x00 gefüllt wird.

Nochmals vielen Dank für die Referenzen und Tipps.

+0

So füllt füllen nur Lücken innerhalb des Abschnitts, nicht Lücken zwischen den Abschnitten. Ich wollte das, weil mein Frontend, das ich für das Bootloading erstellt habe, die .bin-Datei und nicht die .hex-Datei anzeigt. – kowalski5233

1

Die Adresse der Dinge wird in der Linker-Phase bestimmt und für den Linker ist alles nur ein Symbol. So, während Ihre gcc linker description file force symbol to be at specific address ein Beispiel für eine Funktion geben, die gleich für Daten funktioniert. Definieren Sie Ihre Version und legen Sie sie im C-Code in einen separaten Abschnitt "Version". Dann kann der Linker diesen Abschnitt irgendwo platzieren.

Jetzt ist der schwierige Teil, es zu Ende der ROM zu bekommen, was bedeutet, eine Startadresse gerade niedrig genug zu spezifizieren, dass der Abschnitt am Ende von Rom endet. Eine feste Größe (Ihre 3 Bytes) zu machen macht das einfacher. Sehen Sie, wie ram_end im Linker-Skript definiert ist.Tun Sie dasselbe für rom_version_start, aber mit ROM anstelle von RAM und verwenden Sie das, um den Start der "Version" -Sektion mit '. = rom_version_start; '

+0

Danke! Ich musste ein bisschen herumspielen, um es zu verstehen, aber in der Tat ist das Grundkonzept dasselbe. – kowalski5233