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

 
 
 
Reply to this topicStart new topic
> Неверная компиляция при высокой оптимизации под ARM
veteq
сообщение May 27 2014, 07:30
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 5-12-06
Пользователь №: 23 160



Здравствуйте

Есть такая проблема с компиляцией проекта под cortex-m3 (stm32l). Если компилировать с уровнем оптимизации medium все компилируется верно.
Но если выставить оптимизацию на high balanced или speed даже если выключить все доступные оптимизации которые доступны при уровне high проект компилируется неверно.
Пробовал на IAR ARM 7.1.3 и 7.2.1
Пример функции которая идет в комплекте драйверов ST

Код
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
....  
  /* Select STOP mode entry --------------------------------------------------*/
  if(PWR_STOPEntry == PWR_SLEEPEntry_WFI)
  {  
    /* Request Wait For Interrupt */
    __WFI();
  }
  else
  {
    /* Request Wait For Event */
    __WFE();
  }
}

PWR_SLEEPEntry_WFI = 1;
PWR_STOPEntry передается 1;

И условие IF ELSE которые по логике должны быть взаимоисключающими выполняются последовательно, т.е. сначала __WFI(); и потом сразу __WFE();
Это видно в отладчике и дизассемблере эти функции идут подряд.

Сообщение отредактировал IgorKossak - May 27 2014, 15:02
Причина редактирования: пользуйтесь тэгами
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 27 2014, 15:42
Сообщение #2


Гуру
******

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



Цитата(veteq @ May 27 2014, 14:40) *
Это видно в отладчике и дизассемблере эти функции идут подряд.
Покажите дизассемблер. Всей функции.


--------------------
На любой вопрос даю любой ответ
"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
veteq
сообщение May 29 2014, 02:21
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 5-12-06
Пользователь №: 23 160



CODE
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;

/* Check the parameters */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));

/* Select the regulator state in STOP mode ---------------------------------*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDSR bits */
tmpreg &= CR_DS_MASK;

/* Set LPDSR bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;

/* Store the new value */
PWR->CR = tmpreg;

/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;

/* Select STOP mode entry --------------------------------------------------*/
if(PWR_STOPEntry == PWR_SLEEPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}

CODE
08002382: 0x4770 BX LR
685 tmpreg = PWR->CR;
PWR_EnterSTOPMode:
08002384: PWR_EnterSTOPMode:
0x4a0a LDR.N R2, ??DataTable12_1 ; 0x40007000 (1073770496)
08002386: 0x6813 LDR R3, [R2]
693 PWR->CR = tmpreg;
08002388: 0x089b LSRS R3, R3, #2
0800238a: 0xea40 0x0083 ORR.W R0, R0, R3, LSL #2
0800238e: 0x6010 STR R0, [R2]
08002390: 0x2901 CMP R1, #1
696 SCB->SCR |= SCB_SCR_SLEEPDEEP;
08002392: 0x4808 LDR.N R0, ??DataTable12_6 ; SCR
08002394: 0x6802 LDR R2, [R0]
08002396: 0xf042 0x0204 ORR.W R2, R2, #4
0800239a: 0x6002 STR R2, [R0]
699 if(PWR_STOPEntry == PWR_SLEEPEntry_WFI)
0800239c: 0xbf0c ITE EQ
702 __WFI();
0800239e: 0xbf30 WFIEQ
707 __WFE();
080023a0: 0xbf20 WFENE
710 SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
080023a2: 0x6801 LDR R1, [R0]
080023a4: 0xf021 0x0104 BIC.W R1, R1, #4
080023a8: 0x6001 STR R1, [R0]
711 }


Сообщение отредактировал IgorKossak - May 29 2014, 15:16
Причина редактирования: используйте тэги
Go to the top of the page
 
+Quote Post
den_po
сообщение May 29 2014, 02:33
Сообщение #4


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

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



0800239e: 0xbf30 WFIEQ
080023a0: 0xbf20 WFENE

вот эти EQ и NE в конце означают условие выполнения. выполнится лишь одна из них, в зависимости от флага Z (или как он там в армах называется)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 29 2014, 03:11
Сообщение #5


Гуру
******

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



Цитата(den_po @ May 29 2014, 09:43) *
вот эти EQ и NE в конце означают условие выполнения.
Именно. То, что отладчик показал проход по этой команде еще не означает, что она выполнилась. Подробнее можно узнать в описании команды ITE (на описании этой команды можно голову сломать biggrin.gif ).


--------------------
На любой вопрос даю любой ответ
"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
veteq
сообщение May 29 2014, 08:34
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 5-12-06
Пользователь №: 23 160



Чет в первый раз слышу чтобы отладчик прошелся по той функции которая не выполняется. Знаю и видел что по коду он может прыгнуть в неожиданные места из-за высокой оптимизации.
Да и к тому же при средней оптимизации если я останавливаю программу, то я вижу что отладчик встал на инструкции WFI, при высокой оптимизации он уже встает именно на WFE. Да и нигде в коде я не передаю
функции использование WFE, по хорошему компилятор должен был вообще выкинуть ее из функции как неиспользуемую.

Вот код при средней оптимизации:

CODE
080011fe: 0x4770 BX LR
685 tmpreg = PWR->CR;
PWR_EnterSTOPMode:
08001200: PWR_EnterSTOPMode:
0x4a0b LDR.N R2, ??DataTable12_1 ; 0x40007000 (1073770496)
08001202: 0x6813 LDR R3, [R2]
693 PWR->CR = tmpreg;
08001204: 0x089b LSRS R3, R3, #2
08001206: 0xea50 0x0083 ORRS.W R0, R0, R3, LSL #2
0800120a: 0x6010 STR R0, [R2]
696 SCB->SCR |= SCB_SCR_SLEEPDEEP;
0800120c: 0x4809 LDR.N R0, ??DataTable12_6 ; SCR
0800120e: 0x6802 LDR R2, [R0]
08001210: 0xf042 0x0204 ORR.W R2, R2, #4
08001214: 0x6002 STR R2, [R0]
699 if(PWR_STOPEntry == PWR_SLEEPEntry_WFI)
08001216: 0x2901 CMP R1, #1
08001218: 0xd101 BNE.N ??PWR_EnterSTOPMode_0 ; 0x800121e
702 __WFI();
0800121a: 0xbf30 WFI
0800121c: 0xe000 B.N ??PWR_EnterSTOPMode_1 ; 0x8001220
707 __WFE();
0800121e: ??PWR_EnterSTOPMode_0:
0xbf20 WFE
710 SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
08001220: ??PWR_EnterSTOPMode_1:
0x6801 LDR R1, [R0]
08001222: 0xf021 0x0104 BIC.W R1, R1, #4
08001226: 0x6001 STR R1, [R0]
711 }


Сообщение отредактировал IgorKossak - May 29 2014, 15:16
Причина редактирования: используйте тэги
Go to the top of the page
 
+Quote Post
adnega
сообщение May 29 2014, 08:45
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(veteq @ May 29 2014, 16:44) *
Чет в первый раз слышу чтобы отладчик прошелся по той функции которая не выполняется.

Все верно. Только особенность блока IT в том, что некоторые команды (которые имеют ложное условие) при исполнении аппаратно заменяются на NOP.
Это гораздо лучше для конвеера, нежели переходы, и для крошечных веток сравнения (как у Вас) очень эффективно.
Go to the top of the page
 
+Quote Post
den_po
сообщение May 29 2014, 09:19
Сообщение #8


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

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Цитата(veteq @ May 29 2014, 16:44) *
Чет в первый раз слышу чтобы отладчик прошелся по той функции которая не выполняется. Знаю и видел что по коду он может прыгнуть в неожиданные места из-за высокой оптимизации.
Да и к тому же при средней оптимизации если я останавливаю программу, то я вижу что отладчик встал на инструкции WFI, при высокой оптимизации он уже встает именно на WFE. Да и нигде в коде я не передаю
функции использование WFE, по хорошему компилятор должен был вообще выкинуть ее из функции как неиспользуемую.

считайте эти команды составными

WFIEQ == IF(EQUAL)WFI

WFENE == IF(NOT EQUAL)WFE

Сообщение отредактировал den_po - May 29 2014, 09:19
Go to the top of the page
 
+Quote Post
scifi
сообщение May 29 2014, 09:39
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Осталось ещё добавить, что в наборе инструкций ARM (в том, который полный, а не Thumb и проч.) каждая инструкция может быть условной.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 19:40
Рейтинг@Mail.ru


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