VladislavS 39 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Что-то совсем заработался... :( Ваяю начальный загрузчик. Основная программа лежит по адресу 0x10000000 в параллельном flash. По окончании всех действий надо просто передать на неё управление. Как? EWARM 4.40. Процессор AT91RM9200. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Спасибо. Сработало. Как все просто когда знаешь... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Есть еще способ (без линкера): ((void(*)(void))0x10000000)(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikolayZ 0 8 ноября, 2007 Опубликовано 8 ноября, 2007 (изменено) · Жалоба Есть еще способ (без линкера): ((void(*)(void))0x10000000)(); Дык при желании можно не только без линкера обойтись - в принципе можно даже без компилятора.... Правильнее делать то и так, как Сергей Борщ написал. Изменено 8 ноября, 2007 пользователем Николай Z Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Дык при желании можно не только без линкера обойтись - в принципе можно даже без компилятора.... Правильнее делать то и так, как Сергей Борщ написал. А если этот адрес не константа? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikolayZ 0 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба А если этот адрес не константа? В топе был вопрос про известный, фиксированный адрес... В вашем варианте - адрес не константа - надо сперва определить задачу. Вам мало просто прыгнуть на заданный адрес - надо же чтобы там лежали точки входа в программы иначе это не имеет смысла. Уточните Вашу задачу - получите и ответ. А так ничего кроме совета создать указатель функции, кторый вы сами и заполните любым нужным Вам значением, чтобы ее потом вызвать - вы вряд ли что-то услышите в ответ. Первое, что надо определить - а зачем вообще нужно вызывать функцию по некоему переменному адресу? У вас функции ползают по памяти что ли? У меня обычно нет и мне трудно сообразить - зачем мне вообще нужно делать вызовы по неким переменным адресам в общем случае. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба В топе был вопрос про известный, фиксированный адрес... Я понимаю. Представим себе ситуацию, что в процессе развития этого начального загрузчика будет необходимо загружать код не только на адрес 0x10000000, но и на любой другой адрес, который будет передаваться загрузчику (ну например в коммандной строке). Тогда придется перейти к моему варианту. Так чем он плох? Ничем. Так что пусть человек знает, что решений задачи несколько, есть и более универсальные. PS Ах да, кроме всего прочего мое решение стрельнет на любом компиляторе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба В топе был вопрос про известный, фиксированный адрес... Налили воды, однако :) По-моему, вариант перехода ((void(*)(void))0x10000000)(); куда как лучше извратов с линкером. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NikolayZ 0 8 ноября, 2007 Опубликовано 8 ноября, 2007 (изменено) · Жалоба Налили воды, однако :) По-моему, вариант перехода ((void(*)(void))0x10000000)(); куда как лучше извратов с линкером. Нравится - так используйте... Никто не против... Только Вы быстро сами поймете, что чем меньше в проекте статически распределенных объектов, тем она удобнее и мобилнее и легче носится с одной архитектуры на другую. Это вовсе не вода. Это некоторый опыт, который даже не я собирал, а в общем-то все сообщество программистов от первого компьютера и до ныненшних дней. Статические адреса и распределения памяти - это кажется удобным только в простейших случаях. А с линкером - это как раз никакой не изврат, а можно сказать общее и классическое решение, которое приводит к гораздо меньшим проблемам, чем статическое определение адресов вызываемых функций прямо в коде на С. Сами достаточно быстро в этом убедитесь... И трех лет не пройдет как поймете, что рекомендация данная Вам выше - намного правильнее, чем то, что ам так понравилось... Так что - я ничего не имею против Вашего решения - набивайте себе шишки сами... Изменено 8 ноября, 2007 пользователем Николай Z Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Нравится - так используйте... Никто не против... Только Вы быстро сами поймете, что чем меньше в проекте статически распределенных объектов, тем она удобнее и мобилнее и легче носится с одной архитектуры на другую. ... Вообще-то речь шла о передаче управления от загрузчика к основной программе, объекту по определению статическому. И каким боком тут нужен линкер? Насчет переносимости уже сказали: поменяете компилятор (и трех лет не пройдет, ага :) ), и Вам придется искать другое решение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Насчет переносимости уже сказали: поменяете компилятор (и трех лет не пройдет, ага :) ), и Вам придется искать другое решение.Объясню, почему я пришел к такому решению. Потому что и IAR для AVR и WinAVR на конструкцию с константным указанием генерировали у меня один и тот же код - загрузку в Z и косвенный вызов. Вариант с линкером генерит честный RCALL. Это во-первых. Во-вторых. При портировании того же самого загрузчика с AVR на ARM я поменял константу в файле линкера. Констант там немного и они сгруппированы в одном месте - не нужно искать по всему исходнику. Исходник вообще не трогал - как там было Application(), так и осталось. Перейдя с IAR на WinAVR я нашел как определять символы линкеру (а это позволяет любой нормальный линкер) и снова никаких проблем. К слову, для AVR надо указывать адрес слова, хотя вся остальная адресация что у IAR, что у WinAVR идет побайтно. Что касается IAR для ARM, там тоже вызов через константу компилится во что-то не совсем красивое. Такие пироги. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Представим себе ситуацию, что в процессе развития этого начального загрузчика будет необходимо загружать код не только на адрес 0x10000000, но и на любой другой адрес... Так оно и есть. Запуск кода из параллельной flash был только первым шагом. Теперь буду загружать разные приложения из DataFlash в SDRAM. Так чем он плох? Ничем. Так что пусть человек знает, что решений задачи несколько, есть и более универсальные. Да мне вообще стыдно за такой вопрос. Просто заклинило. Сидел побеждал размещение сегментов в памяти, копирование векторов прерываний, стартовые инициализации, флэшлоадер. Когда все вроде заработало и осталась такая мелочь как передать управление на код и пришлось воспользоваться подзатыльником. Теперь после просветления никакого труда не составит сделать указатель на функцию и по нему запускать код в любом нужном месте памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба Объясню, почему я пришел к такому решению. Потому что и IAR для AVR и WinAVR на конструкцию с константным указанием генерировали у меня один и тот же код - загрузку в Z и косвенный вызов. Вариант с линкером генерит честный RCALL. По-моему, издержек в любом случае будет немного. Не такой уж частый случай. При портировании того же самого загрузчика с AVR на ARM я поменял константу в файле линкера. Констант там немного и они сгруппированы в одном месте - не нужно искать по всему исходнику. Исходник вообще не трогал - как там было Application(), так и осталось. Перейдя с IAR на WinAVR я нашел как определять символы линкеру (а это позволяет любой нормальный линкер) и снова никаких проблем. Ну, #define еще никто не отменял, а в данном случае это будет родной define, а не опция линкера. А если бы Вы переходили на ADS/RVDS, то проблемы бы возникли - не знаю, как протащить там подобную конструкцию, кроме как через symdefs-файл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 8 ноября, 2007 Опубликовано 8 ноября, 2007 · Жалоба По-моему, издержек в любом случае будет немного. Не такой уж частый случай.Да. Но если без напряжения можно сделать лучше - почему бы и да? А не пытаюсь никого отговаривать. Просто мне так кажется логичнее - функция располагается в другом модуле, адрес ее фиксированный, на мой взгляд проставлять в код адрес такой функции скорее задача линкера. Да и прозрачнее как-то код смотрится - объявлена функция, явно указано, что она внешняя, и вызов. Аналогично можно объявлять и функции с параметрами, причем указывать фиктивные самодокументирующие имена параметров. Кстати, вызов 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, и растолковал ограничения и правильность каждого решения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться