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

Конкретно, хочу, чтобы

DELAY(1) превратилось в

__nop()

DELAY(2)

__nop();

__nop()

...

DELAY(20)

for(uint32_t i = 4; i--; ) __nop()

Варианты найдутся. Вопрос, как их задать в одном макроопределении?

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


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

#define DELAY(cyсles) if((cycles) == 1) asm volatile("nop"); else if((cycles)==2) { asm volatile ("nop\n\tnop"); } else ....

Если параметр константа и включена хотя бы минимальная оптимизация - компилятор выкинет проверку и лишние ветки.

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


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

Если параметр константа и включена хотя бы минимальная оптимизация - компилятор выкинет проверку и лишние ветки.
В кейле не прокатывало (пару лет назад пробовал). В GCC да.

 

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


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

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

Получается в Кейле. При всех оптимизациях.

Хотел было рекурсивный вызов макро сделать. Нельзя.

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


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

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

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


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

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

 

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


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

Пробовал лет 8 назад в ИАРе - там тоже работало. Неужели кейл не умел выкидывать мертвый код? У меня о нем тогда сложилось довольно хорошее впечатление, хоть и работал с ним совсем недолго.
Сам был неприятно удивлён. Также как и отсутствием возможности вычисления на этапе компиляции cos(const) и т.д.

Именно это меня и сподвигло перейти на gcc и на arm платформе.

Пробовал на ARM C/C++ Compiler, 4.1

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


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

Сотворил.

/*!****************************************************************************
@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--); }

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


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

Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор,

иначе, если применить его после if, будут неприятности.

do
{
    Текст макроса.
}
while(0)

 

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


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

Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор,

иначе, если применить его после if, будут неприятности.

do
{
    Текст макроса.
}
while(0)

Помню-помню... разговоры. Но я не вставляю после if.

P.S. у меня же все ветки в скобках { }, может, их хватит? :rolleyes:

 

Другой вопрос всплыл - Как можно определить, с какими параметрами оптимизации задана копмиляция? Что можно было в одном случае в формулу подсунуть 5, а в другом 6.

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


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

Как можно определить, с какими параметрами оптимизации задана копмиляция?
А какой у нас компилятор?

 

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


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

А какой у нас компилятор?

Кейловский, ARMCC из uVision.

Там из списка выбирается -O0... -O3, отдельно галка -Otime.

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


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

Не с той стороны подходите к решению задачи.

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

В моём примере она имеется в каком-то виде.

И будет вам счастье:)

 

Надо бы, наверное, весь макрос поместить внутрь блока, чтобы вставлялся как один оператор
+1

 

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


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

Кейловский, ARMCC из uVision.
Я пас.

 

Чтобы не было зависимости от уровня оптимизации напишите асмовую вставку.
Угу. Вместо последнего цикла. А потом вспомнить про прерывания и забить на эту погрешность.

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


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

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

Взялся было... Но мне нужно загрузить переменную цикла в регистр. Где гарантия, это это регистр ничем не занят? :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:

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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