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

Странная проблема при оптимизации

Есть такой код

uint32_t master_ack;  //global
master_ack = CAN_RX_Master();      
if (master_ack == 1)
{ 
      //пришел сюда если optimization = Low
}
else //no response
{    //пришел сюда если optimization = High
}

master_ack равен 1. при optimization = High я попадаю в else. при optimization = Low я попадаю в if.

Все? Сливаем IAR?

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

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


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

Грабли обычно одни и те же: volatile и гонки.

 

Все? Сливаем IAR?

Есть и другие варианты. 1) Найти косяк в своём коде. 2) Не включать оптимизацию.

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


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

Грабли обычно одни и те же: volatile и гонки.

 

 

Есть и другие варианты. 1) Найти косяк в своём коде. 2) Не включать оптимизацию.

 

volatile? а с чего он оптимизирует обычную глобальную переменную?

Не включать оптимизацию? оптимизация - это единственное наиболее сильное преимущество IAR. Без оптимизации и в Атолике можно кропать.

 

определил как volatile - то же самое - заходит в else.

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

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


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

CAN_RX_Master() покажите. Предполагаю, что оптимизатор видит ее тело, находит в нем только один возможный результат и выкидывает все условие.

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


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

volatile? а с чего он оптимизирует обычную глобальную переменную?

Мы же не видим ваш код и настройки сборки. Компилятор даже умеет собирать программы, смешивая код и переменные из разных файлов. Если увидит, что переменная не нужна (да хотя бы и глобальная) - может выкинуть её. Ну а volatile - это в качестве примера, и скорее всего в каком-то другом месте. Кстати, из очевидных кандидатов - переменные, через которые передаются сигналы из обработчиков прерываний.

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


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

CAN_RX_Master() покажите. Предполагаю, что оптимизатор видит ее тело, находит в нем только один возможный результат и выкидывает все условие.

 

uint32_t CAN_RX_Master(void){
   uint32_t mot_num;
   uint32_t opcode;
   uint32_t pos;  
   uint32_t ack = 0;

   if (can_params.message_received)
   {
           can_params.message_received = 0;

           mot_num = (RxMessage.ExtId & 0xFF) - BASE_MOTOR_ID;
           if (mot_num > MAX_MOTORS)
                  return 0;

           opcode = (RxMessage.ExtId >> 8) & 0xFF;

           switch (opcode)
           {
         case CAN_COM_GET_ALL :

                             motor_rt_params[mot_num].current = ((RxMessage.Data[1]<<8) | RxMessage.Data[0]);
                             motor_rt_params[mot_num].speed = ((RxMessage.Data[3]<<8)  | RxMessage.Data[2]);
                             motor_rt_params[mot_num].position = ((RxMessage.Data[5]<<8)  | RxMessage.Data[4]);
                             ack = 1; 
                     break;

                    case CAN_COM_I_AM :
           motor_rt_params[mot_num].ena = 1;
                            motor_rt_params[mot_num].mot_id = BASE_MOTOR_ID + mot_num;
                           ack = 1; 
                    break;

                    case CAN_COM_IGET :
                              motor_rt_params[mot_num].current = ( RxMessage.Data[1]<<8)  |  RxMessage.Data[0]);
                              pos = CAN_IGET_POS;
                             ack = 1;
                    break;

                    case CAN_COM_PGET :
                                motor_rt_params[mot_num].position = (( RxMessage.Data[1]<<8)  |  RxMessage.Data[0]);
                                pos = CAN_PGET_POS;
                               ack = 1;
                    break;

        case CAN_COM_VGET :
                                 motor_rt_params[mot_num].speed = (( RxMessage.Data[1]<<8)  |  RxMessage.Data[0]);
                                 pos = CAN_VGET_POS;
                                ack = 1;
      break;
        }

   if (ack)
         motor_rt_params[mot_num].rx_flags |= (1<<pos);     

       return ack; 
}

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


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

Процитирую себя:

Кстати, из очевидных кандидатов - переменные, через которые передаются сигналы из обработчиков прерываний.

Обработчик прерывания есть?

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


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

Процитирую себя:

 

Обработчик прерывания есть?

 

у меня есть несколько обработчиков прерывания, на UART, на CAN, но там эта переменная никак не появляется. я прбовал объявить ее static - не помогло.

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


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

у меня есть несколько обработчиков прерывания, на UART, на CAN, но там эта переменная никак не появляется. я прбовал объявить ее static - не помогло.

Да не эта переменная. Вообще любая переменная, которая используется в обработчике прерывания и вне его. :cranky:

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


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

Да не эта переменная. Вообще любая переменная, которая используется в обработчике прерывания и вне его. :cranky:

 

объявить их volatile?

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


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

объявить их volatile?

Можно и так, типа ковровой бомбардировки. А можно внимательно посмотреть на код и попробовать понять, какие из них требуют volatile, а какие - нет.

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


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

Либо mot_num становится отрицательным из-за (RxMessage.ExtId & 0xFF) < BASE_MOTOR_ID, либо opcode не соответствует перечню команд в switch.

Копайте в этом направлении.

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


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

Теперь покажите объявление can_params. Ее член message_received меняется в прерываниии?

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


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

Либо mot_num становится отрицательным из-за (RxMessage.ExtId & 0xFF) < BASE_MOTOR_ID, либо opcode не соответствует перечню команд в switch.

Копайте в этом направлении.

 

так в любом случае return ack; ack - oн всегда будет определен.

 

Теперь покажите объявление can_params. Ее член message_received меняется в прерываниии?

 

я заменил флаг can_params.message_received на volatile uint32_t can_message_received; и он устанавливается в прерывании

void USB_LP_CAN1_RX0_IRQHandler(void)
{
  can_params.fifo_num = CAN_FIFO0;
  
  can_message_received = 1;

  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
}

 

ради эксперемента сделал /*master_ack = */ CAN_RX_Master(); и в начале функции опроса жестко поставил master_ack = 1; - все равно заходит в else.

 

О! Только после того как определил static volatile uint32_t master_ack; - все стало на свои места. отдельно static или отдельно volatile не работает.

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

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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