|
|
  |
Стартап и скрипт линкера из CMSIS для Sourcery CodeBench |
|
|
|
Jun 12 2013, 14:58
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Вопросы по Вашему скрипту. Зачем вообще придумали так много разных секций? Где узнать назначение каждой секции? Секции .text, .data, .bss, .isr_vector понятно для чего. .ARM.exidx для чего? Код /* higher address of the user mode stack */ PROVIDE ( _estack = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - 8 ,8) ); Зачем тут PROVIDE()? Если в программе уже определен символ _estack, то линкер использует его. А если символ не определен, но есть ссылки на него, то линкер сам создаст этот символ. Так? Не понял что тут с выравниванием и зачем так... Код .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } > FLASH Зачем тут эти выравнивания? Зачем вообще во всем скрипте так много выравниваний? KEEP(), как я понимаю, нужен для того, чтобы при линковке с --gc-sections линкер не отбросил секцию .isr_vector? Не совсем понятно как он чистит мусор. Код ._usrstack : { . = ALIGN(4); _susrstack = .; . = . + _Minimum_Stack_Size; . = ALIGN(4); _eusrstack = .; } >RAM _Minimum_Stack_Size, это размер стека? _susrstack и _eusrstack могут использоваться программой для отслеживания переполнения стека? Код /* remove the debugging information from the standard libraries */ DISCARD : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } Как я понимаю, все входные секции, перечисленные в выходной секции DISCARD не попадают в выходной файл. Здесь - все секции из перечисленных файлов. А почему в комментарии это названо отладочной информацией? Что-то я не понимаю, мы же используем эти библиотеки, а если мы их используем, то не мешает ли выше перечисленное?! Или получается так, что ранее мы уже включили все нужное нам из этих библиотек в выходной файл (секции .text, .data, .bss) и все что остается - нам не нужно? Код /* Stabs debugging sections. */ .stab 0 : { *(.stab) } ... Почему мы все располагаем по адресу "0"?
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 12 2013, 18:45
|

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

|
Ничего себе, сколько вопросов  Сразу предупреждаю, так глубоко я не копал, так что не на все вопросы у меня есть ответы. Цитата(koluna @ Jun 12 2013, 20:58)  Зачем вообще придумали так много разных секций? Где узнать назначение каждой секции? Секции .text, .data, .bss, .isr_vector понятно для чего. .ARM.exidx для чего? Это что-то связанное с обработкой исключений. Хотя мы отключаем эту обработку, всё равно что-то иногда пролазит. Короче, без этой секции какой-то из линкеров не собирал. Цитата(koluna @ Jun 12 2013, 20:58)  Код /* higher address of the user mode stack */ PROVIDE ( _estack = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - 8 ,8) ); Зачем тут PROVIDE()? Если в программе уже определен символ _estack, то линкер использует его. А если символ не определен, но есть ссылки на него, то линкер сам создаст этот символ. Так? Не понял что тут с выравниванием и зачем так... Да, так. Если мы сильно захотим, то можем в программе задать свой адрес для _estack. Выравнивание на 8 байт - это требование ARM EABI. Без этого бывают трудноуловимые глюки. Цитата(koluna @ Jun 12 2013, 20:58)  Зачем тут эти выравнивания? Зачем вообще во всем скрипте так много выравниваний? KEEP(), как я понимаю, нужен для того, чтобы при линковке с --gc-sections линкер не отбросил секцию .isr_vector? Не совсем понятно как он чистит мусор. Выравнивания полезны  Я не помню, зачем они в каждом конкретном случае, но хуже от них точно не будет. Лично наблюдал приличное уменьшение времени переключения контекста scmRTOS при добавлении выравнивания функции переключения контекста. Мусор чистит очень просто. То, что KEEP - оставляет, далее строит дерево вызовов. Всё, что не вызывается из того, что KEEP - выкидывается. Цитата(koluna @ Jun 12 2013, 20:58)  Код ._usrstack : { . = ALIGN(4); _susrstack = .; . = . + _Minimum_Stack_Size; . = ALIGN(4); _eusrstack = .; } >RAM _Minimum_Stack_Size, это размер стека? _susrstack и _eusrstack могут использоваться программой для отслеживания переполнения стека? Здесь простейшая проверка, что перед _eusrstack у нас останется _Minimum_Stack_Size свободного места. Если не останется, то линкер ругнётся. Цитата(koluna @ Jun 12 2013, 20:58)  Как я понимаю, все входные секции, перечисленные в выходной секции DISCARD не попадают в выходной файл. Здесь - все секции из перечисленных файлов. А почему в комментарии это названо отладочной информацией? Что-то я не понимаю, мы же используем эти библиотеки, а если мы их используем, то не мешает ли выше перечисленное?! Или получается так, что ранее мы уже включили все нужное нам из этих библиотек в выходной файл (секции .text, .data, .bss) и все что остается - нам не нужно? Да, всё полезное из этих файлов мы уже забрали выше. Цитата(koluna @ Jun 12 2013, 20:58)  Код /* Stabs debugging sections. */ .stab 0 : { *(.stab) } ... Почему мы все располагаем по адресу "0"? Тут ничего не скажу, не знаю. Этот кусок есть во всех скриптах, которые я видел, поэтому он, наверное, нужен
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 13 2013, 07:40
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(AHTOXA @ Jun 12 2013, 22:45)  Ничего себе, сколько вопросов  Сразу предупреждаю, так глубоко я не копал, так что не на все вопросы у меня есть ответы. Я посмотрел на скрипт внимательно, почитал доку на линкер и понял, что надо позадавать еще вопросов  Цитата Это что-то связанное с обработкой исключений. Хотя мы отключаем эту обработку, всё равно что-то иногда пролазит. Короче, без этой секции какой-то из линкеров не собирал. Зачем вообще она нужна для ARM? Почему ее полностью не отключат изначально? Или тулчейн один и на мелкие процы, и на крупные процы, а на крупных обработка исключений в ходу, в отличие от мелких? Цитата Да, так. Если мы сильно захотим, то можем в программе задать свой адрес для _estack. Ууу... что, может понадобиться? Цитата Выравнивание на 8 байт - это требование ARM EABI. Без этого бывают трудноуловимые глюки. Ветку почитаем, спасибо. Пруфлинк можно про выравнивание, пожалуйста? Цитата Выравнивания полезны  Я не помню, зачем они в каждом конкретном случае, но хуже от них точно не будет. Дырки в памяти образуются  И большое количество команд выравнивания вводит в ступор: не понимаешь для чего это и почему именно так и нужно ли вообще... А хочется все понимать... Цитата Лично наблюдал приличное уменьшение времени переключения контекста scmRTOS при добавлении выравнивания функции переключения контекста. Может, связано с выборкой команд? Ну там... ARM-инструкции (32 бита), THUMB-инструкции (16 бит)... т. е., адрес расположеня должен почему-то быть кратным 4 или 2 байтам... Цитата Мусор чистит очень просто. То, что KEEP - оставляет, далее строит дерево вызовов. Всё, что не вызывается из того, что KEEP - выкидывается. Т. е., то, на что есть ссылки в коде и то, что обрамлено KEEP оставляется, все остальное - выкидывается? Цитата Здесь простейшая проверка, что перед _eusrstack у нас останется _Minimum_Stack_Size свободного места. Если не останется, то линкер ругнётся. Код ._usrstack : { . = ALIGN(4); _susrstack = .; . = . + _Minimum_Stack_Size; . = ALIGN(4); _eusrstack = .; } >RAM Как я понимаю, эта секция - последнее, что будет размещено в RAM. И, если не хватит места для ее размещения, то линкер об этом сообщит? Фактически мы проверям (на этапе линковки), что размер стека будет не менее чем _Minimum_Stack_Size? А во время выполнения программы?  Стек ведь может переполниться... Цитата Да, всё полезное из этих файлов мы уже забрали выше. Как я понимаю, это влияет на размер бинаря. А еще что на размер влияет? Встречал где-то, что многие сталкиваются с "раздуванием" бинаря при использовании Си++, но сам пока не изучал вопрос.
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 13 2013, 08:36
|

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

|
Цитата(koluna @ Jun 13 2013, 13:40)  Зачем вообще она нужна для ARM? Почему ее полностью не отключат изначально? Или тулчейн один и на мелкие процы, и на крупные процы, а на крупных обработка исключений в ходу, в отличие от мелких? GCC один на все, видимо есть места, где эти исключения никак не выпилить при портировании. Цитата(koluna @ Jun 13 2013, 13:40)  Ууу... что, может понадобиться? Ну мало ли. Возможность не помешает  Цитата(koluna @ Jun 13 2013, 13:40)  Ветку почитаем, спасибо. Пруфлинк можно про выравнивание, пожалуйста? Дык, там же, во втором сообщении темы: Eight-byte Stack AlignmentЦитата(koluna @ Jun 13 2013, 13:40)  Т. е., то, на что есть ссылки в коде и то, что обрамлено KEEP оставляется, все остальное - выкидывается? Да. Цитата(koluna @ Jun 13 2013, 13:40)  Как я понимаю, эта секция - последнее, что будет размещено в RAM. И, если не хватит места для ее размещения, то линкер об этом сообщит? Фактически мы проверям (на этапе линковки), что размер стека будет не менее чем _Minimum_Stack_Size? А во время выполнения программы?  Стек ведь может переполниться... Ну, время выполнения - это уж никак не забота линкера  Цитата(koluna @ Jun 13 2013, 13:40)  Как я понимаю, это влияет на размер бинаря. А еще что на размер влияет? Встречал где-то, что многие сталкиваются с "раздуванием" бинаря при использовании Си++, но сам пока не изучал вопрос. Не бинаря, а elf. При прошивке вся эта ботва всё равно выкидывается. Насчёт раздувания при использовании Си++ - не замечал такого. Если не подцепились исключения, то всё очень компактно получается.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 13 2013, 08:43
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(koluna @ Jun 13 2013, 11:40)  Зачем вообще она нужна для ARM? Почему ее полностью не отключат изначально? Или тулчейн один и на мелкие процы, и на крупные процы, а на крупных обработка исключений в ходу, в отличие от мелких? Мне вот пригодилась кое-где. Хотите отключить вообще - наверное можно и так собрать тулчейн, просто зачем? Цитата Т. е., то, на что есть ссылки в коде и то, что обрамлено KEEP оставляется, все остальное - выкидывается? Есть флаги компиляции, которые заведуют разбиением на секции - -ffunction-sections, --fdata-sections и флаг линкера --gc-sections Цитата А во время выполнения программы?  Стек ведь может переполниться... А во время выполнения программы - нужны динамические проверки. К примеру в конце стека размещаем некий паттерн, а потом периодически проверяем, что паттерн не затерт... Цитата Встречал где-то, что многие сталкиваются с "раздуванием" бинаря при использовании Си++, но сам пока не изучал вопрос. Я столкнулся Включение исключений добавляют несколько десятков килобайт, включение rtti - дает накладные расходы на каждый тип с виртуальными функциями. Использование чего-то вроде iostream - дает еще порядка 150 килобайт  А это включение происходит в потрохах стандартной библиотеки при включении исключений. Так как исключения мне были нужны, пришлось немного подхачить libc++. Ну а дальше - как обычно, чем больше кода, тем больше размер. При этом надо учитывать, что какой-то код генерится автоматически - вроде инстанцирования шаблонов. Итого, если отключить rtti и исключения - оверхеда по сравнению с С нет. Если включить и использовать stl - тут уже надо сравнивать с аналогичным рукопашным кодом на С. Ну и мозг надо не выключать
|
|
|
|
|
Jun 13 2013, 18:41
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Вот здесь зачем выравнивание перед таблицей векторов? Ведь по адресу 0 должен сохраняться указатель начального адреса стека, но он уже включен в таблицу из .isr_vector. Код .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } > FLASH По VMA и LMA тоже не все понятно. Как я понял, LMA - это адрес расположения секции в ROM, а VMA - расположения в RAM? Используется только при создании образа в ROM для инициализации инициализированных переменных в RAM? Код .text.align : { . = ALIGN(8); _etext = .; _sidata = _etext; /* start of initialized data label */ } > FLASH
.data : AT ( _sidata ) /* AT makes the LMA follow on in the binary image */ { . = ALIGN(4); _sdata = .; /* start of .data label */ KEEP( *(.data) ) KEEP( *(.data.*) ) . = ALIGN(4); _edata = .; /* end of .data label */ } > RAM Т. е., выше перечисленное следует понимать как-то так. Размещаем образ для ининицилизации переменных после чудной секции .ARM.exidx (опять с непонятным выравниванием на 8) во FLASH. Тут у нас используется LMA. Размещаем данные (хотя, наверное, не размещаем, а резервируем место для размещения) с выравниванием 4 (т. е., от начала RAM адрес расположения переменных будет 4) в RAM. Тут у нас используется VMA. Кстати, зачем .data обертывать в KEEP()? В этих секциях ведь находятся данные, на которые мы ссылаемся, поэтому линкер не должен их выбрасывать при чистке мусора. Или я чего-то не допонял  Код KEEP(SORT(*)(.init_array)) Какой смысл в сортировке файлов при размещении статических конструкторов?
Сообщение отредактировал koluna - Jun 13 2013, 18:42
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 13 2013, 19:12
|

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

|
QUOTE (koluna @ Jun 13 2013, 21:41)  Вот здесь зачем выравнивание перед таблицей векторов? Ведь по адресу 0 должен сохраняться указатель начального адреса стека, но он уже включен в таблицу из .isr_vector. Считайте это перестраховкой. Чтобы когда захочется эту программу использовать с загрузчиком и адрес начала региона будет задан не 0 и, возможно, не кратным 4, программа продолжала собираться в рабочее состояние. Чтобы в варианте с загрузчиком, добавление секции перед этой .isr_vector не ломало программу. QUOTE (koluna @ Jun 13 2013, 21:41)  По VMA и LMA тоже не все понятно. Как я понял, LMA - это адрес расположения секции в ROM, а VMA - расположения в RAM? Да. QUOTE (koluna @ Jun 13 2013, 21:41)  Используется только при создании образа в ROM для инициализации инициализированных переменных в RAM? Чаще всего - да. Также используется для загружаемых в ОЗУ функций. QUOTE (koluna @ Jun 13 2013, 21:41)  Кстати, зачем .data обертывать в KEEP()? В этих секциях ведь находятся данные, на которые мы ссылаемся, поэтому линкер не должен их выбрасывать при чистке мусора. Верно. Антоха что-то намудрил. и .data : AT ( _sidata ) тоже не лучший вариант. Предпочитаю CODE .data : { ...... } > RAM AT > FLASH QUOTE (koluna @ Jun 13 2013, 21:41)  Какой смысл в сортировке файлов при размещении статических конструкторов? кто-то может использовать для задания порядка вызова конструкторов. Т.е. Объект ADC будет создан до объекта UART. Но по секркту - это рудимент от найденного в интернете образца скрипта  Не мешает.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 13 2013, 19:48
|

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

|
Цитата(koluna @ Jun 14 2013, 00:41)  Вот здесь зачем выравнивание перед таблицей векторов? Ведь по адресу 0 должен сохраняться указатель начального адреса стека, но он уже включен в таблицу из .isr_vector. Ох, дались вам эти выравнивания  Если мы 0 выровняем на 4, то останется 0, так что дырки не будет. А вот если мы будем размещать .isr_vector где-то в другом месте, то выравнивание необходимо. Цитата(koluna @ Jun 14 2013, 00:41)  По VMA и LMA тоже не все понятно. Как я понял, LMA - это адрес расположения секции в ROM, а VMA - расположения в RAM? Используется только при создании образа в ROM для инициализации инициализированных переменных в RAM? Да, всё верно. Цитата(koluna @ Jun 14 2013, 00:41)  Размещаем данные (хотя, наверное, не размещаем, а резервируем место для размещения) с выравниванием 4 (т. е., от начала RAM адрес расположения переменных будет 4) в RAM. Нет, выравнивание на 4 - это не то же самое, что отступ на 4:) Если начало ОЗУ выровнено на 4 (а обычно так и есть), то никакого отступа не будет. Цитата(koluna @ Jun 14 2013, 00:41)  Кстати, зачем .data обертывать в KEEP()? В этих секциях ведь находятся данные, на которые мы ссылаемся, поэтому линкер не должен их выбрасывать при чистке мусора. Или я чего-то не допонял  Тут я не помню, если честно. Вроде бы это я боролся с LTO. И вроде бы, без этого линкер что-то выкидывал нужное. Но точно не помню, могу и соврать. Цитата(koluna @ Jun 14 2013, 00:41)  Какой смысл в сортировке файлов при размещении статических конструкторов? Удобно, чтоб по алфавиту вызывались. Цитата(Сергей Борщ @ Jun 14 2013, 01:12)  Верно. Антоха что-то намудрил. и .data : AT ( _sidata ) тоже не лучший вариант. Предпочитаю Код .data : { ...... } > RAM AT > FLASH С KEEP() я написал выше, хотя может и правда намудрил  А чем хуже вариант с ".data : AT ( _sidata )" ? Мне он кажется как-то понятнее по записи.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 14 2013, 01:51
|

Местный
  
Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382

|
Цитата(Сергей Борщ @ Jun 14 2013, 02:12)  Верно. Антоха что-то намудрил. и .data : AT ( _sidata ) тоже не лучший вариант. Предпочитаю Код .data : { ...... } > RAM AT > FLASH А как, при такой записи, определить по какому адресу FLASH эти данные расположились? Цитата(Сергей Борщ @ Jun 14 2013, 02:12)  Цитата(koluna) Какой смысл в сортировке файлов при размещении статических конструкторов? кто-то может использовать для задания порядка вызова конструкторов. Т.е. Объект ADC будет создан до объекта UART. Но по секркту - это рудимент от найденного в интернете образца скрипта  Не мешает. Если SORT убрать, то будут вызываться в порядке появления в cpp файле?
|
|
|
|
|
Jun 14 2013, 13:41
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(Сергей Борщ @ Jun 13 2013, 23:12)  кто-то может использовать для задания порядка вызова конструкторов. Т.е. Объект ADC будет создан до объекта UART. Но по секркту - это рудимент от найденного в интернете образца скрипта  Не мешает. Вот смотрю я доку на линкер и не понимаю (Sourcery Codebench)... Цитата SORT is an alias for SORT_BY_NAME. Ну тут понятно. В доке все время упоминается синтаксис вида: Код ... SORT_BY_NAME(.text*) ... SORT_BY_NAME (SORT_BY_NAME (wildcard section pattern)) .... Т. е., SORT обрамляет шаблон секций. А в скрипте - SORT обрамляет шаблон файлов: Код ... SORT(*)(.init_array) ... И, мне, например, непонятно из всего прочитанного/увиденного, толи только файлы будут сортироваться по имени, толи всетаки сначала файлы а внутри них и содержимое секций... В моем понимании надо делать как-то так: Код ... SORT( *( .init_array ) ) ... Ну, или так: Код ... *( SORT( .init_array ) ) ... Цитата(Terminator @ Jun 14 2013, 05:51)  А как, при такой записи, определить по какому адресу FLASH эти данные расположились? Видимо, линкер разместит эти данные во FLASH сразу за предыдущей секцией, размещенной во FLASH. Цитата The load address is specified by the AT or AT> keywords. Specifying a load address is optional. The AT keyword takes an expression as an argument. This specifies the exact load address of the section. The AT> keyword takes the name of a memory region as an argument. See Section 3.7 [MEMORY], page 63. The load address of the section is set to the next free address in the region, aligned to the section’s alignment requirements.
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 14 2013, 18:25
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(AHTOXA @ Jun 13 2013, 23:48)  Ох, дались вам эти выравнивания  Если мы 0 выровняем на 4, то останется 0, так что дырки не будет. А вот если мы будем размещать .isr_vector где-то в другом месте, то выравнивание необходимо. ... Нет, выравнивание на 4 - это не то же самое, что отступ на 4:) Если начало ОЗУ выровнено на 4 (а обычно так и есть), то никакого отступа не будет. Ааа... понял... выравнивание и отступ - разные вещи  Если счетчик позиций == 0, ALIGN( 4 ) == 0. Если счетчик позиций == 3, ALIGN( 4 ) == 4. Если счетчик позиций == 4, ALIGN( 4 ) == 4. Если счетчик позиций == 5, ALIGN( 4 ) == 8. Если счетчик позиций == 7, ALIGN( 4 ) == 8. И т. д. Ну а отступ, это было бы что-то вроде: ". += <отступ>;" Выравнивание начала ОЗУ на 4 тоже требование ARM EABI, как и выравнивание начала стека на 8 байт? Так, т. е., выравнивание таблицы векторов, начала стека и начала ОЗУ - обязательные требования, получается? Исходя из скрипта, куча начинается сразу за неинициализированными данными и растет вверх навстречу стеку? Чтобы стек и куча не пересеклись используются менеджеры кучи?
Сообщение отредактировал koluna - Jun 14 2013, 18:14
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 14 2013, 19:19
|

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

|
Цитата(koluna @ Jun 15 2013, 00:25)  Ааа... понял... выравнивание и отступ - разные вещи  Да  Цитата(koluna @ Jun 15 2013, 00:25)  Выравнивание начала ОЗУ на 4 тоже требование ARM EABI, как и выравнивание начала стека на 8 байт? Нет, я такого требования не припоминаю. Скорее, это сделано для удобства инициализации данных (чтоб копировать данные по слову). Цитата(koluna @ Jun 15 2013, 00:25)  Так, т. е., выравнивание таблицы векторов, начала стека и начала ОЗУ - обязательные требования, получается? Начала стека - да. Начала ОЗУ - нет (вроде). А вот с таблицей векторов на самом деле требования гораздо жестче. Нужно выравнивать на ближайшую степень двойки, большую размера таблицы векторов. Так что мы недовыравнивали  Цитата(koluna @ Jun 15 2013, 00:25)  Исходя из скрипта, куча начинается сразу за неинициализированными данными и растет вверх навстречу стеку? Чтобы стек и куча не пересеклись используются менеджеры кучи? Да, всё так.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 14 2013, 19:50
|

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

|
QUOTE (AHTOXA @ Jun 13 2013, 22:48)  А чем хуже вариант с ".data : AT ( _sidata )" ? Мне он кажется как-то понятнее по записи. Тем, что если захочется добавить еще одну секцию между .text и .data - то придется заводить еще один символ, аналогичный _sidata и вписывать его сюда вместо _sidata. В случае же "AT > " ничего этого делать не нужно, все происходит автоматически. QUOTE (Terminator @ Jun 14 2013, 04:51)  А как, при такой записи, определить по какому адресу FLASH эти данные расположились? CODE __data_load_start = LOADADDR(.data); __data_load_end = __data_load_start + SIZEOF(.data); QUOTE (AHTOXA @ Jun 13 2013, 22:48)  Если SORT убрать, то будут вызываться в порядке появления в cpp файле? Да. А для разных единиц компиляции порядок не определен. Вот для этого и делается сортировка по именам файлов (спасибо koluna, что обратил внимание). Сортировать по именам секций смысла нет, ибо все конструкторы помещаются в одну секцию, сортировать нечего.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 15 2013, 05:43
|

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

|
Цитата(Сергей Борщ @ Jun 15 2013, 01:50)  Тем, что если захочется добавить еще одну секцию между .text и .data - то придется заводить еще один символ, аналогичный _sidata и вписывать его сюда вместо _sidata. В случае же "AT > " ничего этого делать не нужно, все происходит автоматически. Код __data_load_start = LOADADDR(.data); __data_load_end = __data_load_start + SIZEOF(.data); А, точно! Вот значит почему я в скрипте для F4 сделал с "AT > " -- чтоб не заводить ещё один символ для ramfunc. Хорошая болезнь - склероз  (Но символ _sidata всё-таки вручную там завёл, не подумал про LOADADDR()). Цитата(Сергей Борщ @ Jun 15 2013, 01:50)  Цитата(AHTOXA @ Jun 14 2013, 01:48)  Если SORT убрать, то будут вызываться в порядке появления в cpp файле? Да. А для разных единиц компиляции порядок не определен. Это не я спрашивал, а Terminator
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 15 2013, 10:27
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(AHTOXA @ Jun 14 2013, 23:19)  Начала стека - да. Начала ОЗУ - нет (вроде). А вот с таблицей векторов на самом деле требования гораздо жестче. Нужно выравнивать на ближайшую степень двойки, большую размера таблицы векторов. Так что мы недовыравнивали  Недовыравнивали - ошибка?  Т. е., первый ". = ALIGN(4);" в секции должен выравнивать по-другому? Хитрые там вычисления какие-то и зависят от количества векторов почему-то... Кстати, выравненное смещение этим самым хитрым образом нужно записать в регистр VTOR, как я понимаю. Где осуществляется запись? В стартапе и в init_HW() не нашел. Или используется значение по умолчанию? Проекты с данным скриптом нормально собираются в Sourcery CodeBench? Какими компиляторами собирается без проблем? Кстати, точка входа, как я понимаю для проекта с данным скриптом будет - первый байт в секции .text?
--------------------
Благодарю заранее!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|