artemkad 88 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Может кто подскажет как бороться с зависанием полученного кода если в нем использованы указатели на функцию. Бо шаманить с лишними nop-ами уже порядком надоело... :angry2: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bill 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Может кто подскажет как бороться с зависанием полученного кода если в нем использованы указатели на функцию. Бо шаманить с лишними nop-ами уже порядком надоело... :angry2: А в чем, собственно, проблема? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба ...и при чём тут nop'ы ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 88 26 июня, 2006 Опубликовано 26 июня, 2006 (изменено) · Жалоба ...и при чём тут nop'ы ? Да я ж говорю - код зависает. Насколько я понял зависит от адреса вызываемой функции. Если по четному, то вызывается нормально, а если по нечетному - то ИНОГДА зависает. Вот лишними nop-ами и приходится ровнять код вызываемых процедур (меняю одни, а подвисают другие....) - иначе не работает... А если учесть, что эта зараза константы втыкает перед кодом, то по мере развития проекта перетыкивать nop-ы приходится регулярно :-( Изменено 26 июня, 2006 пользователем ArtemKAD Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Крутой наверное компилятор. У меня-то неопытного всегда код ложился с чётного адреса. Причём даже все переходы в командах переходят только на чётный адрес. Но это... просто нечто. Может речь не об AVR? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 88 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба А шут его знает, вроде АВР :-) ... Адрес естественно в словах. Собственно патч по этому поводу у них на -про версию ВРОДИ-бы здесь: ftp://ftp.iar.se/WWWfiles/avr/PatchReadme_412b.html Так, что читайте "описание от производителей". Лично мне поймать условие когда 100% код виснет так и не удалось (не помог и асм полученного кода :( ). А вот что делать с -евал версией? Кстати, в 4,20 -евал этот баг все еще присутствует.... Да, и еще любопытный вопрос - если в 4.20 EV баг все еще есть, где гарантия, что тот патч решает проблему в полной версии? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Вы случаем не абсолютные ли адреса присваиваете указателям? Если так, то нужно учитывать, что IAR все адреса меряет в байтах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба А на самом деле, дайте зыркнуть на кусок кода, который Вас смущает. И желательно на его же листинг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 88 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Примерно так: // Структура таблицы ключевых слов struct token { const char __flash *str; void (*fun)(void); }; // Таблица ключевых слов и их обработчиков __root __flash const struct token token_table[] = {CR_LF,fun_VOID, OK, fun_OK, .............................................................. } void fun_VOID(void) { asm("nop"); // Лекарство от зависания :( !!! return; } /* Обработчик "OK" */ void fun_OK(void) { if(error_cnt) error_cnt --; (*fun_OK_addr)(); // Запуск обработчика по указателю asm("nop"); // Лекарство от зависания :( !!! return; } .......................................... // а вот так вызывается в коде из таблицы.... void (*p)(void); Response--; p = token_table[Response].fun; (*p)(); // token_table[Response].fun(); - тоже самое, но так вроде стабильнее ;( ............................................. К сожалению с кодом проблемы - надо перекомпилировать и много кода сюда писать.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 26 июня, 2006 Опубликовано 26 июня, 2006 (изменено) · Жалоба 1. Попробуйте перед созданием таблицы костант описать прототипы функций, которые потом в таблицу положите. Чтобы компилер сразу въехал, что это адрес функции, а не переменной. 2. Не понимаю, почему компилер разрешает указывать в этой структуре имя функции без префикса адреса. Вроде бы нужно типа такого: CR_LF,&fun_VOID, ... Вспомнил ещё кое-что. 3. Когда процедуру/функцию предполагается вызывать через переменную/константу, то перед ней нужно писать: static void ... (...) Во всяком случае на АРМе так. Может здеся тоже. Изменено 26 июня, 2006 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Скомпилировал код версией 4.11А. NOP'ы повыкидывал. Как и ожидалось, структуры инициализируются правильно, указатели указывают, куда нужно. void (*fun_OK_addr)(); __root __flash const struct token token_table[] = {"\r\n",fun_VOID, "OK", fun_OK }; 0000000A: 0004 0000000C: 0009; верно, байтовый адрес fun_VOID - 18 0000000E: 0007 00000010: 000A; верно, байтовый адрес fun_OK - 20 fun_OK_addr = fun_VOID; 00000018: E009 ldi r16,#9 0000001A: E010 ldi r17,#0 0000001C: EAE0 ldi r30,#160 0000001E: E0F0 ldi r31,#0 00000020: 8300 st z,r16 00000022: 8311 std z+1,r17 (*fun_OK_addr)(); 00000024: EAA0 ldi r26,#160 00000026: E0B0 ldi r27,#0 00000028: 91ED ld r30,x+ 0000002A: 91FC ld r31,x 0000002C: 9509 icall fun_OK_addr = token_table[0].fun; 0000002E: E0EC ldi r30,#12 00000030: E0F0 ldi r31,#0 00000032: 9105 lpm r16,z+ 00000034: 9114 lpm r17,z 00000036: EAE0 ldi r30,#160 00000038: E0F0 ldi r31,#0 0000003A: 8300 st z,r16 0000003C: 8311 std z+1,r17 (*fun_OK_addr)(); 0000003E: EAA0 ldi r26,#160 00000040: E0B0 ldi r27,#0 00000042: 91ED ld r30,x+ 00000044: 91FC ld r31,x 00000046: 9509 icall (*token_table[0].fun)(); 00000048: E0EC ldi r30,#12 0000004A: E0F0 ldi r31,#0 0000004C: 9105 lpm r16,z+ 0000004E: 9114 lpm r17,z 00000050: 01F8 movw r30,r16 00000052: 9509 icall Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 88 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Естественно есть прототипы описаные до констант - иначе компилятор выругается.... По поводу & - ......... Кстати, обращу внимание - это рабочий вариант. А вот если убрать nop из первой функции (длина которой станет 1 слово), то при вызове второй МК отправляется в "спячку" :( ... Собственно так и "спасаюсь" - все адреса функций в таблице нопами делаю четными. Но иногда ( когда IAR "с оптимизирует" очередную константу перед этим кодом) приходится увеличивать константы "загоняя" адрес первой функции в нужный диапазон.... Естественно с оптимизацией тут уже почти никак :( . Вот если-бы можно было указать выравнивание кода процедур или явно указать их адреса.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Кого будем бить за дезинформацию? {"\r\n",fun_VOID, "OK", fun_OK }; Это же вроде отличается от оригинала? И напоследок вопрос, который интересует меня: __root __flash const struct token token_table[] зачем в этой строке стоит "struct" ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Ну, не придирайтесь :) в условии задачи эти строки не были определены. Да и не важны они. Главное - адресации корректны, как адреса 9 (байтовый 18), так и адреса 10 (20). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 88 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Скомпилировал код версией 4.11А. NOP'ы повыкидывал. Как и ожидалось, структуры инициализируются правильно, указатели указывают, куда нужно. Наблюдая как этот код зависает в МК мне от его правильности как-то не легче :( ... void (*fun_OK_addr)(); __root __flash const struct token token_table[] = {"\r\n",fun_VOID, "OK", fun_OK }; 0000000A: 0004 0000000C: 0009; верно, байтовый адрес fun_VOID - 18 0000000E: 0007 00000010: 000A; верно, байтовый адрес fun_OK - 20 fun_OK_addr = fun_VOID; 00000018: E009 ldi r16,#9 0000001A: E010 ldi r17,#0 0000001C: EAE0 ldi r30,#160 0000001E: E0F0 ldi r31,#0 00000020: 8300 st z,r16 00000022: 8311 std z+1,r17 (*fun_OK_addr)(); 00000024: EAA0 ldi r26,#160 00000026: E0B0 ldi r27,#0 00000028: 91ED ld r30,x+ 0000002A: 91FC ld r31,x 0000002C: 9509 icall fun_OK_addr = token_table[0].fun; 0000002E: E0EC ldi r30,#12 00000030: E0F0 ldi r31,#0 00000032: 9105 lpm r16,z+ 00000034: 9114 lpm r17,z 00000036: EAE0 ldi r30,#160 00000038: E0F0 ldi r31,#0 0000003A: 8300 st z,r16 0000003C: 8311 std z+1,r17 (*fun_OK_addr)(); 0000003E: EAA0 ldi r26,#160 00000040: E0B0 ldi r27,#0 00000042: 91ED ld r30,x+ 00000044: 91FC ld r31,x 00000046: 9509 icall (*token_table[0].fun)(); 00000048: E0EC ldi r30,#12 0000004A: E0F0 ldi r31,#0 0000004C: 9105 lpm r16,z+ 0000004E: 9114 lpm r17,z 00000050: 01F8 movw r30,r16 00000052: 9509 icall Ну предположим там был (*token_table[Response].fun)() Поэтому в настоящем коде вместо ldi константа было ldi r30, 0x02 ldi r31, 0x02 mov r16, r24 ldi r17, 0 lsl r16 rol r17 lsl r16 rol r17 add r30,r16 adc r31,r17 и далее те самые lpm r16,z+ lpm r17,z movw r26,r16 movw r30,r26 icall но это дела не меняет - если все адреса функций в таблице четные то программа не висла, если в разнобой - певый же нечетный чаще всего зависал... Причем больше всего бесило, что иногда и не зависал. Хотя сейчас я понимаю, что оптимизатор IARa мог просто удачно на тот момент перетасовать код. Лучший критерий - программа в МК это очень ярко показывает.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться