реклама на сайте
подробности

 
 
5 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Стартап и скрипт линкера из CMSIS для Sourcery CodeBench
koluna
сообщение Jun 6 2013, 08:09
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Всем привет!

Помогите разобраться, пожалуйста.
Стартап и скрипт взял из CMSIS 3.01 (\Device\ARM\ARMCM3\Source\GCC): gcc_arm.ld, startup_ARMCM3.S (приложил к теме).
Подцепляю к простейшему тестовому проекту.
При сборке линкер ругался сначала на отсутствие libnosys.a (ее действительно нет в дистрибе компилятора) - убрал ее из списка в скрипте. Ошибка пропала.
Но так и не нашел, что это за либа, для чего нужна и почему ее нет...
Потом линкер ругался на отсутствие "_start". Странно, откуда эта метка в стартапе и почему так называется? Поставил вместо нее "main" - все собралось. Ошибок нет.
Но осадок сомнения остался - уже две ошибки в этих двух файлах... кто знает, что там еще? Надеялся, что все заработает "из коробки".
Пока не зашивал, не уверен в работоспособности, будем пробовать.
Насколько можно верить этим файлам? Что еще в них придется корректировать (ну, кроме размеров RAM, ROM, размеров стека и кучи)?
Прикрепленные файлы
Прикрепленный файл  GCC.zip ( 3.82 килобайт ) Кол-во скачиваний: 14
 


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 6 2013, 08:22
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Я в свое время сам писал и скрипт и стартап. Чем-то меня смсисовские не устроили.

Кстати, неясно зачем там асм. Для кортексов стартап прекрасно пишется на С...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 6 2013, 08:42
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(Непомнящий Евгений @ Jun 6 2013, 12:22) *
Я в свое время сам писал и скрипт и стартап. Чем-то меня смсисовские не устроили.


Да я бы и сам написал, если бы знал как sm.gif
Хочется разобраться, но времени пока нет.
Поэтому решил начать с более простого - подключить имеющиеся файлы.

Что, неужели "коробочные" файлы так плохи и никто их не использует?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 6 2013, 11:58
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Кто-нибудь выскажет свое мнение?
Или мир разделился на два лагеря: одни пишут скрипты/стартапы сами, другие используют среды программирования с уже имеющимися скриптами/стартапами и не заморачиваются? sm.gif

Еще стартапы есть в стандартной библиотеке периферии от STM. Правда при сборке с ними ошибок гораздо больше.
И нет почему-то скриптов линкера...


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jun 6 2013, 17:32
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(koluna @ Jun 6 2013, 14:58) *
И нет почему-то скриптов линкера...

Скрипты должны быть - иначе как собрать откомпилированный код?
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 6 2013, 18:27
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(_Артём_ @ Jun 6 2013, 21:32) *
Скрипты должны быть - иначе как собрать откомпилированный код?


Ясное дело, что где-то они есть - без них никак!
Я говорю о другом. В комплекте с SPL их нет. Стартапы есть, а скриптов нет.
Поэтому взял все из CMSIS. Но при сборке возникли ошибки.
Поправил. Заработало. Пока не зашивал. Не уверен в работоспособности полученного кода из-за скрипта и стартапа. Не знаю какие там могут быть ошибки еще - вот и спрашиваю у опытных людей.
Кто-нибудь использовал эти самые файлы из комплекта CMSIS с минимальными изменениями (и какими)?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 6 2013, 18:29
Сообщение #7


фанат дивана
******

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



Попробуйте скрипты и стартап от scmRTOS. Я точно знаю, что они рабочиеsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 7 2013, 10:59
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



AHTOXA, спасибо большое!
Но мне хотелось бы все-таки получить ответы на свои вопросы касательно файлов из CMSIS sm.gif

Кстати, какими основными принципами надо руководствоваться при написании стартапов (для Ассемблера и Си)?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 7 2013, 14:44
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



AHTOXA, есть вопросы по Вашему стартапу, прошу помочь разобраться sm.gif

Строки 12-23.
Что это? Где определено? В доке на компилятор не нашел.

Строки 207-454.
(intfunc)((unsigned long)&_estack) - для чего это вначале таблицы векторов?

Строки 465-487.
Тут, вроде, более менее понятно.
Инициализируем инициализируемые переменные своими значениями, инициализируем нулями неинициализируемые переменные, инициализируем железо (что конкретно только не понятно пока), инициализируем внешнюю память, если она есть, вызываем конструкторы.
init_HW() - это что-то типа SystemInit() из system_stm32f10x.c в SPL?
Вызов init_HW() до вызова конструкторов т. к., конструкторы могут работать с железом?
Видимо в scmRTOS есть реализованная функция init_HW()? sm.gif



--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 7 2013, 16:59
Сообщение #10


фанат дивана
******

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



Цитата(koluna @ Jun 7 2013, 20:44) *
Строки 12-23.
Что это? Где определено? В доке на компилятор не нашел.

Это переменные из линкерного скрипта. Границы секций.
Цитата(koluna @ Jun 7 2013, 20:44) *
Строки 207-454.
(intfunc)((unsigned long)&_estack) - для чего это вначале таблицы векторов?

Ну, у нас таблица указателей на функции, а первый элемент в ней - адрес стека. Приходится преобразовывать тип, чтобы компилятор не ругался.

Цитата(koluna @ Jun 7 2013, 20:44) *
Строки 465-487.
Тут, вроде, более менее понятно.
Инициализируем инициализируемые переменные своими значениями, инициализируем нулями неинициализируемые переменные, инициализируем железо (что конкретно только не понятно пока), инициализируем внешнюю память, если она есть, вызываем конструкторы.
init_HW() - это что-то типа SystemInit() из system_stm32f10x.c в SPL?
Вызов init_HW() до вызова конструкторов т. к., конструкторы могут работать с железом?
Видимо в scmRTOS есть реализованная функция init_HW()? sm.gif

Да, всё именно так. Просто сначала я придумал название init_HW(), а потом в ST придумали SystemInit() sm.gif Можете заменить одно на другое.
(Если что, то функцию init_HW() можно посмотреть здесь).


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 7 2013, 19:53
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 7 2013, 20:59) *
Это переменные из линкерного скрипта. Границы секций.


Я потом посмотрел скрипт, увидел их там и понял... к тому же они используются для инициализации переменных и вызова конструкторов.
Просто названия у них не особо очевидные...
Кстати, это именно переменные, которые определяются в скрипте и глобальны для всей программы?

Не совсем понятно что это. Вроде, одно и тоже... но зачем тогда два идентификатора?
Код
extern unsigned long _etext;
extern unsigned long _sidata;


Тут правильно?
Код
extern unsigned long _sdata; // Начало секции размещения инициализированных данных (RAM)
extern unsigned long _edata; // Ее конец
extern unsigned long _sbss; // Начало секции размещения неициализированных данных (RAM)
extern unsigned long _ebss; // Ее конец
extern unsigned long _estack; // Конец стека (конец RAM)
extern unsigned long __ctors_start__; // Начало секции размещения конструкторов (FLASH)
extern unsigned long __ctors_end__; // Ее конец
extern unsigned long __dtors_start__; // Начало секции размещения деструкторов (FLASH)
extern unsigned long __dtors_end__; // Ее конец


Код
Ну, у нас таблица указателей на функции,  а первый элемент в ней - адрес стека. Приходится преобразовывать тип, чтобы компилятор не ругался.


С преобразованием-то понятно, а вот с тем что первый элемент адрес стека - нет, видимо, так для ARM надо. Перечитаю про прерывания sm.gif

Спасибо большое за консультации.
В общем, параллельно надо в скрипт линкера вникать sm.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 7 2013, 21:39
Сообщение #12


фанат дивана
******

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



Цитата(koluna @ Jun 8 2013, 01:53) *
Кстати, это именно переменные, которые определяются в скрипте и глобальны для всей программы?

Да. Линкер знает их адреса (из скрипта). В любом месте программы вы можете объявить переменную с таким именем. (Здесь нам нужна не сама переменная, а её адрес. Хотя я видел, как в линкерном скрипте объявляли регистры процессора. В этом нет особого смысла, но это возможноsm.gif ).

Цитата(koluna @ Jun 8 2013, 01:53) *
Не совсем понятно что это. Вроде, одно и тоже... но зачем тогда два идентификатора?
Код
extern unsigned long _etext;
extern unsigned long _sidata;

Там есть какой-то перечень предопределённых имён, которые нужны встроенным стартапам. Так что в скрипте объявляются разные возможные варианты, например, end и __end. Памяти они не занимают, так что не жалко.

Цитата(koluna @ Jun 8 2013, 01:53) *
Тут правильно?

Да, всё так.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 10 2013, 12:41
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 8 2013, 01:39) *
Да. Линкер знает их адреса (из скрипта). В любом месте программы вы можете объявить переменную с таким именем. (Здесь нам нужна не сама переменная, а её адрес. Хотя я видел, как в линкерном скрипте объявляли регистры процессора. В этом нет особого смысла, но это возможноsm.gif ).


Кстати, а для чего в программе могут понадобиться такие переменные?

Цитата
Там есть какой-то перечень предопределённых имён, которые нужны встроенным стартапам. Так что в скрипте объявляются разные возможные варианты, например, end и __end. Памяти они не занимают, так что не жалко.


А где, кстати, перечень? Может быть так много имен для совместимости?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 10 2013, 18:56
Сообщение #14


фанат дивана
******

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



Цитата(koluna @ Jun 10 2013, 18:41) *
Кстати, а для чего в программе могут понадобиться такие переменные?

Ну мало ли. Например, end/_end/__end часто используются менеджерами кучи.
Цитата(koluna @ Jun 10 2013, 18:41) *
А где, кстати, перечень? Может быть так много имен для совместимости?

Не уверен, что этот перечень где-то формализован. Скорее, это происходит так: перестаёт компилироваться каким-то компилятором программа - добавляем ещё одну переменную.
В общем, не надо особо с этим заморачиваться, основную идею поняли, заработало - и нормуль. Если вдруг понадобится что-то специфическое, то тогда уже погружаться, даsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 11 2013, 07:46
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 10 2013, 22:56) *
Ну мало ли. Например, end/_end/__end часто используются менеджерами кучи.
Не уверен, что этот перечень где-то формализован. Скорее, это происходит так: перестаёт компилироваться каким-то компилятором программа - добавляем ещё одну переменную.


Понятно, спасибо sm.gif
Разбираюсь с линкером потихонечку.
Будут и по нему вопросы sm.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 12 2013, 14:58
Сообщение #16


Профессионал
*****

Группа: Участник
Сообщений: 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"?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 12 2013, 18:45
Сообщение #17


фанат дивана
******

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



Ничего себе, сколько вопросовsm.gif
Сразу предупреждаю, так глубоко я не копал, так что не на все вопросы у меня есть ответы.
Цитата(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?
Не совсем понятно как он чистит мусор.

Выравнивания полезныsm.gif Я не помню, зачем они в каждом конкретном случае, но хуже от них точно не будет.
Лично наблюдал приличное уменьшение времени переключения контекста 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"?

Тут ничего не скажу, не знаю. Этот кусок есть во всех скриптах, которые я видел, поэтому он, наверное, нуженsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 13 2013, 07:40
Сообщение #18


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 12 2013, 22:45) *
Ничего себе, сколько вопросовsm.gif
Сразу предупреждаю, так глубоко я не копал, так что не на все вопросы у меня есть ответы.


Я посмотрел на скрипт внимательно, почитал доку на линкер и понял, что надо позадавать еще вопросов sm.gif

Цитата
Это что-то связанное с обработкой исключений. Хотя мы отключаем эту обработку, всё равно что-то иногда пролазит. Короче, без этой секции какой-то из линкеров не собирал.


Зачем вообще она нужна для ARM? Почему ее полностью не отключат изначально? Или тулчейн один и на мелкие процы, и на крупные процы, а на крупных обработка исключений в ходу, в отличие от мелких?

Цитата
Да, так. Если мы сильно захотим, то можем в программе задать свой адрес для _estack.


Ууу... что, может понадобиться?

Цитата
Выравнивание на 8 байт - это требование ARM EABI. Без этого бывают трудноуловимые глюки.


Ветку почитаем, спасибо. Пруфлинк можно про выравнивание, пожалуйста?

Цитата
Выравнивания полезныsm.gif Я не помню, зачем они в каждом конкретном случае, но хуже от них точно не будет.


Дырки в памяти образуются wink.gif И большое количество команд выравнивания вводит в ступор: не понимаешь для чего это и почему именно так и нужно ли вообще...
А хочется все понимать...

Цитата
Лично наблюдал приличное уменьшение времени переключения контекста 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?
А во время выполнения программы? wink.gif
Стек ведь может переполниться...

Цитата
Да, всё полезное из этих файлов мы уже забрали выше.


Как я понимаю, это влияет на размер бинаря. А еще что на размер влияет? sm.gif
Встречал где-то, что многие сталкиваются с "раздуванием" бинаря при использовании Си++, но сам пока не изучал вопрос.


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 13 2013, 08:36
Сообщение #19


фанат дивана
******

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



Цитата(koluna @ Jun 13 2013, 13:40) *
Зачем вообще она нужна для ARM? Почему ее полностью не отключат изначально? Или тулчейн один и на мелкие процы, и на крупные процы, а на крупных обработка исключений в ходу, в отличие от мелких?

GCC один на все, видимо есть места, где эти исключения никак не выпилить при портировании.
Цитата(koluna @ Jun 13 2013, 13:40) *
Ууу... что, может понадобиться?

Ну мало ли. Возможность не помешаетsm.gif
Цитата(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?
А во время выполнения программы? wink.gif
Стек ведь может переполниться...

Ну, время выполнения - это уж никак не забота линкераsm.gif
Цитата(koluna @ Jun 13 2013, 13:40) *
Как я понимаю, это влияет на размер бинаря. А еще что на размер влияет? sm.gif
Встречал где-то, что многие сталкиваются с "раздуванием" бинаря при использовании Си++, но сам пока не изучал вопрос.

Не бинаря, а elf. При прошивке вся эта ботва всё равно выкидывается.
Насчёт раздувания при использовании Си++ - не замечал такого. Если не подцепились исключения, то всё очень компактно получается.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 13 2013, 08:43
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(koluna @ Jun 13 2013, 11:40) *
Зачем вообще она нужна для ARM? Почему ее полностью не отключат изначально? Или тулчейн один и на мелкие процы, и на крупные процы, а на крупных обработка исключений в ходу, в отличие от мелких?

Мне вот пригодилась кое-где. Хотите отключить вообще - наверное можно и так собрать тулчейн, просто зачем?


Цитата
Т. е., то, на что есть ссылки в коде и то, что обрамлено KEEP оставляется, все остальное - выкидывается?

Есть флаги компиляции, которые заведуют разбиением на секции - -ffunction-sections, --fdata-sections и флаг линкера --gc-sections

Цитата
А во время выполнения программы? wink.gif
Стек ведь может переполниться...

А во время выполнения программы - нужны динамические проверки. К примеру в конце стека размещаем некий паттерн, а потом периодически проверяем, что паттерн не затерт...

Цитата
Встречал где-то, что многие сталкиваются с "раздуванием" бинаря при использовании Си++, но сам пока не изучал вопрос.


Я столкнулся sm.gif
Включение исключений добавляют несколько десятков килобайт, включение rtti - дает накладные расходы на каждый тип с виртуальными функциями. Использование чего-то вроде iostream - дает еще порядка 150 килобайт sm.gif А это включение происходит в потрохах стандартной библиотеки при включении исключений. Так как исключения мне были нужны, пришлось немного подхачить libc++.

Ну а дальше - как обычно, чем больше кода, тем больше размер. При этом надо учитывать, что какой-то код генерится автоматически - вроде инстанцирования шаблонов.

Итого, если отключить rtti и исключения - оверхеда по сравнению с С нет. Если включить и использовать stl - тут уже надо сравнивать с аналогичным рукопашным кодом на С. Ну и мозг надо не выключать sm.gif
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 13 2013, 18:41
Сообщение #21


Профессионал
*****

Группа: Участник
Сообщений: 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()? В этих секциях ведь находятся данные, на которые мы ссылаемся, поэтому линкер не должен их выбрасывать при чистке мусора. Или я чего-то не допонял sad.gif

Код
KEEP(SORT(*)(.init_array))


Какой смысл в сортировке файлов при размещении статических конструкторов?

Сообщение отредактировал koluna - Jun 13 2013, 18:42


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 13 2013, 19:12
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 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. Но по секркту - это рудимент от найденного в интернете образца скрипта wink.gif Не мешает.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 13 2013, 19:48
Сообщение #23


фанат дивана
******

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



Цитата(koluna @ Jun 14 2013, 00:41) *
Вот здесь зачем выравнивание перед таблицей векторов?
Ведь по адресу 0 должен сохраняться указатель начального адреса стека, но он уже включен в таблицу из .isr_vector.

Ох, дались вам эти выравниванияsm.gif Если мы 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()? В этих секциях ведь находятся данные, на которые мы ссылаемся, поэтому линкер не должен их выбрасывать при чистке мусора. Или я чего-то не допонял sad.gif

Тут я не помню, если честно. Вроде бы это я боролся с LTO. И вроде бы, без этого линкер что-то выкидывал нужное. Но точно не помню, могу и соврать.
Цитата(koluna @ Jun 14 2013, 00:41) *
Какой смысл в сортировке файлов при размещении статических конструкторов?

Удобно, чтоб по алфавиту вызывались.

Цитата(Сергей Борщ @ Jun 14 2013, 01:12) *
Верно. Антоха что-то намудрил. и .data : AT ( _sidata ) тоже не лучший вариант. Предпочитаю
Код
.data :
{
   ......
} > RAM AT > FLASH

С KEEP() я написал выше, хотя может и правда намудрилsm.gif А чем хуже вариант с ".data : AT ( _sidata )" ? Мне он кажется как-то понятнее по записи.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Terminator
сообщение Jun 14 2013, 01:51
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 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. Но по секркту - это рудимент от найденного в интернете образца скрипта wink.gif Не мешает.

Если SORT убрать, то будут вызываться в порядке появления в cpp файле?
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 14 2013, 13:41
Сообщение #25


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(Сергей Борщ @ Jun 13 2013, 23:12) *
кто-то может использовать для задания порядка вызова конструкторов. Т.е. Объект ADC будет создан до объекта UART. Но по секркту - это рудимент от найденного в интернете образца скрипта wink.gif Не мешает.


Вот смотрю я доку на линкер и не понимаю (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.


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 14 2013, 18:25
Сообщение #26


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 13 2013, 23:48) *
Ох, дались вам эти выравниванияsm.gif Если мы 0 выровняем на 4, то останется 0, так что дырки не будет. А вот если мы будем размещать .isr_vector где-то в другом месте, то выравнивание необходимо.

...

Нет, выравнивание на 4 - это не то же самое, что отступ на 4:) Если начало ОЗУ выровнено на 4 (а обычно так и есть), то никакого отступа не будет.


Ааа... понял... выравнивание и отступ - разные вещи sm.gif
Если счетчик позиций == 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


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 14 2013, 19:19
Сообщение #27


фанат дивана
******

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



Цитата(koluna @ Jun 15 2013, 00:25) *
Ааа... понял... выравнивание и отступ - разные вещи sm.gif

Даsm.gif
Цитата(koluna @ Jun 15 2013, 00:25) *
Выравнивание начала ОЗУ на 4 тоже требование ARM EABI, как и выравнивание начала стека на 8 байт?

Нет, я такого требования не припоминаю. Скорее, это сделано для удобства инициализации данных (чтоб копировать данные по слову).
Цитата(koluna @ Jun 15 2013, 00:25) *
Так, т. е., выравнивание таблицы векторов, начала стека и начала ОЗУ - обязательные требования, получается?

Начала стека - да. Начала ОЗУ - нет (вроде). А вот с таблицей векторов на самом деле требования гораздо жестче. Нужно выравнивать на ближайшую степень двойки, большую размера таблицы векторов. Так что мы недовыравнивалиsm.gif
Цитата(koluna @ Jun 15 2013, 00:25) *
Исходя из скрипта, куча начинается сразу за неинициализированными данными и растет вверх навстречу стеку?
Чтобы стек и куча не пересеклись используются менеджеры кучи?

Да, всё так.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 14 2013, 19:50
Сообщение #28


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 15 2013, 05:43
Сообщение #29


фанат дивана
******

Группа: Свой
Сообщений: 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. Хорошая болезнь - склерозsm.gif (Но символ _sidata всё-таки вручную там завёл, не подумал про LOADADDR()).
Цитата(Сергей Борщ @ Jun 15 2013, 01:50) *
Цитата(AHTOXA @ Jun 14 2013, 01:48) *
Если SORT убрать, то будут вызываться в порядке появления в cpp файле?

Да. А для разных единиц компиляции порядок не определен.

Это не я спрашивал, а Terminator sm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 15 2013, 10:27
Сообщение #30


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 14 2013, 23:19) *
Начала стека - да. Начала ОЗУ - нет (вроде). А вот с таблицей векторов на самом деле требования гораздо жестче. Нужно выравнивать на ближайшую степень двойки, большую размера таблицы векторов. Так что мы недовыравнивалиsm.gif


Недовыравнивали - ошибка? wink.gif
Т. е., первый ". = ALIGN(4);" в секции должен выравнивать по-другому?
Хитрые там вычисления какие-то и зависят от количества векторов почему-то...

Кстати, выравненное смещение этим самым хитрым образом нужно записать в регистр VTOR, как я понимаю.
Где осуществляется запись? В стартапе и в init_HW() не нашел. Или используется значение по умолчанию?


Проекты с данным скриптом нормально собираются в Sourcery CodeBench?
Какими компиляторами собирается без проблем?

Кстати, точка входа, как я понимаю для проекта с данным скриптом будет - первый байт в секции .text?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 15 2013, 10:57
Сообщение #31


фанат дивана
******

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



Цитата(koluna @ Jun 15 2013, 16:27) *
Недовыравнивали - ошибка? wink.gif

Давайте лучше применим терминологию Сергея Борща, и скажем: "недомудрил" sm.gif
То есть, скрипт рассчитан на размещение приложения по умолчанию, но в нём были приняты некоторые меры для более лёгкой его адаптации для приложений, загружаемых по другим адресам. И меры эти - оказались недостаточными.
Цитата(koluna @ Jun 15 2013, 16:27) *
Т. е., первый ". = ALIGN(4);" в секции должен выравнивать по-другому?
Хитрые там вычисления какие-то и зависят от количества векторов почему-то...

Насколько я понял, это необходимо, чтобы адрес любого вектора из таблицы своими старшими битами совпадал с VTOR. Типа, контроллер прерываний вычисляет адрес вектора как VTOR | (номер_прерывания * 4).
Но у меня чисто теоретические познания в этой области, я не писал загрузчиков и приложений под них. Надеюсь, Сергей Борщ что-нибудь добавит.
Цитата(koluna @ Jun 15 2013, 16:27) *
Кстати, выравненное смещение этим самым хитрым образом нужно записать в регистр VTOR, как я понимаю.
Где осуществляется запись? В стартапе и в init_HW() не нашел. Или используется значение по умолчанию?

Да, по умолчанию.
Цитата(koluna @ Jun 15 2013, 16:27) *
Проекты с данным скриптом нормально собираются в Sourcery CodeBench?
Какими компиляторами собирается без проблем?

Sourcery я давно не проверял, старыми собиралось нормально. Недавно проверял с Yagarto - работало. А сам на постоянной основе использую kgp и gcc-arm-embedded, которую здесь ещё называют Linaro (что не совсем верно, имхо).
Цитата(koluna @ Jun 15 2013, 16:27) *
Кстати, точка входа, как я понимаю для проекта с данным скриптом будет - первый байт в секции .text?

Точка входа будет вот такая:
Код
    ENTRY(Reset_Handler)


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 15 2013, 19:56
Сообщение #32


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 15 2013, 14:57) *
Давайте лучше применим терминологию Сергея Борща, и скажем: "недомудрил" sm.gif
То есть, скрипт рассчитан на размещение приложения по умолчанию, но в нём были приняты некоторые меры для более лёгкой его адаптации для приложений, загружаемых по другим адресам. И меры эти - оказались недостаточными.


Давайте применим sm.gif
Все хорошо, спасибо Вам и всем окружающим!
Достаточно полезная беседа получается!

Цитата
Насколько я понял, это необходимо, чтобы адрес любого вектора из таблицы своими старшими битами совпадал с VTOR. Типа, контроллер прерываний вычисляет адрес вектора как VTOR | (номер_прерывания * 4).
Но у меня чисто теоретические познания в этой области, я не писал загрузчиков и приложений под них. Надеюсь, Сергей Борщ что-нибудь добавит.


Подождем sm.gif

Цитата
Точка входа будет вот такая:
Код
    ENTRY(Reset_Handler)


Из доки на линкер.
Цитата
3.4.1 Setting the Entry Point

There are several ways to set the entry point. The linker will set the entry point by trying
each of the following methods in order, and stopping when one of them succeeds:
• the ‘-e’ entry command-line option;
• the ENTRY(symbol ) command in a linker script;
• the value of a target specific symbol, if it is defined; For many targets this is start,
but PE and BeOS based systems for example check a list of possible entry symbols,
matching the first one found.
• the address of the first byte of the ‘.text’ section, if present;
• The address 0.


Как я понимаю, наш случай - предпоследний?
Так... а по логике вещей при включении должно генерироваться прерывание сброса, где мы как раз и попадаем в Reset_Handler().
Ну а зачем тогда команда ENTRY и вообще разговоры об этом?


Кстати, атрибуты регионов здесь зачем?
Цитата
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
}


Как я понимаю, если линкер встречает входную секцию, которая не замаплена на выходную секцию, то он создаст выходную секцию с именем входной секции и подберет регион памяти для ее расположения с участием этих атрибутов?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 15 2013, 20:26
Сообщение #33


фанат дивана
******

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



Цитата(koluna @ Jun 16 2013, 01:56) *
Как я понимаю, наш случай - предпоследний?

Нет. Потому что в начале секции .text у нас лежит начальный стек. В принципе, всё работало и без строчки
ENTRY(Reset_Handler)
в скрипте. Но отладка при этом глючила.
Зачем нужны атрибуты регионов - я не задумывался, есть и есть sm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 15 2013, 22:03
Сообщение #34


Гуру
******

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



QUOTE (AHTOXA @ Jun 15 2013, 13:57) *
Но у меня чисто теоретические познания в этой области, я не писал загрузчиков и приложений под них. Надеюсь, Сергей Борщ что-нибудь добавит.
Из описания VTOR:
QUOTE
Bits 29:11 TBLOFF[29:9]: Vector table base offset field.
It contains bits [29:9] of the offset of the table base from memory address 0x00000000. When
setting TBLOFF, you must align the offset to the number of exception entries in the vector table.
The minimum alignment is 128 words.
Собственно тут все сказано: выравнивание должно быть на 128 байт.
QUOTE (koluna @ Jun 15 2013, 22:56) *
Как я понимаю, наш случай - предпоследний?
Нет. Но в двух словах: программа будет работать в железе и без строчки ENTRY(), ибо старт с вектора по адресу 0x00000004 в процессоре прибит гвоздями. Эта строка (в приведенном AHTOXой виде) нужна отладчику, ибо он не умеет (пока) брать стартовый адрес из таблицы векторов, а пытается, по старинке, считать код команды по адресу 0. А у Cortex там лежит начальное значение указателя стека и получается конфуз.

QUOTE (koluna @ Jun 15 2013, 22:56) *
Кстати, атрибуты регионов здесь зачем?

QUOTE
К программисту подходит сынишка:
- Папа, почему солнышко каждый день встает на востоке, а садится на западе?
- Что, правда?
- Да.
- Каждый день?
- Да.
- По-другому было когда нибудь?
- Нет.
- О! Вот это работает - не трогай.
sm.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 15 2013, 22:33
Сообщение #35


фанат дивана
******

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



Цитата(Сергей Борщ @ Jun 16 2013, 04:03) *
Собственно тут все сказано: выравнивание должно быть на 128 байт.

Понятно, то есть, вариативность в описании от АРМовцев - это для производителей проца. А ST сделал жёстко 128 слов, убрав ещё пару младших битов у VTOR. С точки зрения написания линкерных скриптов это хорошо: надо просто поменять выравнивание с 4 на 512:)
Цитата(Сергей Борщ @ Jun 16 2013, 04:03) *
работает - не трогай.

Именно! beer.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 15 2013, 23:15
Сообщение #36


Гуру
******

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



QUOTE (AHTOXA @ Jun 16 2013, 01:33) *
128 слов
Да, виноват, ошибся. 128 слов, 512 байт.
Да я вам больше скажу: они там сами никак не определятся. На картинке замаскированы 9 бит, а полностью описание звучит так:
QUOTE
Bits 29:11 TBLOFF[29:9]: Vector table base offset field.
It contains bits [29:9] of the offset of the table base from memory address 0x00000000. When
setting TBLOFF, you must align the offset to the number of exception entries in the vector table.
The minimum alignment is 128 words. Table alignment requirements mean that bits[8:0] of the
table offset are always zero.
Bit 29 determines whether the vector table is in the code or SRAM memory region.
0: Code
1: SRAM
Note: Bit 29 is sometimes called the TBLBASE bit.
Bits 10:0 Reserved, must be kept cleared
Так все-таки 29:11 или 29:9? Судя по последующим "Bits 10:0" маскируются 11 бит и выравнивание должно быть на 2048 байт. "Ребус, краксворд!".


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 16 2013, 07:25
Сообщение #37


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 16 2013, 00:26) *
Нет. Потому что в начале секции .text у нас лежит начальный стек. В принципе, всё работало и без строчки
ENTRY(Reset_Handler)


Код
    .text :
    {
        __ctors_start__ = .;
        KEEP(SORT(*)(.init_array))  /* eabi uses .init_array for static constructor lists */
        __ctors_end__ = .;

        __dtors_start__ = .;
        __dtors_end__ = .;
        
        . = ALIGN(4);
        *(.text)                   /* remaining code */
        *(.text.*)
        *(.rodata)                 /* read-only data (constants) */
        *(.rodata*)

        *(.eh_frame_hdr)
        *(.eh_frame)
        *(.ARM.extab* .gnu.linkonce.armextab.*)
        *(.gcc_except_table)
        *(.eh_frame_hdr)
        *(.eh_frame)

        *(.glue_7)
        *(.glue_7t)
        . = ALIGN(4);
    } > FLASH


Так, я где здесь начальный стек? sm.gif Вижу конструкторы вначале.


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 16 2013, 10:00
Сообщение #38


фанат дивана
******

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



Цитата(koluna @ Jun 16 2013, 13:25) *
Так, я где здесь начальный стек? sm.gif Вижу конструкторы вначале.

А, ну да. Тогда тем более не "предпоследний случай".


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 16 2013, 19:48
Сообщение #39


фанат дивана
******

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



Цитата(Сергей Борщ @ Jun 16 2013, 05:15) *
Так все-таки 29:11 или 29:9? Судя по последующим "Bits 10:0" маскируются 11 бит и выравнивание должно быть на 2048 байт. "Ребус, краксворд!".

В PM0214 (Programming manual для F4) всё однозначно:
Цитата
Bits 29:9 TBLOFF: Vector table base offset field.
Bits 8:0 Reserved, must be kept cleared

Видимо была опечатка в предыдущих PM.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 17 2013, 14:51
Сообщение #40


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



О счетчике позиций.

Может быть вот это:
Код
__exidx_start = .;
.ARM.exidx :
{
    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;


было бы правильнее сделать так:
Код
.ARM.exidx :
{
    __exidx_start = .;
    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    __exidx_end = .;
} > FLASH


Есть определенные сомнения после прочтения документации.

Цитата
The GNU Linker
3.10.5 The Location Counter
...
Setting symbols to the value of the location counter outside of an output section statement
can result in unexpected values if the linker needs to place orphan sections.
...


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 18 2013, 07:54
Сообщение #41


Гуру
******

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



QUOTE (koluna @ Jun 17 2013, 17:51) *
было бы правильнее сделать так:
Похоже, что так.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 18 2013, 08:46
Сообщение #42


фанат дивана
******

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



Вот ведь дилемма... С одной стороны, "возможны проблемы", а с другой - "работает - не трогай!" sm.gif

Да, надо поправить.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 18 2013, 11:02
Сообщение #43


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Не совсем разобрался с адресацией: абсолютная и относительная.
Как я понял, вне описания секций адресация абсолютная, внутри описания секций - относительная.
Вот в чем проблема. Если внутри секций мы присваиваем значение счетчика позиций (или просто число) какому-нибудь символу, то присваевается относительный адрес (адрес относительно начала секции).

Код
__ctors_start__ = .;
__ctors_end__ = .;
_sdata = .;
_edata = .;
_sbss = .;
_ebss = .;


Потом в программе (в первую очередь в стартапе) мы используем эти символы.
Но адреса-то они содержат относительные! Программе, как я понимаю, нужны абсолютные адреса?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 18 2013, 13:00
Сообщение #44


фанат дивана
******

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



Цитата(koluna @ Jun 18 2013, 17:02) *
Вот в чем проблема. Если внутри секций мы присваиваем значение счетчика позиций (или просто число) какому-нибудь символу, то присваевается относительный адрес (адрес относительно начала секции).

Нет. Это адрес в выходной секции (в нашем случае это FLASH или RAM):
Цитата


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 18 2013, 13:25
Сообщение #45


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 18 2013, 17:00) *
Нет. Это адрес в выходной секции (в нашем случае это FLASH или RAM):


Знаю. Но тогда это что значит?

Цитата
Note: . actually refers to the byte offset from the start of the current containing object. Normally this is the SECTIONS statement, whose start address is 0, hence . can be used as an absolute address. If . is used inside a section description however, it refers to the byte offset from the start of that section, not an absolute address


Сообщение отредактировал koluna - Jun 18 2013, 15:27


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 18 2013, 15:52
Сообщение #46


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Пока так и не понял, "--gc-sections" работает без "-ffunction-sections и -fdata-sections"?
Ну поместит компилятор при использовании ключей "-ffunction-sections и -fdata-sections" каждую функцию в ".text.имя_функции", и каждую переменную (глобальную или статическую) в ".data.имя_переменной" (".bss.имя_переменной") и что дальше?
Или линкер не может отбросить при оптимизации функции и просто переменные, которые не используются в программе, т. е., он может отбросить только секции, в которые компилятор и помещает функции/переменные при использовании ключей "-ffunction-sections и -fdata-sections"?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 18 2013, 16:58
Сообщение #47


фанат дивана
******

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



Цитата(koluna @ Jun 18 2013, 19:25) *
Знаю. Но тогда это что значит?

А фиг его знает. Либо меня подводит мой англицкий, либо там написана неправда. sm.gif
Но по факту точка - это адрес в области, куда помещается секция. Может быть, дело в ">"? Там примеры без ">".
Цитата(koluna @ Jun 18 2013, 21:52) *
Или линкер не может отбросить при оптимизации функции и просто переменные, которые не используются в программе, т. е., он может отбросить только секции, в которые компилятор и помещает функции/переменные при использовании ключей "-ffunction-sections и -fdata-sections"?

Да, линкер умеет отбрасывать только секции.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 18 2013, 17:43
Сообщение #48


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 18 2013, 20:58) *
А фиг его знает. Либо меня подводит мой англицкий, либо там написана неправда. sm.gif
Но по факту точка - это адрес в области, куда помещается секция. Может быть, дело в ">"? Там примеры без ">".


Вот и я сомневаюсь... предлагаю подождать Сергея sm.gif

Цитата
Да, линкер умеет отбрасывать только секции.


В итоге.
Секции, перечисленные в команде KEEP() не отбрасываются линкером при чистке мусора (актуально при компиляции с опциями “-ffunction-sections”, “-fdata-sections” и одновременной линковке с опцией “--gc-sections”). При компиляции с опциями “-ffunction-sections” и “-fdata-sections” компилятор помещает каждую функцию и переменную в отдельную секцию вида “.text.имя”, “.data.имя”, “.bss.имя”. Далее, при линковке с опцией “--gc-sections”, линкером отбрасываются все эти входные секции, на которые нет ссылок в программе (нет ссылок на функции и переменные, содержащиеся в них), кроме помеченых KEEP().
Правильно? sm.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 18 2013, 17:54
Сообщение #49


фанат дивана
******

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



Да, всё так.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 18 2013, 18:34
Сообщение #50


Гуру
******

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



QUOTE (koluna @ Jun 18 2013, 20:43) *
Вот и я сомневаюсь... предлагаю подождать Сергея sm.gif
Я пас.

QUOTE (koluna @ Jun 18 2013, 20:43) *
Правильно? sm.gif
Да.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 18 2013, 18:37
Сообщение #51


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Мучает меня вопрос по секциям все-таки...

.init_array - конструкторы EABI.
.ctors - конструкторы не EABI.
Для совместимости лучше использовать в скрипте и то и другое?

.dtors
Деструкторы. EABI? Нет? Все? sm.gif

Это зачем?
.comment
.line


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 18 2013, 19:44
Сообщение #52


фанат дивана
******

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



Цитата(koluna @ Jun 19 2013, 00:37) *
.init_array - конструкторы EABI.
.ctors - конструкторы не EABI.
Для совместимости лучше использовать в скрипте и то и другое?

Можно использовать. Насчёт "лучше" - не уверен. Зачем поддерживать такие старые компиляторы?

Цитата(koluna @ Jun 19 2013, 00:37) *
.dtors
Деструкторы. EABI? Нет? Все? sm.gif

Деструкторы нам не нужны. Поэтому мы их игнорируем, где бы они не были размещены.

Цитата(koluna @ Jun 19 2013, 00:37) *
Это зачем?
.comment
.line

Не знаю, и знать не хочу! sm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 19 2013, 07:41
Сообщение #53


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 18 2013, 23:44) *
Можно использовать. Насчёт "лучше" - не уверен. Зачем поддерживать такие старые компиляторы?


Насколько старые?
Просто встречаю в других скриптах... видимо, авторы не особо задумывались над этим...

Цитата
Деструкторы нам не нужны. Поэтому мы их игнорируем, где бы они не были размещены.


И деструкторы тоже встречаю в других скриптах...
Ну, да... по сути и не нужны деструкторы для глобальных и статических объектов.
Но вдруг у кого-то фантазия проснется и он решит вызвать деструктор? sm.gif

Цитата
Не знаю, и знать не хочу! sm.gif


А вот я хочу, это бодрит sm.gif

Со счетчиком позиций вопрос пока открыт sad.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 19 2013, 08:04
Сообщение #54


фанат дивана
******

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



Цитата(koluna @ Jun 19 2013, 13:41) *
Насколько старые?

Емнимс, уже года три-четыре как перешли на eabi.
Цитата(koluna @ Jun 19 2013, 13:41) *
Но вдруг у кого-то фантазия проснется и он решит вызвать деструктор? sm.gif

Вызвать вручную -- без проблем. Та секция отвечает за автоматический вызов деструкторов при завершении программы.
Цитата(koluna @ Jun 19 2013, 13:41) *
А вот я хочу, это бодрит sm.gif

Мне кажется, что вы уже достаточно прокачали свой уровень по скрипту и стартапу, и уже можно смело двигаться дальшеsm.gif
Цитата(koluna @ Jun 19 2013, 13:41) *
Со счетчиком позиций вопрос пока открыт sad.gif

По факту всё работает как надо. Скорее всего либо мы что-то не так поняли в описании, либо там (в описании) ошибка.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 19 2013, 09:44
Сообщение #55


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(AHTOXA @ Jun 19 2013, 12:04) *
Емнимс, уже года три-четыре как перешли на eabi.


Теперь все поддерживаемые (развиваемые) в данный момент компиляторы компиляторы стали EABI?

Цитата
Вызвать вручную -- без проблем. Та секция отвечает за автоматический вызов деструкторов при завершении программы.


А, ну да...
Если хотим автоматом, то используем в скрипте входные секции ".dtors*" (мапим входные куда-нибудь в ".text", наверняка даже с KEEP()). Создаем символы, указывающие на начало и конец области размещения деструкторов в этих секциях, а потом в стартапе после вызова main() в цикле вызываем все деструкторы по указателю, используя выше определенные символы...

Кстати, в ".ctors" (для EABI ".init_array") помещаются только конструкторы по умолчанию, а остальные конструкторы попадают в ".text*"?
А деструкторы-то куда компилятор пихает? По аналогии с конструкторами в ".dtors*"?

Цитата
По факту всё работает как надо. Скорее всего либо мы что-то не так поняли в описании, либо там (в описании) ошибка.


Вот-вот... не понятно...

Кстати, зачем такой префикс жуткий "arm-none-eabi-"? И что вообще означает "none-eabi"? Похоже на "не EABI", но ведь компилятор мой однозначно EABI!
Читал, что такой префикс придумали, чтобы отличать от других компиляторов. Но неужели нельзя было придумать что-нибудь покороче и попроще, без двусмысленности? sm.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 19 2013, 10:02
Сообщение #56


Гуру
******

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



QUOTE (koluna @ Jun 19 2013, 12:44) *
Кстати, в ".ctors" (для EABI ".init_array") помещаются только конструкторы по умолчанию, а остальные конструкторы попадают в ".text*"?
Поскольку конструкторы являются кодом - они помещаются в .text В .init_array и .ctors в нужном порядке помещаются указатели на них. Собственно вот код их вызова, по нему все понятно:
CODE
extern void(* const __ctors_start__[])();
extern void(* const __ctors_end__[])();
...
    /* Call constructors */
    void(* const *ctor)();
    for( ctor = __ctors_start__; ctor < __ctors_end__; )
        (*ctor++)();

QUOTE (koluna @ Jun 19 2013, 12:44) *
Кстати, зачем такой префикс жуткий "arm-none-eabi-"? И что вообще означает "none-eabi"?
Это два префикса. -none и -eabi. Гляньте сюда.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 19 2013, 12:31
Сообщение #57


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Понятно, спасибо.

А с деструкторами все-таки что? Аналогично?
Для EABI и не EABI одинаково?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 19 2013, 13:11
Сообщение #58


Гуру
******

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



QUOTE (koluna @ Jun 19 2013, 15:31) *
А с деструкторами все-таки что? Аналогично?
Мы их не используем, потому и не разбирались. Вы можете сами провести такое исследование и огласить результат.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 19 2013, 14:10
Сообщение #59


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Судя по всему для EABI, по аналогии с конструкторами (".init_array"), для деструкторов используется ".fini_array".
Вот на эту тему: http://electronix.ru/forum/index.php?showt...=79902&st=0.


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 19 2013, 18:30
Сообщение #60


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Что такое common-символы (секция COMMON)?
Из доки на линкер толком не понял.
Это к вопросу зачем нужно делать *(COMMON).

Цитата
В некоторых форматах объектных файлов общие символы (common) не привязаны к конкретной секции, поэтому линкер, считает, что они находятся в секции COMMON. Следовательно, чтобы использовать эти символы необходимо применить выражение вида *(COMMON).


Но что такое "общие символы (common)" - не раскрывается sad.gif

Сообщение отредактировал koluna - Jun 20 2013, 08:29


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 20 2013, 16:26
Сообщение #61


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



И все-таки хотелось бы немного поговорить и о скрипте из моего первого поста (скрипт и стартап в архиве).
Без этого тема не будет для меня закрыта. Уж извините меня sm.gif

Код
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)


Это, как я понял, для того, чтобы в командной строке библиотеки не подключать.
Что за библиотека "libnosys.a", которой нет? Насколько она нужна?

CODE
.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


Выравнивания для таблицы векторов здесь нет. Как я понимаю, выравнивание в стартапе. Но на 2, а не на 512 байт.
Хотя скрипт ведь не заточен конкретно под STM...
Рудименты "*(.ctors) и *(.dtors)" от не EABI-компиляторов достались, судя по всему?
Для чего "crtbegin", "crtend"? В скрипте от scmRTOS этого нет.

Так и не понял, нужны ли входные секции ".eh_frame" и ".eh_framehdr" или нет...
Что-то для этих исключений сделано много непонятных секций... что вызывает уйму вопросов... а исключения в основном не используются...

CODE
.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 = .);

. = ALIGN(4);
/* All data end */
__data_end__ = .;

} > RAM


Вот тут секция "vtable" используется, нужна ли она все-таки или нет? Помню, находил сообщение, где Сергей Борщ писал о том, что у него без этой секции все работает (таблица виртуальных функций помещается в ".rodata").
Входные секции ".preinit_array", ".init_array.*", ".fini_array.*", содержащие указатели на конструкторы, деструкторы (и что еще для ".preinit_array"?) размещаются в RAM. Наверное, это добавляет быстродействия, но заметно убавляет RAM, если объектов много... так что, лучше бы их было разместить во FLASH?

Выходные секции ".heap" и ".stack_dummy" создаются для того, чтобы на этапе линковки уже быть уверенным в том, что хватит места для стека и кучи (просто предполагаем, что для стека и кучи нам потребуется столько-то байт)?

Такое ощущение, что скрипт нужно допиливать sm.gif

Сообщение отредактировал IgorKossak - Jun 21 2013, 12:07
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 21 2013, 20:50
Сообщение #62


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Посмотрел у себя файлы crt* в папках компилятора:

Код
find /home/koluna/soft/arm/arm-2013.05/ -name crt*
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/crtn.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/crti.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb2/crtn.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb2/crti.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb2/crtbegin.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb2/crtend.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/armv6-m/crtn.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/armv6-m/crti.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/armv6-m/crtbegin.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/armv6-m/crtend.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb/crtn.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb/crti.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb/crtbegin.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/thumb/crtend.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/crtbegin.o
/home/koluna/soft/arm/arm-2013.05/lib/gcc/arm-none-eabi/4.7.3/crtend.o


Вот, нагуглилось:
http://gcc.gnu.org/onlinedocs/gccint/Initialization.html
http://l4u-00.jinr.ru/usoft/WWW/www_debian.../elf/node4.html

Правильно ли я понимаю, что файлы эти отвечают только за вызов конструкторов и деструкторов (формирование функций _init(), _fini())?

В конечном итоге получается что-то типа этого (обработчик сброса в стандартном стартапе):
Код
void Reset_Handler( void )
{
      _init();

      ИнициализацияЖелеза();

      main();

      _fini();
}


Сообщение отредактировал koluna - Jun 21 2013, 22:11


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post

5 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 3rd July 2025 - 05:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.02375 секунд с 7
ELECTRONIX ©2004-2016