Технический форум по робототехнике.
Michael_K » 17 ноя 2011, 12:46
В общем задача такая:
Делаю бутлоадер. Бутлоадер расположен в отдельной секции памяти и себя не перезаписывает.
Внешний API - всего одна функция - "Обновить прошивку"
Она вызывает другие функции в своей секции, обращается к таблицам из своей же секции и т.п.
Внимание вопрос:
Как _правильно_ заставить компилятор (GCC) расположить эту функцию в самом начале секции?
(чтобы пользовательский код обращался к ней по абсолютному адресу).
Заводить лишние секции памяти _имхо_ неправильно (потому что заранее неизвестны размеры кода и т.п.)
P.S.
АДМИНЫ, АУ!!!
Заведите, пожалуйста, раздел "программирование - общие вопросы", не в первый раз прошу!
Сергей » 17 ноя 2011, 13:00
В RealView было все просто __attribute__((at(address))). А вот в GCC нужно создать секцию или прописать в init.
Michael_K » 17 ноя 2011, 13:08
Секция создана (читаем внимательно!).
Вопрос о том, как их _правильно_ упорядочить внутри секции.
Глупо же под одну функцию заводить отдельную секцию неизвестного размера (или нет?)
Flexz » 17 ноя 2011, 14:20
Может я чего-то недопонимаю, но для AVR-ки вопрос размещения бутлоадера всегда решался примерно так
-Wl,-section-start=.text=0x1E000
С этого адреса размещается начало загрузчика со всеми вытекающими.
У вас-то процессор какой?
Vooon » 17 ноя 2011, 14:47
Заведи подсекцию. Ни кого же не смущает заводить подсекции для каждой функции (чтобы потом лишнее gc вытер).
Сергей » 17 ноя 2011, 14:54
Вот пример
- Код: Выделить всё • Развернуть
*(.after_vectors*)
*(.test_section) <<<
*(.text*)
*(.rodata .rodata.*)
. = ALIGN(4);
- Код: Выделить всё • Развернуть
void safe_process_data( void ) __attribute__((section(".test_section")));
void safe_process_data( void )
{
}
Michael_K » 17 ноя 2011, 18:29
Сергей, на какой вопрос вы ответили своим примером?
Сергей » 17 ноя 2011, 18:45
Я на твой отвечал. В данном примере - адрес почти явно задан, он после таблицы векторов. Это наверное подойдет для одной функции. Если надо больше, то проще делать таблицу адресов функций и прочее.
Michael_K » 17 ноя 2011, 19:02
Завести секцию и сказать, что функция лежит в ней - не проблема.
И вопрос вовсе не в этом, если вы внимательно почитаете первое сообщение.
Точка входа - одна. Одна функция. И она должна начаться сразу же в начале секции.
Но она использует и другие функции (которые, естественно, тоже должны располагаться в секции бутлоадера,
чтобы не терять линковку. ...ну и чтобы их не затереть, например).
Кроме того она использует таблицы данных (аналогично).
Я конечно нагородил какой-то воркараунд, но мне он страшно не нравится.
Попытки облагородить линкер-скрипт закончились тем, что компилятор ругается про "section type conflict".
Как выяснилось, это баг компилятора, который иногда по непонятным причинам отказывается
складывать константы и функции в одну секцию.
По ходу разбирательств возник еще один капитальный вопрос: А что делать с библиотечными вызовами?
(Ну вдруг компилятору с какого-нибудь перепуга захочется вызвать из секции бутлоадера
какую-нибудь дурацкую "функцию умножения"...) Как ему сказать, что в секциях "text" и "bootloader"
библиотечные вызовы должны быть раздельными?
Сергей » 17 ноя 2011, 19:09
Есть секция bootloader. Есть функция API, которая должна лежать в начале секции bootloader. Для этого необходимо в начале секции bootloader сделать подсекцию, в которую положить необходимую API функцию с помощью __attribute__((section("")))
Flexz » 17 ноя 2011, 19:49
имхо вы не в ту сторону копаете, а то и вовсе изобретаете велосипед.
Бутлоадер можно и нужно сделать самостоятельной программой, со своим стартапом, библиотеками и т.д. Разместить его по адресу начальной загрузки (если у вас не авр). Основная программа, естественно тоже является самодостаточной и начинается с более высоких адресов. Бут отработав передает управление на начало (стартап) основной программы. А при необходимости вызова бута делаем просто резет, джамп на бут делать опасно, т.к. могут остаться включенные обработчики прерываний основного кода, и при вызове прерывания по адресу, который в данный момент пишется ничего хорошего не произойдет.
Таким подходом вы все свои проблемы решите.
Michael_K » 17 ноя 2011, 20:57
Таким подходом я огребу других проблем еще больше.
В любом случае, ваше сообщение считаю оффтопиком. Оно никак не отвечает на поставленные вопросы.
Вопрос конкретно стоит про GCC. Не про процессор, не про бутлоудер, не про прерывания. Можете заменить в стартовом топике слово "бутлоадер" на "експлоудер" - суть вопроса не поменяется.
blindman » 18 ноя 2011, 05:27
Michael_K писал(а):Можете заменить в стартовом топике слово "бутлоадер" на "експлоудер" - суть вопроса не поменяется.
Как ни назови, важно для чего предназначен код . Если его задача - обновить программу, то это не может быть функция в привычном понимании. Во-первых, возвращаться из нее после обновления некуда. Есть и во-вторых, и в третьих. Поэтому не стоит городить огород. Сделать бутлоадер как обычно, а переходить в него когда надо просто джампом по известному адресу.
Michael_K » 18 ноя 2011, 12:56
Ребята, во-первых, я проблему решил. Правда пришлось заводить отдельную секцию под константы.
Во-вторых, то что вы тут пишете никак не снимает проблемы.
Потому что неважно, что запускается сначала, а что потом - так или иначе нужно располагать код (и данные) в разных секциях. Кроме того, в моей идеологии бутлоадер придется делить на две части - первая, которая загружает прошивку (там всякий красивый юзер интерфейс, файловая система, коммуникации и прочая борода) и вторая, которая собственно стирает кусок флэша и записывает туда новый софт. Первую логично делать перезаписываемой. А вторую как раз можно зашить раз и навсегда. То есть получится аж три секции "верхний бутлоадер", "аппликэйшн" и "низкоуровневый прошивальщик" - и у всех нужно завиксировать хотя бы одну точку входа, чтобы они смогли быть независимыми.
Так или иначе код придется разделять на непересекающиеся по ресурсам секции.
Так что проблему описанную в стартовом топике ваши "так называемые предложения" не решают никак.
И не надо тут оффтопить.
Добавлено спустя 2 минуты 56 секунд:blindman писал(а):Сделать бутлоадер как обычно, а переходить в него когда надо просто джампом по известному адресу.
Именно в этом и был вопрос. Я просто не ожидал от компилятора такого поведения, когда он по непонятным для меня причинам начинает выдавать "section type conflict", хотя с моей точки зрения никакого конфликта не видно.
blindman » 18 ноя 2011, 13:04
Михаил, надо описывать задачу полностью. Кто там знает про гуй и всякое другое. А функция, которая вызывается из программы и которая эту самую программу затирает - нонсенс