Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Странности при вычислении значений!
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Sergio66
Добрый день!
1.
Столкнулся с такой странностью, выглядит примерно так:
Код
typedef UINT32 flash_address_t;
flash_address_t Next_Data_Area_Address;
#define IF_PAGE_SIZE    264

void Func(void)
{
flash_address_t PageNum , PageOffs;

              PageNum = Next_Data_Area_Address    / IF_PAGE_SIZE;
              PageOffs =Next_Data_Area_Address   % IF_PAGE_SIZE;

....
}
По контексту Next_Data_Area_Address не может занимать в памяти более 3 байт. (Ну значения больше 0x0fff просто не возможны). Кстати, она глобальная! И в функции имеет правильное значение...

При вычислении PageNum и PageOffs присутствует "мусор" в старшем байте!!!
Вылечилось таким объявлением:
volatile flash_address_t PageNum = 0, PageOffs = 0;

Включена опция полной оптимизации по размеру кода.

2.
Второй интересный случай -
Код
char Func(char a)
{
...
}

void Func_1(void)
{
char a,b;
a=0;
b=Func(a);
}
обратил внимание. что с некоторых пор функция Func стала возвращать неверное значение. Вычисляет его правильно, а возвращает - нет!!!
Посмотрел как происходит возврат - оказалось, что Func при выходе помещает результат в R16, а вызывавшая функция принимает его в R24!!!
Стоило чуть изменить тело Func, как все встало на свои места. Изменения коснулись некоторой смены порядка выполняемых операций...

Использую
IAR C/C++ Compiler for AVR
6.11.1 (6.11.1.50453)

Может кто нибудь прокомментировать?
Больше всего интересует п.1., т.к. не знаешь, чего ждать от программы, если не понятен механизм образования мусора...
prottoss
Цитата(Sergio66 @ Jan 16 2013, 12:29) *
По контексту Next_Data_Area_Address не может занимать в памяти более 3 байт. (Ну значения больше 0x0fff просто не возможны). Кстати, она глобальная! И в функции имеет правильное значение...
Вообще то в памяти она занимает 4 байта - т.к. базовый тип - UINT32

Цитата(Sergio66 @ Jan 16 2013, 12:29) *
Посмотрел как происходит возврат - оказалось, что Func при выходе помещает результат в R16, а вызывавшая функция принимает его в R24!!!
...
Использую
IAR C/C++ Compiler for AVR
6.11.1 (6.11.1.50453)
Функция обязана возвращать результат в R16, только если компилятор ее не оптимизировал и не заинлайнил sm.gif, и вызывающая функция, если вызываемая функция не заинлайнина, примет результат в R16, в противном случае вполне возможно что как раз из R24.

Почитайте FUNCTION ENTRANCE в мануале на компилятор.
KRS
Цитата(Sergio66 @ Jan 16 2013, 10:29) *
Может кто нибудь прокомментировать?

А чего тут без листинга комментировать?
Исходник + листинг с указанием где компилятор ошибся!
(в большинстве случаев конечно находится своя ошибка, но и у IAR иногда бывают при оптимизации и в принципе чаще чем у других)

prottoss
Цитата(KRS @ Jan 16 2013, 17:49) *
....но и у IAR иногда бывают при оптимизации и в принципе чаще чем у других)
Млин... crying.gif Ни разу не сталкивался rolleyes.gif
KRS
Цитата(prottoss @ Jan 16 2013, 15:59) *
Млин... crying.gif Ни разу не сталкивался rolleyes.gif

Например, чуть ниже есть тема про ARM
я на AVR еще версии 3.20 налетал (в 3.20 D исправили) с очисткой младшего бита в регистровой(зарезервированной) переменной - он всю чистил.
Но обычно там ошибки связанные с "не красивым кодом" поэтому и не сталкивались sm.gif


У IAR часто такие "смешные" ошибки оптимизатора, видно что он старается сделать как можно лучше код и короче и иногда переусердствует! Ну и для AVR конечно конкурентов нет!
prottoss
Цитата(KRS @ Jan 16 2013, 18:12) *
Но обычно там ошибки связанные с "не красивым кодом" поэтому и не сталкивались sm.gif

Спасибо biggrin.gif

Цитата(KRS @ Jan 16 2013, 18:12) *
У IAR часто такие "смешные" ошибки оптимизатора, видно что он старается сделать как можно лучше код и короче и иногда переусердствует!
Это правда!

Цитата(KRS @ Jan 16 2013, 18:12) *
Ну и для AVR конечно конкурентов нет!
Там тоже есть переусердствования иногда.
Sergio66
Цитата(KRS @ Jan 16 2013, 15:49) *
А чего тут без листинга комментировать?
Исходник + листинг с указанием где компилятор ошибся!
(в большинстве случаев конечно находится своя ошибка, но и у IAR иногда бывают при оптимизации и в принципе чаще чем у других)

Код
            volatile flash_address_t PageNum = 0, PageOffs = 0;
            

            if (g_Int_F_Configurator.Overload == 1) {
              PageNum = (g_Int_F_Configurator.Next_Data_Area_Address  + IF_JOURNAL_START_ADDRESS)
                / IF_PAGE_SIZE;
              PageOffs =(g_Int_F_Configurator.Next_Data_Area_Address  ) % IF_PAGE_SIZE;
            }
            else {
              PageNum = 0;
              PageOffs = 0;
            }


Пока было просто - flash_address_t PageNum , PageOffs - вычисления всегда приводили к какой то ерунде в старшем байте PageNum .
Ну, кроме, разумеется строк PageNum = 0; и PageOffs = 0;
KRS
Цитата(Sergio66 @ Jan 16 2013, 16:31) *
Пока было просто - flash_address_t PageNum , PageOffs - вычисления всегда приводили к какой то ерунде в старшем байте PageNum .
Ну, кроме, разумеется строк PageNum = 0; и PageOffs = 0;

А как Вы об этом узнали? В отладчике?
Мы здесь не можем запустить отладчик с Вашим кодом, поэтому нужен листинг. Код тут не сложный там сразу все видно будет!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.