Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как сделать IJMP внутри программы на Си?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
hakimulla
Объясните, пожалуйста, как оформить индексный переход IJMP в программе
на Си.
Можно ли как-нибудь прочитать значение Program Counter (PC) для
AT90USB162?
_Артём_
Цитата(hakimulla @ Mar 28 2012, 21:50) *
Объясните, пожалуйста, как оформить индексный переход IJMP в программе
на Си.

Зачем именно IJMP?

Цитата(hakimulla @ Mar 28 2012, 21:50) *
Можно ли как-нибудь прочитать значение Program Counter (PC) для
AT90USB162?

Напрямую - нет. И зачем он?
Ненапрямую можно так:
Код
unsigned short GetPC()
{
    unsigned char *ptr=(unsigned char *)SP;
    ptr+=2;
    unsigned short result=*ptr--;
    result+=(*ptr)<<8;
    
    return result;
}
hd44780
Цитата(hakimulla @ Mar 28 2012, 21:50) *
Объясните, пожалуйста, как оформить индексный переход IJMP в программе
на Си.
Можно ли как-нибудь прочитать значение Program Counter (PC) для
AT90USB162?


А зачем вообще это в программе на Си?
Хотите применять ассемблерные переходы и сопутствующую хрень (типа значения PC) - пишите на асме.
В Си об этом компилятор думает. Это одна из его задач.
-SANYCH-
На языке С джампы можно сделать с помощью "goto". Хотя это не есть хорошо.
hakimulla
Цитата(_Артём_ @ Mar 28 2012, 22:27) *
Зачем именно IJMP?
Напрямую - нет. И зачем он?

Спасибо за подсказку, но можно ли это сделать без хитростей со стеком?
Мне нужно поднять производительность. Оптимизирую код ассемблерными
вставками. Прога большая - поэтому она на СИ.
Для выполнения команды IJMP в регистр Z нужно загружать адреса
меток, но как их получить в ассемблерной вставке? На момент компиляции
и линковки эти адреса меток известны. Вопрос в синтаксисе. Как их
задать и как к ним обратиться внутри ассемблерной вставки?


Сергей Борщ
QUOTE (hakimulla @ Mar 29 2012, 09:26) *
Для выполнения команды IJMP в регистр Z нужно загружать адреса
меток, но как их получить в ассемблерной вставке?
Какой компилятор-то хоть? В памяти отложилось, что GCC позволяет брать адреса от меток. Универсального средства нет - не Сишное это дело. Возможно стоить подумать и переписать полностью на асме отдельные узкие функции, а не мешать компилятору отдельными вставками?
=GM=
Цитата(hakimulla @ Mar 29 2012, 05:26) *
Для выполнения команды IJMP в регистр Z нужно загружать адреса
меток, но как их получить в ассемблерной вставке?

Попробуйте вот так
asm volatile ("ldi r30,lo8(pm(desiredLabel))");
asm volatile ("ldi r31,hi8(pm(desiredLabel))");
Alex11
Или поставьте параллельно ассемблерные метки: asm("AsmLabel1:"); и потом обращайтесь к ним.
prottoss
Вообще конечно это муть полная. Оптимизировать нужно алгоритм программы глобально а не "вылизывать код" в каком то одном месте. Но это сугубо мое мнение. Простите за оффтоп.
ReAl
Цитата(Сергей Борщ @ Mar 29 2012, 10:06) *
В памяти отложилось, что GCC позволяет брать адреса от меток.

Есть такое
http://electronix.ru/forum/index.php?showtopic=61802&hl=
http://electronix.ru/forum/index.php?showt...mp;#entry520130
alexeyv
В стандартной библиотеке Си есть файл setjmp.h, объявляющий макросы и тип данных для нелокальных переходов. Посмотри, может тебе это подойдет.
Navovvol
нужно просто избавиться от злого _delay_ms(...); wink.gif
_Pasha
Цитата(Navovvol @ Apr 3 2012, 16:00) *
нужно просто избавиться от злого _delay_ms(...); wink.gif


Или использовать Protothreads
Или РТОСь
Д_М
Не надо использовать IJMP, так как это грубо и вульгарно,
особенно с точки зрения программирования на С.
Используйте ICALL
void (*ptr)(void);//объявление пременной типа указатель на фунцию типа void
(*ptr)();//вызов функции типа void косвенно, через адрес в перенной

А лучше оформить массив с адресами функций
__flash void (*hnd_I2C_steps [])(void) = {I2C_step_0, I2C_step_1, I2C_step_2,
I2C_step_3, I2C_step_4, I2C_step_5};

(*hnd_I2C_steps [I2C_step])();
kolobok0
Цитата(hakimulla @ Mar 29 2012, 10:26) *
...в регистр Z нужно загружать адреса
меток, но как их получить в ассемблерной вставке?...эти адреса меток известны. Вопрос в синтаксисе. Как их
задать и как к ним обратиться внутри ассемблерной вставки?


я поддерживаю мысли тут высказанные:
1) гоу-ту на сях это зло. можно писать без него.
2) оптимизировать надо общий алгоритм а не портить жизнь оптимизатору(кстати он то включён правильно, с максимальным приоритетом по скорости выполнения???)
3) но если хочется на азме...

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

Пример(рыба):

CODE
.equ OFFSET_TO_SUBROUTINE_1 = (Subroutine_1 - PointGetTempAddres)
.equ OFFSET_TO_SUBROUTINE_2 = (Subroutine_2 - PointGetTempAddres)
rcall PointGetTempAddres
PointGetTempAddres:
pop YH
pop YL
;-- YH:YL = address in FLASH "PointGetTempAddres"

movw ZL,YL
adiw ZL,OFFSET_TO_SUBROUTINE_2
;-- call Subroutine_2
icall


movw ZL,YL
adiw ZL,OFFSET_TO_SUBROUTINE_1
;-- call Subroutine_1
icall

;-- stop
Halt:
rjmp Halt

Subroutine_1:
ldi r16,100
ret
Subroutine_2:
ldi r16,200
ret



прау слов:
этому подходу - в обед сто лет. впервые приенялся в вирусной технологии на заре досика...
если адреса подпрограмм дальше чем 64 байта, то команды adiw надо заменить на пару add,adc
оффсеты и базовый адрес на рантайме не обязательно складывать. можно эту требуху хранить и в памяти, в таблице (к примеру).
ReAl
Цитата(Д_М @ Aug 8 2012, 22:22) *
Не надо использовать IJMP, так как это грубо и вульгарно,
(*ptr)();//вызов функции типа void косвенно, через адрес в перенной
(*hnd_I2C_steps [I2C_step])();

По стандарту достаточно писать
Код
ptr();
hnd_I2C_steps[I2Cstep]();


А GNU-тые адреса меток и goto *ptr; отлично используются в соответствующей реализации protothreads.
И ничуть это не вульгарнее, чем адреса функций.
Maik-vs
Не вижу, чем ijmp отличается от goto?
ну хорошо, goto (label+index)

"IJMP: ...jump to the address pointed to by the Z pointer register ..."
kolobok0
Цитата(Maik-vs @ Aug 10 2012, 08:40) *
Не вижу, чем ijmp отличается от goto?...


в смысле не видите?
icall & ijmp
имеет смысл применять когда адресс не известен на момент компиляции.

Например "оверлейная" логика = прошиваете через самопрограмирование свой МК. Не затирая предыдущую прошивку. Явные адреса будут другие уже. Данный подход более помехоустойчив и востребован в пром. автоматике.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.