Полная версия этой страницы:
Функция __delay_cycles(...);
Oleg_IT
Jul 14 2005, 09:35
Использую компилятор IAR. В фирменных исходниках применяют функцию __delay_cycles(...); Но в документации её нет. Только скудное упоминание в каком-то htm файле. Ведёт себя странно, компилятор её то оптимизирует, то оставляет.
Какие обции компилятора (или что ещё) нужно задействовать, что бы она всегда работала?
Какая максимальная задержка на ней возможна?
А может есть ещё какая-нибудь функция задержки на N мс?
Цитата(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
Jul 14 2005, 12:19
Минимальная задержка один такт. Компилятор просто вставит NOP, который выполняется один такт. Если больше задержка, то будет подставлен код, выполняющийся указанное количество тактов. Действительно, посмотри листинг и все поймешь.
Практически все, кто работает на 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
Jul 14 2005, 13:30
Код функции я вижу в дисассемблере. Но вопрос в другом. Иногда эта функция вообще не вставляется. Почему компилятор её оптимизирует? На 480 мс работает, 1 с нет, частота проца 4 МГц. Ставлю подряд 3 вызова по 400 мс, нет их в коде. В другом месте программы подряд 5-10 вызовов работают. Что за чудеса?
Проблема до конца непонятна...
Тогда поясните из какого места в своей программы Вы пытаетесь сделать вызов подпрограммы задержки на 1000мс (1с)?
Oleg_IT
Jul 15 2005, 05:19
Точек задержек в программе несколько, в разных файлах проекта. В одних файлах они работают, а в других оптимизируются. В html-ках что-то сказано про это, но я с IAR-ом пока на ВЫ и не пойму в чём дело.
Максимальная задержка на (unsigned long int) нопов? (unsigned long int) в IAR-е 4 байта?
Стоят ли у Вас
#include <inavr.h>
#include <io'ваш тип контроллера'.h>
во всех файлах c/cpp?
Обычно все работает, как положено...
bialix
Jul 15 2005, 08:45
Цитата(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
Jul 18 2005, 06:20
Цитата(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.
У меня оптимизация "минимум размер кода" может это мой случай? Но в других точках проекта эта функция работает.
Если все же не так критично отнестись к требованиям Вашей оптимизации попробуйте "поиграться" с отключением элементов оптимизации в разделе: Project->Options...->ICCAVR->Optimizations: Enabled optimizations. Возможно это даст какой то результат. Других вариантов пока нет, кроме как организовать задержку на таймерах, если они в данный момент не используются.
P.S. Непредвиденными последствиями после "оптимизации кода" страдают многие компиляторы, особенно это проявляется, когда производиться дезассемблирование кода. Дизассемблер не может восстановить участки исходника, т.к. они оптимизированы, а попросту говоря их не существует.
subver
Jul 19 2005, 02:44
Можно переписать функцию задержки с внутренней переменной, объявленной как
volatile:
Код
void delayms(unsigned long ms)
{
volatile unsigned long dly;
dly=ms;
while(--dly) __delay_cycles(_1ms));
}
Тогда никакие оптимизации не страшны
Согласен. Возможно, что вариант с применением volatile будет иметь положительный эффект(надо пробовать, практика подтвердит!).
http://www.kalinin.ru/programming/cpp/12_09_00.shtml
subver
Jul 21 2005, 03:09
Цитата
//Наверное нужно так переписать
Да, конечно

,
запарка вышла.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.