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

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

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

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

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти