luben111 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Мне надо было сделать JMP к адресу 0200. Код такой: /*---------------------------------------------------------------------------*/ __C_task void main(void) /* the main code is here */ /*---------------------------------------------------------------------------*/ { Initialize(); if (testCode == 0) /* bad code */ { ((void (*)())0x200)(); /* jump to the fixed address (!!!! USES ICALL!!!!)*/ } if (busReceiveByte() == seq1) { if (busReceiveByte() == seq2) { loader(); } } ((void (*)())0x200)(); /*(!!!! USES IJMP!!!!) */ } Но на дизассемблере находил что первый JMP \"сделан\" из ICALL а второй из IJMP, что то вроде: LDI R30, 0x00 LDI R31, 0x02 ICALL LDI R30, 0x00 LDI R31, 0x02 IJMP Мне хотелось как нибудь чтобы компилятор поставил RJMP и не мучил меня с IJMP. Конечно я совсем не согласен когда он огорчил меня с ICALL. Слово goto точно подходить для меня но как установить этикет по адресу 0x200? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
luben111 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Мне надо было сделать JMP к адресу 0200. Код такой: /*---------------------------------------------------------------------------*/ __C_task void main(void) /* the main code is here */ /*---------------------------------------------------------------------------*/ { Initialize(); if (testCode == 0) /* bad code */ { ((void (*)())0x200)(); /* jump to the fixed address (!!!! USES ICALL!!!!)*/ } if (busReceiveByte() == seq1) { if (busReceiveByte() == seq2) { loader(); } } ((void (*)())0x200)(); /*(!!!! USES IJMP!!!!) */ } Но на дизассемблере находил что первый JMP \"сделан\" из ICALL а второй из IJMP, что то вроде: LDI R30, 0x00 LDI R31, 0x02 ICALL LDI R30, 0x00 LDI R31, 0x02 IJMP Мне хотелось как нибудь чтобы компилятор поставил RJMP и не мучил меня с IJMP. Конечно я совсем не согласен когда он огорчил меня с ICALL. Слово goto точно подходить для меня но как установить этикет по адресу 0x200? Камень - Tiny88. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Может так? GOTO desiredAddress; и сишный эквивалент конструкции .ORG 0x0200 desiredAddress: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба extern void Application(); __C_task void main(void) { .... Application(); .... } Линкеру объявить символ Application равный 0x200 - в командной строке или скрипте дописать -DApplication=200 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Student2, если вы изобретаете бутлоадер с проверкой на валидность прикладной задачи, то сообщаю по секрету, что бутлоадер пишется и компилируется отдельно от нее и управление бутлоадеру передается еще ДО вызова main в функции типа __low_level_init или как-то похоже. Почитайте документацию на компилятор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
luben111 0 30 октября, 2009 Опубликовано 30 октября, 2009 (изменено) · Жалоба extern void Application(); __C_task void main(void) { .... Application(); .... } Линкеру объявить символ Application равный 0x200 - в командной строке или скрипте дописать -DApplication=200 Спасибо Сергей,! Сейчас вижу RJMP и все работает как надо. Видно что у вас большой опыт в программирование! Изменено 30 октября, 2009 пользователем Student2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба extern void Application(); .... Линкеру объявить символ Application равный 0x200 - в командной строке или скрипте дописать -DApplication=200Сергей, можете объяснить почему так происходит? Т.е. почему в этом случае генрится jmp а не icall. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Сергей, можете объяснить почему так происходит? Т.е. почему в этом случае генрится jmp а не icall. Спасибо! А что тут загадочного? В первом случае компилятор предусматривает возврат, во втором - нет, т.к. вызов стоит в самом конце main. Т.е. "jump xxx" используется как более оптимальный аналог "call xxx; ret". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Сергей, можете объяснить почему так происходит? Т.е. почему в этом случае генрится jmp а не icall.Я не знаю, почему ИАР генерит ICALL для перехода по фиксированному адресу, заданному константой. Это очевидная недоработка и вопрос к его создателям. RJMP тоже сюрприз для меня, объянение aaarrr вполне правдоподобно. Обычно компилятор всталяет ®CALL, мы ведь описали Application() как обычную функцию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Я не знаю, почему ИАР генерит ICALL для перехода по фиксированному адресу, заданному константой. Это очевидная недоработка и вопрос к его создателям.Если я правильно помню, то avr-gcc ведёт себя так же. RJMP тоже сюрприз для меня, объяснение aaarrr вполне правдоподобно. Обычно компилятор вставляет ®CALL, мы ведь описали Application() как обычную функцию.Вот и я сильно удивился. Хорошо когда среди нас много догадливых сотоварищей:-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Если пишу (WinAVR): __attribute__((noreturn)) void testing_workmode(void) { } То вызов транслируется в: rcall .-1268 ; 0x130a4 <testing_workmode> Где я ошибаюсь, почему тоже call? :unsure: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 30 октября, 2009 Опубликовано 30 октября, 2009 · Жалоба Потому что (имхо) noreturn влияет на формирование пролога и эпилога функции (убирает сохранение используемых регистров), и не влияет на способ вызова этой функции. Она может быть вообще в другом модуле, и вызывающая функция понятия не имеет, что вызываемая - noreturn. Для проверки напишите __attribute__((noreturn)) void f2(void) { for (;;); } __attribute__((noreturn)) void f1(void) { f2(); } И получите warning на f1, что типа noreturn-функция похоже делает return. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
luben111 0 3 ноября, 2009 Опубликовано 3 ноября, 2009 · Жалоба Программа сейчас работает, но возникла вот такая проблема поддержки и структурной чистотой - адрес установлен в линкере и он не виден из компилятора. Если хочу использовать то же значение 0200 для установки других параметров мне надо заново установит в файле параметр (например #define SIZE_AREA 0x200). Поддержка кода усложнена и возможность сделать ошибки больше потому что надо менять данные на 2 места . Я попробовал #define SIZE_AREA 0x200 ..... ((void (*)())SIZE_AREA)(); Все работает прекрасно но нахожу в дизассемблере LDI R30, 00 LDI R31, 02 IJMP В итоге 4 байта больше! Подскажите как вернут добрый RJMP на месте и вместе с тем установить адрес SIZE_AREA внутри С файла - т.е. был доступен внутри С файла для дополнительные операции как __root __flash uint16_t MARKER @ (SIZE_AREA-2) = 0x434C; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 3 ноября, 2009 Опубликовано 3 ноября, 2009 · Жалоба Программа сейчас работает, но возникла вот такая проблема поддержки и структурной чистотой - адрес установлен в линкере и он не виден из компилятора.Почему? Преркрасно виден. Вы же получали адрес функции Application(). Вы можете этот адрес привести к любому нужному типу:extern void Application(); __C_task void main(void) { .... Application(); uint16_t Size_Area = (uint16_t)Application; .... } __root __flash uint16_t MARKER @ (SIZE_AREA-2) = 0x434C;Вам надо в скрипте линкера создать новый сегмент для этих данных и заставить линкер правильно расположить его: -DApplication=200 -Z(CODE)MARKER_seg#0-(Application-1) #pragma segment = "MARKER_seg" #pragma location = "MARKER_seg" __root __flash uint16_t MARKER = 0x434C; примерно так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 4 ноября, 2009 Опубликовано 4 ноября, 2009 · Жалоба Мне надо было сделать JMP к адресу 0200. Код такой: asm( "jmp 0x200"); - поймет любой компилятор AVR. Альтернативно можно определить макрос, который при переносе с платформы на платформу можно легко изменять: #define GoToApplication() asm("jmp 0x200") main { ... GoToApplication(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться