Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Функция __delay_cycles(...);
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Oleg_IT
Использую компилятор IAR. В фирменных исходниках применяют функцию __delay_cycles(...); Но в документации её нет. Только скудное упоминание в каком-то htm файле. Ведёт себя странно, компилятор её то оптимизирует, то оставляет.
Какие обции компилятора (или что ещё) нужно задействовать, что бы она всегда работала?
Какая максимальная задержка на ней возможна?
А может есть ещё какая-нибудь функция задержки на N мс?
nml
Цитата(Oleg_IT @ Jul 14 2005, 12:35)
Использую компилятор IAR. В фирменных исходниках применяют функцию __delay_cycles(...); Но в документации её нет. Только скудное упоминание в каком-то htm файле. Ведёт себя странно, компилятор её то оптимизирует, то оставляет.
*


Да ну что вы... вот из PDFки что идет в комплекте:

__delay_cycles __delay_cycles(unsigned long int);
Makes the compiler generate code that takes the given amount of cycles to perform, that is it inserts a time delay that lasts the specified number of cycles.
Note: The specified value must be a constant integer expression and not an expression that is evaluated at runtime.

на самом деле код будет сгенерирован примитивный - константу в регистр(ы) и вертушка(ки). В случае необходимости добавляются NOPы. Да вы напишите и посмотрите в листинг... Все сразу станет ясно.
VladislavS
Минимальная задержка один такт. Компилятор просто вставит NOP, который выполняется один такт. Если больше задержка, то будет подставлен код, выполняющийся указанное количество тактов. Действительно, посмотри листинг и все поймешь.
BVU
Практически все, кто работает на IAR пользуются этой встроенной функцией для создания задержки:

__delay_cycles __delay_cycles(unsigned long int);

Делаете такие определения:
//**********************************************
#define ClkFreq 16000000 // частота кварцевого резонатора или частота на которой работает контроллер.
#define _1us (unsigned long int)((ClkFreq / 1000000) / 1.25) // 1.25 погрешность на вызов функции для 1us.
#define _1ms (unsigned long int)(ClkFreq / 1000)
//**********************************************

Сами функции задержки соответственно могут выглядеть так:
void DelayMs(unsigned int d)
{
while(--d)__delay_cycles(_1ms);
}

void DelayUs(unsigned int d)
{
while(--d)__delay_cycles(_1us);
}

Делаете вызов той или другой функции в зависимости на сколько милисекунд или микросекунд делаете задержку.
Oleg_IT
Код функции я вижу в дисассемблере. Но вопрос в другом. Иногда эта функция вообще не вставляется. Почему компилятор её оптимизирует? На 480 мс работает, 1 с нет, частота проца 4 МГц. Ставлю подряд 3 вызова по 400 мс, нет их в коде. В другом месте программы подряд 5-10 вызовов работают. Что за чудеса?
BVU
Проблема до конца непонятна...
Тогда поясните из какого места в своей программы Вы пытаетесь сделать вызов подпрограммы задержки на 1000мс (1с)?
Oleg_IT
Точек задержек в программе несколько, в разных файлах проекта. В одних файлах они работают, а в других оптимизируются. В html-ках что-то сказано про это, но я с IAR-ом пока на ВЫ и не пойму в чём дело.
Максимальная задержка на (unsigned long int) нопов? (unsigned long int) в IAR-е 4 байта?
BVU
Стоят ли у Вас
#include <inavr.h>
#include <io'ваш тип контроллера'.h>
во всех файлах c/cpp?
Обычно все работает, как положено...
bialix
Цитата(Oleg_IT @ Jul 15 2005, 07:19)
Точек задержек в программе несколько, в разных файлах проекта. В одних файлах они работают, а в других оптимизируются. В html-ках что-то сказано про это, но я с IAR-ом пока на ВЫ и не пойму в чём дело.
Максимальная задержка на (unsigned long int) нопов? (unsigned long int) в IAR-е 4 байта?
*


Максимальная задержка -- посмотрите экспериментально, она существенно меньше доступного диапазона unsigned long, что-то в районе 480 тысяч если я еще помню.
С иаром идет комплект документации в pdf-файлах, ищите раздел Intrinsic function или что-то подобное
Oleg_IT
Цитата(BVU @ Jul 15 2005, 12:24)
Стоят ли у Вас
#include <inavr.h>
#include <io'ваш тип контроллера'.h>
во всех файлах c/cpp?
Обычно все работает, как положено...
*


Да, всё везде стоит.
В файле iccavr.htm говорится

AVRC0012: When compiling with optimization level 6 or higher, calls to the __delay_cycles intrinsic function were considered to be dead code, and were thus removed.

У меня оптимизация "минимум размер кода" может это мой случай? Но в других точках проекта эта функция работает.
BVU
Если все же не так критично отнестись к требованиям Вашей оптимизации попробуйте "поиграться" с отключением элементов оптимизации в разделе: Project->Options...->ICCAVR->Optimizations: Enabled optimizations. Возможно это даст какой то результат. Других вариантов пока нет, кроме как организовать задержку на таймерах, если они в данный момент не используются.
P.S. Непредвиденными последствиями после "оптимизации кода" страдают многие компиляторы, особенно это проявляется, когда производиться дезассемблирование кода. Дизассемблер не может восстановить участки исходника, т.к. они оптимизированы, а попросту говоря их не существует.
subver
Можно переписать функцию задержки с внутренней переменной, объявленной как volatile:

Код
void delayms(unsigned long ms)
{
volatile unsigned long dly;
       dly=ms;
       while(--dly) __delay_cycles(_1ms));
}


Тогда никакие оптимизации не страшны smile.gif
BVU
Согласен. Возможно, что вариант с применением volatile будет иметь положительный эффект(надо пробовать, практика подтвердит!).
http://www.kalinin.ru/programming/cpp/12_09_00.shtml
jimmi
sad.gif
subver
Цитата
//Наверное нужно так переписать

Да, конечно smile.gif ,
запарка вышла.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.