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

Неверная компиляция при высокой оптимизации под ARM

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

 

Есть такая проблема с компиляцией проекта под 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
пользуйтесь тэгами

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


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

Это видно в отладчике и дизассемблере эти функции идут подряд.
Покажите дизассемблер. Всей функции.

 

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


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

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);  
}

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
используйте тэги

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


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

0800239e: 0xbf30 WFIEQ

080023a0: 0xbf20 WFENE

 

вот эти EQ и NE в конце означают условие выполнения. выполнится лишь одна из них, в зависимости от флага Z (или как он там в армах называется)

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


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

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

 

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


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

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

Да и к тому же при средней оптимизации если я останавливаю программу, то я вижу что отладчик встал на инструкции WFI, при высокой оптимизации он уже встает именно на WFE. Да и нигде в коде я не передаю

функции использование WFE, по хорошему компилятор должен был вообще выкинуть ее из функции как неиспользуемую.

 

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

 

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
используйте тэги

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


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

Чет в первый раз слышу чтобы отладчик прошелся по той функции которая не выполняется.

Все верно. Только особенность блока IT в том, что некоторые команды (которые имеют ложное условие) при исполнении аппаратно заменяются на NOP.

Это гораздо лучше для конвеера, нежели переходы, и для крошечных веток сравнения (как у Вас) очень эффективно.

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


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

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

Да и к тому же при средней оптимизации если я останавливаю программу, то я вижу что отладчик встал на инструкции WFI, при высокой оптимизации он уже встает именно на WFE. Да и нигде в коде я не передаю

функции использование WFE, по хорошему компилятор должен был вообще выкинуть ее из функции как неиспользуемую.

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

 

WFIEQ == IF(EQUAL)WFI

 

WFENE == IF(NOT EQUAL)WFE

Изменено пользователем den_po

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


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

Осталось ещё добавить, что в наборе инструкций ARM (в том, который полный, а не Thumb и проч.) каждая инструкция может быть условной.

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


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

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

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

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

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

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

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

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

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

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