реклама на сайте
подробности

 
 
> #define DELAY(CY), Как задать выбор вариантов определения?
ViKo
сообщение Apr 9 2014, 04:44
Сообщение #1


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Конкретно, хочу, чтобы
DELAY(1) превратилось в
__nop()
DELAY(2)
__nop();
__nop()
...
DELAY(20)
for(uint32_t i = 4; i--; ) __nop()
Варианты найдутся. Вопрос, как их задать в одном макроопределении?
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
Сергей Борщ
сообщение Apr 9 2014, 05:34
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Код
#define DELAY(cyсles) if((cycles) == 1) asm volatile("nop"); else if((cycles)==2) { asm volatile ("nop\n\tnop"); } else ....
Если параметр константа и включена хотя бы минимальная оптимизация - компилятор выкинет проверку и лишние ветки.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 9 2014, 06:40
Сообщение #3


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Сергей Борщ @ Apr 9 2014, 09:34) *
Если параметр константа и включена хотя бы минимальная оптимизация - компилятор выкинет проверку и лишние ветки.
В кейле не прокатывало (пару лет назад пробовал). В GCC да.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 9 2014, 06:50
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Код
#define DELAY_CY(CY) \
  if (CY == 1)       \
    __nop()           \
  else if (CY == 2) {  \
    __nop();          \
    __nop();           \
  }

Получается в Кейле. При всех оптимизациях.
Хотел было рекурсивный вызов макро сделать. Нельзя.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 9 2014, 06:54
Сообщение #5


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Вот это в 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);


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 9 2014, 07:02
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(demiurg_spb @ Apr 9 2014, 08:40) *
В кейле не прокатывало (пару лет назад пробовал). В GCC да.
Пробовал лет 8 назад в ИАРе - там тоже работало. Неужели кейл не умел выкидывать мертвый код? У меня о нем тогда сложилось довольно хорошее впечатление, хоть и работал с ним совсем недолго.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 9 2014, 07:11
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Сергей Борщ @ Apr 9 2014, 11:02) *
Пробовал лет 8 назад в ИАРе - там тоже работало. Неужели кейл не умел выкидывать мертвый код? У меня о нем тогда сложилось довольно хорошее впечатление, хоть и работал с ним совсем недолго.
Сам был неприятно удивлён. Также как и отсутствием возможности вычисления на этапе компиляции cos(const) и т.д.
Именно это меня и сподвигло перейти на gcc и на arm платформе.
Пробовал на ARM C/C++ Compiler, 4.1


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 9 2014, 15:23
Сообщение #8


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Сотворил.
CODE

/*!****************************************************************************
@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--); }
Go to the top of the page
 
+Quote Post
Shamil
сообщение Apr 10 2014, 01:18
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 160
Регистрация: 23-12-04
Из: Уфа
Пользователь №: 1 631



Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор,
иначе, если применить его после if, будут неприятности.
Код
do
{
    Текст макроса.
}
while(0)

Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 10 2014, 02:24
Сообщение #10


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Shamil @ Apr 10 2014, 04:18) *
Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор,
иначе, если применить его после if, будут неприятности.
Код
do
{
    Текст макроса.
}
while(0)

Помню-помню... разговоры. Но я не вставляю после if.
P.S. у меня же все ветки в скобках { }, может, их хватит? rolleyes.gif

Другой вопрос всплыл - Как можно определить, с какими параметрами оптимизации задана копмиляция? Что можно было в одном случае в формулу подсунуть 5, а в другом 6.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 10 2014, 02:58
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Apr 10 2014, 04:24) *
Как можно определить, с какими параметрами оптимизации задана копмиляция?
А какой у нас компилятор?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 10 2014, 03:01
Сообщение #12


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Apr 10 2014, 05:58) *
А какой у нас компилятор?

Кейловский, ARMCC из uVision.
Там из списка выбирается -O0... -O3, отдельно галка -Otime.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2014, 03:15
Сообщение #13


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ViKo @ Apr 10 2014, 07:01) *
Не с той стороны подходите к решению задачи.
Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку.
В моём примере она имеется в каком-то виде.
И будет вам счастьеsm.gif

Цитата(Shamil @ Apr 10 2014, 05:18) *
Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор
+1


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 10 2014, 03:24
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Apr 10 2014, 05:01) *
Кейловский, ARMCC из uVision.
Я пас.

Цитата(demiurg_spb @ Apr 10 2014, 05:15) *
Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку.
Угу. Вместо последнего цикла. А потом вспомнить про прерывания и забить на эту погрешность.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 10 2014, 06:51
Сообщение #15


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата
Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку.

Взялся было... Но мне нужно загрузить переменную цикла в регистр. Где гарантия, это это регистр ничем не занят? laughing.gif

Цитата(Сергей Борщ @ Apr 10 2014, 06:24) *
Угу. Вместо последнего цикла. А потом вспомнить про прерывания и забить на эту погрешность.

Да, прерывания меня уже смутили, при проверке на больших длительностях. Но эта функция написана для коротких интервалов. Конкретно, для работы с двухстрочным ЖКИ. А для "серьезных" задержек у меня есть макро с таймером. И др.

Что-то "не лезет" 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.gif
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 21:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.0148 секунд с 7
ELECTRONIX ©2004-2016