|
Перемещение кода в память, как указать где копия кода должна быть размещена во флеше. |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Feb 15 2016, 12:46
|

Местный
  
Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007

|
1. Всё, что должно помещаться в ram, есть initialized data - секция .data по умолчанию. Ну и ссылки начала и конца - _sidata, _edata. По сути то, что вы описали - есть ramfunc. Если абстрагироваться от заморочек с ресетом по питанию и передачей управления, то кусок скрипта линкёра примерно такой должен быть: Код .text.align : { . = ALIGN(8); _etext = .; _sidata = _etext; /* start of initialized data label */ } > FLASH
/* .ramfunc : AT ( _sidata ) */ /* RAM functions section */ /* RAM functions section */ .ramfunc : { . = ALIGN(8); __exec_mem_start__ = .; _sdata = .; /* start of .data label */ SORT(*)(.ramfunc) SORT(*)(.ramfunc.*) SORT(*)(EXECUTABLE_MEMORY_SECTION*) /* eeprom functions from MDR_StdPeriph_Driver */ . = ALIGN(4); __exec_mem_end__ = .; } > RAM AT > FLASH
.data : /* AT makes the LMA follow on in the binary image */ { . = ALIGN(4); SORT(*)(.data) SORT(*)(.data*) . = ALIGN(4); _edata = .; /* end of .data label */ } > RAM AT > FLASH Играясь с указателем адреса .ramfunc : AT ( _sidata ), можно расположить где захотите. В моём примере будет как раз то, что вы просите. 2. Если вы стёрли флэш и сделали ресет, то передача управления идёт в соответствие с режимом загрузки. Если ваш МК позволяет стартовать из ОЗУ после ресета, то всё должно проканать... Не знаю, надо думать!
|
|
|
|
|
Feb 15 2016, 13:45
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(scifi @ Feb 15 2016, 16:01)  Вне зависимости от того, как этот ВКП будет размещён в ОЗУ, нужно гарантировать, что все функции, которые вызывает этот ВКП, тоже сидели в ОЗУ. GCC неявно вызывает функции для многих дел: арифметика, копирование памяти и т.п. Почему ?
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Feb 15 2016, 16:08
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Цитата(Aaron @ Feb 15 2016, 15:46)  1. Всё, что должно помещаться в ram, есть initialized data - секция .data по умолчанию. Ну и ссылки начала и конца - _sidata, _edata. По сути то, что вы описали - есть ramfunc. Если абстрагироваться от заморочек с ресетом по питанию и передачей управления, то кусок скрипта линкёра примерно такой должен быть Странно, примерно такой же вариант пробовал и линковалось всё равно в конец. Попробую подредактировать под свои нужды Ваш. Цитата(scifi @ Feb 15 2016, 16:01)  Вне зависимости от того, как этот ВКП будет размещён в ОЗУ, нужно гарантировать, что все функции, которые вызывает этот ВКП, тоже сидели в ОЗУ. GCC неявно вызывает функции для многих дел: арифметика, копирование памяти и т.п. Это понятная грабля, спасибо за напоминание.
|
|
|
|
|
Feb 18 2016, 16:04
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Было бы предпочтительней понять как перемещать сразу объектные файлы, без редактирования исходников. Пробую так: CODE INCLUDE "corp_AES_TEST_Debug_library.ld" INCLUDE "corp_AES_TEST_Debug_memory.ld"
ENTRY(ResetISR)
SECTIONS { /* MAIN TEXT SECTION */ .text : ALIGN(4) { FILL(0xff) __vectors_start__ = ABSOLUTE(.) ; KEEP(*(.isr_vector)) /* Global Section Table */ . = ALIGN(4) ; __section_table_start = .; __data_section_table = .; LONG(LOADADDR(.data)); LONG( ADDR(.data)); LONG( SIZEOF(.data)); LONG(LOADADDR(.data_RAM2)); LONG( ADDR(.data_RAM2)); LONG( SIZEOF(.data_RAM2)); __data_section_table_end = .; __bss_section_table = .; LONG( ADDR(.bss)); LONG( SIZEOF(.bss)); LONG( ADDR(.bss_RAM2)); LONG( SIZEOF(.bss_RAM2)); __bss_section_table_end = .; __section_table_end = . ; /* End of Global Section Table */
*(.after_vectors*)
/* Code Read Protect data */ . = 0x000002FC ; PROVIDE(__CRP_WORD_START__ = .) ; KEEP(*(.crp)) PROVIDE(__CRP_WORD_END__ = .) ; ASSERT(!(__CRP_WORD_START__ == __CRP_WORD_END__), "Linker CRP Enabled, but no CRP_WORD provided within application"); /* End of Code Read Protect */ } >MFlash128
/* Main DATA section (RamLoc8) */ .data : ALIGN(4) { FILL(0xff) _data = . ; *(vtable) *(.ramfunc*) *wdt.o(.text*) *wdt.o(.rodata .rodata.* .constdata .constdata.*) *eeprom.o(.text*) *eeprom.o(.rodata .rodata.* .constdata .constdata.*) . = ALIGN(4); *(.data*) . = ALIGN(4) ; _edata = . ; } > RamLoc8 AT>MFlash128
.text : ALIGN(4) { *(EXCLUDE_FILE(*wdt.o *eeprom.o) .text*)*(EXCLUDE_FILE(*wdt.o *eeprom.o) .rodata .rodata.* .constdata .constdata.*) . = ALIGN(4); } > MFlash128 /* * for exception handling/unwind - some Newlib functions (in common * with C++ and STDC++) use this. */ .ARM.extab : ALIGN(4) { *(.ARM.extab* .gnu.linkonce.armextab.*) } > MFlash128 __exidx_start = .;
.ARM.exidx : ALIGN(4) { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > MFlash128 __exidx_end = .;
_etext = .; /* DATA section for RamUsb2 */ .data_RAM2 : ALIGN(4) { FILL(0xff) PROVIDE(__start_data_RAM2 = .) ; *(.ramfunc.$RAM2) *(.ramfunc.$RamUsb2) *(.data.$RAM2*) *(.data.$RamUsb2*) . = ALIGN(4) ; PROVIDE(__end_data_RAM2 = .) ; } > RamUsb2 AT>MFlash128
/* MAIN DATA SECTION */ .uninit_RESERVED : ALIGN(4) { KEEP(*(.bss.$RESERVED*)) . = ALIGN(4) ; _end_uninit_RESERVED = .; } > RamLoc8 /* BSS section for RamUsb2 */ .bss_RAM2 : ALIGN(4) { PROVIDE(__start_bss_RAM2 = .) ; *(.bss.$RAM2*) *(.bss.$RamUsb2*) . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */ PROVIDE(__end_bss_RAM2 = .) ; } > RamUsb2 /* MAIN BSS SECTION */ .bss : ALIGN(4) { _bss = .; *(.bss*) *(COMMON) . = ALIGN(4) ; _ebss = .; PROVIDE(end = .); } > RamLoc8 /* NOINIT section for RamUsb2 */ .noinit_RAM2 (NOLOAD) : ALIGN(4) { *(.noinit.$RAM2*) *(.noinit.$RamUsb2*) . = ALIGN(4) ; } > RamUsb2 /* DEFAULT NOINIT SECTION */ .noinit (NOLOAD): ALIGN(4) { _noinit = .; *(.noinit*) . = ALIGN(4) ; _end_noinit = .; } > RamLoc8
PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .); PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc8 - 0);
/* ## Create checksum value (used in startup) ## */ PROVIDE(__valid_user_code_checksum = 0 - (_vStackTop + (ResetISR + 1) + (( DEFINED(NMI_Handler) ? NMI_Handler : M0_NMI_Handler ) + 1) + (( DEFINED(HardFault_Handler) ? HardFault_Handler : M0_HardFault_Handler ) + 1) ) ); }
В мапе в итоге получаю: .data 0x10000000 0x28 load address <адрес в конце слинкованого флеша>
Сообщение отредактировал Kabdim - Feb 18 2016, 16:05
|
|
|
|
|
Feb 18 2016, 17:19
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Посмотрел у себя - то же самое. Похоже, то, что кладётся в секцию через AT>, попадает туда в последнюю очередь. Хм... Попробуйте тогда вот так: Код .text : ALIGN(4) { __vectors_start__ = ABSOLUTE(.); KEEP(*(.isr_vector)) _label1 = . } >FLASH
.data : AT ( _label1 ) { . = ALIGN(4); *(.ramfunc*) *(.data) *(.data.*) } >RAM Я думал, что это одно и то же, но теперь вижу, что этот вариант даёт больше контроля.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 19 2016, 16:59
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Прошу помочь с этим сдвигом. Мозги кипят. Пробую: Код .data : AT ( _label1 ) ... } > RamLoc8
. += SIZEOF(.data); /* . = _label1 + SIZEOF(.data); */ .text2 : ALIGN(4) { ... Не хочет он сдвигать начало секции. А если поставить внутри секции то будет просто зарезервированный кусок, который всё равно будет конфликтовать.
Сообщение отредактировал Kabdim - Feb 19 2016, 16:59
|
|
|
|
|
Feb 20 2016, 13:10
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Тихо сам с собой. Похоже получилось сдвинуть секцию, но как-то через 5 точку. Код примерно такой: Код /* в конце первой секции с кодом */ _label2 = ABSOLUTE(.); }
.data : AT ( _label1 ) _data = .; ... _edata = .; _new_flash_addr = _label2 + _edata - _data - 0x10000000; } > RamLoc8
/* Если перенести код сюда, то прибавится лишних 0x20000000 */ .text2 _new_flash_addr : ALIGN(4) { ... Как избавится от дополнительного смещения на размер смещенения секции памяти пока не могу догадаться. Но такое решение уже работает, но подозреваю что что-то очень важное в логике gnu ld от меня ускользнуло. Ну и добивая тему: Цитата _new_flash_addr = ABSOLUTE(_label2 + _edata - _data); Наверное надо отшлифовать использованием SIZEOF.
|
|
|
|
|
Feb 26 2016, 14:07
|

Местный
  
Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007

|
Подождите, что значит, не работает } > RAM AT > FLASH ??? Может, у вас всё же что-то не так в скриптах? К слову, навороченный у вас скрипт! Его ещё покурить надо, да на заметку себе взять, пригодится!  Ставлю секцию ramfunc вперёд, выхлоп в map-файле: Цитата 4 .ramfunc 00000538 20000000 08019a68 00020000 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 5 .data 00000890 20000538 08019fa0 00020538 2**3 CONTENTS, ALLOC, LOAD, DATA 6 .bss 00005d54 20000dc8 0801a830 00020dc8 2**3 ALLOC Ставлю в центр, выхлоп: Цитата 4 .data 00000890 20000000 08019a68 00020000 2**3 CONTENTS, ALLOC, LOAD, DATA 5 .ramfunc 00000538 20000890 0801a2f8 00020890 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 6 .bss 00005d54 20000dc8 0801a830 00020dc8 2**3 ALLOC Хочу, ставлю даже после bss, выхлоп: Цитата 4 .data 00000890 20000000 08019a68 00020000 2**3 CONTENTS, ALLOC, LOAD, DATA 5 .bss 00005d54 20000890 0801a2f8 00020890 2**3 ALLOC 6 .ramfunc 00000538 200065e8 0801a2f8 000265e8 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE Далее, по поводу объектников - указываете прямо их имена в линкер-скрипте: Цитата .my_objects: { . = WDT_NEED_ADDR path1/wdt.o . = EEPROM_NEED_ADDR path2/eeprom.o } > FLASH Что вам мешает перемещать эти объектники целиком, используя те же указатели . = WDT_NEED_ADDR? Более того, для отладки можете смотреть из c-кода своего (ну или просто в map-файле) глобальные переменные вида: Цитата void * _binary_path1_wdt_c_start, _binary_path1_wdt_c_end; void * _binary_path2_eeprom_c_start, _binary_path2_eeprom_c_end;
|
|
|
|
|
Feb 26 2016, 15:18
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Цитата(Aaron @ Feb 26 2016, 17:07)  Подождите, что значит, не работает } > RAM AT > FLASH ??? Может, у вас всё же что-то не так в скриптах? В вашем же примере у вас после отмапленных в память секций нет секций с кодом во флеше. Если её добавить, то размещение секций смапленных в память во флеше сдвинется, если указывать "> RAM AT > FLASH". А рецепт Антохи и позволяет произвольно тасовать секции во флеше и загрузочные куски секций, который будут скопированы в память. Аля: прерывания - код для копирования во флеш - код который остается во флеше. Тасовать секции который находятся только во флеше или только в памяти между собой порядком объявления - нет проблем. А вот всё вместе и было задачей. Цитата(Aaron @ Feb 26 2016, 17:07)  К слову, навороченный у вас скрипт! Его ещё покурить надо, да на заметку себе взять, пригодится!  Вы меня зря хвалите, он отредактирован после генератора, а не ручками написан.
Сообщение отредактировал Kabdim - Feb 26 2016, 15:24
|
|
|
|
|
Feb 26 2016, 16:15
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Какие-то сложные у вас решения Код .text : { _image_start = .; KEEP(*(.isr_vector)) LONG((_image_end - _image_start) / 4); /* application size, in 4-byte words */ } > TEXT .data : { . = ALIGN(4); _sdata = .; /* start of .data label */ *(.ramfunc) *(.ramfunc.*) *(.data) *(.data.*) . = ALIGN(4); _edata = .; /* end of .data label */ } > RAM AT > TEXT _sidata = LOADADDR(.data); /* start of initialized data label */ .text.1 : { . = ALIGN(8); __ctors_start__ = .; KEEP(*(.init_array)) /* eabi uses .init_array for static constructor lists */ .... } > TEXT Код .text 0x08001000 0x124 0x08001000 _image_start = . *(.isr_vector) .isr_vector 0x08001000 0x120 ./release/obj/startup.o 0x08001000 g_pfnVectors 0x08001120 0x4 LONG 0x1b79 ((_image_end - _image_start) / 0x4)
.vfp11_veneer 0x08001124 0x0 .vfp11_veneer 0x00000000 0x0 linker stubs
.v4_bx 0x08001124 0x0 .v4_bx 0x00000000 0x0 linker stubs
.iplt 0x08001124 0x0 .iplt 0x00000000 0x0 ./release/obj/startup.o
.rel.dyn 0x08001124 0x0 .rel.iplt 0x00000000 0x0 ./release/obj/startup.o
.data 0x20000000 0x4 load address 0x08001124 0x20000000 . = ALIGN (0x4) 0x20000000 _sdata = . *(.ramfunc) *(.ramfunc.*) *(.data) *(.data.*) .data.__ctype_ptr__ 0x20000000 0x4 /home/serzh/opt/arm-gcc/launchpad/20150306/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m/libc.a(lib_a-ctype_.o) 0x20000000 __ctype_ptr__ 0x20000004 . = ALIGN (0x4) 0x20000004 _edata = . 0x08001124 _sidata = LOADADDR (.data)
.igot.plt 0x20000004 0x0 load address 0x08001128 .igot.plt 0x00000000 0x0 ./release/obj/startup.o
.text.1 0x08001128 0x6cb4 0x08001128 . = ALIGN (0x8) 0x08001128 __ctors_start__ = . *(.init_array) .init_array 0x08001128 0x4 ./release/obj/adc.o
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|