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

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

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

вызов функции по фиксированному адресу приводит к непредсказуемым последствиям.

Это касается младших контроллеров AVR у которых все jmp и call существуют только в

версии rjmp и rcall.

Mega8:

169:      ((void(*)(void))0x0000)();
+00000450:   DBF0        RCALL   PC-0x040F        Relative call subroutine

Mega128:

169:      ((void(*)(void))0x0000)();
+00000489:   940E0000    CALL    0x00000000       Call subroutine

 

WinAVR-20060421

 

Может в новых версиях они чего-то и подправили...

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


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

Да. Но если без напряжения можно сделать лучше - почему бы и да?

Чем лучше?

ИМХО, задание левых символов для линкера - это изврат. Особенно, если имеешь дело с полудюжиной разных архитектур и, соответственно, разных линкеров.

 

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

То же самое легко делается дефайном:

#define    func(x, y)    ((int(*)(int, int))0x10000000)((x), (y))

И объявить функцию в любом виде можно.

 

Не спорю - можно и так. Ненаказуемо :)Возможность-то наверняка есть, просто мы о ней (пока) не знаем. Хотя бы и через файл.

Нет там такой возможности - только через symdefs, который в обычной жизни не нужен.

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


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

Если делать на классическом С, то что-то типа того получается:

 

typedef void (*MyFunc)(void);
MyFunc MyCode;

int main()
{
  MyCode = (MyFunc)0x10000000;
  MyCode();
}

 

Только вызов по всем книжкам (*MyCode)() должен быть, а работает правильно и просто MyCode().

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


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

ИМХО, задание левых символов для линкера - это изврат. Особенно, если имеешь дело с полудюжиной разных архитектур и, соответственно, разных линкеров.

 

Могу только повториться... Да можно и без линкера... и даже без компилятора, можно даже без ассемблера.... В пределе - можно вообще без процессора - все на логических схемах...

 

Скорее всего Вы просто плохо понимаете назначение линкера и описания make, которые как раз и отвечают за создание исполняемого кода и распределение памяти.

 

Зачем говорить о разных процессорах, если уже в программе main - вы себя жестко привязали к одной-единственной архитектуре наглухо практически - именно путем задания статического адреса? Причем тут тогда другие процессоры c другой архитектурой - у них точка входа почти наверняка будет в другом месте?

 

А вот символическое задание имен в программе - позволяет ее как раз переносить между разными архитектурами намного легче... Задача только увязать с требуемыми адресами заданными архитектурой - т.е. в make файле или как раз в параметрах линкера и нигде больше... А саму программу править уже и не надо в 99% cлучаев, если Вы в нее не запихнете еще какую-то архитектурную зависимость.

==============================================

PS: По поводу легко или нелегко- практически притча... Представьте себе у Вас в квартире - новую стену после ремонта... Новые обои - все красиво... Стоит на полу картина... Задача - повесить ее на стену.... Решаться может разными способами...

Первый способ - находите три ржавых гвоздя в сундуке... и какой попало молоток... Два вбиваете как попало в дорогую раму - сзади.... И привязываете к гвоздям кусок первого попавшегося шпагата.... Третий - криво и с трудом вгоняете в стену.... Ржавый такой гвоздь... кривой... Вешаете за шпагатину Вашу замечательную картину... Ну - нравится Вам этот самый простой способ? ведь проще не бывает... :biggrin:

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

 

Мне кажется, что второй способ при его кажущейся большей сложности - правильнее первого и намного эстетичности. А часто - еще и более простой и легкий... Да еще и мобильный - ибо специальный крепеж легко и удалется и вид стены не испортит - а попробуйте без последствий вырнуть из стены 100 мм ржавый гвоздь? :biggrin:

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

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


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

Могу только повториться... Да можно и без линкера...

 

Не без линкера, а без использования определенных СТАТИЧЕСКИ в линкере адресов.

 

Скорее всего Вы просто плохо понимаете назначение линкера и описания make, которые как раз и отвечают за создание исполняемого кода и распределение памяти.

 

Отлично понимаю, и в другом случае конечно по возможности определю адреса в .xcl-файле например.

 

Зачем говорить о разных процессорах, если уже в программе main - вы себя жестко привязали к одной-единственной архитектуре наглухо практически - именно путем задания статического адреса? Причем тут тогда другие процессоры c другой архитектурой - у них точка входа почти наверняка будет в другом месте?

 

Причем тут архитектура. Понятное дело, что бутлоадер - вещь сугубо интимная со всех сторон.

 

Только вот вы видимо невнимательно читаете. Я (уж простите такую вольность) предположил, что автору возможно понадобится расширить функционал до вызова функции по произвольному адресу.

 

Вот что я написал:

 

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

 

И автор топика ответил (болд мой)

 

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

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

 

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

 

Давайте, ваш удар, принц - сделайте это линкером - запускать код в любом нужном месте памяти

 

Так зачем вы нам тут притчи рассказываете?

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


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

Давайте, ваш удар, принц - сделайте это линкером - запускать код в любом нужном месте памяти

 

Так зачем вы нам тут притчи рассказываете?

 

А мы тут что - боксируем? Извините - я во-первых тут этого делать не собираюсь...

А во-ворых Вам уже все рассказали...

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

 

А притча затем - что Ваше решение - как раз те самые три ржавых гвоздя.

А второе - это то что Вам рекомендовал г-н Сергей Борщ - это и есть правильное и довольно мобильное решение. Может и не идеальное - но классическое и проверенное.

 

Но Вы вправе ему как следовать, так и не следовать. Больше тут добавить нечего.

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

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


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

А во-ворых Вам уже все рассказали...

 

Что именно?

 

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

 

Мне нравится подход. Но он стреляет только в том случае, если этот адрес - константа.

 

А притча затем - что Ваше решение - как раз те самые три ржавых гвоздя.

А второе - это то что Вам рекомендовал г-н Сергей Борщ - это и есть правильное и довольно мобильное решение. Может и не идеальное - но классическое и проверенное.

 

Не поверите - классика - это как раз то что я написал :biggrin:

 

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

 

В более общем случае рассмотрите вопрос загрузки выполняемых приложений на разные адреса (куда malloc вернул указатель, там и будет приложение). Как такое победить линкером?

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


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

Мне нравится подход. Но он стреляет только в том случае, если этот адрес - константа.

Нравится так нравится... Но Вам никто не мешает использовать вместо вашей константы зарезервированный заранее пойнтер и инициировать его перед использованием как Вам угодно.

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


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

Нравится так нравится... Но Вам никто не мешает использовать вместо вашей константы зарезервированный заранее пойнтер и инициировать его перед использованием как Вам угодно.

 

 

Видимо я недостаточно точно сформулировал. Правильно будет звучать так -

"Мне нравится подход с указанием адреса в скрипте/параметрах линкера. Но он стреляет только в том случае, если этот адрес - константа."

 

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

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


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

Видимо я недостаточно точно сформулировал. Правильно будет звучать так -

"Мне нравится подход с указанием адреса в скрипте/параметрах линкера. Но он стреляет только в том случае, если этот адрес - константа."

 

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

 

Я начинаю подозревать что мы говорим о чем-то разном... Я о вопросе заданном в топе...

А Вы об чем?

 

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

 

Зачем надо переменную точку старта - вообще?

 

В более общем случае рассмотрите вопрос загрузки выполняемых приложений на разные адреса (куда malloc вернул указатель, там и будет приложение). Как такое победить линкером?

 

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

Если я правильно понимаю - то у Вас уже что-то работает в процессоре - ведь кто-то должен вызвать Ваш malloc(), который вам дает указатель?

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

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


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

Я начинаю подозревать что мы говорим о чем-то разном... Я о вопросе заданном в топе...

А Вы об чем?

 

Я о том, что автор уточнил задачу чуть позже

 

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

 

Так что уже 2 точки входа как минимум.

 

А теперь представьте себе, что автору понадобится загрузить два приложения на разные адреса, которые, например, ему вернет malloc. Как он выйдет из положения?

 

 

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

 

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

typedef long TElfEntry(char *, void *,void *,void *);
long elfload(char *filename, void *param1, void *param2, void *param3){
....
....
  //выделим эту область и очистим ее
  if ((base=(char *)malloc(maxadr-minadr))==0){        //не выделяеться память под ельф
...
...
  ((TElfEntry *)(base+ehdr.e_entry-minadr))(filename,param1,param2,param3);
...

 

Зачем надо переменную точку старта - вообще?

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

Если я правильно понимаю - то у Вас уже что-то работает в процессоре - ведь кто-то должен вызвать Ваш malloc(), который вам дает указатель?

 

Я не собираюсь. А автор топика - вполне возможно. Посему лучше использовать вариант, предложеный мной. На будущее.

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


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

Да расшумелись :(.

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

что вместо нормального "выхода в дверь" используют "выход в окно". Однако любое правило сильно исключениями для перехода куда-то безвозвратно в bootloader я явно отдам предпочтение действительно очевидно-классическому варианту, а не указания линкеру виртуальных имен. Причина проста - сразу видно, что "выход именно в окно", а не нечто обыденное.

 

А вот практический результат в виде полученного кода в одном и другом случае надо иметь ввиду.

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


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

А теперь представьте себе, что автору понадобится загрузить два приложения на разные адреса, которые, например, ему вернет malloc. Как он выйдет из положения?

 

Это и есть механизм дозагрузки софта в уже работающем...

Как раз типа механизма работы оверлея...

 

malloc() не сам вызвался - его вызвала уже загруженная часть ситемы которая стартовала - раньше когда система стартовала...

 

Потому тут задача вглядит немного иначе:

Надо просто вызвать подпрограмму, которую вы прочли из Флэша или откуда-то еще в память, которую Вам указал вызванный malloc...

 

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

Система у Вас уже работает... В ней ваш модуль определил место дозагрузки - вызовом malloc() и получил адрес места для размещения программы...

 

Замечу - я честно говоря не знаю зачем для этого malloc() использовать - но предположим пусть так, хотя это можно сделать гораздо более эффективно...

 

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

 

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

Во FreeRTOS нету встроенного механизма работы с Оверлеями и софт для их поддержки непредусмотрен. Его надо делать самому... или исать в каких-то других системах...

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

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


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

Да ладно вам на пустом месте ругаться... Чтобы никому не было обидно я оставил вызов кода из флэшь по первому варианту (изменить её адрес всё равно не получится), а загруженный в SDRAM код по второму варианту. Работают оба варианта, а практика критерий истины.

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


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

Да ладно вам на пустом месте ругаться... Чтобы никому не было обидно я оставил вызов кода из флэшь по первому варианту (изменить её адрес всё равно не получится), а загруженный в SDRAM код по второму варианту. Работают оба варианта, а практика критерий истины.

 

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

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


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

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

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

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

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

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

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

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

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

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