Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблемы с оптимизацией в WinAVR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Skaf
Всем привет.

С тех пор как мои проекты стали немного сложнее Hello World испытываю проблемы с программированием на WinAVR.

Из-за его оптимизатора программа изменяется на столько, что часто просто не работает. Я слышал про такие тонкости, что если подпрограмма не возвращает значения (если она void) то она может и выкинуться из выполнения вообще. Вот хотелось бы узнать про все такие тонкости, чтобы иметь возможность писать программы нормально. Или придется уходить на ассемблер. Никто не знает где почитать про это дело?
AHTOXA
Для начала пройдитесь поиском по форуму по ключевому слову volatile. Уверен, что 99% проблем уйдётsmile.gif
Огурцов
Цитата(Skaf @ Nov 1 2009, 09:46) *
С тех пор как мои проекты стали немного сложнее Hello World испытываю проблемы с программированием на WinAVR.

И при чем здесь оптимизатор ?

Цитата(Skaf @ Nov 1 2009, 09:46) *
чтобы иметь возможность писать программы нормально.

Учиться, учиться и учиться (с)
Skaf
Код
struct StatusStruct {
    volatile unsigned char RXbusy;
    volatile unsigned char TXbusy;
    unsigned char RXbuffer[15];
    unsigned char TXbuffer[15];
    unsigned char DataForSend[15];
    unsigned char RXdataSize;
    unsigned char TXdataSize;
    unsigned char RXcurrentByte;
    unsigned char TXcurrentByte;

    unsigned char ADCrawData[20];

    unsigned char ConversionChannel;
    unsigned char ConversionType; // 1 - All; 2 - One

    unsigned char DataForSendSize;
    unsigned char DataCurrentSendByte;

} Status;

......
.....

ISR(USART_RXC_vect){

    unsigned char Rbyte, ByteCount;

    volatile unsigned char  a;

    Rbyte = UDR;
    
    if (Status.RXcurrentByte < 15){
        Status.RXbuffer[Status.RXcurrentByte] = Rbyte;
        Status.RXcurrentByte++;

        a = Status.RXbuffer[Status.RXcurrentByte-2];

        if ((Rbyte == 0xBC) && (a==0xBB)){
            ByteCount = Status.RXcurrentByte-1;
            Status.RXcurrentByte = 0;
            DecodeFrame(ByteCount);
        }
    } else {
        Status.RXcurrentByte = 0;
    }
    
}


Во-первых в Wach про переменную a сказано Location not valid. Пока она не была volatile при отладке он просто перескакивал через строку

a = Status.RXbuffer[Status.RXcurrentByte-1];
А сейчас не перескакивает, но толку мало. в а все равно ничего не появляется и

if ((Rbyte == 0xBC) && (a==0xBB)){

всегда дает ложь. Причем реально данные в

Status.RXbuffer[Status.RXcurrentByte] = Rbyte;

записываются. Это видно в окошке Memory (Data) данные там действительно появляются.

структура Status объявлена глобально.
AHTOXA
Цитата(Skaf @ Nov 1 2009, 15:02) *
Во-первых в Wach про переменную a сказано Location not valid.


Правильно сказано. Изначально Status.RXcurrentByte == 0. Вы приняли первый символ, записали его в буфер, увеличили Status.RXcurrentByte (стало 1). А потом читаете a = Status.RXbuffer[Status.RXcurrentByte-2];

Цитата
Пока она не была volatile при отладке он просто перескакивал через строку


Кто "он"?
Skaf
Цитата
Правильно сказано. Изначально Status.RXcurrentByte == 0. Вы приняли первый символ, записали его в буфер, увеличили Status.RXcurrentByte (стало 1). А потом читаете a = Status.RXbuffer[Status.RXcurrentByte-2];


Это на первой итерации. Приходит несколько байтов и необходимо знать какой байт пришел предыдущим, чтобы обнаружить последовательность окончания пакета. На второй итерации, например, выражение

a = Status.RXbuffer[Status.RXcurrentByte-2]

уже имеет смысл.

Код
Кто "он"?


Отладчик
AHTOXA
Цитата(Skaf @ Nov 1 2009, 15:46) *
Это на первой итерации.

Вы считаете нормальным писать программы, которые работают правильно лишь на некоторых итерациях? И при чём тут оптимизатор?
Цитата
На второй итерации, например, выражение
a = Status.RXbuffer[Status.RXcurrentByte-2]
уже имеет смысл.

Ну на второй итерации "он" наверное и не пишет про "Location not valid".
Цитата
Отладчик

Какой отладчик? Вам помощь нужна или так, поболтать заглянули? smile.gif
baralgin
Skaf Как уже сказали необходимо исключить ситуации типа этой: Status.RXbuffer[Status.RXcurrentByte-2] - и не важно, что на каком-то из шагов это корректно.
Во вторых, вы всё же неправильно понимаете назначение слова volatile. Переменной a в обработчике ни к чему быть как volatile. А вот всем переменным структуры, учавствующих в обработчике, очень может пригодиться быть volatile. Изучите этот вопрос подробно.

Больше полагайтесь на элегатные,короткие алгоритмы, а не на отладчик smile.gif .
Skaf
Убрал пока эту конструкцию.

Но в Watch и переменные Rbyte, ByteCount являются Location not valid. На любой итерации.
xemul
Цитата(Skaf @ Nov 1 2009, 13:02) *
...

Не изобретайте велосипед - на прием/передачу заведите кольцевые буферы.
В прерывании по RX, имхо, кроме записи принятого байта в буфер, модификации указателя головы буфера и, может быть, взведения флажка приёма новых данных ничего делать не стОит.
Цитата
структура Status

похожа на сборную солянку.
_Pasha
Цитата(Skaf @ Nov 1 2009, 17:54) *
Но в Watch и переменные Rbyte, ByteCount являются Location not valid. На любой итерации.

Тяжелый случай... укзанные переменные размещаются в регистрах и не отображаются в отладочной. Смотрите регистры.
sigmaN
Кстати, да. Watch будет показывать всё и вся только когда выключена ВСЯ оптимизация и в проект включена Debug Info.
Верно и то, что для нормальной работы оптимизации желательно выключить Debug info ибо это только мешает оптимизации.
Более того, во время серьёзной оптимизации код может быть достаточно серьёзно перетасован/упрощен/прочее. Перескоки через строку не являются чем-то необычным. Просто после оптимизации этой строки больше нетsmile.gif Нужно смотреть на результат цикла/функции. И вот если результат поменялся после включения оптимизации - тогда уже смотреть что там должно быть volatile, чтобы результат был правильным. Ну и конечно нужно писать нормальный код - тут хоть с оптимизатором, хоть без него..... smile.gif

added: да, код ужасен smile.gif Переписать ВСЁ начисто!

Кстати говоря я раньше тоже писал типа
Код
if(){
   bla_bla_bla();
   foo();
}


Но практика показала, что
Код
if()
{
   bla_bla_bla();
   foo();
}
на много лучше. Советую привыкать сразу smile.gif Все эти мелочи помогают потом самому же разобраться что куда.
Skaf
Цитата
Но практика показала, что

Эта привычка с Perl'а осталась )
XVR
Отключите оптимизации и включите отладочнцю информацию (-Oo -g). Отладка оптимизированного кода - это занятие не для начинающих wink.gif
_Pasha
Цитата(XVR @ Nov 2 2009, 12:40) *
Отключите оптимизации и включите отладочнцю информацию (-Oo -g).

И при этом не иметь ни малейшего понятия, сколько времени будет выполняться код. И вообще - отлаживать одно - а получать на выходе совсем другое - это как минимум нетехнологично

Цитата
Отладка оптимизированного кода - это занятие не для начинающих wink.gif

Контрольные примеры надо составлять и без нужды не лезть за пошаговой отладкой.
sigmaN
Да да. Шагать ТОЛЬКО при выключенной оптимизации. Иначе можно так на шагать.
Я сам подрывался на таких, заложенных мною же минах smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.