Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Адрес функции
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Vadim.Dyachuk
Доброго времени суток!

Как можно узнать адрес определенной процедуры или функции которая находится в Boot Section?
Сергей Борщ
QUOTE (Vadim.Dyachuk @ Oct 24 2013, 11:46) *
Как можно узнать адрес определенной процедуры или функции которая находится в Boot Section?
Вы так формулируете вопрос, что даже и непонятно, что на него отвечать. Что в этой теме, что в ваших предыдущих.
Этот адрес нужен вам лично, вы его хотите увидеть глазами или его нужно использовать в вашей программе?
Если первое - смотрите .map -файл той программы, которая загружена в область загрузчика.
Если второе - то функция является частью этой же программы или же какой-то другой?

Если хотите получить подробный и/или полезный ответ - формулируйте вопрос максимально подробно, как будто для своей жены или бабушки. А еще лучше, если вы будете писать не только "как сделать что-либо" но и "чтобы с помощью этого сделать то-то и то-то"
Vadim.Dyachuk
Извините за неполное формулирование предложения.

Я хочу в основной программе (которая находится а AppSection) вызвать процедуру которая находится в BootLoader'е. Но для этого мне нужно знать адрес этой процедуры. Поскольку я пишу программу в IAR EW то его компилятор не дает нормального .map-файла, и по этому я решил спросить у Вас, как можно определить этот адрес программно или хотя бы вручную (увидеть своими глазами).
Сергей Борщ
QUOTE (Vadim.Dyachuk @ Oct 24 2013, 13:00) *
Извините за неполное формулирование предложения.

Я хочу в основной программе (которая находится а AppSection) вызвать процедуру которая находится в BootLoader'е. Но для этого мне нужно знать адрес этой процедуры.
Теперь понятно. Но если делать так, как вы хотите - это будет работать до того момента, как вы захотите что-то поменять (исправить) в BootLoader`е и адрес этой функции "уплывет".

QUOTE (Vadim.Dyachuk @ Oct 24 2013, 13:00) *
Поскольку я пишу программу в IAR EW то его компилятор не дает нормального .map-файла,
Неправда, ой неправда... Либо вы не включили его генерацию, либо не разобрались в его содержимом. Вот отрывок из моего очень-очень старого проекта:
CODE
################################################################################
#                                                                              #
#      IAR Universal Linker V4.53O/WIN                                         #
#                                                                              #
#           Link time     =  18/May/2005  13:09:41                             #
.........
CODE
  Relative segment, address: CODE 00000506 - 00000527 (22 bytes), align: 1
  Segment part 28.
           ENTRY                   ADDRESS         REF BY
           =====                   =======         ======
           main                    00000506        ?cstartup_call_main (?C_STARTUP)


QUOTE (Vadim.Dyachuk @ Oct 24 2013, 13:00) *
и поэтому я решил спросить у Вас, как можно определить этот адрес программно или хотя бы вручную (увидеть своими глазами).
Вот теперь вопрос понятнен. Посмотрите ответ на аналогичный вопрос тут и тут. Там описана идея. Вам останется просто переложить ее на ваш компилятор. Увы, с IARом давно не работаю, поэтому дать готовое решение для вашего случая не могу.
zombi
Пишу только на ассемблере.
И если мне нужно "прыгать" между разными программами компилируемыми отдельно,
то адреса входов всех необходимых функций размещаю по фиксированным заранее определённым адресам в начале.
Что бы ничего не "уплывало".
Может и на СИ тоже так же можно.
kolobok0
Цитата(zombi @ Oct 24 2013, 14:56) *
...адреса входов всех необходимых функций размещаю по фиксированным заранее определённым адресам...


+1
правильный ответ...

я больше скажу, можно не только звать из бута, можно звать "не зная адреса" и те функции, которые находятся внутри переписываемого блока. Для этого достаточно сделать следующее:
1) закрепить за каждой такой функцией дальний джамп из таблицы переходов.
2) разместить таблицу переходов по фиксированным адресам
3) всегда использовать табличный переход как "дальний колл" по статичному адресу таблицы.
(в принципе ничего нового, см. устройство форточной дэлеле).

Более того. Если не перезаписывать флэш, а писать рядом (определить две области - одну пишем, во второй работаем). И определить две таких таблицы, а контрольные вещи целостности этих участков флэша упаковать сразу за таблицей векторов (как правило таблица векторов меньше чем сегмент записи), то перепрошивать можно на лету с достаточно высокой отказоустойчивостью (т.е. слетит только, если слетит первый сектор флэша).

схема рабочая, в одном проекте под авр-ки так и юзаю...

ARV
появилась одна идея по поводу этого вопроса... в МК с секцией бутлоадера есть одна область, которая гарантированно никуда не переместится - область таблицы векторов. если в своей программе выделить часть векторов под свои интерфейсные функции, то при помощи этой таблицы можно отлично выкрутиться! допустим, вектор переполнения таймера_1 в бутлоадере не используется, и мы используем этот вектор для функции чтения команды из USART, например. саму функцию организуем в виде традиционного для GCC макроса ISR, только в конце вместо return используем ассемблерную вставку с ret вместо reti.
по-моему, должно получиться...
_Pasha
Можно откусить 2-3 байта ОЗУ под адрес размещения таблицы. Надо подправить инит стека в стартапе приложения и поскольку бут стартует первым, он должен в последние ячейки записать адрес таблицы.

Можно написать бут таким образом, чтобы проверить, со сброса ли мы попали на адрес старта бута, если нет, то вернуть адрес таблицы.
Тогда вызов может быть таким
Код
void *(*boot_func)(void);
//blah blah
boot_func = (void*) BOOT_ADDRESS;//это здеся фиксир адрес старта загрузчика
function_tbl = boot_func();// get address of table


Передача параметров, очевидно, должна быть в виде указателя на структуру.
Дальше, можно вынести в хедер то, что используется из бута и сделать две реализации этого набора - через собственно вызов в буте и через формирование описанного выше вызова.
Соглашения о регистрах лучше использовать свои, т.е. при передаче параметров их адрес структуры должен быть в самостоятельно определенной паре регистров.
Tarbal
Цитата(ARV @ Oct 25 2013, 14:06) *
появилась одна идея по поводу этого вопроса... в МК с секцией бутлоадера есть одна область, которая гарантированно никуда не переместится - область таблицы векторов. если в своей программе выделить часть векторов под свои интерфейсные функции, то при помощи этой таблицы можно отлично выкрутиться! допустим, вектор переполнения таймера_1 в бутлоадере не используется, и мы используем этот вектор для функции чтения команды из USART, например. саму функцию организуем в виде традиционного для GCC макроса ISR, только в конце вместо return используем ассемблерную вставку с ret вместо reti.
по-моему, должно получиться...


жалко нет софтверных прерываний sm.gif
Сергей Борщ
QUOTE (Tarbal @ Oct 25 2013, 16:15) *
жалко нет софтверных прерываний sm.gif
Ну да. Если бы они были, это делалось бы через команды SWI(123) или INT 21h sm.gif
_Pasha
Цитата(Tarbal @ Oct 25 2013, 16:15) *
жалко нет софтверных прерываний sm.gif

Собственно, есть еще удобный вариант, тсз в развитие @ARV.
Поскольку на неиспользуемые прерывания ставится WEAK-заглушка, можно переписать её для обработки нашего SWI (в тексте бута, ессно) - и вызывать любым понравившимся способом, вплоть до генерации хардверного прерывания.
Правда, ограничения на IVSEL и LOCK с запрещением чтения, выполнения итд не позволят.
--
По сему, универсальных решений нет.
ARV
а софтверное прерывание для обращения к "вектору" и не требуется. номер вектора нам известен, адрес начала таблицы нам известен. длина элемента таблицы нам известна. путем простых вычислений мы легко определяем адрес этого вектора и делаем обычный вызов функции по указателю... джамп на саму функцию уже проставлен в таблице компилятором - что еще надо?
допустим, прерывание по срабатыванию аналогового компаратора в загрузчике - оно хотя бы теоретически кому-нибудь может понадобиться? почему бы его не сделать "стандартной" точкой входа по типу int21 ? wink.gif
Tarbal
Цитата(ARV @ Oct 26 2013, 12:41) *
а софтверное прерывание для обращения к "вектору" и не требуется. номер вектора нам известен, адрес начала таблицы нам известен. длина элемента таблицы нам известна. путем простых вычислений мы легко определяем адрес этого вектора и делаем обычный вызов функции по указателю... джамп на саму функцию уже проставлен в таблице компилятором - что еще надо?
допустим, прерывание по срабатыванию аналогового компаратора в загрузчике - оно хотя бы теоретически кому-нибудь может понадобиться? почему бы его не сделать "стандартной" точкой входа по типу int21 ? wink.gif

Да мы и в первый раз поняли. Просто подход/отход был бы стандартным и более простым.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.