Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Странная проблема при оптимизации
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Jenya7
Есть такой код
Код
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?
scifi
Грабли обычно одни и те же: volatile и гонки.

Цитата(Jenya7 @ Sep 28 2018, 12:29) *
Все? Сливаем IAR?

Есть и другие варианты. 1) Найти косяк в своём коде. 2) Не включать оптимизацию.
Jenya7
Цитата(scifi @ Sep 28 2018, 15:50) *
Грабли обычно одни и те же: volatile и гонки.


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


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

определил как volatile - то же самое - заходит в else.
Сергей Борщ
CAN_RX_Master() покажите. Предполагаю, что оптимизатор видит ее тело, находит в нем только один возможный результат и выкидывает все условие.
scifi
Цитата(Jenya7 @ Sep 28 2018, 12:55) *
volatile? а с чего он оптимизирует обычную глобальную переменную?

Мы же не видим ваш код и настройки сборки. Компилятор даже умеет собирать программы, смешивая код и переменные из разных файлов. Если увидит, что переменная не нужна (да хотя бы и глобальная) - может выкинуть её. Ну а volatile - это в качестве примера, и скорее всего в каком-то другом месте. Кстати, из очевидных кандидатов - переменные, через которые передаются сигналы из обработчиков прерываний.
Jenya7
Цитата(Сергей Борщ @ Sep 28 2018, 16:05) *
CAN_RX_Master() покажите. Предполагаю, что оптимизатор видит ее тело, находит в нем только один возможный результат и выкидывает все условие.


CODE
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;
}
scifi
Процитирую себя:
Цитата(scifi @ Sep 28 2018, 13:08) *
Кстати, из очевидных кандидатов - переменные, через которые передаются сигналы из обработчиков прерываний.

Обработчик прерывания есть?
Jenya7
Цитата(scifi @ Sep 28 2018, 16:24) *
Процитирую себя:

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


у меня есть несколько обработчиков прерывания, на UART, на CAN, но там эта переменная никак не появляется. я прбовал объявить ее static - не помогло.
scifi
Цитата(Jenya7 @ Sep 28 2018, 13:27) *
у меня есть несколько обработчиков прерывания, на UART, на CAN, но там эта переменная никак не появляется. я прбовал объявить ее static - не помогло.

Да не эта переменная. Вообще любая переменная, которая используется в обработчике прерывания и вне его. cranky.gif
Jenya7
Цитата(scifi @ Sep 28 2018, 16:28) *
Да не эта переменная. Вообще любая переменная, которая используется в обработчике прерывания и вне его. cranky.gif


объявить их volatile?
VladislavS
Цитата(Jenya7 @ Sep 28 2018, 13:40) *
объявить их volatile?
А когда-то можно было не объявлять?
scifi
Цитата(Jenya7 @ Sep 28 2018, 13:40) *
объявить их volatile?

Можно и так, типа ковровой бомбардировки. А можно внимательно посмотреть на код и попробовать понять, какие из них требуют volatile, а какие - нет.
E.V.G.
Либо mot_num становится отрицательным из-за (RxMessage.ExtId & 0xFF) < BASE_MOTOR_ID, либо opcode не соответствует перечню команд в switch.
Копайте в этом направлении.
Сергей Борщ
Теперь покажите объявление can_params. Ее член message_received меняется в прерываниии?
Jenya7
Цитата(E.V.G. @ Sep 28 2018, 16:50) *
Либо mot_num становится отрицательным из-за (RxMessage.ExtId & 0xFF) < BASE_MOTOR_ID, либо opcode не соответствует перечню команд в switch.
Копайте в этом направлении.


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

Цитата(Сергей Борщ @ Sep 28 2018, 17:04) *
Теперь покажите объявление 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 не работает.
scifi
Цитата(Jenya7 @ Sep 28 2018, 14:12) *
в начале функции опроса жестко поставил master_ack = 1; - все равно заходит в else.

Кстати, с "заходит" тоже бывают сюрпризы. При высоком уровне оптимизации исходник и машинный код соотносятся очень условно. Курсор в отладчике может прыгать по исходнику довольно хаотично. Чтобы точно сказать, что "заходит", надо там сделать вывод в UART или что-то типа того.
Jenya7
Цитата(scifi @ Sep 28 2018, 17:27) *
Кстати, с "заходит" тоже бывают сюрпризы. При высоком уровне оптимизации исходник и машинный код соотносятся очень условно. Курсор в отладчике может прыгать по исходнику довольно хаотично. Чтобы точно сказать, что "заходит", надо там сделать вывод в UART или что-то типа того.

да но если я не ставлю точку останова а код свободно бежит то в результате мастер не находит слейв. а без оптимизации находит.
scifi
Цитата(Jenya7 @ Sep 28 2018, 15:58) *
да но если я не ставлю точку останова а код свободно бежит то в результате мастер не находит слейв. а без оптимизации находит.

Скорее всего, не на тот участок кода смотрите. Надёжнее выводить значения интересующих переменных через тот же UART, так оптимизатор их не покорёжит. Внутрисхемный отладчик может и не помочь.
kolobok0
Цитата(scifi @ Sep 28 2018, 14:27) *
Кстати, с "заходит" тоже ...



+100500

2TC
странно когда программист говорит компилятору - а теперь сделай красиво как хошь... а потом требует на отладке все стэпы которые ему казались что должны быть. Не находите?
Если вы хотите дебажить выхлоп оптимизатора - то ТОЛЬКО(!) на уровне азма. всё остальное будет от лукавого.

scifi
Цитата(Jenya7 @ Sep 28 2018, 14:12) *
О! Только после того как определил static volatile uint32_t master_ack; - все стало на свои места. отдельно static или отдельно volatile не работает.

Пляски с бубном. Отключите оптимизацию, Вы к ней явно не готовы.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.