Kabdim 0 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба Есть связка: важный кусок программы(ВКП)+остальное. Среди прочего ВКП нужно скопировать в память и выполняться оттуда. Причем нужно что бы в случае если "остальное" будет стерто из флеша, то ВКП смог бы продолжать работать даже после ресета. Да, похоже на связку бут+программа, но связей между 2 кусками больше причем в обе стороны и они НЕ должны обновляться независимо. Соответственно что бы не городить разделение логически одной программы на 2 куска хочется указать линкеру что бы он часть ВКП отмапленную в память хранил в части флеша относящейся к ВКП же. Т.е. структура флеша: прерывания, startup&main, код и переменные ВКП который нужно загрузить в память, остальное структура памяти: код и переменные ВКП, память для остальной части программы Как бы это сделать через ld? Пробовал через разные секции для разных частей кода, однако сохраненное для загрузки в память всё равно линкуется в конец бинарника. Как это сделать правильно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aaron 1 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба 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. Если вы стёрли флэш и сделали ресет, то передача управления идёт в соответствие с режимом загрузки. Если ваш МК позволяет стартовать из ОЗУ после ресета, то всё должно проканать... Не знаю, надо думать! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба Причем нужно что бы в случае если "остальное" будет стерто из флеша, то ВКП смог бы продолжать работать даже после ресета. Вне зависимости от того, как этот ВКП будет размещён в ОЗУ, нужно гарантировать, что все функции, которые вызывает этот ВКП, тоже сидели в ОЗУ. GCC неявно вызывает функции для многих дел: арифметика, копирование памяти и т.п. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 42 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба Вне зависимости от того, как этот ВКП будет размещён в ОЗУ, нужно гарантировать, что все функции, которые вызывает этот ВКП, тоже сидели в ОЗУ. GCC неявно вызывает функции для многих дел: арифметика, копирование памяти и т.п. Почему ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба 1. Всё, что должно помещаться в ram, есть initialized data - секция .data по умолчанию. Ну и ссылки начала и конца - _sidata, _edata. По сути то, что вы описали - есть ramfunc. Если абстрагироваться от заморочек с ресетом по питанию и передачей управления, то кусок скрипта линкёра примерно такой должен быть Странно, примерно такой же вариант пробовал и линковалось всё равно в конец. Попробую подредактировать под свои нужды Ваш. Вне зависимости от того, как этот ВКП будет размещён в ОЗУ, нужно гарантировать, что все функции, которые вызывает этот ВКП, тоже сидели в ОЗУ. GCC неявно вызывает функции для многих дел: арифметика, копирование памяти и т.п. Это понятная грабля, спасибо за напоминание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 18 февраля, 2016 Опубликовано 18 февраля, 2016 · Жалоба Сделал как предложил Aaron, но всё равно во флеше загружаемое в память отправляется в конец, а не как должно было бы быть если заполнять флеш по порядку как в скрипте. Т.е флеш вместо того что в 1 сообщении получается: прерывания, startup&main, остальное, код и переменные ВКП который нужно загрузить в память ЧЯДНТ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 18 февраля, 2016 Опубликовано 18 февраля, 2016 · Жалоба Покажите скрипт линкера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 18 февраля, 2016 Опубликовано 18 февраля, 2016 (изменено) · Жалоба Было бы предпочтительней понять как перемещать сразу объектные файлы, без редактирования исходников. Пробую так: 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 <адрес в конце слинкованого флеша> Изменено 18 февраля, 2016 пользователем Kabdim Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 18 февраля, 2016 Опубликовано 18 февраля, 2016 · Жалоба Посмотрел у себя - то же самое. Похоже, то, что кладётся в секцию через AT>, попадает туда в последнюю очередь. Хм... Попробуйте тогда вот так: .text : ALIGN(4) { __vectors_start__ = ABSOLUTE(.); KEEP(*(.isr_vector)) _label1 = . } >FLASH .data : AT ( _label1 ) { . = ALIGN(4); *(.ramfunc*) *(.data) *(.data.*) } >RAM Я думал, что это одно и то же, но теперь вижу, что этот вариант даёт больше контроля. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 19 февраля, 2016 Опубликовано 19 февраля, 2016 · Жалоба Размещение в памяти теперь правильное, но конфликтует с остальным содержимым, последний линкуется во флеш в то же место: section .data loaded at [00000300,00000327] overlaps section .text loaded at [00000000,0000480f] Видимо надо сделать вторую секцию для кода и размещать её так же принудительно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 19 февраля, 2016 Опубликовано 19 февраля, 2016 (изменено) · Жалоба Прошу помочь с этим сдвигом. Мозги кипят. Пробую: .data : AT ( _label1 ) ... } > RamLoc8 . += SIZEOF(.data); /* . = _label1 + SIZEOF(.data); */ .text2 : ALIGN(4) { ... Не хочет он сдвигать начало секции. А если поставить внутри секции то будет просто зарезервированный кусок, который всё равно будет конфликтовать. Изменено 19 февраля, 2016 пользователем Kabdim Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 20 февраля, 2016 Опубликовано 20 февраля, 2016 · Жалоба Тихо сам с собой. Похоже получилось сдвинуть секцию, но как-то через 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aaron 1 26 февраля, 2016 Опубликовано 26 февраля, 2016 · Жалоба Подождите, что значит, не работает } > 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 26 февраля, 2016 Опубликовано 26 февраля, 2016 (изменено) · Жалоба Подождите, что значит, не работает } > RAM AT > FLASH ??? Может, у вас всё же что-то не так в скриптах? В вашем же примере у вас после отмапленных в память секций нет секций с кодом во флеше. Если её добавить, то размещение секций смапленных в память во флеше сдвинется, если указывать "> RAM AT > FLASH". А рецепт Антохи и позволяет произвольно тасовать секции во флеше и загрузочные куски секций, который будут скопированы в память. Аля: прерывания - код для копирования во флеш - код который остается во флеше. Тасовать секции который находятся только во флеше или только в памяти между собой порядком объявления - нет проблем. А вот всё вместе и было задачей. К слову, навороченный у вас скрипт! Его ещё покурить надо, да на заметку себе взять, пригодится! ;) Вы меня зря хвалите, он отредактирован после генератора, а не ручками написан. Изменено 26 февраля, 2016 пользователем Kabdim Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 26 февраля, 2016 Опубликовано 26 февраля, 2016 · Жалоба Какие-то сложные у вас решения .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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться