|
Указатели на функции |
|
|
|
Jun 26 2006, 14:27
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Цитата(vet @ Jun 26 2006, 14:25)  ...и при чём тут nop'ы ? Да я ж говорю - код зависает. Насколько я понял зависит от адреса вызываемой функции. Если по четному, то вызывается нормально, а если по нечетному - то ИНОГДА зависает. Вот лишними nop-ами и приходится ровнять код вызываемых процедур (меняю одни, а подвисают другие....) - иначе не работает... А если учесть, что эта зараза константы втыкает перед кодом, то по мере развития проекта перетыкивать nop-ы приходится регулярно :-(
Сообщение отредактировал ArtemKAD - Jun 26 2006, 14:30
|
|
|
|
|
Jun 26 2006, 16:03
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
А шут его знает, вроде АВР :-) ... Адрес естественно в словах. Собственно патч по этому поводу у них на -про версию ВРОДИ-бы здесь: ftp://ftp.iar.se/WWWfiles/avr/PatchReadme_412b.htmlТак, что читайте "описание от производителей". Лично мне поймать условие когда 100% код виснет так и не удалось (не помог и асм полученного кода  ). А вот что делать с -евал версией? Кстати, в 4,20 -евал этот баг все еще присутствует.... Да, и еще любопытный вопрос - если в 4.20 EV баг все еще есть, где гарантия, что тот патч решает проблему в полной версии?
|
|
|
|
|
Jun 26 2006, 16:37
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Примерно так: // Структура таблицы ключевых слов 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(); - тоже самое, но так вроде стабильнее ;( ............................................. К сожалению с кодом проблемы - надо перекомпилировать и много кода сюда писать....
|
|
|
|
|
Jun 26 2006, 17:15
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Скомпилировал код версией 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
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
Jun 26 2006, 17:29
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Естественно есть прототипы описаные до констант - иначе компилятор выругается.... По поводу & - ......... Кстати, обращу внимание - это рабочий вариант. А вот если убрать nop из первой функции (длина которой станет 1 слово), то при вызове второй МК отправляется в "спячку"  ... Собственно так и "спасаюсь" - все адреса функций в таблице нопами делаю четными. Но иногда ( когда IAR "с оптимизирует" очередную константу перед этим кодом) приходится увеличивать константы "загоняя" адрес первой функции в нужный диапазон.... Естественно с оптимизацией тут уже почти никак  . Вот если-бы можно было указать выравнивание кода процедур или явно указать их адреса....
|
|
|
|
|
Jun 26 2006, 17:34
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Ну, не придирайтесь  в условии задачи эти строки не были определены. Да и не важны они. Главное - адресации корректны, как адреса 9 (байтовый 18), так и адреса 10 (20).
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
Jun 26 2006, 17:59
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Цитата(vet @ Jun 26 2006, 20:15)  Скомпилировал код версией 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 мог просто удачно на тот момент перетасовать код. Лучший критерий - программа в МК это очень ярко показывает....
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|