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

 
 
> #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
 
Start new topic
Ответов
ViKo
сообщение Apr 10 2014, 06:51
Сообщение #2


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

Группа: Модераторы
Сообщений: 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
Леонид Иванович
сообщение Apr 13 2014, 19:24
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986



Цитата(ViKo @ Apr 10 2014, 09:51) *
Конкретно, для работы с двухстрочным ЖКИ.


А я для таких целей использую функции микросекундных задержек, которая пользуется таймером SysTick, не мешая ему выполнять свою основную функцию - генерирование системного интервала 1 мс:

Код
void TSysTimer::Delay_us(uint16_t d)
{
  uint32_t DelayStart = SysTick->VAL;
  uint32_t DelayTicks = d * CLK_PER_US;
  int32_t  Delta;
  do
  {
    Delta = DelayStart - SysTick->VAL;
    if(Delta < 0) Delta += CLK_PER_MS;
  }
  while(Delta < DelayTicks);
}



--------------------
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 14 2014, 04:38
Сообщение #4


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

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



Цитата(Леонид Иванович @ Apr 13 2014, 22:24) *
А я для таких целей использую функции микросекундных задержек, которая пользуется таймером SysTick, не мешая ему выполнять свою основную функцию - генерирование системного интервала 1 мс

Годится, но только для интервалов короче 1 мс.
А для этого ЖКИ есть интервалы и по 30 мс. (Вообще, темный лепс, скачал несколько datasheet-ов на разные ЖКИ, есть такие странные процедуры установки режимов...)
Go to the top of the page
 
+Quote Post
toweroff
сообщение Apr 14 2014, 05:01
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(ViKo @ Apr 14 2014, 08:38) *
Годится, но только для интервалов короче 1 мс.
А для этого ЖКИ есть интервалы и по 30 мс. (Вообще, темный лепс, скачал несколько datasheet-ов на разные ЖКИ, есть такие странные процедуры установки режимов...)

а у него нет никакого флага BUSY? чтобы не городить с задержками, а когда можно флаг опросить и дальше работать
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 14 2014, 05:13
Сообщение #6


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

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



Цитата(toweroff @ Apr 14 2014, 08:01) *
а у него нет никакого флага BUSY? чтобы не городить с задержками, а когда можно флаг опросить и дальше работать

Есть, но чтобы его опросить (что и делаю), нужно прочитать байт, по всем правилам, с задержками. sm.gif
Go to the top of the page
 
+Quote Post
toweroff
сообщение Apr 14 2014, 05:27
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(ViKo @ Apr 14 2014, 09:13) *
Есть, но чтобы его опросить (что и делаю), нужно прочитать байт, по всем правилам, с задержками. sm.gif

ок, можно отдать SysTick генерить все управляющие сигналы по стэйт-машине некой, а из него уже отсылать программный сигнал (или просто флаг) ждущей задаче
я так понимаю, этот таймер все равно по микросекундам генерится?
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 14 2014, 05:52
Сообщение #8


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

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



Цитата(toweroff @ Apr 14 2014, 08:27) *
ок, можно отдать SysTick генерить все управляющие сигналы по стэйт-машине некой, а из него уже отсылать программный сигнал (или просто флаг) ждущей задаче
я так понимаю, этот таймер все равно по микросекундам генерится?

У меня задержка считается в ns. С точностью до такта микроконтроллера. SysTick Timer считает такты (или поделенные на 8) до 1-10 ms для RTOS (и у меня тоже есть), потом перезагружается. Поэтому более длинные интервалы не получить.
Можно большие задержки считать одним способом, а малые другим. А можно все одним. rolleyes.gif

Цитата(Сергей Борщ @ Apr 14 2014, 08:45) *
Да дайте вы удвоенную от максимальной задержку и забудьте о чтении. Оператор не заметит лишние 10 мс на перерисовку всего экрана, а программа упростится раза в три.

Так уж в три...? sm.gif Задержка занимает у меня от 3 до 6 ассемблерных команд. Куда уж проще? И выполняется именно столько времени, сколько мне нужно.
Там же все обращения к контроллеру ЖКИ идут ногодрыгом, без задержек - никак не обойтись.
А для выполнения ЖКИ команд нужны задержки побольше. Зачем мне терять время, если не проверять, когда они закончатся, а тупо ждать больше срока?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 14 2014, 06:15
Сообщение #9


Гуру
******

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



Цитата(ViKo @ Apr 14 2014, 08:52) *
Так уж в три...? sm.gif Задержка занимает у меня от 3 до 6 ассемблерных команд. Куда уж проще?
Выкинуть чение Busy, дав задержки на выполнение команд дисплеем вдвое от максимальных в даташите (50мкс на все команды кроме очистки экрана, на нее 2мс или вообще не использовать). Уже только избавление он необходимости переключать порт на ввод и анализивровать Busy сводит все управление дисплеем к трем примитивнейшим функциям:
Код
void hd44780::write_tetrade(uint8_t tetrade)    // assume data in upper tetrade, lower tetrade is all zeros
{
    ON(LCD_EN);
    LCD_PORT = (LCD_PORT & 0x0F) | tetrade;
    _delay_us(1);
    OFF(LCD_EN);
    _delay_us(1);
}

void hd44780::write_data(uint8_t byte)
{
    write_tetrade(byte & 0xF0);
    write_tetrade(byte << 4);
    _delay_us(50);
    ON(LCD_RS);
}

void hd44780::write_command(uint8_t command)
{
    OFF(LCD_RS);
    write_data(command);
}
Сравните со своим ногодрыгом с чтением Busy.

Ну хорошо, еще инициализация:
Код
inline hd44780::hd44780()
{
    OFF(LCD_RS);
    _delay_ms(200);
    write_tetrade(3 << 4);      // set 8-bit mode
    _delay_ms(50);
    write_tetrade(3 << 4);      // set 8-bit mode again
    _delay_ms(50);
    write_tetrade(3 << 4);      // set 8-bit mode again, see http://electronix.ru/forum/index.php?s=&showtopic=19594&view=findpost&p=143374
    _delay_us(50);              // delay slightly longer than typical command execution time.
    write_tetrade(2 << 4);      // set 4-bit mode
    _delay_us(50);
    write_command(CURSOR_HOME);
    _delay_ms(2);
    write_command(0x06);        // increment cursor position during data write, disable display shift
    write_command(CURSOR_OFF);
}


Цитата(ViKo @ Apr 14 2014, 08:52) *
а тупо ждать больше срока?
А вы и так "тупо ждете больше срока" потому что в вашу задержку вклиниваются прерывания. Вывод на дисплей происходит так редко, что будет там задержка 50мкс или 20мкс на байт не заметит никто. Ну пусть у вас дисплей 4*40, пусть обновляете его целиком 4 раза в секунду (быстрее он не успеет отобразить, а оператор воспринять), ну потеряете вы лишних (50-20)*40*4*4=19200 мкс. Ах, 19мс каждую секунду ушло впустую, катастрофа. Зато сэкономлена неделя рабочего времени, за которую эти 19мс можно с большей пользой отыграть где-то в другом месте.


--------------------
На любой вопрос даю любой ответ
"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 14 2014, 15:35
Сообщение #10


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

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



Цитата(Сергей Борщ @ Apr 14 2014, 09:15) *
А вы и так "тупо ждете больше срока" потому что в вашу задержку вклиниваются прерывания.

Зато я могу посылать в ЖКИ символы, когда захочу. Совсем не обязательно "тупо ждать" задержку или флаг Busy, можно заняться чем-нибудь общественно-полезным между выводами, не опасаясь "уже можно посылать, или еще подождать?".

Нюанс всплыл - невозможно заинлайнить функцию (DelayCY4), находящуюся в другом файле. Пришлось в один объединить.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 15 2014, 06:18
Сообщение #11


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

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



Цитата(ViKo @ Apr 14 2014, 19:35) *
Нюанс всплыл - невозможно заинлайнить функцию (DelayCY4), находящуюся в другом файле. Пришлось в один объединить.
Это не нюанс, это стандартное поведение.
Для решения подобных задач нужно всё в заголовочном файле размещать:
Код
static __inline void delay(int x)
{
    ....
}

Цитата(toweroff @ Apr 14 2014, 19:54) *
не панацея, конечно, но позволит уйти от асма, тем более что точная задержка как таковая не критична прям уж так
Не системный подход с кучей сорного кода, заслоняющего основную идею.
Здесь асм не столько для точности, а больше для снятия зависимости от уровня оптимизации.

Тут у меня самого возник вопрос, касательно задержек в gcc.
Вот такой код упорно приводит проект в нерабочее состояние:
Код
#define delay_4cycles(cy)                \
(__extension__({                         \
    uint32_t __x = (uint32_t)(cy);       \
    __asm__ __volatile__                 \
    (                                    \
        "loop%=: subs %[cnt],#1"  "\n\t" \
        "        bne  loop%="     "\n\t" \
        :                                \
        : [cnt]"r"(__x)                  \
        : "cc"                           \
    );                                   \
}))

for(;;)
{
    delay_4cycles(1);
    pin_toggle(LED_RED);
}
А именно не производится перезагрузка счётчика цикла внутри цикла for.
В данном примере 1 загружается в регистр единожды перед циклом for, что собственно является нежелательным поведением:
Код
8001df6:    f04f 0001     mov.w    r0, #1
...
8001e0a:    3801          subs    r0, #1
8001e0c:    d1fd          bne.n    8001e0a
8001e0e:    682b          ldr    r3, [r5, #0]
8001e10:    ea6f 0703     mvn.w    r7, r3
8001e14:    6037          str    r7, [r6, #0]
8001e16:    e7f8          b.n    8001e0a
А без использования асм всё нормально:
Код
8001e04:    bf00          nop
8001e06:    bf00          nop
8001e08:    bf00          nop
8001e0a:    bf00          nop
8001e0c:    6806          ldr    r6, [r0, #0]
8001e0e:    ea6f 0306     mvn.w    r3, r6
8001e12:    602b          str    r3, [r5, #0]
8001e14:    e7f6          b.n    8001e04

Прошу помощи у аудитории!

arm-none-eabi-gcc.EXE (GNU Tools for ARM Embedded Processors / bleeding-edge-toolchain-131005) 4.7.4 20130913 (prerelease)
CFLAGS += -flto
CFLAGS += -fomit-frame-pointer
CFLAGS += -falign-functions=16
CFLAGS += -fgraphite
CFLAGS += -funroll-loops
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
CFLAGS += -O3
#CFLAGS += -O1


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


Гуру
******

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



Цитата(demiurg_spb @ Apr 15 2014, 09:18) *
Прошу помощи у аудитории!
cnt у вас меняется в асм-вставке, а компилятору вы об этом не сообщаете.
Попробуйте так, если в синтаксисе не ошибся:
Код
    __asm__ __volatile__                 \
    (                                    \
        "loop%=: subs %[cnt],#1"  "\n\t" \
        "        bne  loop%="     "\n\t" \
        : =[cnt]"r"(__x)                 \
        :                   \
        : "cc"                           \
    );                                   \



--------------------
На любой вопрос даю любой ответ
"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 15 2014, 07:15
Сообщение #13


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

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



Цитата(Сергей Борщ @ Apr 15 2014, 10:59) *
cnt у вас меняется в асм-вставке, а компилятору вы об этом не сообщаете.
Согласно доке и не должен я об этом ничего сообщать.
Вы предлагаете использовать cnt как выходной write only регистр:
Код
#define delay_4cycles(cy)                \
(__extension__({                         \
    uint32_t __x = (uint32_t)(cy);       \
    __asm__ __volatile__                 \
    (                                    \
        "loop%=: subs %[cnt],#1"  "\n\t" \
        "        bne  loop%="     "\n\t" \
        : [cnt]"=r"(__x)                 \
        :                                \
        : "cc"                           \
    );                                   \
}))
что на мой взгляд несколько неверно, т.к. компилятор его вообще перестал инициализировать:
Код
8001e06:    3b01          subs    r3, #1
8001e08:    d1fd          bne.n    8001e06 <loop3411>
8001e0a:    6806          ldr    r6, [r0, #0]
8001e0c:    ea6f 0306     mvn.w    r3, r6
8001e10:    602b          str    r3, [r5, #0]
8001e12:    e7f8          b.n    8001e06 <loop3411>
На мой взгляд cnt - это input, а не output операнд (кстати =&r даёт такой же результат).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ViKo   #define DELAY(CY)   Apr 9 2014, 04:44
- - Сергей Борщ   Код#define DELAY(cyсles) if((cycle...   Apr 9 2014, 05:34
|- - demiurg_spb   Цитата(Сергей Борщ @ Apr 9 2014, 09:34) Е...   Apr 9 2014, 06:40
|- - Сергей Борщ   Цитата(demiurg_spb @ Apr 9 2014, 08:40) В...   Apr 9 2014, 07:02
|- - demiurg_spb   Цитата(Сергей Борщ @ Apr 9 2014, 11:02) П...   Apr 9 2014, 07:11
- - ViKo   Код#define DELAY_CY(CY) \ if (C...   Apr 9 2014, 06:50
|- - demiurg_spb   Вот это в GCC отлично рабртает, а в кейле, когда я...   Apr 9 2014, 06:54
- - ViKo   Сотворил. CODE /*!****************************...   Apr 9 2014, 15:23
|- - Shamil   Надо бы, наверное, весь макрос поместить внутрь бл...   Apr 10 2014, 01:18
|- - ViKo   Цитата(Shamil @ Apr 10 2014, 04:18) Надо ...   Apr 10 2014, 02:24
|- - Сергей Борщ   Цитата(ViKo @ Apr 10 2014, 04:24) Как мож...   Apr 10 2014, 02:58
|- - ViKo   Цитата(Сергей Борщ @ Apr 10 2014, 05:58) ...   Apr 10 2014, 03:01
|- - demiurg_spb   Цитата(ViKo @ Apr 10 2014, 07:01) Не с то...   Apr 10 2014, 03:15
- - Сергей Борщ   Цитата(ViKo @ Apr 10 2014, 05:01) Кейловс...   Apr 10 2014, 03:24
|- - Сергей Борщ   Цитата(ViKo @ Apr 10 2014, 08:51) Взялся ...   Apr 10 2014, 07:07
||- - ViKo   Цитата(Сергей Борщ @ Apr 10 2014, 10:07) ...   Apr 10 2014, 07:57
|- - demiurg_spb   Цитата(ViKo @ Apr 10 2014, 10:51) Из ARM ...   Apr 10 2014, 09:07
|- - demiurg_spb   Цитата(Леонид Иванович @ Apr 13 2014, 23...   Apr 14 2014, 03:30
||- - toweroff   Цитата(ViKo @ Apr 14 2014, 19:35) Нюанс в...   Apr 14 2014, 15:54
||- - Сергей Борщ   Цитата(demiurg_spb @ Apr 15 2014, 10:15) ...   Apr 15 2014, 07:21
||- - demiurg_spb   Цитата(Сергей Борщ @ Apr 15 2014, 11:21) ...   Apr 15 2014, 07:31
|- - Сергей Борщ   Цитата(ViKo @ Apr 14 2014, 08:13) Есть, н...   Apr 14 2014, 05:45
- - ViKo   В-общем, не помогло. Код__inline void DelAsm(u...   Apr 10 2014, 09:14
|- - demiurg_spb   Цитата(ViKo @ Apr 10 2014, 13:14) Вот отс...   Apr 10 2014, 09:41
|- - ViKo   Цитата(demiurg_spb @ Apr 10 2014, 12:35) ...   Apr 10 2014, 09:49
||- - demiurg_spb   Цитата(ViKo @ Apr 10 2014, 13:49) Насчет ...   Apr 10 2014, 10:08
||- - demiurg_spb   Цитата(ViKo @ Apr 10 2014, 13:49) Не о то...   Apr 10 2014, 10:13
||- - ViKo   Цитата(demiurg_spb @ Apr 10 2014, 13:13) ...   Apr 10 2014, 10:54
||- - demiurg_spb   Цитата(ViKo @ Apr 10 2014, 14:54) Если в ...   Apr 10 2014, 11:52
|- - ViKo   Цитата(demiurg_spb @ Apr 10 2014, 12:41) ...   Apr 10 2014, 10:08
- - MaxiMuz   А вот такая ситуация: Пишу под Keil макрос OUTPIN...   Apr 10 2014, 09:16
|- - ViKo   Цитата(MaxiMuz @ Apr 10 2014, 12:16) #def...   Apr 10 2014, 09:24
- - ViKo   Сотворил.v2 Код/*!****************************...   Apr 10 2014, 13:59


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

 


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


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