Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблемная опция Use Link-Time code generation, RVCT.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
baralgin
Столкнулся с проблемой при включении этой опции в настройках Keil'а (MDK-4.10). Судя по описанию это поззволяет компилятору "глубже" проводить оптимизиацию. В общем суть проблемы: есть функция, запускаемая прямо из main():

Код
void HardTest_Run()
{
    int counter = 0;
    while( counter < 100 )
    {
        while( !ready );
        ready = false;

        if( !isV15Valid( CalcValue(sums_saved.V15) ) )
        {
            lcd_manualSet(26,16,12);
//            lcd_setState(LCD_STATE_EHA);
            counter = 0;
        }
        else
        {
            counter++;
            int dig = 9 - (counter / 10) % 10;
            lcd_manualSet(dig, dig , dig);
        }
    }
}


переменная ready (volatile bool) периодически меняется функцией этого же модуля, которая вызывается из другого модуля обработчиком прерывания. При закоментированной строчке   lcd_setState(LCD_STATE_EHA); срабатывает if(!isV15Valid(...)) - хотя не должен. Если же закоментировать lcd_manualSet и раскомментировать lcd_setState, то if не срабатывает (как и должно быть). Самое смешное, что обе эти функции(lcd_xxx) по сути делают одно и тоже:

Код
void lcd_manualSet(uint_fast8_t d0, uint_fast8_t d1, uint_fast8_t d2)
{
    point1_on = false;
    point2_on = false;
    dig0 = d0;
    dig1 = d1;
    dig2 = d2;
}

void lcd_setState(uint_fast8_t state)
{
    point1_on = false;
    point2_on = false;
    dig2 = some_states[state][0];
    dig1 = some_states[state][1];
    dig0 = some_states[state][2];
}


где массив some_states константный.

В итоге этот код работает без проблем, если не ставить галочку "Use Link-Time code generation" , иначе только с плясками типа замены одной функции на другую(lcd_xxx). Чувствую что проблема где-то в коде, но не знаю какому типу ошибок характерны такие глюки.

ps: Стэк и кучу увеличивал, да и судя по статистике компилятора там с лихвой числа.
aaarrr
Нет, так не пойдет, слишком много вопросов: что такое isV15Valid, как объявлен тип bool и т.д. и т.п. Выделите "глюк" в компактный и самодостаточный пример.
baralgin
aaarrr
Код
volatile bool ready = false;

static bool isV15Valid(int val)
{
    return ( val > HardTest_V15_Min && val < HardTest_V15_Max );
}

static int CalcValue(int val)
{
    return (( val + (ADC_SCAN_COUNT / 2) ) / ADC_SCAN_COUNT);
}
HardTest_V15_Min, HardTest_V15_Max, ADC_SCAN_COUNT - константы.
Я и так уже выделил(функции упрощены). Я не знаю на каком этапе это произошло, т.к. вёл массовый рефакторинг, заворачивая всё что нужно и не нужно в классы. Но как выяснилось не в них дело, сейчас их нет, а глюк есть.

Добавил плотную задержку перед вызовом HardTest_Run() и заработало... Перед вызовом этой функции в общем то происходит инициализация переферии, в том числе и запуск АЦП на периодическое сканирование. Задержка сделана так:
Код
    volatile int xxx = 1000000;
    while( --xxx > 0 );

Причём она существенна(по ощущениям десятые доли секунды). Уменьшение xxx хотябы на один ноль и проблема "цветёт". В общем Немного прояснилось - завтра буду дальше разбираться...
baralgin
После долгих и мучительных танцев с известным музыкальным инструментом причину выяснил: компилятор слишком агрессивно соптимизировал переменную sums_saved.V15. Придётся все переменные структуры объявлять как volatile, во избежании. А их много...

Формально, кажется, что компилятор прав: в данном модуле есть функция модифицирующая переменные структуры sums_saved, но она вызывается из прерывания(к тому же из другого модуля). Но всё равно возникает ряд вопросов:
1) Оптимизация 03, time. Проблема возникает только при активации опции из названия топика.
2) Непонятное исчезновение проблемы в зависимости от того, что именно вызывается внутри злополучного if. Причём танцы вокруг функций модуля lcd меня окончательно запутали. Чертовщина просто smile.gif .
3) несколько раз полностью перерабатывал модуль меняя логику и порядок проверки параметров(и даже порядок объявления переменных и имена идентификаторов): проблема возникает строго в одном месте(V15), хотя кроме этого проверяются и другие параметры.
4) непонятно каким образом помогает гиганская задержка из предыдущего поста - никакой логики я не вижу. На данном этапе программы всё предельно просто(большую часть программы я просто отключил).
5) Под IAR 4.41 всё работает без проблем(естественно тоже при максимальной оптимизации на скорость).

Собственно мне скорость не критична(в реальном изделлии будет O3,size), но всё равно хочется не зависить от компилятора совсем...

ps: это типа крик души smile.gif : неужели придётся всё volatil'ить, что каким-нибудь боком связано с прерываниями...
igorsk
Цитата(baralgin @ May 16 2010, 13:40) *
ps: это типа крик души smile.gif : неужели придётся всё volatil'ить, что каким-нибудь боком связано с прерываниями...

А это, имхо, всегда хорошая идея.
aaarrr
Цитата(igorsk @ May 16 2010, 19:09) *
А это, имхо, всегда хорошая идея.

Нет, это всегда плохая идея - ставить volatile где надо и не надо, не разбираясь.
AHTOXA
Цитата(baralgin @ May 16 2010, 18:40) *
неужели придётся всё volatil'ить

Есть другой выход - не использовать Link-Time code generation. Особенно если
Цитата(baralgin @ May 16 2010, 18:40) *
скорость не критична

smile.gif
zltigo
Цитата(igorsk @ May 16 2010, 18:09) *
А это, имхо, всегда хорошая идея.

Глупее трудно придумать. Это называется полностью расписаться в собственной некомпетентности.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.