vovo 0 7 апреля, 2017 Опубликовано 7 апреля, 2017 · Жалоба Доброго времени дня! Никак не могу найти решение проблемы. linking... ./gnu/startup_armcm3.o: In function `Reset_Handler': E:\ARM_F/SRC/startup_ARMCM3.S:172: undefined reference to `__copy_table_start__' E:\ARM_F/SRC/startup_ARMCM3.S:173: undefined reference to `__copy_table_end__' E:\ARM_F/SRC/startup_ARMCM3.S:204: undefined reference to `__data_start__' E:\ARM_F/SRC/startup_ARMCM3.S:205: undefined reference to `__data_end__' E:\ARM_F/SRC/startup_ARMCM3.S:233: undefined reference to `__zero_table_start__' E:\ARM_F/SRC/startup_ARMCM3.S:234: undefined reference to `__zero_table_end__' collect2.exe: error: ld returned 1 exit status Toolchain GNU Tools ARM Embedded\5.4 2016q3 Файл startup_ARMCM3.S взят из папки c тулчейном. Включён взамен стартового файла рабочего проекта, собранного на ARM MDK. Проект на GCC успешно компилится но не хочет собираться по указанным выше причинам. Вопрос - чего в супе не хватает? Это ведь области RAM, которые при старте инициализируются или обнуляются, что не так? Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DmitryM 0 7 апреля, 2017 Опубликовано 7 апреля, 2017 (изменено) · Жалоба А в линкер-файле эти регионы определены и именуются также ? Изменено 7 апреля, 2017 пользователем IgorKossak бездумное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aaron 1 7 апреля, 2017 Опубликовано 7 апреля, 2017 (изменено) · Жалоба заимствовали стартап файл и линкер-файл от разных проектов? нотация имён необычная. ищите в ld-файле что-то вида: _etext = .; .data : /* AT makes the LMA follow on in the binary image */ { . = ALIGN(4); _sidata = _etext; /* start of initialized data label */ _sdata = .; /* start of .data label */ KEEP( *(.data) ) KEEP( *(.data.*) ) . = ALIGN(4); _edata = .; /* end of .data label */ } > RAM AT > FLASH /* .bss section - uninitialized data */ .bss : { . = ALIGN(4); _sbss = .; /* start of .bss label (for startup) */ *(.bss) *(.bss.*) *(COMMON) . = ALIGN(4); _ebss = .; /* end of .bss label (for startup) */ _end = .; /* end of used ram (start of free memory, for malloc) */ __end = .; /* the same */ end = .; /* the same */ } > RAM и приводите имена в ссылках на память (строчки вида _end = .;) к вашим именам из ассемблерного файла Изменено 7 апреля, 2017 пользователем IgorKossak [codebox] для длинного кода. [code]-для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovo 0 7 апреля, 2017 Опубликовано 7 апреля, 2017 · Жалоба Линкер файл я даже не цеплял. Думал, по аналогии с MDK, что по умолчанию что то должно быть. Стартап взят отсюда C:\Program Files (x86)\GNU Tools ARM Embedded\5.4 2016q3\share\gcc-arm-none-eabi\samples\startup, тул скачан с ARMа. Я посмотрел *.ld файл, предлагаемый в тулчейне, там тоже нет этих символов, кроме __bss_start__, этот совпадает. Ok, спасибо за подсказки, пошёл изучать скрипты линкера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovo 0 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба Ещё раз благодарю за подсказки, с multi RAM разбрался. А вот как быть с multi ROM? Только когда секция FLASH едина, только тогда правильно выставляестя топ стека и стартовый переход. А вот стоит мне порезать FLASH на куски, то секция векторов прерываний и стартовый код ложатся таки куда надо, а вот топ стека адрес перехода на стартовый код нулевые выходят. И параллельно вопрос- а что в GCC нет возможности одной директивой все функции одного файла исходника отправить в свою секцию, только каждой функции __attribute__ прикручивать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба А вот стоит мне порезать FLASH на куски, то секция векторов прерываний и стартовый код ложатся таки куда надо, а вот топ стека адрес перехода на стартовый код нулевые выходят.«Дорогие учёные. У меня который год в подполе происходит подземный стук. Объясните, пожалуйста, как он происходит». И параллельно вопрос- а что в GCC нет возможности одной директивой все функции одного файла исходника отправить в свою секцию, только каждой функции __attribute__ прикручивать?Читайте документацию на линкер. Это все делается в скрипте линкера. Пару раз у меня возникало желание сделать такое, но всякий раз выяснялось, что это тянет за собой кучу других проблем и при другом подходе к решению задачи этого не требуется и проблем не возникает. Опишите более подробно вашу задачу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба все функции одного файла исходника отправить в свою секцию, только каждой функции __attribute__ прикручивать? В скрипте линкера. В нужную секцию добавить: *<имя файла>.o(.text .text* .rodata .rodata.* .constdata .constdata.*) потом в той секции откуда взят файл: *(EXCLUDE_FILE(*<имя файла>.o ...) .text*) Имена секций поправьте сами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovo 0 11 апреля, 2017 Опубликовано 11 апреля, 2017 (изменено) · Жалоба Да, по второму вопросу протупил, виноват, исправлюсь. Хотя..., а если это библиотека, я не знаю имён модулей, но хочу разместить её в определённом фрагменте памяти? А вот по первому /* Linker script to configure memory regions. * Need modifying for a specific board. * FLASH.ORIGIN: starting address of flash * FLASH.LENGTH: length of flash * RAM.ORIGIN: starting address of RAM bank 0 * RAM.LENGTH: length of RAM bank 0 */ MEMORY { FLASH1 (rx) : ORIGIN = 0x0, LENGTH = 0x1000 FLASH2 ® : ORIGIN = 0x1000, LENGTH = 0x1000 FLASH3 (rx) : ORIGIN = 0x2000, LENGTH = 0x80000 - 0x2000 RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000 /* 8K */ RAM2 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x8000 /* 8K */ } /* Linker script to place sections and symbol values. Should be used together * with other linker script that defines memory regions FLASH and RAM. * It references following symbols, which must be defined in code: * Reset_Handler : Entry of reset handler * * It defines following symbols, which code can use without definition: * __exidx_start * __exidx_end * __copy_table_start__ * __copy_table_end__ * __zero_table_start__ * __zero_table_end__ * __etext * __data_start__ * __preinit_array_start * __preinit_array_end * __init_array_start * __init_array_end * __fini_array_start * __fini_array_end * __data_end__ * __bss_start__ * __bss_end__ * __end__ * end * __HeapLimit * __StackLimit * __StackTop * __stack */ ENTRY(Reset_Handler) SECTIONS { .text0 0x0: { KEEP(*(.isr_vector)) KEEP(*(.Reset_Handler_s)) KEEP(*(.init)) KEEP(*(.fini)) } > FLASH1 .dfdata 0x1000: { /*. = 0x1000;*/ *(.ARM.__AT_0x00001000) } > FLASH2 .text 0x2000 : { /*. = 0x2000;*/ *(.text*) /* .ctors */ *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) *(SORT(.ctors.*)) *(.ctors) /* .dtors */ *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) *(SORT(.dtors.*)) *(.dtors) *(.rodata*) KEEP(*(.eh_frame*)) } > FLASH3 __exab_start = .; .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH3 __exab_end = .; __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > FLASH3 __exidx_end = .; /* To copy multiple ROM to RAM sections, * uncomment .copy.table section and, * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ /* .copy.table : { . = ALIGN(4); __copy_table_start__ = .; LONG (__etext) LONG (__data_start__) LONG (__data_end__ - __data_start__) LONG (__etext2) LONG (__data2_start__) LONG (__data2_end__ - __data2_start__) __copy_table_end__ = .; } > FLASH3 */ /* To clear multiple BSS sections, * uncomment .zero.table section and, * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ /* .zero.table : { . = ALIGN(4); __zero_table_start__ = .; LONG (__bss_start__) LONG (__bss_end__ - __bss_start__) LONG (__bss2_start__) LONG (__bss2_end__ - __bss2_start__) __zero_table_end__ = .; } > FLASH3 */ __etext = .; .data : AT (__etext) { __data_start__ = .; *(vtable) *(.data*) . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); KEEP(*(.jcr*)) . = ALIGN(4); /* All data end */ __data_end__ = .; } > RAM .bss_RAM2 : ALIGN(4) { PROVIDE(__start_bss_RAM2 = .) ; *(LWIP_ram_heap*) *(.bss.$RamAHB32*) . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */ PROVIDE(__end_bss_RAM2 = .) ; } > RAM2 .bss : { . = ALIGN(4); __bss_start__ = .; *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; } > RAM .heap (COPY): { __end__ = .; PROVIDE(end = .); *(.heap*) __HeapLimit = .; } > RAM2 /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign * values to stack symbols later */ .stack_dummy (COPY): { *(.stack*) } > RAM2 /* Set stack top to end of RAM, and stack limit move down by * size of stack_dummy section */ __StackTop = ORIGIN(RAM) + LENGTH(RAM); __StackLimit = __StackTop - SIZEOF(.stack_dummy); PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds RAM limit */ /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/ } Вот так мне нужно, но не работает А вот так работает /* Linker script to configure memory regions. * Need modifying for a specific board. * FLASH.ORIGIN: starting address of flash * FLASH.LENGTH: length of flash * RAM.ORIGIN: starting address of RAM bank 0 * RAM.LENGTH: length of RAM bank 0 */ MEMORY { FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000 /* 128K */ RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000 /* 8K */ RAM2 (rwx) : ORIGIN = 0x200c7000, LENGTH = 0x8000 /* 8K */ } /* Linker script to place sections and symbol values. Should be used together * with other linker script that defines memory regions FLASH and RAM. * It references following symbols, which must be defined in code: * Reset_Handler : Entry of reset handler * * It defines following symbols, which code can use without definition: * __exidx_start * __exidx_end * __copy_table_start__ * __copy_table_end__ * __zero_table_start__ * __zero_table_end__ * __etext * __data_start__ * __preinit_array_start * __preinit_array_end * __init_array_start * __init_array_end * __fini_array_start * __fini_array_end * __data_end__ * __bss_start__ * __bss_end__ * __end__ * end * __HeapLimit * __StackLimit * __StackTop * __stack */ ENTRY(Reset_Handler) SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text*) KEEP(*(.init)) KEEP(*(.fini)) /* .ctors */ *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) *(SORT(.ctors.*)) *(.ctors) /* .dtors */ *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) *(SORT(.dtors.*)) *(.dtors) *(.rodata*) KEEP(*(.eh_frame*)) } > FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > FLASH __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > FLASH __exidx_end = .; /* To copy multiple ROM to RAM sections, * uncomment .copy.table section and, * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ .copy.table : { . = ALIGN(4); __copy_table_start__ = .; LONG (__etext) LONG (__data_start__) LONG (__data_end__ - __data_start__) LONG (__etext2) LONG (__data2_start__) LONG (__data2_end__ - __data2_start__) __copy_table_end__ = .; } > FLASH /* To clear multiple BSS sections, * uncomment .zero.table section and, * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ .zero.table : { . = ALIGN(4); __zero_table_start__ = .; LONG (__bss_start__) LONG (__bss_end__ - __bss_start__) LONG (__bss2_start__) LONG (__bss2_end__ - __bss2_start__) __zero_table_end__ = .; } > FLASH __etext = .; .data : AT (__etext) { __data_start__ = .; *(LWIP_ram_heap) __data_end__ = .; } > RAM __etext2 = __etext + SIZEOF(.data); .data2 : AT (__etext2) { __data2_start__ = .; *(vtable) *(.data*) . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); KEEP(*(.jcr*)) . = ALIGN(4); /* All data end */ __data2_end__ = .; } > RAM2 .bss : { . = ALIGN(4); __bss_start__ = .; *(.bss*) . = ALIGN(4); __bss_end__ = .; } > RAM .bss2 : { . = ALIGN(4); __bss2_start__ = .; *(COMMON) . = ALIGN(4); __bss2_end__ = .; } > RAM2 .heap (COPY): { __end__ = .; PROVIDE(end = .); *(.heap*) __HeapLimit = .; } > RAM2 /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign * values to stack symbols later */ .stack_dummy (COPY): { *(.stack*) } > RAM2 /* Set stack top to end of RAM, and stack limit move down by * size of stack_dummy section */ __StackTop = ORIGIN(RAM) + LENGTH(RAM); __StackLimit = __StackTop - SIZEOF(.stack_dummy); PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } Изменено 11 апреля, 2017 пользователем vovo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба Вот так мне нужно, но не работаетНо вы так и не сказали, зачем вам это нужно. Зачем вы дважды указываете адрес - при задании региона и при объявлении выходной секции? Замените .text0 0x0: { ...... } > FLASH1 на .text0: { ...... } > FLASH1 и с остальными секциями аналогично. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба Да, по второму вопросу протупил, виноват, исправлюсь. Хотя..., а если это библиотека, я не знаю имён модулей, Что значит не знаете? Можете узнать с помощью *ar если не путаю, но не хотите напрягаться и гуглить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovo 0 11 апреля, 2017 Опубликовано 11 апреля, 2017 (изменено) · Жалоба Но вы так и не сказали, зачем вам это нужно. Зачем вы дважды указываете адрес - при задании региона и при объявлении выходной секции? Замените .text0 0x0: { ...... } > FLASH1 на .text0: { ...... } > FLASH1 и с остальными секциями аналогично. Попробовал, в строке где скобка открывающая, линкер выдаёт ошибку синтаксиса. c:/program files (x86)/gnu tools arm embedded/5.4 2016q3/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe:./SRC/gcc.ld:55: syntax error Мне не совсем понятен настойчивый вопрос про цель всего этого, но отвечу: в нулевом сегменте лежит код, на который смотрит bootloader чипа, его трогать нельзя, в первом сегменте, лежат данные, изменяемые программой по внешним воздействиям, в последующих сегментах остальной код программы, причём желательно его также разместить по необходимым адресам. Изменено 11 апреля, 2017 пользователем vovo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба Попробовал, в строке где скобка открывающая, линкер выдаёт ошибку синтаксиса.Извиняюсь. Пробел перед двоеточием, после ".text0" поставьте. Мне не совсем понятен настойчивый вопрос про цель всего этого, но отвечу: в нулевом сегменте лежит код, на который смотрит bootloader чипа, его трогать нельзя, в первом сегменте, лежат данные, изменяемые программой по внешним воздействиям, в последующих сегментах остальной код программы, причём желательно его также разместить по необходимым адресам.Вот-вот-вот. Я примерно это и предполагал. Не нужно совершенно разные вещи (bootloader и приложение) запихивать в один проект. Сделайте два совершенно отдельных проекта, у каждого секцию .text разместите куда нужно, ссылки на необходимые адреса другого проекта сделайте через extern в коде и символы в скрипте линкера. И ничего не придется переносить. Потому что при текущем подходе вы столкнетесь с необходимостью иметь две копии библиотечных функций (чтобы обновлять их вместе с приложением и чтобы загрузчик работал пока приложения нет), потом вдруг выяснится, что вы, развивая приложение, случайно что-то поменяли в загрузчике и приложение уже месяц как несовместимо с проданными год назад устройствами, но прекрасно совместимо с текущим загрузчиком и поэтому вы целый месяц ничего не замечали. Чтобы выпустить обновление для рассылки заказчикам вам придется каким-то образом отделять мух от котлет из результатов сборки проекта вырезать загрузчик не повредив приложение. Загрузчик надо делать отдельным проектом и при необходимости объединять с приложением слиянием выходных .hex-файлов. P.S. И постарайтесь избегать избыточного цитирования, оно является нарушением Правил форума. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovo 0 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба Извиняюсь. Пробел перед двоеточием, после ".text0" поставьте. Про пробел я и сам уже понял, но это не спасает P.S. И постарайтесь избегать избыточного цитирования, оно является нарушением Правил форума. С таким движком форума впервые общаюсь. Не нужно совершенно разные вещи (bootloader и приложение) запихивать в один проект загрузчик это не проект, он прошит в ROM чипа, при наличие программы (по оценке сектора 0 и тела программы) он её запускает, но для этого а адресе 0x00000000 должен быть адрес вершины стека, а в адресе 0x00000004 адрес перехода на начало программы. Вот их то в таком случае ликер и не помещает образ. Если область флеша одна, линкер правильно размещает начальные адреса, размещает данные с адреса 0х1000 по 0х2000, но заполняет нулями и главное включает в образ, что при программировании приводит к уничтожению этих данных. С ARM компилятором всё великолепно получается, но требуется переход на GCC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 123 11 апреля, 2017 Опубликовано 11 апреля, 2017 · Жалоба загрузчик это не проект, он прошит в ROM чипа, при наличие программы (по оценке сектора 0 и тела программы) он её запускает, но для этого а адресе 0x00000000 должен быть адрес вершины стека, а в адресе 0x00000004 адрес перехода на начало программы. Вот их то в таком случае ликер и не помещает образ.Теперь понятно. Попробуйте назвать выходную секцию не ".text0", а ".text.0". размещает данные с адреса 0х1000 по 0х2000, но заполняет нулями и главное включает в образ, что при программировании приводит к уничтожению этих данных.Для этого есть атрибут секции NOLOAD (пока на форуме проблемы с редиректом скопируйте ссылку вручную). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovo 0 12 апреля, 2017 Опубликовано 12 апреля, 2017 · Жалоба Хорошая ссылка, гораздо гораздее чем штатный pdf, спасибо. А ларчик открылся весьма просто - надо было всего лишь явно указать startup модуль в первом регионе))) Спасибо всем кто участвовал))), пока вроде всё намазывается, если что, ещё вас помучаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться