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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> #define DELAY(CY), Как задать выбор вариантов определения?
Сергей Борщ
сообщение Apr 10 2014, 07:07
Сообщение #16


Гуру
******

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



Цитата(ViKo @ Apr 10 2014, 08:51) *
Взялся было... Но мне нужно загрузить переменную цикла в регистр. Где гарантия, это это регистр ничем не занят? laughing.gif
"Нормальный" инлайн-асм дает вам возможность сообщить компилятору, что вы испортили регистр. Или попросить компилятор выделить вам свободный в данный момент регистр.

Цитата(ViKo @ Apr 10 2014, 08:51) *
Но эта функция написана для коротких интервалов. Конкретно, для работы с двухстрочным ЖКИ.
Для ЖКИ паузы могут быть и длинее. Поставьте наибольшее значение, 6 циклов и забудьте. Разницу глазом заметить не успеете.

Цитата(ViKo @ Apr 10 2014, 08:51) *
Что-то "не лезет" asm, не принимает его компилятор! В чем дело?
Может ему кавычки не нравятся?

Цитата(ViKo @ Apr 10 2014, 08:51) *
Из ARM документа:
...
uint32_t Reg;
Вот - очень наглядно показано как попросить у компилятора регистр.


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


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

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



Цитата(Сергей Борщ @ Apr 10 2014, 10:07) *
Вот - очень наглядно показано как попросить у компилятора регистр.

Это я сам... попросил. rolleyes.gif
В-общем, путь есть... пойду.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2014, 09:07
Сообщение #18


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

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



Цитата(ViKo @ Apr 10 2014, 10:51) *
Из ARM документа:
The inline assembler supports ARM assembly language only.
The embedded assembler can be used for Thumb and Thumb-2 support.
Отдельно писать?
Для CM3 используется Thumb-2. Поэтому нет никакой возможности писать инлайн вставки.
Зато можно целиком процедуру:
Код
static __inline __asm uint32_t get_interrupt_state(void)
{
    mrs r0, primask
    bx lr
}

Цитата(ViKo @ Apr 10 2014, 10:51) *
Взялся было... Но мне нужно загрузить переменную цикла в регистр. Где гарантия, это это регистр ничем не занят? laughing.gif
http://infocenter.arm.com/help/topic/com.a...0042E_aapcs.pdf
пункт 5.1.1


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


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

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



В-общем, не помогло.
Код
__inline void DelAsm(uint32_t CY)
{
__asm {
    LOOP:
    SUBS CY, CY, #1
    BNE LOOP
  }
}

Превращается при оптимизации -O0 в
Код
0000f0  2005              MOVS     r0,#5
0000f2  bf00              NOP      
0000f4  bf00              NOP      
                  |L1.246|
0000f6  1e40              SUBS     r0,r0,#1
0000f8  d000              BEQ      |L1.252|
0000fa  e7fc              B        |L1.246|
                  |L1.252|
0000fc  bf00              NOP

Компилятор чудит. И зачем?
P.S. Во всех остальных случаях компилируется, как надо.
Код
0000ca  2005              MOVS     r0,#5
                  |L1.204|
0000cc  1e40              SUBS     r0,r0,#1
0000ce  d1fd              BNE      |L1.204|



Цитата(demiurg_spb @ Apr 10 2014, 12:07) *
пункт 5.1.1

Вот отсюда ссылки нужные
http://www.keil.com/support/docs/3369.htm
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Apr 10 2014, 09:16
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



А вот такая ситуация:
Пишу под Keil макрос OUTPIN_PP(port,nbit) который должен в случае , если nbit<8 выполнить
Код
do { GPIO##port->CRL&=~(GPIO_CRL_CNF##nbit); GPIO##port->CRL|=GPIO_CRL_MODE##nbit; } while (0);

а если иначе , то
Код
do { GPIO##port->CRH&=~(GPIO_CRH_CNF##nbit); GPIO##port->CRH|=GPIO_CRH_MODE##nbit; } while (0)

В идеальном варианте на этапе компиляции какимто образом выполнить проверку условия и вставить нужные операторы.
Вариант с
Код
#if nbit<8 OUTPIN_PP(port,nbit) do { GPIO##port->CRL&=~(GPIO_CRL_CNF##nbit); GPIO##port->CRL|=GPIO_CRL_MODE##nbit; } while (0);
#endif
не прокатывает
А с использованием программного вывода:
Код
#define _OUTPIN_PP(port,nbit)  if ((nbit)<8) {do { GPIO##port->CRL&=~(GPIO_CRL_CNF##nbit); GPIO##port->CRL|=GPIO_CRL_MODE##nbit; } while (0); }\
                                                             else do { GPIO##port->CRH&=~(GPIO_CRH_CNF##nbit); GPIO##port->CRH|=GPIO_CRH_MODE##nbit; } while (0)

выдает ошибку отсутствия предопределенного макроса.
Вариант с определением базового адреса и последующим вычислением адреса регистра известен
Код
#define PORTA   ((u32*)(APB2PERIPH_BASE + 0x0800))
#define PORTB   ((u32*)(APB2PERIPH_BASE + 0x0C00))
#define PORTC   ((u32*)(APB2PERIPH_BASE + 0x1000))
#define PORTD   ((u32*)(APB2PERIPH_BASE + 0x1400))
#define PORTE   ((u32*)(APB2PERIPH_BASE + 0x1800))
#define PORTF   ((u32*)(APB2PERIPH_BASE + 0x1C00))
#define PORTG   ((u32*)(APB2PERIPH_BASE + 0x2000))

#define pinOutPP_b(port,bit)  {*(port+((bit)/8))|=3UL<<(((bit)-(8*((bit)/8)))<<2); *(port+((bit)/8))&=~(3UL<<((((bit)-(8*((bit)/8)))<<2)+2));}
, хочу делать по другому .. собственно вопрос как
Go to the top of the page
 
+Quote Post
ViKo
сообщение Apr 10 2014, 09:24
Сообщение #21


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

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



Цитата(MaxiMuz @ Apr 10 2014, 12:16) *
#define pinOutPP_b(port,bit) {*(port+((bit)/8))|=3UL<<(((bit)-(8*((bit)/8)))<<2); *(port+((bit)/8))&=~(3UL<<((((bit)-(8*((bit)/8)))<<2)+2));}[/code], хочу делать по другому .. собственно вопрос как

Код
/*!****************************************************************************
@brief        Bit of Low/High byte Port configuration
@details    Конфигурация одиночного бита порта
@param        PORT - имя порта (A..G)
@param        BIT - номер бита (0..15)
@param        CM - конфигурация бита
@note        Используется перечисляемый тип CONF_MODE
@note        Для IN_PDPU нужный pull-down/pull-up задается в ODR
*/
#define GPIO_CONFB(PORT, BIT, CM)                    \
    *(uint32_t *)((uint32_t)(GPIO##PORT) + BIT / 8 * 4) =         \
    *(uint32_t *)((uint32_t)(GPIO##PORT) + BIT / 8 * 4)        \
        & (~(0xF << (BIT % 8) * 4)) | (CM << (BIT % 8) * 4)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2014, 09:41
Сообщение #22


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

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



Цитата(ViKo @ Apr 10 2014, 13:14) *
Вот отсюда ссылки нужные
При чём тут нужные или нет?
Я вам ответил на вопрос о том какие регистры и как можно использовать, дав ссылку на первоисточник: AAPCS.
Зная, что кейл соответствует AAPCS.
Вот так никаких вариантов для компилятора изменить что-то при изменении уровня оптимизации нет.
Код
static __inline __asm void delay_8cycles(uint32_t x)
{
loop_delay_8cycles:
    nop
    nop
    nop
    nop
    subs r0,r0,#1
    bne  loop_delay_8cycles
    bx lr
}
Совет: придумывайте более сложные имена меткам, т.к. могут быть совпадения в одной единице трансляции и вылезет ошибка.
Незамеченной она конечно не останется, но зачем заранее закладывать мину?


Цитата(MaxiMuz @ Apr 10 2014, 13:16) *
А вот такая ситуация:
Очень неприлично влезать в чужой топик с вопросом совсем не по теме...
Хотите спросить - создайте тему со своим вопросом, или поищите по форуму. Ваш вопрос неоднократно обсуждался...


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


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

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



Цитата(demiurg_spb @ Apr 10 2014, 12:35) *
При чём тут нужные или нет?
Я вам ответил на вопрос о том какие регистры и как можно использовать, дав ссылку на первоисточник: AAPCS.

Не о том был вопрос.
http://infocenter.arm.com/help/topic/com.a...9124245889.html
http://infocenter.arm.com/help/topic/com.a..._user_guide.pdf
7.14 Inline assembler and register access in C and C++ code

Насчет меток - пока не нашел, думаю, компилятор сам их различает в разных функциях.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2014, 10:08
Сообщение #24


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

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



Цитата(ViKo @ Apr 10 2014, 13:49) *
Насчет меток - пока не нашел, думаю, компилятор сам их различает в разных функциях.
Ну думайте...
Я вам говорю о том, с чем лично УЖЕ сталкивался (не на самой последней версии компилятора).



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


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

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



Цитата(demiurg_spb @ Apr 10 2014, 12:41) *
Вот так никаких вариантов для компилятора изменить что-то при изменении уровня оптимизации нет.

Вызываю функцию напрямую.
Код
  DelAsm(6);

__forceinline void DelAsm(uint32_t CY)
{
__asm {
    LOOP:
    SUBS CY, CY, #1
    BNE LOOP
  }
}

Получаю при -O0.
Код
0000f2  2006              MOVS     r0,#6
0000f4  bf00              NOP      
0000f6  bf00              NOP      
                  |L1.248|
0000f8  1e40              SUBS     r0,r0,#1
0000fa  d000              BEQ      |L1.254|
0000fc  e7fc              B        |L1.248|
                  |L1.254|
0000fe  bf00              NOP

А при -O1
Код
0000cc  2006              MOVS     r0,#6
                  |L1.206|
0000ce  1e40              SUBS     r0,r0,#1
0000d0  d1fd              BNE      |L1.206|
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2014, 10:13
Сообщение #26


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

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



Цитата(ViKo @ Apr 10 2014, 13:49) *
Не о том был вопрос.
Как не о том:
Цитата
Но мне нужно загрузить переменную цикла в регистр. Где гарантия, это это регистр ничем не занят?
Именно на этот вопрос и отвечает AAPCS, а не что-то другое. Ну да ладно. Главное результат...

Цитата(ViKo @ Apr 10 2014, 14:08) *
Вызываю функцию напрямую.
Вы мой пример попробуйте (из сообщения 22) - поймёте в чём разница.
Кстати, o0 - это совсем плохой вариант, не нужный НИКОГДА на моей практике.
Если вы увлекались ранее avr-gcc то могли бы увидеть такое в файле задержек delay.h:
Код
#ifndef __OPTIMIZE__
# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
#endif

А для вас возможным выходом из ситуации могло бы стать это решение:
http://www.keil.com/support/man/docs/ARMCC...EF_BCFJFGAA.htm
или это
http://www.keil.com/support/man/docs/ca/ca_optimize.htm


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


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

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



Цитата(demiurg_spb @ Apr 10 2014, 13:13) *
Вы мой пример попробуйте - поймёте в чём разница.

Если в nop-ах - верю на слово.
Цитата
Кстати, o0 - это совсем плохой вариант, не нужный НИКОГДА на моей практике.

Я тоже не пользуюсь. Здесь вопрос, скорее, теоретический. Компилятор будто назло пихает ненужные команды. Для тех, кто не хочет платить? rolleyes.gif
Цитата
А для вас возможным выходом из ситуации могло бы стать это решение:
http://www.keil.com/support/man/docs/ARMCC...EF_BCFJFGAA.htm
или это
http://www.keil.com/support/man/docs/ca/ca_optimize.htm

Первое попробовал - работает! А эта прагма только на одну функцию будет действовать, или до конца файла? biggrin.gif
Вторая ссылка - для старого компилятора. И зачем их только там держат.

Ага, есть:
#pragma push
#pragma O3
function
#pragma pop
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2014, 11:52
Сообщение #28


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

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



Цитата(ViKo @ Apr 10 2014, 14:54) *
Если в nop-ах - верю на слово.
Нет не в них, а в том что у меня __asm задан для всей функции, а у вас для вставки.
Цитата
Ага, есть:
#pragma push
#pragma O3
function
#pragma pop
Отлично!
Для изменения "упакованности" обходился двумя строчками прагмы:
Код
#pragma pack(push, 1)     // set 1 and save prev
...
#pragma pack(pop)          // restore prev
Не знаю можно ли это и тут применить...


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


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

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



Сотворил.v2
Код
/*!****************************************************************************
@brief        Delay program loop
@param        NS - время задержки в ns
@note        Параметр округляется до ближайшего не меньшего, кратного тактам
@note        4 такта в цикле при любой оптимизации (принудительно -O3)
@note        Формула: D = 4 * CY4 - 1 + Nnop
*/
#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 == 1) { __NOP(); }                    \
  else if (CY == 2) { __NOP(); __NOP(); }                \
  else if (CY == 3) { __NOP(); __NOP(); __NOP(); }            \
  else {                                \
    if ((CY + 1) % 4 == 1) { __NOP(); }                    \
    if ((CY + 1) % 4 == 2) { __NOP(); __NOP(); }            \
    if ((CY + 1) % 4 == 3) { __NOP(); __NOP(); __NOP(); }        \
    DelayCY4((CY + 1) / 4); }                        \

/*!****************************************************************************
@brief        Delay 4 clocks in cycle
@param        CY4 - количество 4-тактовых циклов
@note        Delay = 4 * CY4 - 1
*/
#pragma push
#pragma O3
__forceinline void DelayCY4(uint32_t CY4)
{
__asm {
LOOP:
    SUBS CY4, CY4, #1
    BNE LOOP
  }
}
#pragma pop
Go to the top of the page
 
+Quote Post
Леонид Иванович
сообщение Apr 13 2014, 19:24
Сообщение #30


Местный
***

Группа: Участник
Сообщений: 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

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

 


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


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