2014-11-18 34 views
9

Umarım başlık yeterince açıklayıcıdır. İşte burada yapmak istediklerim ve neyle uğraştığım.Verileri derleme sırasında belirli bir adrese yazma

Önce bekleyin, bu yerleşik bir uygulamadır. Atmel Studio IDE ve GCC derleyici/linker kullanarak Atmel SAM4L mikrodenetleyici.

Doğru, bir önyükleyici yazıyorum, ancak önyükleyici sürümünü, önyükleyici için ayrılmış alanın sonuna kadar program belleğine kaydetmek istiyorum (0x3FF0 diyelim). Bu şekilde uygulama sadece belirli bir adrese bakarak bootloader sürümünü kontrol edebilirsiniz. Şu anda, uygulamanın yükleyicinin kendisini güncellemesi için bir yardımcı programla meşgulüm, ancak uygulamanın veya bootloader'ın bir komutla veya kodla 0x3FF0'daki sürümü güncellemesini istemiyorum. .bin/.hex dosyası, böylece bootloader'ı açtığımda, versiyonun yanı sıra yanıp söner. Şu anda projede bir dosya globals.h dosyasında bulunan bootloader türü, büyük sürüm ve küçük sürüm için #define var. Temel olarak, derlediğimde bu 3 byte'ı 0x3FF0'a yazmak istiyorum.

Anladığım kadarıyla, linker ile çekebileceğim çok fazla hileler var, ancak daha önce hiç linker betikleriyle daha önce hiç oynamadım ve bununla bir şeyler yapabildim, ama henüz istediğim gibi değil. Proje ayrıca oldukça yoğun bir linker komut dosyası yaratıyor, bu yüzden de nereye atlayacağımı ve üç byte'mı nereye bırakacağım konusunda biraz ihtiyatlıyım. Adres işaretçisini geri taşımanıza izin verilmediğini biliyorum. İşte

proje tarafından oluşturulan bağlayıcı script

/** 
* \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 = . ; 
} 

Yani bildiğim kadarıyla anladığım kadarıyla, .ARM.exidx ROM yerleştirilen son bölümdür ve .relocate ileriye 0x20000000 den (RAM yer alacak) bölgelere ve MEMORY bildirimlerine dayanarak üç baytım bu ikisi arasında bir yerde olmalıdır.

Sonra NASIL olarak, ben bu örneği http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0803a/BABDJCAA.html denedim ama benim .bin veya Hex dosyaları yansıyan görmüyorum. Sanırım sadece hafızayı ayırıyor ve aslında sadece bir değişken olduğu için bir şey yüklemiyor. Ayrıca bu gibi şeyler buldum gcc linker description file force symbol to be at specific address , ama ben gerçek bir kod yüklemeyi denemiyorum çünkü belirli bir adrese yüklemeye çalışıyorum, bu yöntemi nasıl kullanabileceğimi göremiyorum.

Linker komut dosyasını manipüle ederek ve neyi başarabildiğimi görerek hala etrafta dolaşıyorum, ancak herhangi bir yardım büyük bir memnuniyetle karşılanacaktır.

Daha fazla bilgi gerekirse, lütfen sorunuz ve ben sağlayacağım. (Veya daha iyi isabetler için başlığı veya etiketleri değiştirmem gerekiyorsa).

+0

Gcc'nin bunu nasıl işlediğini bilmiyorum, ancak diğer araç gereçleriyle işlevler ve değişkenler arasında çok fazla fark olmadı. Yani genellikle yerleştirme aynı şekilde yapılır. – user694733

+0

Bu bilgi için en iyi başvuru [** El Kitabı (kaynak yazılımı) **] 'dir (https://sourceware.org/binutils/docs/ld/index.html). Gömülü sistemler veya montajın kendisi ile durumunuzda, 'ld'yi bilmek, derleyicinin kendisini bilmek kadar önemlidir. Bir bak ve soruyu biraz daraltabilir misin diye bak. –

+0

Teşekkürler, orada bir göz atacağım. – kowalski5233

cevap

0

Yani, burada cevap arayanlar için bu, yaptığımın daha ayrıntılı örneğidir. Son bölüm yerleştirilir sonra, bağlayıcı komut,

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); 

} 

Ardından:

main.c içinde Gittiğim bir dizi elde çalıştım, bundan sonra ilk çalışma örneği almak için bir prototip, tanımlanmış 'rom' bölgesi, ben 'rom' bölgede eklemek istediğiniz eşyalarımı ekleyin: sadece işe yaramadı bir değere işaretçi eşit hale örneğini çimdik attı

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


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

Not burada. Bir değişken oluşturmalı ve AT işlevini kullanmalıydım. Testlerim sırasında 'rom' bölgesini ekledim ve eğer kaldırırsam hala çalışıp çalışmadığını kontrol etmedim. (Bin dosyası 0x00 ile doldurur 0x3FF0 son kod, benim jver için kod bayt sonra çift (boşluk) işlevi itibaren

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

: Ben derlerken

, aşağıdaki sonuç elde Muhtemelen sadece jamba_TxBuff işlevine yapılan bir çağrıdır, sonra 0x00'leri "" adresinde bulunan 0x4100'e kadar doldurur. BOOM!!! Şimdi ekleyeceğim tek şey linker betiğinde 0x00 yerine 0xFF ile doldurmak için 'FILL' fonksiyonudur.

Referanslar ve öneriler için tekrar teşekkürler.

+0

Dolayısıyla, bölümler arasındaki boşlukları değil, yalnızca içerdeki boşlukları doldurun. Bunu yapmak istedim çünkü bootloading için yarattığım önyüz, .hex dosyasını değil .bin dosyasını yanıp sönüyor. – kowalski5233

1

Nesnelerin adresi linker aşamasında belirlenir ve linker için her şey sadece sembollerdir. Bu nedenle, gcc linker description file force symbol to be at specific address , verileriniz için eşit olarak çalışan bir işlev için bir örnek verir. Sürümünüzü tanımlayın ve C kodunda ayrı bir "sürüm" bölümüne koyun. Daha sonra bağlayıcı bu bölümü bir yere yerleştirebilir.

Şimdi zor olan kısım, romanın son ucuna getirmektir, bu, başlangıç ​​noktasının rom sonunda sona erecek kadar düşük bir başlangıç ​​adresi belirtmek anlamına gelir. Bunu sabit bir boyutta yapmak (3 Byte'ınız) bunu daha basit hale getirir. Linker betiğinde ram_end'un nasıl tanımlandığına bakın.rom_version_start için aynısını yapın, ancak ram yerine rom kullanın ve bunu kullanarak "version" bölümünün başlangıcını ayarlamak için kullanın. = rom_version_start; '

+0

Teşekkürler! Söze ulaşmak için biraz oynamıştım, ama aslında temel kavram aynı. – kowalski5233

İlgili konular