реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Непонятные действия оптимизации.
Oleg_IT
сообщение Dec 22 2008, 11:01
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Начал проект с простого (WinAVR-20070525), таймер и исключающее ИЛИ пина порта (PORTA) в обработчике прерывания этого самого таймера. На выходе ожидался генератор меандра. Загрузил, не работает. После некоторых мук определил, что виновата оптимизация, собираю проект без оптимизации всё работает. Немного расширил проект, стал работать и с оптимизацией, но всё равно некоторые важные части оптимизирует на свой лад. Я понимаю соптимизировать переменную, которая ничего кроме инвертирования не делает, но выкидывание работы с портом, этого я не понимаю. Может я и правда чего не понимаю.
Go to the top of the page
 
+Quote Post
mandrew
сообщение Dec 22 2008, 11:22
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 28-09-05
Пользователь №: 9 021



Как на счет объявить переменные с квалификатором volatile, а ввод/вывод сделать на асме.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 22 2008, 11:23
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Oleg_IT @ Dec 22 2008, 13:01) *
Может я и правда чего не понимаю.
А уж нам-то каково телепатировать!
Показывайте код.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Dec 22 2008, 12:54
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Я переменными для начала не пользовался и volatile мне не к чему. А на порт volatile ставить… В АСМе порты программировать можно, но если проект на Си, то и с портами желательно в Си работать.

Простенький код

Код
ISR (TIMER0_COMP_vect)
{
    TCNT0 = 0x00;
    PORTA ^= 1;
}

int main(void)
{
    TCCR0   = (1 << CS00);
    TCNT0   = 0x00;
    OCR0    = Dl;
    TIMSK   |= (1 << OCIE0);

    DDRA   = 0xFF;
    PORTA  = 0xFF;

    sei();

    while (1)
    {
    }
    return 0;
}
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 22 2008, 13:13
Сообщение #5


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Oleg_IT @ Dec 22 2008, 16:54) *
Простенький код
************************
TCCR0 = (1 << CS00);

Уважаемый, никакой Си не избавит Вас от необходимости курить мануал и думать головой. sad.gif
Каким макаком у Вас будет прерывание, если Вы не потрудились даже настроить таймер на работу с OCR0???
Go to the top of the page
 
+Quote Post
Ivan A-R
сообщение Dec 22 2008, 13:15
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 21-06-07
Из: Saint-Petersburg
Пользователь №: 28 607



% avr-gcc --version
avr-gcc (GCC) 4.3.1

Полёт нормальный.

% avr-gcc -Os -mmcu=atmega16 -S test.c

В ассемблерном листинге присутствуют в функции прерывания команды которые дрыгают ногой.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 22 2008, 13:28
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Сергей Борщ @ Dec 22 2008, 14:23) *
А уж нам-то каково телепатировать!
Показывайте код.
И для какого MCU Вы компилируете вашу программу?
Невозможно дать Вам совет по инициализации таймера не зная тип MCU.
И ещё, хочу Вам напомнить про сторожевой таймер:
Я не увидел в Вашем коде ни wdt_disable() ни wdt_reset()...
Пожалуйста форматируйте код в постах (есть волшебная кнопка # над окном ввода текста сообщения).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 22 2008, 13:42
Сообщение #8


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(demiurg_spb @ Dec 22 2008, 15:28) *
Я не увидел в Вашем коде ни wdt_disable() ни wdt_reset()...

А зачем им там быть? Раз нет значит не используется.

Цитата(_Pasha @ Dec 22 2008, 15:13) *
если Вы не потрудились даже настроить таймер на работу с OCR0???

Почему же, он всего лишь не выставил CTC (WGM01), и делает сброс таймера вручную. Такой способ тоже имеет право на жизнь. OCIE0 возникнет в любом случае при достижении таймером значения OCR0.


Oleg_IT
Ваша программа работает одинаково, как с оптимизацией, так и без нее.
Уточняйте, где смотреть проблему?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 22 2008, 13:51
Сообщение #9


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(defunct @ Dec 22 2008, 16:42) *
А зачем им там быть? Раз нет значит не используется.
Это не факт..


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 22 2008, 13:55
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(demiurg_spb @ Dec 22 2008, 15:51) *
Это не факт..

Тогда давайте посоветуем автору топика проверить фуз WDTON.
Больше вариантов произвольного включения WDT нет.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 22 2008, 14:11
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(demiurg_spb @ Dec 22 2008, 15:28) *
И для какого MCU Вы компилируете вашу программу?
Да, вдруг у него мега128 и стоит фуз совместимости с m103?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Dec 22 2008, 16:35
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(_Pasha @ Dec 22 2008, 16:13) *
Уважаемый, никакой Си не избавит Вас от необходимости курить мануал и думать головой. sad.gif
Каким макаком у Вас будет прерывание, если Вы не потрудились даже настроить таймер на работу с OCR0???

Уважаемый, я Вас не понял. Где тут ошибка??? В регистр TCCR0 устанавливаю бит CS00, который clkI/O/(No prescaling). Не отметил, МК ATMetga32. Я же говорю, без оптимизации все работает!!!

Вочдог не использую и фьюз не стоит.

Цитата(demiurg_spb @ Dec 22 2008, 16:28) *
Пожалуйста форматируйте код в постах (есть волшебная кнопка # над окном ввода текста сообщения).

Спасибо, учту.

Цитата(defunct @ Dec 22 2008, 16:42) *
Ваша программа работает одинаково, как с оптимизацией, так и без нее.
Уточняйте, где смотреть проблему?

Увы не одинаково и не стабильно. Без оптимизации всё нормально, с –Os и до –O1 чудеса.
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Dec 22 2008, 16:56
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Цитата(Oleg_IT @ Dec 22 2008, 19:35) *
В регистр TCCR0 устанавливаю бит CS00, который...

Так и надо:
Код
TCCR0   = (1 << CS00);
?
Или очепятка?
Код
TCCR0|= (1 << CS00);


Сообщение отредактировал Goodefine - Dec 22 2008, 16:57


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Dec 22 2008, 17:03
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(Goodefine @ Dec 22 2008, 19:56) *
Так и надо:
Код
TCCR0   = (1 << CS00);
?
Или очепятка?
Код
TCCR0|= (1 << CS00);

Нет, именно так
Код
TCCR0   = (1 << CS00);

это не очепяткаsmile.gif Просто в этом регистре мне ни чего не нужно кроме этого бита.
Go to the top of the page
 
+Quote Post
Ivan A-R
сообщение Dec 22 2008, 17:09
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 21-06-07
Из: Saint-Petersburg
Пользователь №: 28 607



Oleg_IT, попробуй сгенерить ассемблерный листинг с включённой оптимизацией и посмотри что выйдет. Если в листинге увидишь, что нужный код выкинут, значит обновляй тулчейн. Если не выкинут, значит ищи багу в другом месте.
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 22 2008, 17:44
Сообщение #16


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Oleg_IT @ Dec 22 2008, 18:35) *
Увы не одинаково и не стабильно. Без оптимизации всё нормально, с –Os и до –O1 чудеса.

Опишите плз. эти самые "чудеса".
Что не так?
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Dec 22 2008, 18:50
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(defunct @ Dec 22 2008, 20:44) *
Опишите плз. эти самые "чудеса".
Что не так?

С той простенькой программой при оптимизации меандра на выходе нет, а без оптимизации есть. В более расширенной версии оптимизатор «выкидывает» всё что в мейне под if (Start == 1) …

Код
ISR (TIMER0_COMP_vect)
{
    TCNT0 = 0x00;
    if (Flag == 1)
    {
        PORTA ^= 0x01;
        if ((PINA & 0x02) == 0)
            CountIn_1++;
        CountCycleImp++;
        if (CountCycleImp == ConstCntCycleImp)
        {
            PORTA          &=~ 0x01;
            Flag            = 0;
            CountCycleImp   = 0;
            Start           = 1;
            return;
        }
    }
    else
    {
        CountCycleImp++;
        if (CountCycleImp == ConstCntCycleWithoutImp)
        {
            Flag            = 1;
            CountCycleImp   = 0;
        }
    }
}

//////////////////////    MAIN   ///////////////////
int main(void)
{
    TCCR0   = (1 << CS00);
    TCNT0   = 0x00;
    OCR0    = 0x50;
    TIMSK   |= (1 << OCIE0);

    DDRA   = 0xFD;
    PORTA  = 0xFF;

    sei();

    while (1)
    {
        if (Start == 1)
        {
            Start = 0;
            if (CountIn_1 < CountIn_1_Min)
                PORT_W |= 0x04;

            if (CountIn_1 > CountIn_1_Max)
                PORT_W &=~ 0x04;

            CountIn_1 = 0;
        }
    }
    return 0;
}
Go to the top of the page
 
+Quote Post
Александр Куличо...
сообщение Dec 22 2008, 19:09
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017



Викидывает, потому что при запуске программы Start равно 0 и, следовательно, проверка условия бессмысленна. Компилятор не знает о том, что переменная может поменятся в прерывании. Ему это нужно указать с помощью квалификатора volatile:

volatile char Flags;
Go to the top of the page
 
+Quote Post
smac
сообщение Dec 22 2008, 19:14
Сообщение #19


Частый гость
**

Группа: Участник
Сообщений: 149
Регистрация: 2-06-08
Из: Москва
Пользователь №: 38 003



Цитата(Oleg_IT @ Dec 22 2008, 21:50) *
С той простенькой программой при оптимизации меандра на выходе нет, а без оптимизации есть. В более расширенной версии оптимизатор «выкидывает» всё что в мейне под if (Start == 1) …

Я конечно полный дилетант в С, но я бы объявил переменные и квалификатор volatile у переменной Start поставил
З. Ы. Надеюсь что нигде не ошибся в терминах
З. З. Ы. Упс, опередили

Сообщение отредактировал smac - Dec 22 2008, 19:15
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 23 2008, 00:48
Сообщение #20


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Oleg_IT @ Dec 22 2008, 20:50) *
С той простенькой программой при оптимизации меандра на выходе нет, а без оптимизации есть.

А что есть вместо меандра? Точнее плз ;>
У меня с той простенькой программой при оптимизации -Os меандр есть, по крайней мере я вижу что порт переключается...

Насчет Вашей новой программы, с учетом советов предыдущих ораторов, можно написать как-то так:
Код
#include <avr/io.h>
#include <avr/interrupt.h>


typedef unsigned char  U8;
typedef unsigned short U16;
typedef unsigned long  U32;

typedef volatile unsigned char  V8;
typedef volatile unsigned short V16;
typedef volatile unsigned long  V32;


#define ConstCntCycleImp 5
#define ConstCntCycleWithoutImp 3

#define CountIn_1_Min    5
#define CountIn_1_Max    10


#define PORT_W   PORTA


typedef struct tagDEVICE_CONTEXT
{
    U8  Flag;
    V8  Start;
    U8  CountIn_1;
    U8  CountCycleImp;
} TDEVICE_CONTEXT, *PDEVICE_CONTEXT;




TDEVICE_CONTEXT devContext = { 0 };


ISR (TIMER0_COMP_vect)
{
    TCNT0 = 0x00;
    if (devContext.Flag == 1)
    {
        PORTA ^= 0x01;
        if ((PINA & 0x02) == 0)
            devContext.CountIn_1++;
        devContext.CountCycleImp++;
        if (devContext.CountCycleImp == ConstCntCycleImp)
        {
            PORTA          &=~ 0x01;
            devContext.Flag            = 0;
            devContext.CountCycleImp   = 0;
            devContext.Start           = 1;
            return;
        }
    }
    else
    {
        devContext.CountCycleImp++;
        if (devContext.CountCycleImp == ConstCntCycleWithoutImp)
        {
            devContext.Flag            = 1;
            devContext.CountCycleImp   = 0;
        }
    }
}

//////////////////////    MAIN   ///////////////////
int main(void)
{
    TCCR0   = (1 << CS00);
    TCNT0   = 0x00;
    OCR0    = 0x50;
    TIMSK   |= (1 << OCIE0);

    DDRA   = 0xFD;
    PORTA  = 0xFF;

    sei();

    while (1)
    {
        if (devContext.Start == 1)
        {
            devContext.Start = 0;
            if (devContext.CountIn_1 < CountIn_1_Min)
                PORT_W |= 0x04;

            if (devContext.CountIn_1 > CountIn_1_Max)
                PORT_W &=~ 0x04;

            devContext.CountIn_1 = 0;
        }
    }
    return 0;
}

Я не знаю значений Ваших констант, поэтому поставьте какие должны быть. Работает абсолютно одинаково, с оптимизацией и без нее. Что я поменял:
1. Сгруппировал все переменные в одну структуру (удобнее писать программу, т.к. не нужно помнить все переменные, можно помнить только имя одной структуры остальное сделает Code Completion, и удобнее отлаживать - в watch достаточно написать только имя структуры и видно сразу все переменные).
2. Объявил типы в удобной форме (вместо длинючих "volatile unsigned char", ведь много удобнее и понятнее написать V8).
3. Объявил поле Start как volatile, чтобы компилятор не выбрасывал обращения к этой переменной на свое усмотрение.
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Dec 23 2008, 04:11
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(defunct @ Dec 23 2008, 03:48) *
А что есть вместо меандра? Точнее плз ;>
У меня с той простенькой программой при оптимизации -Os меандр есть, по крайней мере я вижу что порт переключается...

Спасибо за подсказку модификации кода.

В той простенькой программе с оптимизацией на выходе вообще ни чего нет.
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 23 2008, 19:57
Сообщение #22


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



А вы нам приведите ассемблерный листинг того варианта программы (функцию main и обработчик прерывания), в котором ничего на выходе нет.
Сразу будет видно, где чего не хватает smile.gif
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 01:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01561 секунд с 7
ELECTRONIX ©2004-2016