Перейти к содержанию
    

Стартап и скрипт линкера из CMSIS для Sourcery CodeBench

Всем привет!

 

Помогите разобраться, пожалуйста.

Стартап и скрипт взял из CMSIS 3.01 (\Device\ARM\ARMCM3\Source\GCC): gcc_arm.ld, startup_ARMCM3.S (приложил к теме).

Подцепляю к простейшему тестовому проекту.

При сборке линкер ругался сначала на отсутствие libnosys.a (ее действительно нет в дистрибе компилятора) - убрал ее из списка в скрипте. Ошибка пропала.

Но так и не нашел, что это за либа, для чего нужна и почему ее нет...

Потом линкер ругался на отсутствие "_start". Странно, откуда эта метка в стартапе и почему так называется? Поставил вместо нее "main" - все собралось. Ошибок нет.

Но осадок сомнения остался - уже две ошибки в этих двух файлах... кто знает, что там еще? Надеялся, что все заработает "из коробки".

Пока не зашивал, не уверен в работоспособности, будем пробовать.

Насколько можно верить этим файлам? Что еще в них придется корректировать (ну, кроме размеров RAM, ROM, размеров стека и кучи)?

GCC.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Кстати, неясно зачем там асм. Для кортексов стартап прекрасно пишется на С...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Да я бы и сам написал, если бы знал как :)

Хочется разобраться, но времени пока нет.

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто-нибудь выскажет свое мнение?

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

 

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

И нет почему-то скриптов линкера...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И нет почему-то скриптов линкера...

Скрипты должны быть - иначе как собрать откомпилированный код?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скрипты должны быть - иначе как собрать откомпилированный код?

 

Ясное дело, что где-то они есть - без них никак!

Я говорю о другом. В комплекте с SPL их нет. Стартапы есть, а скриптов нет.

Поэтому взял все из CMSIS. Но при сборке возникли ошибки.

Поправил. Заработало. Пока не зашивал. Не уверен в работоспособности полученного кода из-за скрипта и стартапа. Не знаю какие там могут быть ошибки еще - вот и спрашиваю у опытных людей.

Кто-нибудь использовал эти самые файлы из комплекта CMSIS с минимальными изменениями (и какими)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

AHTOXA, спасибо большое!

Но мне хотелось бы все-таки получить ответы на свои вопросы касательно файлов из CMSIS :)

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Строки 12-23.

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

 

Строки 207-454.

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

 

Строки 465-487.

Тут, вроде, более менее понятно.

Инициализируем инициализируемые переменные своими значениями, инициализируем нулями неинициализируемые переменные, инициализируем железо (что конкретно только не понятно пока), инициализируем внешнюю память, если она есть, вызываем конструкторы.

init_HW() - это что-то типа SystemInit() из system_stm32f10x.c в SPL?

Вызов init_HW() до вызова конструкторов т. к., конструкторы могут работать с железом?

Видимо в scmRTOS есть реализованная функция init_HW()? :)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Строки 12-23.

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

Это переменные из линкерного скрипта. Границы секций.

Строки 207-454.

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

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

 

Строки 465-487.

Тут, вроде, более менее понятно.

Инициализируем инициализируемые переменные своими значениями, инициализируем нулями неинициализируемые переменные, инициализируем железо (что конкретно только не понятно пока), инициализируем внешнюю память, если она есть, вызываем конструкторы.

init_HW() - это что-то типа SystemInit() из system_stm32f10x.c в SPL?

Вызов init_HW() до вызова конструкторов т. к., конструкторы могут работать с железом?

Видимо в scmRTOS есть реализованная функция init_HW()? :)

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

(Если что, то функцию init_HW() можно посмотреть здесь).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это переменные из линкерного скрипта. Границы секций.

 

Я потом посмотрел скрипт, увидел их там и понял... к тому же они используются для инициализации переменных и вызова конструкторов.

Просто названия у них не особо очевидные...

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

 

Не совсем понятно что это. Вроде, одно и тоже... но зачем тогда два идентификатора?

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 надо. Перечитаю про прерывания :)

 

Спасибо большое за консультации.

В общем, параллельно надо в скрипт линкера вникать :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

Не совсем понятно что это. Вроде, одно и тоже... но зачем тогда два идентификатора?

extern unsigned long _etext;
extern unsigned long _sidata;

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

 

Тут правильно?

Да, всё так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Ну мало ли. Например, end/_end/__end часто используются менеджерами кучи.

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну мало ли. Например, end/_end/__end часто используются менеджерами кучи.

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

 

Понятно, спасибо :)

Разбираюсь с линкером потихонечку.

Будут и по нему вопросы :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...