Перейти к содержанию
    

Указатели на функции

Может кто подскажет как бороться с зависанием полученного кода если в нем использованы указатели на функцию. :help:

Бо шаманить с лишними nop-ами уже порядком надоело... :angry2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может кто подскажет как бороться с зависанием полученного кода если в нем использованы указатели на функцию. :help:

Бо шаманить с лишними nop-ами уже порядком надоело... :angry2:

А в чем, собственно, проблема?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...и при чём тут nop'ы ?

Да я ж говорю - код зависает. Насколько я понял зависит от адреса вызываемой функции. Если по четному, то вызывается нормально, а если по нечетному - то ИНОГДА зависает.

Вот лишними nop-ами и приходится ровнять код вызываемых процедур (меняю одни, а подвисают другие....) - иначе не работает...

 

 

А если учесть, что эта зараза константы втыкает перед кодом, то по мере развития проекта перетыкивать nop-ы приходится регулярно :-(

Изменено пользователем ArtemKAD

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Крутой наверное компилятор. У меня-то неопытного всегда код ложился с чётного адреса. Причём даже все переходы в командах переходят только на чётный адрес. Но это... просто нечто. Может речь не об AVR?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А шут его знает, вроде АВР :-) ... Адрес естественно в словах.

Собственно патч по этому поводу у них на -про версию ВРОДИ-бы здесь:

ftp://ftp.iar.se/WWWfiles/avr/PatchReadme_412b.html

Так, что читайте "описание от производителей". Лично мне поймать условие когда 100% код виснет так и не удалось (не помог и асм полученного кода :( ).

 

А вот что делать с -евал версией?

Кстати, в 4,20 -евал этот баг все еще присутствует....

 

Да, и еще любопытный вопрос - если в 4.20 EV баг все еще есть, где гарантия, что тот патч решает проблему в полной версии?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы случаем не абсолютные ли адреса присваиваете указателям?

Если так, то нужно учитывать, что IAR все адреса меряет в байтах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А на самом деле, дайте зыркнуть на кусок кода, который Вас смущает. И желательно на его же листинг.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Примерно так:

// Структура таблицы ключевых слов

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(); - тоже самое, но так вроде стабильнее ;(

 

 

.............................................

 

К сожалению с кодом проблемы - надо перекомпилировать и много кода сюда писать....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Попробуйте перед созданием таблицы костант описать прототипы функций, которые потом в таблицу положите. Чтобы компилер сразу въехал, что это адрес функции, а не переменной.

 

2. Не понимаю, почему компилер разрешает указывать в этой структуре имя функции без префикса адреса. Вроде бы нужно типа такого: CR_LF,&fun_VOID, ...

 

Вспомнил ещё кое-что.

3. Когда процедуру/функцию предполагается вызывать через переменную/константу, то перед ней нужно писать: static void ... (...)

Во всяком случае на АРМе так. Может здеся тоже.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скомпилировал код версией 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Естественно есть прототипы описаные до констант - иначе компилятор выругается....

 

По поводу & - .........

 

 

Кстати, обращу внимание - это рабочий вариант. А вот если убрать nop из первой функции (длина которой станет 1 слово), то при вызове второй МК отправляется в "спячку" :( ...

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

 

Естественно с оптимизацией тут уже почти никак :( .

Вот если-бы можно было указать выравнивание кода процедур или явно указать их адреса....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кого будем бить за дезинформацию?

 

{"\r\n",fun_VOID,

"OK", fun_OK

};

Это же вроде отличается от оригинала?

 

И напоследок вопрос, который интересует меня:

__root __flash const struct token token_table[]

зачем в этой строке стоит "struct" ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, не придирайтесь :) в условии задачи эти строки не были определены. Да и не важны они.

Главное - адресации корректны, как адреса 9 (байтовый 18), так и адреса 10 (20).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скомпилировал код версией 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 мог просто удачно на тот момент перетасовать код.

 

Лучший критерий - программа в МК это очень ярко показывает....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...