SDCC volatile

 ( tovis | 2017. november 21., kedd - 17:56 )

Ismerkedem az STM8S családdal. Egyelőre az SDCC mellett döntöttem. Most jutottam el az interrupt kiszolgáló rutinhoz.
A rutin egyelőre csak egy számlálót ketyegtetne és itt a következőt találtam az SDCC 3.6.9 leírásában:

3.8.1.1 Common interrupt pitfall: variable not declared volatile
If an interrupt service routine changes variables which are accessed by other functions these variables have to be
declared volatile. See http://en.wikipedia.org/wiki/Volatile_variable.

Kicsit zavaros nekem ez a volatile. Ráadásul amit eddig neten találtam stm8x.h a cpu regisztereket *(unsigned shar*) típőusként definiálja. Ha hiszünk a wikipédiának akkor ezeknek is volatile -nak kellene lennie. Vagy valamit félreértek?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Ha a főprogramból és interrupból is használsz egy globális változót, fennáll a veszélye hogy a C fordító a változót regiszterben tárolva használja a gyorsabb futás érdekében, így az interrupt és a főprogram valójában nem ugyanazt a globális változóértéket látja.

A volatile módosító a regiszterben tárolást tiltja, minden művelet után köteles visszaírni.

Lásd egy egyszerű példával (gcc -O2 -S teszt.c):

int tesztreg = 0;

int main() {
    tesztreg++;
    tesztreg++;
    tesztreg++;
    return tesztreg;
}

; volatile nélkül, azaz tárolhatja és optimalizálhatja regiszterben
main:
        movl    tesztreg(%rip), %eax
        addl    $3, %eax
        movl    %eax, tesztreg(%rip)
        ret

; volatile figyelmeztetéssel, azaz olvassa és írja vissza minden lépés után a memóriából/ba
main:
        movl    tesztreg(%rip), %eax
        addl    $1, %eax
        movl    %eax, tesztreg(%rip)
        movl    tesztreg(%rip), %eax
        addl    $1, %eax
        movl    %eax, tesztreg(%rip)
        movl    tesztreg(%rip), %eax
        addl    $1, %eax
        movl    %eax, tesztreg(%rip)
        movl    tesztreg(%rip), %eax
        ret

Ha portcím vagy memóriacím a változó, azt már nem optimalizálja a C fordító regiszterre, hanem kiírja. Eredetileg viszont erre is ajánlott volt a volatile módosítószó.

A volatile ellentétes módosítója egyébként a register, ahol a C fordítót arra utasítod, hogy ezt a változót próbálja CPU regiszterben tartani a gyorsabb futás érdekében. Ma már szinte feledésbe merült a "register" módosító, mert okos lett a legtöbb C fordító és az automatikus döntése megfelelő.

Köszönöm! Így már érthető.

OFF: Ez a szituáció az MCS-51 családnál jöhet elő ott van egy nagy kupac általánosan használható regiszter, de az STM8S ilyen nincs.

* Én egy indián vagyok. Minden indián hazudik.