2016-11-23 120 views
2

對於我在愛特梅爾SAM4E16C上的嵌入式應用程序,我需要在.hex文件末尾放置一個包含固件信息的陣列。我正在使用Atmel Studio 7和GCC。將數組寫入到.hex文件中的特定閃存位置

我已經爲Atmega168PB做了這個,但不知何故它不適用於這個項目。

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

/* Memory Spaces Definitions */ 
MEMORY 
{ 
    rom (rx) : ORIGIN = 0x00420000, LENGTH = 0x000E0000 /* changed to leave space for 128KB Bootloader -> was ORIGIN = 0x00400000, LENGTH = 0x00100000 */ 
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000 
} 

/* The stack size used by the application. NOTE: you need to adjust according to your application. */ 
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x3000; 
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4; 
/* Firmware Info - 8 Bytes long at the end of ROM */ 
__FWInfo_start__ = ORIGIN(rom) + LENGTH(rom) - 8; 
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 = . ; 


/* 8 Byte Firmware Info Section */ 

.FWInfo : AT (__FWInfo_start__) 
{ 
    *(.FWInfo) 
} > rom 
} 

這是我使用的鏈接描述文件。我添加了__FWInfo_start__和.FWInfo部分。

在我的應用程序中,我試圖定義固件信息塊的屬性部分.FWInfo,但我無法找到我的.hex文件中的數據。

#define SIZE_OF_FWINFO 8 
const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO] __attribute__((section(".FWInfo"))) = { 
    0xff, // reserved for future 
    0xff, // reserved for future 
    DEVICE_TYPE, // DeviceType 
    BUILD_NR,  // BuildNr of Firmware 
    VERSION_MINOR, // VersionMinor of Firmware 
    VERSION_MAJOR, // VersionMajor of Firmware 
    0xFF,   // Checksum 
    0xFF   // Checksum 
}; 

我希望有人能幫助我,爲什麼這是行不通的。提前致謝。

編輯:這裏是在.MAP文件中的條目:

.data   0x00000000  0x0 src/main.o 
.FWInfo  0x00000000  0x8 src/main.o 
.debug_macro 0x00000000  0x8b0 src/main.o 

和..

*fill*   0x200133b0  0x3000 
       0x200163b0    . = ALIGN (0x8) 
       0x200163b0    _estack = . 
       0x200163b0    . = ALIGN (0x4) 
       0x200163b0    _end = . 

.FWInfo 
*(.FWInfo) 
OUTPUT(Dali4Net.elf elf32-littlearm) 

據我可以從上下文中所述第二塊中讀取應該有一個寫入.FWInfo之後的地址還是?

+0

@RawN你是什麼意思? – Maku

+0

啊我看,這是某種鏈接腳本。你應該考慮在你的文章中加入atmel或類似的標籤。 – 2016-11-23 16:10:28

+0

好吧,我添加了標籤,認爲在一開始寫atmel就足夠了。 – Maku

回答

0

從GCC variable attribute documentation

used

該屬性,連接到具有靜態存儲的變量,意味着即使看來該變量沒有引用的變量必須發射。

因此,爲了防止由連接子,使用被移除未使用的數據:

const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO] 
       __attribute__((used,section(".FWInfo"))) = 
{ ... } ; 

一種替代但也許不那麼有吸引力的解決方案是聲明數組volatile,然後執行虛設即讀:

const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO] 
       __attribute__((section(".FWInfo"))) = 
{ ... } ; 

int main() 
{ 
    uint8_t dummy = nFirmwareInfoBlock[0] ; 
    ... 
} 

第三種方法是避免工具鏈依賴性完全和使用優良如果有些神祕SRecord實用程序來修補數據直接將十六進制文件作爲後生成操作。這具有獨立於工具鏈的優點,但您需要一個步驟來生成要修補的數據,但爲此編寫一個生成器可能是微不足道的。

+0

謝謝,不知道'used'屬性。我已經使用了一個虛擬直到現在,我打印數組的內容,但它存儲在閃存中的一個隨機地址,而不是給定的。 – Maku

0

從我愛特梅爾工作室6和8位AVR核心經驗:

定義部分.FWInfo(我這樣做是沒有的makefile對不起) Flash config 而做

const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO] 
       __attribute__((used,section(".FWInfo"))) = 
{ ... } ; 

是不夠的,因爲只有編譯器會保留這個變量。那麼鏈接器可能會丟棄它,如果它沒有被使用。當然,一個簡單的引用足以保留它,但是如果它僅用於引導加載程序中,例如可以定義鏈接器標誌。

我再次以圖形方式(對不起)。

linker flag

+0

我試過這個-u標誌,但它沒有工作要麼.. – Maku