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

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> EWARM. Cделать переход по известному адресу?
VladislavS
сообщение Nov 8 2007, 12:56
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140



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

EWARM 4.40. Процессор AT91RM9200.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 8 2007, 13:03
Сообщение #2


Гуру
******

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



Цитата(VladislavS @ Nov 8 2007, 14:56) *
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.


--------------------
На любой вопрос даю любой ответ
"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
VladislavS
сообщение Nov 8 2007, 13:23
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140



Спасибо. Сработало. Как все просто когда знаешь...
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 8 2007, 13:30
Сообщение #4


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



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

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


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Николай Z
сообщение Nov 8 2007, 14:25
Сообщение #5


Местный
***

Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930



Цитата(Rst7 @ Nov 8 2007, 16:30) *
Есть еще способ (без линкера):

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


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

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

Сообщение отредактировал Николай Z - Nov 8 2007, 14:25
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 8 2007, 14:41
Сообщение #6


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата(Николай Z @ Nov 8 2007, 16:25) *
Дык при желании можно не только без линкера обойтись - в принципе можно даже без компилятора....

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


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


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Николай Z
сообщение Nov 8 2007, 15:09
Сообщение #7


Местный
***

Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930



Цитата(Rst7 @ Nov 8 2007, 17:41) *
А если этот адрес не константа?


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

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

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

У меня обычно нет и мне трудно сообразить - зачем мне вообще нужно делать вызовы по неким переменным адресам в общем случае.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 8 2007, 15:23
Сообщение #8


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата(Николай Z @ Nov 8 2007, 17:09) *
В топе был вопрос про известный, фиксированный адрес...


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

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

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


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 8 2007, 15:25
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Николай Z @ Nov 8 2007, 18:09) *
В топе был вопрос про известный, фиксированный адрес...

Налили воды, однако smile.gif

По-моему, вариант перехода ((void(*)(void))0x10000000)(); куда как лучше извратов с линкером.
Go to the top of the page
 
+Quote Post
Николай Z
сообщение Nov 8 2007, 16:33
Сообщение #10


Местный
***

Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930



Цитата(aaarrr @ Nov 8 2007, 18:25) *
Налили воды, однако smile.gif

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


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

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

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

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

Сообщение отредактировал Николай Z - Nov 8 2007, 16:37
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 8 2007, 18:49
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Николай Z @ Nov 8 2007, 19:33) *
Нравится - так используйте... Никто не против...
Только Вы быстро сами поймете, что чем меньше в проекте статически распределенных объектов, тем она удобнее и мобилнее и легче носится с одной архитектуры на другую.
...

Вообще-то речь шла о передаче управления от загрузчика к основной программе, объекту по определению статическому. И каким боком тут нужен линкер? Насчет переносимости уже сказали: поменяете компилятор (и трех лет не пройдет, ага smile.gif ), и Вам придется искать другое решение.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 8 2007, 19:36
Сообщение #12


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"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
VladislavS
сообщение Nov 8 2007, 20:01
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140



Цитата(Rst7 @ Nov 8 2007, 18:23) *
Представим себе ситуацию, что в процессе развития этого начального загрузчика будет необходимо загружать код не только на адрес 0x10000000, но и на любой другой адрес...


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

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


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

Теперь после просветления никакого труда не составит сделать указатель на функцию и по нему запускать код в любом нужном месте памяти.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 8 2007, 23:03
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Сергей Борщ @ Nov 8 2007, 22:36) *
Объясню, почему я пришел к такому решению. Потому что и IAR для AVR и WinAVR на конструкцию с константным указанием генерировали у меня один и тот же код - загрузку в Z и косвенный вызов. Вариант с линкером генерит честный RCALL.

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

Цитата(Сергей Борщ @ Nov 8 2007, 22:36) *
При портировании того же самого загрузчика с AVR на ARM я поменял константу в файле линкера. Констант там немного и они сгруппированы в одном месте - не нужно искать по всему исходнику. Исходник вообще не трогал - как там было Application(), так и осталось. Перейдя с IAR на WinAVR я нашел как определять символы линкеру (а это позволяет любой нормальный линкер) и снова никаких проблем.

Ну, #define еще никто не отменял, а в данном случае это будет родной define, а не опция линкера.
А если бы Вы переходили на ADS/RVDS, то проблемы бы возникли - не знаю, как протащить там подобную конструкцию, кроме как через symdefs-файл.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 8 2007, 23:29
Сообщение #15


Гуру
******

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



Цитата(aaarrr @ Nov 9 2007, 01:03) *
По-моему, издержек в любом случае будет немного. Не такой уж частый случай.
Да. Но если без напряжения можно сделать лучше - почему бы и да? А не пытаюсь никого отговаривать. Просто мне так кажется логичнее - функция располагается в другом модуле, адрес ее фиксированный, на мой взгляд проставлять в код адрес такой функции скорее задача линкера. Да и прозрачнее как-то код смотрится - объявлена функция, явно указано, что она внешняя, и вызов. Аналогично можно объявлять и функции с параметрами, причем указывать фиктивные самодокументирующие имена параметров. Кстати, вызов 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
*/


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

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


--------------------
На любой вопрос даю любой ответ
"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

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:33
Рейтинг@Mail.ru


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