ViKo 1 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба Конкретно, хочу, чтобы DELAY(1) превратилось в __nop() DELAY(2) __nop(); __nop() ... DELAY(20) for(uint32_t i = 4; i--; ) __nop() Варианты найдутся. Вопрос, как их задать в одном макроопределении? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба #define DELAY(cyсles) if((cycles) == 1) asm volatile("nop"); else if((cycles)==2) { asm volatile ("nop\n\tnop"); } else .... Если параметр константа и включена хотя бы минимальная оптимизация - компилятор выкинет проверку и лишние ветки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба Если параметр константа и включена хотя бы минимальная оптимизация - компилятор выкинет проверку и лишние ветки.В кейле не прокатывало (пару лет назад пробовал). В GCC да. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба #define DELAY_CY(CY) \ if (CY == 1) \ __nop() \ else if (CY == 2) { \ __nop(); \ __nop(); \ } Получается в Кейле. При всех оптимизациях. Хотел было рекурсивный вызов макро сделать. Нельзя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба Вот это в GCC отлично рабртает, а в кейле, когда я пробовал - облом... Интересно, с тех пор что-нибудь изменилось? //============================================================================= static __inline void delay_8cycles(uint32_t x) { /* subs r0 bcs exit mrs r0, primask exit: bx lr */ while (x--) // 4 SUBS + BCS + PIPLINE_RELOAD { __NOP(); // 5 __NOP(); // 6 __NOP(); // 7 __NOP(); // 8 } } //============================================================================= static __inline void delay_cycles(uint32_t x) { uint32_t rem = x&7; // x%8 if (rem==1) {__NOP();} else if (rem==2) {__NOP();__NOP();} else if (rem==3) {__NOP();__NOP();__NOP();} else if (rem==4) {__NOP();__NOP();__NOP();__NOP();} else if (rem==5) {__NOP();__NOP();__NOP();__NOP();__NOP();} else if (rem==6) {__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();} else if (rem==7) {__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();} if ((x/=8)) delay_8cycles(x); } //============================================================================= static __inline void delay_ns (double ns) {delay_cycles(ns/((double)1e9/(double)F_CPU) + 0.5);} void delay_us (uint32_t us); void delay_ms (uint32_t ms); void delay_sec (uint32_t sec); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба В кейле не прокатывало (пару лет назад пробовал). В GCC да.Пробовал лет 8 назад в ИАРе - там тоже работало. Неужели кейл не умел выкидывать мертвый код? У меня о нем тогда сложилось довольно хорошее впечатление, хоть и работал с ним совсем недолго. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба Пробовал лет 8 назад в ИАРе - там тоже работало. Неужели кейл не умел выкидывать мертвый код? У меня о нем тогда сложилось довольно хорошее впечатление, хоть и работал с ним совсем недолго.Сам был неприятно удивлён. Также как и отсутствием возможности вычисления на этапе компиляции cos(const) и т.д. Именно это меня и сподвигло перейти на gcc и на arm платформе. Пробовал на ARM C/C++ Compiler, 4.1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 апреля, 2014 Опубликовано 9 апреля, 2014 · Жалоба Сотворил. /*!**************************************************************************** @brief Delay program loop @param NS - время задержки в ns @note Параметр округляется до ближайшего не меньшего, кратного тактам @note 5 тактов в цикле при оптимизации -O3 (-Otime), -O2 6 тактов в цикле при оптимизации -O1 и -O0 + 1 такт перед циклом при оптимизации -O0 @note При проверке условия выхода из цикла компиприлятор отбрасывает одиночный цикл, поэтому счет циклов начинается с 2 @note Формула: D = 5 * (CY5 + 1) + Nnop; 6 * (CY5 + 1) + Nnop (+ 1) */ #define SYSCLK_MHZ 72 #define NS2CY(NS) ((NS * SYSCLK_MHZ + 999) / 1000) #define DELAY_NS(NS) DELAY_CY(NS2CY(NS)) #define DELAY_CY(CY) \ if (CY % 5 == 1) \ { __nop(); } \ else if (CY % 5 == 2) \ { __nop(), __nop(); } \ else if (CY % 5 == 3) \ { __nop(), __nop(), __nop(); } \ else if (CY % 5 == 4) \ { __nop(), __nop(), __nop(), __nop(); } \ if (CY > 4 && CY < 10) \ { __nop(), __nop(), __nop(), __nop(), __nop(); } \ else if (CY >= 10) \ { __nop(); uint32_t CY5 = (CY - 5) / 5; do { __nop(); } while (CY5--); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shamil 2 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор, иначе, если применить его после if, будут неприятности. do { Текст макроса. } while(0) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор, иначе, если применить его после if, будут неприятности. do { Текст макроса. } while(0) Помню-помню... разговоры. Но я не вставляю после if. P.S. у меня же все ветки в скобках { }, может, их хватит? :rolleyes: Другой вопрос всплыл - Как можно определить, с какими параметрами оптимизации задана копмиляция? Что можно было в одном случае в формулу подсунуть 5, а в другом 6. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба Как можно определить, с какими параметрами оптимизации задана копмиляция?А какой у нас компилятор? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба А какой у нас компилятор? Кейловский, ARMCC из uVision. Там из списка выбирается -O0... -O3, отдельно галка -Otime. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба Не с той стороны подходите к решению задачи. Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку. В моём примере она имеется в каком-то виде. И будет вам счастье:) Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор+1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба Кейловский, ARMCC из uVision.Я пас. Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку.Угу. Вместо последнего цикла. А потом вспомнить про прерывания и забить на эту погрешность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 апреля, 2014 Опубликовано 10 апреля, 2014 · Жалоба Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку. Взялся было... Но мне нужно загрузить переменную цикла в регистр. Где гарантия, это это регистр ничем не занят? :laughing: Угу. Вместо последнего цикла. А потом вспомнить про прерывания и забить на эту погрешность. Да, прерывания меня уже смутили, при проверке на больших длительностях. Но эта функция написана для коротких интервалов. Конкретно, для работы с двухстрочным ЖКИ. А для "серьезных" задержек у меня есть макро с таймером. И др. Что-то "не лезет" asm, не принимает его компилятор! В чем дело? #define DELAY_CY(CY) \ if (CY >= 10) \ { __asm {"MOVS R1,#CY; LOOP: SUBS R1,R1,#1; BEQ LOOP;"} } (407): error: #2901: Expected an inline assembly instruction (407): error: #3081: expected end of line or a ";" Никак. Из ARM документа: The inline assembler supports ARM assembly language only. The embedded assembler can be used for Thumb and Thumb-2 support. Отдельно писать? void DelAsm(uint32_t CY) { uint32_t Reg; __asm { MOVS Reg, #CY LOOP: SUBS Reg, Reg, #1 BEQ LOOP } } :yeah: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться