Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ARM gcc, вызвать THUMB функцию из ROM
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
SM
Я что-то запутался... Как мне объявить внешнюю thumb функцию, расположенную по заданному статическому адресу?

Я сделал вот так:

1) arm-rom.h
Код
int rom_func (void* dev_descr, int data);


2) скрипт для линкера
Код
....
SECTIONS {
....
  rom_func = 0x123456;
}


Все тут хорошо, но линкер думает, что rom_func следует исполнять как ARM, а не как THUMB, и генерирует соотв. BLX инстукцию (при вызове из THUMB кода). А как мне указать, что он THUMB?
SM
Проблему сам решил, через ж. автогеном. Сделал ассемблерный файл rom_funcs.S, внутри которого написал:

Код
      .globl rom_func
      .thumb_set rom_func, 0x123456


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

-----
Но вопрос остался - а не через зад, можно? Прямо линкеру указать, что этот символ thumb и имеет такое-то значение?
den_po
можно без линкера сделать указатель на функцию, а в качестве адреса указывать адрес функции +1

void (*fn)() = (void(*)())(0x123456+1);

fn();
jcxz
Цитата(SM @ Aug 28 2014, 00:23) *
Проблему сам решил, через ж. автогеном. Сделал ассемблерный файл rom_funcs.S, внутри которого написал:

Выключайте автоген:
typedef void (__thumb *iap_entry_typ)(u32 *, u32 *);
#define iap_entry ((iap_entry_typ)0x7FFFFFF1)
iap_entry(buf, buf);

for IAR
SM
Цитата(jcxz @ Aug 28 2014, 06:02) *
for IAR

Спасибо, конечно, но в теме было про gcc. Никаких IAR там быть не может. Это около-линуксовая тема. Обхожу баг ROM-загрузчика AM3517, который не может загрузить из NAND больше 2К кода, если NAND имеет размер страницы больше, чем 2К.

Цитата(den_po @ Aug 28 2014, 02:17) *
а в качестве адреса указывать адрес функции +1

Проверено, при этом линкер при оптимизации накладывает маску на адрес 0xFFFFFFF8, чем убивает и +1, и если код находится на смещениях +2 (если gcc понимает, что указатель можно соптимизировать в прямой вызов). И генерирует команды перехода BLX... В общем, мимо. Можно, конечно, volatile указатель объявить, но не хочется указатели, хочется прямой вызов сделать корректно (без asm).
Golikov A.
ИМХО корректнее честный АСМ вызов, чем игры со смещением... может есть какая дирректива аля pragma, для тхумб вызовов? Кстати вроде есть регистр режима работы, если вы работаете в дном режиме, вызовы в другом режиме разрешены?
den_po
Цитата(SM @ Aug 28 2014, 09:58) *
Проверено, при этом линкер при оптимизации накладывает маску на адрес 0xFFFFFFF8, чем убивает и +1

И с какой, интересно, стати?
Или речь о непосредственном операнде?
Тут такое дело, если из арм кода вызывается BLX 0x123456 (обратите внимание - чётно), то оно переключает в тумбу. Может лажанул с кратностью 2, но сути не меняет, чётный адрес в непосредственном операнде BLX переключит режим.
scifi
Цитата(SM @ Aug 27 2014, 21:02) *
Я сделал вот так:

1) arm-rom.h
Код
int rom_func (void* dev_descr, int data);

А если так:
Код
int __attribute__((interfacethumb)) rom_func (void* dev_descr, int data);
SM
Цитата(den_po @ Aug 28 2014, 14:20) *
И с какой, интересно, стати?
Или речь о непосредственном операнде?

О непосредственном. То есть, когда gcc понимает, что указатель можно заоптимизировать до его смерти. При этом линкер, не видя какого-то атрибута, что адрес, куда перейти, относится к thumb режиму, обнуляет ему младшие два бита принудительно, причем без всяких варнингов.

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

Цитата(scifi @ Aug 28 2014, 14:36) *
А если так:

То так:
warning: 'interfacethumb' attribute directive ignored [-Wattributes]

gcc 4.7.2

PS
И, все наоборот - в тумбу переключает нечетный адрес, и при этом в тумбе адресация кратна двум. А четный адрес переключает в ARM, и там кратность уже равна четырем.
Сергей Борщ
Там есть еще одна фигня - линкер может вставлять BLX просто потому, что для BL не хватает дальности "прыжка".
SM
Цитата(Сергей Борщ @ Aug 28 2014, 16:02) *
Там есть еще одна фигня - линкер может вставлять BLX просто потому, что для BL не хватает дальности "прыжка".

Хватает, хватает... Только .thumb_set-ом все объявишь, сразу BL. Да и BL вроде не отличается от BLX по "дальности".
den_po
Цитата(SM @ Aug 28 2014, 14:41) *
О непосредственном. То есть, когда gcc понимает, что указатель можно заоптимизировать до его смерти. При этом линкер, не видя какого-то атрибута, что адрес, куда перейти, относится к thumb режиму, обнуляет ему младшие два бита принудительно, причем без всяких варнингов.

Кто-то из нас что-то недопонимает.
Если адрес thumb функции N*4, на выходе из предложенного мной кода получается обычно один из двух вариантов:
1) BLX (N*4)
2) LDR Rx, =N*4+1
BLX Rx

Если адрес thumb функции N*4+2, на выходе получается один вариант:
LRD Rx, =N*4+2+1
BLX Rx

У вас какой-то другой результат получается?

Цитата(SM @ Aug 28 2014, 14:41) *
Да и ручное прибавление единицы к адресу в указателе, это еще более мощный автоген в ж., чем ассемблерный .thumb_set

Чем это хуже использования заданного статического адреса?
SM
Цитата(den_po @ Aug 28 2014, 16:44) *
У вас какой-то другой результат получается?

Естественно, другой.

- Если я делаю вызов ф-ции, описанной по .thumb_set из THUMB-кода, то я получаю
BL N*2 ; thumb -> thumb

- Если я делаю вызов ф-ции, описанной по .set из THUMB-кода, то я получаю
BLX N*4 ; thumb -> arm

- Если я делаю вызов ф-ции, описанной по .thumb_set из ARM-кода, то я получаю (должен получить, не пробовал, не надо)
BLX N*2+1 ; arm -> thumb

- Если я делаю вызов ф-ции, описанной по .set из ARM-кода, то я получаю
BL N*4 ; arm -> arm

ну, естественно, линкеру дана опция ком. строки --use-blx, иначе она всякий там гемор с регистрами генерирует

Цитата(den_po @ Aug 28 2014, 16:44) *
Чем это хуже использования заданного статического адреса?

Тем, что линкер/компилятор разбираются сами, где там +1 сделать, где не сделать, где BL поставить, где BLX. (тем более, докучи, откуда компилятор узнает, что при переходе по указателю нужен будет BLX, а не BL).

Собственно, вопрос то не в этом. Вопрос - как уйти от .thumb_set и ассемблера, по аналогии с IAR-овским __thumb
den_po
В общем, говорим мы о разных вещах.
Если в исходнике указывать адрес указанным мной способом, всё будет работать нормально, никакой линкер никакие биты самовольно не сбросит. Задачу из первой строки первого поста это решает.
jcxz
Цитата(SM @ Aug 28 2014, 18:09) *
Хватает, хватает... Только .thumb_set-ом все объявишь, сразу BL. Да и BL вроде не отличается от BLX по "дальности".

Как оно может не отличаться? если BX - косвенная адресация, соотв. -32битное смещение, а B - с адресом в команде (т.е. - явно меньше 32 бит).
jcxz
Цитата(Сергей Борщ @ Aug 28 2014, 18:02) *
Там есть еще одна фигня - линкер может вставлять BX просто потому, что для B не хватает дальности "прыжка".

Линкёр команды не генерит. Максимум, что он может - вставить врапперы (или как оно там называется), когда видит, что цель перехода - вне пределов досягаемости.
Когда компилятор генерит выходные секции из исходника, то внутри секции он может вычислить расстояния переходов, и соответственно - использовать команду перехода с непосредственным смещением в теле.
Если же переход идёт в другую секцию, то расстояние станет известно только на этапе компоновки, а значит при компиляции оно не известно. Тогда линкёр может вставить враппер с косвенным
переходом внутри для увеличения длины перехода.

А в данном случае переход идёт из перемещаемой области (для компилятора её адрес не известен) в константный адрес. Тут само собой нужен BX сразу без всяких доп. врапперов.
SM
Цитата(jcxz @ Aug 29 2014, 06:41) *
если BX


Не BX, а BLX, речь только о BLX с непосредственной адресацией. Ее отличие от BL (тоже с непосредственной адресацией) только в том, что она переключает режим ARM/THUMB, а BL - нет.

Собственно, первоисточник - http://infocenter.arm.com/help/index.jsp?t...c/Cihfddaf.html
BLX Label, как и BL Label, имеют зону досягаемости +-32 Мбайт.

И, вообще, повторю в стодвадцатый раз уже. Генерация кода происходит так, как мне надо, если для задания адреса ф-ции я использую ассемблерный .thumb_set (собственно, все уже работает, красоты не хватает). Вопрос в том, как сделать без ассемблера так, чтобы вызовы были при помощи непосредственной адресации и корректными (иначе чутка не влезаю в нужный мне размер кода), то есть я хочу описать средствами С и/или линкера THUMB-функцию, расположенную вне моего кода в ROM, так, чтобы при генерации кода она вызывалась через BL/BLX с непосредственной адресацией.
Golikov A.
А у меня есть другое предложение, а что если вам сделать переход все равно какой, а переключиться на thumb режим уже внутри вашей функции? Тогда вам не надо будет следить за переходами на вашу функцию, переход может быть любым, а функция всегда отработает правильно не зависимо от того как на нее перешли?
SM
Цитата(Golikov A. @ Aug 29 2014, 10:31) *
А у меня есть другое предложение, а что если вам сделать переход все равно какой, а переключиться на thumb режим уже внутри вашей функции?


У меня задача обратная sm.gif Мне надо НЕ переключаться в ARM, при вызове ROM-функций (они находятся по фиксированным адресам в ROM (в бутлоадере) в процессоре, и все имеют thumb-код), из моего кода, который тоже THUMB. А по умолчанию gcc считает, что такая функция, объявленная заданием адреса через скрипт линкера, она ARM.

При этом без излишеств, так как у меня всего 500 байт есть на весь мой код... С .thumb_set я уложился в 480 байт, но хочу сделать без него, и чтобы с тем же результатом.
Golikov A.
да пофиг, пусть переключается, вы в функции насильно переключите обратно и дальше поехали, ну потеряете немного тактов, но как я понимаю если пошли по пути экономии памяти, с тактами уже можно прощатьсяsm.gif .
В thumb режиме если я не ошибаюсь команда перехода уже не +-32MB, а всего то +-2MB если мы про 16 битный режим, может это как-то влияет на попытки переключится?
Еще следить надо что команда перехода с переключением а не выбором режима, то есть надо еще считать число переходовsm.gif


Цитата
При этом без излишеств, так как у меня всего 500 байт есть на весь мой код... С .thumb_set я уложился в 480 байт,

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


Ну если уж так жметесь, то даже не знаю что предложить...
jcxz
Цитата(Golikov A. @ Aug 29 2014, 12:31) *
А у меня есть другое предложение, а что если вам сделать переход все равно какой, а переключиться на thumb режим уже внутри вашей функции? Тогда вам не надо будет следить за переходами на вашу функцию, переход может быть любым, а функция всегда отработает правильно не зависимо от того как на нее перешли?

Да, непонятно мне тоже. Почему-бы SM не сделать просто функцию-обёртку этого ROM-вызова, переключаясь внутри этой обёртки в thumb, а вызывая её обычным образом?
SM
Цитата(Golikov A. @ Aug 29 2014, 10:45) *
В thumb режиме если я не ошибаюсь команда перехода уже не +-32MB, а всего то +-2MB

В thumb допустимы и 32-битные команды, с ".W" - в общем, блин, нету проблем с этим. Ведь !!!! с .thumb_set все происходит как надо, и проблем нет. Но он мне просто не нравится. Красоты хочется, чтобы без ассемблерной добавки.

Цитата(jcxz @ Aug 29 2014, 10:47) *
Да, непонятно мне тоже. Почему-бы SM не сделать просто функцию-обёртку этого ROM-вызова, переключаясь внутри этой обёртки в thumb, а вызывая её обычным образом?

Вылезаю за допустимый размер. Код + три слова данных (два на хидер и одно в конце моё) должны влезть в один ECC-сектор NAND памяти (512 байт).

Цитата(Golikov A. @ Aug 29 2014, 10:45) *
Как же вы машину заправляетеsm.gif.....

Вот тут я отрываюсь по полной! lol.gif

UPD
Я бы, конечно, как это вообще люблю делать (на других процах), написал бы все от начала и до конца на асме... Но дюже неудобный он у ARM-а для писания на нем... Вот и извращаюсь с С.
jcxz
Цитата(SM @ Aug 29 2014, 12:40) *
При этом без излишеств, так как у меня всего 500 байт есть на весь мой код... С .thumb_set я уложился в 480 байт, но хочу сделать без него, и чтобы с тем же результатом.

Если вопрос в размере и известно, что расстояние до этих ROM-функций позволяет использовать BL (с его укороченной досягаемостью) и известен стартовый адрес образа
вашего кода в памяти, то можно в асм-файле определить команды перехода на ROM-функции как обычные константы (не знаю как в gcc, но в IAR):
wrap_funcX: DC16 XXXX ;здесь код команды безусловный B с непосредственным 11-битным смещением
описать wrap_funcX как функцию, прилинковать в известное место (по известному смещению) своего выходного исполняемого образа и вызывать как обычную функцию.
SM
Цитата(jcxz @ Aug 29 2014, 10:59) *
то можно в асм-файле определить

Ну елки-палки. С asm-файлом у меня все и без таких извратов работает! Хочется средствами С обойтись.

rom_func.h:
Код
int rom_func (void* dev_descr, int data);


rom_func.S:
Код
.globl rom_func
.thumb_set rom_func, 0x123456


и в результате в thumb-коде получается обычный BL 0x123456, что и требуется.
Golikov A.
А второй вопрос, если все вызовы этой функции сделать ассемблерными вставками с правильным переходом? То есть вызывать ее не через
My_func()... А переходом с сохранением и восстановлением регистров потом ручками, коль вы искушены в асме?
Я так понимаю что если код столь мал, то вряд ли он потом будет сильно кем то еще модифицироваться и наращиваться, можно и последить, коли такая острая задача.

ассемблерные вставки вполне допустимы и всеми нормально воспринимаются в коде на С
SM
Цитата(Golikov A. @ Aug 29 2014, 11:05) *
Я так понимаю что если код столь мал, то вряд ли он потом будет сильно кем то еще модифицироваться и наращиваться, можно и последить, коли такая острая задача.

Не хочется вставок и лишнего асма. Это опенсурс проект... Выкладывать его буду в виде патча к x-loader-у для работы с AM3517 с NAND-ами с 4К-страницами, как обход бага его ROM-бутлоадера, связанного с такими NAND.
jcxz
Цитата(SM @ Aug 29 2014, 13:07) *
Не хочется вставок и лишнего асма. Это опенсурс проект... Выкладывать его буду в виде патча к x-loader-у для работы с AM3517 с NAND-ами с 4К-страницами, как обход бага его ROM-бутлоадера, связанного с такими NAND.

Вряд-ли без асм или intrinsic-функций или без какой другой привязки к компилятору обойдётесь.
По-моему это всё ерунда.
Лучше-бы тогда уж ROM-бутлоадер OMAP L-137 поправили. sm.gif
Чтобы он грузился с SPI-флеши находящейся в Sleep-mode. Это, имхо, полезнее.
SM
Цитата(jcxz @ Aug 29 2014, 11:18) *
Это, имхо, полезнее.


У каждого свое IMHO. Мы купили 1000 NAND-ов с 4К страницами, из них половину запаяли sm.gif Не выкидывать же и перепаивать... Об этом баге и в TI не знали...

Короче, как я понял, нет другого способа объявить функцию как thumb, кроме как:
1) скомпилировать ее (она должна быть в файле определена вместе с ее телом, то есть не быть внешней) вместе с файлом с указанием ключа -mthumb
2) ассемблерный .thumb_set
3) ассемблерный .thumb_func

А чего-то типа __attribute__ ((thumb)) или __thumb в арсенале gcc нет.

Итого, объявить внешнюю функцию по заданному адресу можно только методом 2) - .thumb_set.

это верные выводы?

PS
о том, как вызвать некий адрес как thumb или ARM речь не ведется, и не велась. Речь именно про объявление функции средствами C или линкера по заранее заданному адресу.
jcxz
Цитата(SM @ Aug 29 2014, 13:35) *
А чего-то типа __attribute__ ((thumb)) или __thumb в арсенале gcc нет.
Итого, объявить внешнюю функцию по заданному адресу можно только методом 2) - .thumb_set.

Мне кажется Ваш вопрос больше не про ARM, а про средства разработки. Так что здесь более уместна: http://electronix.ru/forum/index.php?showforum=162
может там лучше подскажут.
SM
Цитата(jcxz @ Aug 29 2014, 11:44) *
Мне кажется Ваш вопрос больше не про ARM

Мне так не кажется... thumb - это сугубо ARM-овское - ни к какому другому ядру отношения не имеет.

В общем, долгое гугление на эту тему тоже ничего не дало, кроме .thumb_set... Так что, пожалуй, перспектив что-то еще узнать практически нет. Я тут надеялся, что кто-то уже это проходил до меня из местных.
Сергей Борщ
Увы... Максимум, что приходит в голову - засунуть этот .thumb_set в ассемблерную вставку.
sasamy
Цитата(SM @ Aug 29 2014, 11:48) *
В общем, долгое гугление на эту тему тоже ничего не дало, кроме .thumb_set... Так что, пожалуй, перспектив что-то еще узнать практически нет.


тут есть еще два варианта

http://answers.launchpad.net/gcc-arm-embed...question/224550
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.