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

IAR-CVAVR и глюки с прерываниями

В CVAVR был с помощью CodeWizardAVR проект, в котором по таймеру менялось значение одного из портов. Практически без изменений этот же проект был перенесен в IAR. При тестировании в AVRStudio4 обе программы вели себя полностью одинаково и корректно. Однако в микроконтроллере корректно работала только программа, написанная в CVAVR. В IAR программа выполнялась, но без вызова прерывания. Контроллер прошивался в обоих случаях через CVAVR STK200. Поскольку в симуляторе обе программы работали корректно, то ошибка скорее всего возникает при создании hex файла. Формат вывода выставлен как Intel standart.

В чем может быть проблема и какие настройки надо изменить, чтобы все работало нормально?

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


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

В чем может быть проблема
В программе и настройках. Посмотрите размер стеков, хотя он не должен влиять на вызов прерываний, скорее на работоспособность всей программы. Показывайте код, будем смотреть. Можете выкинуть все, кроме инициализации, прерывания и пустого цикла в main(). Только сначала сами убедитесь, что в таком виде программа не работает. Если вдруг заработает - постепенно добваляйте код, пока не перестанет работать.

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


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

Показывайте код, будем смотреть.

Спасибо за участие и советы. Привожу код для CVAVR и IAR. Код, по-моему, проще не куда. Я его сделал после того, как два дня убил на отладку своей программы.

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

 

IAR:

...

 

CVAVR:

 

...

 

Исправил, больше так не делайте.

IgorKossak

src.rar

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

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


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

А вы листинг смотрели? 99%, что цикл while (flag); ассемблировался в RJMP $-2. А ошибка ваша вот: volatile unsigned char flag;

P.S. А такие большие куски кода надо прикладывать в виде файлов. Исправьте, пока не поздно, а то модераторы по шапке надают

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


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

А вы листинг смотрели? 99%, что цикл while (flag); ассемблировался в RJMP $-2. А ошибка ваша вот: volatile unsigned char flag;

P.S. А такие большие куски кода надо прикладывать в виде файлов. Исправьте, пока не поздно, а то модераторы по шапке надают

 

Огромное спасибо, буду пробовать.

Листинг, конечно, смотрел, я его сам и писал :biggrin:. По поводу

while(flag);

: если он неправильно ассемблируется, то что можно использовать вместо него для задержки до срабатывания прерывания?

По поводу ошибки: никогда не думал, что оптимизация может зайти так далеко. :crying:

 

Можно еще вопросик не по теме? :help:

У меня в целевой программе есть переменная типа Int. При передачи нужно как можно быстрее передавать побайтно значение этой переменной. В настоящий момент данные передаются следующим образом:

PORTA=A_int; ... PORTA=(A_int>>8) ...

. Как мне кажется, такая передача не оптимальна. По-идее, можно зарезервировать определенные регистры под переменную и выводить уже регистры:

PORTA=r15; ... PORTA=r15

. Подскажите пожалуйста, будет ли такой алгоритм более быстрым по сравнению с первым и каким образом можно зарезервировать регистры под переменную? Когда я пытался осуществить резервирование, IAR говорил что-то о необходимости в изменении каких-то настроек. Заранее благодарен.

 

P.S. За большие вставки извиняюсь, не знал, больше не повторится.

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


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

в опциях проекта C/C++ Compiler - Code - поле Register utilization

резервируешь сколько тебе нужно байт (сильно не увлекайся)

а потом в тексте пишешь что-то вроде

__regvar __no_init unsigned char FLASH @ 15; // переменная FLASH в регистре 15

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


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

Листинг, конечно, смотрел, я его сам и писал :biggrin:.
Недопонял. Листинг генерит компилятор - там ассемблерный текст, в который скомпилился ваш исходник.
По поводу
while(flag);

: если он неправильно ассемблируется, то что можно использовать вместо него для задержки до срабатывания прерывания?

Он компилируется правильно. Вы неправильно написали исходный код - не указали компилятору (с помощью квалификатора volatile), что flag может в любой момент измениться где-то еще (в прерывании). Он видит, что перед циклом вы присвоили flag=1 и дальше сорвершенно правомерно решает, что поскольку внутри цикла flag не меняется, то и проверять его снова не имеет смысла. И поэтому цикл вырождается в бесконечный. Если же вы укажите flag как volatile - компилятор будет вынужден на каждом проходе цикла считывать flag снова. И ваш цикл будет работать так, как вы и задумали.

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


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

Недопонял. Листинг генерит компилятор - там ассемблерный текст, в который скомпилился ваш исходник.

У нас разные понятия о листинге программы. Поскольку я не силен в ассемблере (знаю только в общих чертах), то для меня листинг - это то, что я написал на C.

Спасибо за разъяснения по ошибке. Теперь более понятно, получается, что CVAVR по-умолчанию считает все переменные volatile и поэтому работает правильно. Удручает при этом, что в симуляторе обе программы ведут себя одинаково. Впредь буду все глобальные переменные, используемые в прерывании, отмечать как volatile. Еще раз спасибо.

 

 

в опциях проекта C/C++ Compiler - Code - поле Register utilization

резервируешь сколько тебе нужно байт (сильно не увлекайся)

а потом в тексте пишешь что-то вроде

__regvar __no_init unsigned char FLASH @ 15; // переменная FLASH в регистре 15

 

Мне нужна всего одна переменная типа int. Спасибо за разъяснения, теперь понятно где чего резервировать.

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


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

У нас разные понятия о листинге программы. Поскольку я не силен в ассемблере (знаю только в общих чертах), то для меня листинг - это то, что я написал на C.
Во избежание дальнейших недоразумений - это называется исходным текстом, исходниками, source. А ассемблер надо знать хотя бы на уровне чтения листингов со словарем - т.е посмотреть, что же нагенерил компилятор и поставив себя на место процессора прокрутить в голове интересующий участок кода.
получается, что CVAVR по-умолчанию считает все переменные volatile и поэтому работает правильно.
У него просто более слабый опримизатор, видимо не способный вынести из цикла вычисления, которые не влияют на остальные операции в цикле.
Удручает при этом, что в симуляторе обе программы ведут себя одинаково.
В симуляторе в обоих программах вызывается прерывание? Тогда надо копать глубже. Если не победите к понедельнику, гляну на результат компиляции.

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


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

У меня в целевой программе есть переменная типа Int. При передачи нужно как можно быстрее передавать побайтно значение этой переменной. В настоящий момент данные передаются следующим образом:
PORTA=A_int; ... PORTA=(A_int>>8) ...

.

 

Можно не волноваться по данному поводу. IAR правильно поймёт вашу операцию и скомпилирует это в две команды МК. То есть эти два оператора будут соответствовать двум операторам ассемблера и выполнятся за два такта. Ну не считая конечно времени обращения к ячейкам. А время обращения зависит от типа применённой переменной A_int. Если она статическая, то время уйдёт примерно 7 тактов. Если это у вас в п/п, то переменная будет размещена в регистрах.

 

PS: Ассемблер не страшен. :biggrin: Можно посмотреть результирующий листинг и посмотреть описание инструкций МК.

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


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

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

С volatile все заработало. На самом деле в симуляторе я смотрел cof файл. В этом, наверное, и кроется результат несовпадения.

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


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

У меня в целевой программе есть переменная типа Int. При передачи нужно как можно быстрее передавать побайтно значение этой переменной.

Как вариант - использование объединения:

union{
  uchar Bytes[2]; 
  uint Word; 
}Val16;
...
//где-то в программе...
Val16.Word=0x1234;
PORTA=Val16.Bytes[0];  // PORTA=0x34 
PORTB=Val16.Bytes[1];  // PORTB=0x12

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


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

Как вариант - использование объединения:
И как это может ускорить выдачу в порт?

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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