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

EWARM. Cделать переход по известному адресу?

Что-то совсем заработался... :(

Ваяю начальный загрузчик. Основная программа лежит по адресу 0x10000000 в параллельном flash. По окончании всех действий надо просто передать на неё управление. Как?

 

EWARM 4.40. Процессор AT91RM9200.

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


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

EWARM 4.40. Процессор AT91RM9200.
// если C++
extern "C" void Application();
// если C
extern void Application();
int main()
{
......

   Application();
}

В .xcl добавить -DApplication=0x10000000 или в Project->Options->Linker->#define вписать Application=0x10000000.

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


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

Есть еще способ (без линкера):

 

((void(*)(void))0x10000000)();

 

Дык при желании можно не только без линкера обойтись - в принципе можно даже без компилятора....

 

Правильнее делать то и так, как Сергей Борщ написал.

Изменено пользователем Николай Z

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


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

Дык при желании можно не только без линкера обойтись - в принципе можно даже без компилятора....

 

Правильнее делать то и так, как Сергей Борщ написал.

 

А если этот адрес не константа?

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


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

А если этот адрес не константа?

 

В топе был вопрос про известный, фиксированный адрес...

В вашем варианте - адрес не константа - надо сперва определить задачу.

Вам мало просто прыгнуть на заданный адрес - надо же чтобы там лежали точки входа в программы иначе это не имеет смысла.

 

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

 

Первое, что надо определить - а зачем вообще нужно вызывать функцию по некоему переменному адресу? У вас функции ползают по памяти что ли?

 

У меня обычно нет и мне трудно сообразить - зачем мне вообще нужно делать вызовы по неким переменным адресам в общем случае.

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


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

В топе был вопрос про известный, фиксированный адрес...

 

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

 

Так чем он плох? Ничем. Так что пусть человек знает, что решений задачи несколько, есть и более универсальные.

 

PS Ах да, кроме всего прочего мое решение стрельнет на любом компиляторе.

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


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

В топе был вопрос про известный, фиксированный адрес...

Налили воды, однако :)

 

По-моему, вариант перехода ((void(*)(void))0x10000000)(); куда как лучше извратов с линкером.

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


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

Налили воды, однако :)

 

По-моему, вариант перехода ((void(*)(void))0x10000000)(); куда как лучше извратов с линкером.

 

Нравится - так используйте... Никто не против...

Только Вы быстро сами поймете, что чем меньше в проекте статически распределенных объектов, тем она удобнее и мобилнее и легче носится с одной архитектуры на другую.

 

Это вовсе не вода. Это некоторый опыт, который даже не я собирал, а в общем-то все сообщество программистов от первого компьютера и до ныненшних дней. Статические адреса и распределения памяти - это кажется удобным только в простейших случаях.

 

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

 

Так что - я ничего не имею против Вашего решения - набивайте себе шишки сами...

Изменено пользователем Николай Z

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


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

Нравится - так используйте... Никто не против...

Только Вы быстро сами поймете, что чем меньше в проекте статически распределенных объектов, тем она удобнее и мобилнее и легче носится с одной архитектуры на другую.

...

Вообще-то речь шла о передаче управления от загрузчика к основной программе, объекту по определению статическому. И каким боком тут нужен линкер? Насчет переносимости уже сказали: поменяете компилятор (и трех лет не пройдет, ага :) ), и Вам придется искать другое решение.

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


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

Насчет переносимости уже сказали: поменяете компилятор (и трех лет не пройдет, ага :) ), и Вам придется искать другое решение.
Объясню, почему я пришел к такому решению. Потому что и IAR для AVR и WinAVR на конструкцию с константным указанием генерировали у меня один и тот же код - загрузку в Z и косвенный вызов. Вариант с линкером генерит честный RCALL. Это во-первых. Во-вторых. При портировании того же самого загрузчика с AVR на ARM я поменял константу в файле линкера. Констант там немного и они сгруппированы в одном месте - не нужно искать по всему исходнику. Исходник вообще не трогал - как там было Application(), так и осталось. Перейдя с IAR на WinAVR я нашел как определять символы линкеру (а это позволяет любой нормальный линкер) и снова никаких проблем. К слову, для AVR надо указывать адрес слова, хотя вся остальная адресация что у IAR, что у WinAVR идет побайтно. Что касается IAR для ARM, там тоже вызов через константу компилится во что-то не совсем красивое. Такие пироги.

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


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

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

 

Так оно и есть. Запуск кода из параллельной flash был только первым шагом. Теперь буду загружать разные приложения из DataFlash в SDRAM.

 

Так чем он плох? Ничем. Так что пусть человек знает, что решений задачи несколько, есть и более универсальные.

 

Да мне вообще стыдно за такой вопрос. Просто заклинило. Сидел побеждал размещение сегментов в памяти, копирование векторов прерываний, стартовые инициализации, флэшлоадер. Когда все вроде заработало и осталась такая мелочь как передать управление на код и пришлось воспользоваться подзатыльником.

 

Теперь после просветления никакого труда не составит сделать указатель на функцию и по нему запускать код в любом нужном месте памяти.

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


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

Объясню, почему я пришел к такому решению. Потому что и IAR для AVR и WinAVR на конструкцию с константным указанием генерировали у меня один и тот же код - загрузку в Z и косвенный вызов. Вариант с линкером генерит честный RCALL.

По-моему, издержек в любом случае будет немного. Не такой уж частый случай.

 

При портировании того же самого загрузчика с AVR на ARM я поменял константу в файле линкера. Констант там немного и они сгруппированы в одном месте - не нужно искать по всему исходнику. Исходник вообще не трогал - как там было Application(), так и осталось. Перейдя с IAR на WinAVR я нашел как определять символы линкеру (а это позволяет любой нормальный линкер) и снова никаких проблем.

Ну, #define еще никто не отменял, а в данном случае это будет родной define, а не опция линкера.

А если бы Вы переходили на ADS/RVDS, то проблемы бы возникли - не знаю, как протащить там подобную конструкцию, кроме как через symdefs-файл.

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


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

По-моему, издержек в любом случае будет немного. Не такой уж частый случай.
Да. Но если без напряжения можно сделать лучше - почему бы и да? А не пытаюсь никого отговаривать. Просто мне так кажется логичнее - функция располагается в другом модуле, адрес ее фиксированный, на мой взгляд проставлять в код адрес такой функции скорее задача линкера. Да и прозрачнее как-то код смотрится - объявлена функция, явно указано, что она внешняя, и вызов. Аналогично можно объявлять и функции с параметрами, причем указывать фиктивные самодокументирующие имена параметров. Кстати, вызов IAP у LPC таким образом тоже красиво получается:
// (Philips) Status Codes
enum iap_status_t 
{
    CMD_SUCCESS, INVALID_CMD,
    SRC_ADDR_ERROR, DST_ADDR_ERROR, SRC_ADDR_NOT_MAPPED, DST_ADDR_NOT_MAPPED,
    COUNT_ERROR, INVALID_SECTOR, SECTOR_NOT_BLANK, SECTOR_NOT_PREPARED,
    COMPARE_ERROR, BUSY, PARAM_ERROR, ADDR_ERROR, ADDR_NOT_MAPPED,
    CMD_LOCKED, INVALID_CODE, INVALID_BAUD_RATE, INVALID_STOP_BIT, CODE_READ_PROT_ENABLED, MAX_ERROR
};

enum iap_cmd_t
{
    PREPARE = 50, COPY, ERASE, BLANK_CHECK, GET_PART_ID, GET_BOOT_VER, COMPARE, SIZE_ALIGN = 0xFFFFFFFF
};

#pragma pack    (push,4)
struct iap_command_t 
{
    iap_cmd_t   Command;
    uint32_t    Param[4];
};
struct iap_result_t 
{
    iap_status_t    Status;
    uint32_t        Result[4];
};
#pragma pack    (pop)
extern "C" __thumb void IAP(iap_command_t *params, iap_result_t *result);
/* 
in .xcl: 
// IAP routine, thumb code
-DIAP=7FFFFFF1
*/

 

.

Ну, #define еще никто не отменял, а в данном случае это будет родной define, а не опция линкера.
Не спорю - можно и так. Ненаказуемо :)
А если бы Вы переходили на ADS/RVDS, то проблемы бы возникли - не знаю, как протащить там подобную конструкцию, кроме как через symdefs-файл.
Возможность-то наверняка есть, просто мы о ней (пока) не знаем. Хотя бы и через файл.

 

P.S. Мнения четко разделились на два подхода. Вот пришел бы кто-нибудь умный, вроде ReAl, и растолковал ограничения и правильность каждого решения.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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