2016-11-23 4 views
2

Для моего встроенного приложения на Atmel 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 
}; 

Я надеюсь, что кто-то может мне помочь, почему это не работает. Заранее спасибо.

EDIT: Вот записи в файле .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» или аналогичного тега в свой пост. –

+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 для исправления данных непосредственно шестнадцатеричный файл как post-build операция. Это имеет то преимущество, что является независимой от цепочки, но вам понадобится шаг, возможно, для генерации данных для исправления, но создание генератора для этого, вероятно, тривиально.

+0

Спасибо, не знал атрибут 'used'. Я использовал манекен до сих пор, и я должен распечатать содержимое массива, но он хранится на случайном адресе во вспышке, а не на одном из них. – Maku

0

Из моего опыта в Atmel студии 6 и 8 бит AVR ядра:

определить раздел .FWInfo (я делаю это без Makefile пардон) Flash config И делает

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

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

Снова я сделал это графически (извините).

linker flag

+0

Я попробовал этот флаг -u, но он не работа либо .. – Maku

Смежные вопросы