Miejscowe wyłączenie optymalizacji kodu

0

Witam

Chciałbym wiedzieć czy istnieje możliwość wyłączenia w danym miejscu kodu jego optymalizacji. Piszę obecnie kod na stm32f4 za pomocą kompilatora GNU GCC. Optymalizacja jest ustawiona na -Os.

timerBaseConfig(TIM_TypeDef* timer, uint32_t speed_hz, uint32_t period_ms)
{
    uint32_t clock_speed=rccGetCoreFrequency();

    timer->PSC = clock_speed/speed_hz -1;       // Set prescaler to defined speed in hz
    timer->ARR = (speed_hz/1000)*period_ms;     // Auto reload value // @error trzba dojśc co zle liczy - dziwne zachowanie debuga
    timer->DIER |= TIM_DIER_UIE;
    timer->CR1  |= TIM_CR1_CEN;// Enable timer
} 

Po przejrzeniu kodu w assemblerze jak wygląda proces wyliczania wartości okazało się, że w linijce timer->ARR kompilator wpierw dzieli zmienne, następnie przechodzi linijkę niżej, przypisze makro i powraca do poprzedniego miejsca. Przez co dwukrotnie są zapisywane wartości do rejestrów i mi się krzaczy kod. Jeśli nie ma takiej opcji to po prostu wezmę zadeklaruję zmienną, która wymusi wcześniejsze policzenie wyniku tych działań.
Z góry dzięki za pomoc.

1

Wrzuć kod do osobnego pliku, który będziesz kompilował bez optymalizacji.

0

Dobry pomysł :]
Choć to jest jak dla mnie ominięcie problemu, podobne do mojego.

1

A ja nie do końca rozumiem co ci optymalizator psuje. Możesz wrzucić wynik gcc -S? Przecież kod po optymalizacji powinien być równoważny, więc w czym rzecz?

2

gcc ma pragma GCC optimize: https://gcc.gnu.org/onlinedoc[...]ction-Specific-Option-Pragmas

czyli #pragma GCC optimize ("O0")

0

Szczerze to jeszcze nie wiem co, bo zmienne są wyliczane poprawnie. Ale to co siedzi w rejestrach po wyjściu z funkcji w żaden sposób nie odzwierciedla tego co chciałem uzyskać. Te wywołanie timer->ARR zwraca bezpośredni adres rejestru w pamięci mikrokontrolera i podejrzewam, że przez te dziwne zachowanie jest on wywoływany conajmniej 2 razy przez co trafiają do niego śmieci a nie wyliczony wynik. Obecnie nie mam takiej możliwości potem podrzuce.

0
timer->ARR = (speed_hz/1000)*period_ms;

Jaką orientacyjną wartość ma speed_hz? Pamiętaj, że typy całkowite w dzieleniu zwracają wartość całkowitą, więc dla speed_hz == 999 wartość (speed_hz/1000)*period_ms będzie równa (999/1000) * period_ms czyli 0 * period_ms

0
kq napisał(a):

gcc ma pragma GCC optimize: https://gcc.gnu.org/onlinedoc[...]ction-Specific-Option-Pragmas

czyli #pragma GCC optimize ("O0")

Dzięki o coś takiego mi chodziło :] Przy kompilacji z "O0" wszystko pięknie śmiga.

#pragma GCC optimize ("-O0")

inline void
timerBaseConfig(TIM_TypeDef* timer, uint32_t speed_hz, uint32_t period_ms)
{
    uint32_t temp, clock_speed=rccGetCoreFrequency();

    timer->PSC =    clock_speed/speed_hz -1;    // Set prescaler to defined speed in hz
    timer->ARR = (speed_hz/1000)*period_ms; // Auto reload value // @error trzba dojśc co zle liczy - dziwne zachowanie debuga
    timer->DIER = TIM_DIER_UIE;
    timer->CR1 = TIM_CR1_CEN;// Enable timer
}
#pragma GCC optimize ("-Os")

Jeżeli dobrze rozumiem to jak na końcu umieszczę #pragma GCC optimize ("-Os") to dalszą część kodu skompiluje mi dalej na stary opcjach, a czy zamiast -Os jest jakiś jakiś parametr, który by użył starych ustawień z Makefile? Mam zamiar po prostu używać tego częściej, a nie chce by za każdym razem kiedy zmienię rodzaj kompilacji szukać po całym kodzie miejsc gdzie wyłączyłem optymalizację.

2

Do tego lepiej użyj #pragma GCC push_options i #pragma GCC pop_options.

#pragma GCC push_options
#pragma GCC  optimize("-O0")

void f(){}

#pragma GCC pop_options
0
kq napisał(a):
timer->ARR = (speed_hz/1000)*period_ms;

Jaką orientacyjną wartość ma speed_hz? Pamiętaj, że typy całkowite w dzieleniu zwracają wartość całkowitą, więc dla speed_hz == 999 wartość (speed_hz/1000)*period_ms będzie równa (999/1000) * period_ms czyli 0 * period_ms

To są rzędy do kilku kilo do kilkunastu mega Hertzów. Dodatkowo rejestr do, którego zapisuję i tak przyjmuje tylko typy całkowite więc nie tracę za bardzo na rozdzielczości.
Ale tak czy siak dzięki, za zainteresowanie :]

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0