[MEGOLDVA]STM8S SDCC optimalizációs probléma

Fórumok

STM8S -re írok egy egyszerű polling -os i2c handlert.
Több helyen szükség van arra, hogy kiolvassak egy-egy státusz regisztert, így lehet tovább lépni. A beolvasott értékkel nem érdekel, nem kell vele műveleteket végeznem, de ki kell olvasnom, különben nem lehet tovább lépni.

Az egyik forrásban pl. így oldotta meg a szerző "(void) I"C_SR3;" - no ezt a mostani SDCC simán ki optimalizálja, hiszen semmire nincs használva.
Egyelőre úgy "kerültem meg" hogy foglaltam egy fájl globál változót és abba "olvasom bele" a regiszter értékét. (Később, lehet még jó valamire, mondjuk hiba kezelésre, de most semmi szükségem rá, csak foglalja az értékes memóriát.)

Tudtok valami más megoldást?

OFF: A terv az, hogy majd interrupt -ba kerül az egész, valószínűleg assembly -ben. De itt inkább az elv lenne a lényeg.

Hozzászólások

vagy írsz inline assembly-t az utasítás helyére vagy ha van az SDCC-ben olyan #pragma amivel ki lehet kapcsolni az optimalizálást (nem ismerem ezt a compilert pontosan) akkor használod azt.

Az inline assembly -vel az lehet a gond, hogy milyen utasítást is, hogy ne zavarjon bele a regiszter használatba.
Sajnos én sem ismerem elégg az SDCC -t. Még azt sem tudnám megmondani, milyen optimalizáció eredménye is ez, vagy mit is kellene kikapcsolni.

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

Az I2C_SR3-at volatile-kent kell deklaralni. Ha nem ugy van deklaralva akkor biztos kioptimalizalja fordito. Nem ismerem az STM8-as cimtartomanyait de pl AVR-bol kiindulva imigyen kellene, ha ott is igy hivnak ezt a 8 bites regisztert:

#define  I2C_SR3  ( *(volatile uint8_t *)(0x23))

De egzaktul ugyanez a sema ARM+STM32 eseteben is, csak ott inkabb 32-bites I/O van (bar van ott is 16 meg 8 bites is, sok esetben a doksi nem is explicit irja hogy kell 8 bites access, de... na mindegy, az mar mas problemakor, de a volatile oda is kell).

Na ez a helyes válasz.
Alapvetően ebből a blogból indultam el: https://lujji.github.io/blog/bare-metal-programming-stm8/
Itt az i2c kezelésnél az utasítás így néz ki: "(void) I2C_SR3;"
Először én is ezt használtam, majd miután nem működött elkezdtem molyolni a listában és kiszúrtam hogy be sem fordul.
Alapvetően egy másik fickó stm8s.h fájlját használtam, nem a lujji félét, ahol volatile -nak vannak definiálva a regiszterek.
Na nézhetem át mindent amit eddig csináltam :(

TANULSÁG: Van még mit tanulnom.

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

Nagyobb volt az ijedség mint a baj :)
Csak az interrupt címek nevét kellet módosítani (az én forrásomban).
Működik a volatile és (void).

Más kérdés, hogy így a compiler két utasítást is bevágott, egyszer tölti a az Y 16 bites "címző" regisztert, majd beolvassa a akksiba az ott talált értéket. Lehet ez gyorsabb mint implicite olvasni a regisztert ... megnéztem nem, ugyanúgy 4 ciklus.
(Borzasztó zavaró, hogy az STM és az SDCC jelölései kicsit eltérnek)

Köszönöm a tippet!

OFF: Több évtizede használok C nyelvet, de a "type qualifiers", ami const vagy volatile nem igen kellett. Legalább is nem emlékszem rá. (Sokkal gyakrabban jön elő, a "storage class specifier", lehet kevertem is a fogalmakat) Jó kis lavinát indított el ez nálam.

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

Más kérdés, hogy így a compiler két utasítást is bevágott, egyszer tölti a az Y 16 bites "címző" regisztert, majd beolvassa a akksiba az ott talált értéket. Lehet ez gyorsabb mint implicite olvasni a regisztert ... megnéztem nem, ugyanúgy 4 ciklus.

Ez itten valoszinuleg optimalizacio-fuggo. Az avr-gcc is csinal olyat hogy egy *(volatile uint8_t *)(0x20) olvasast azt siman asm("in r24, 0x00;");-nak fordit mondjuk -O3-as optimalizacioval. De optimalizacio nelkul pedig ugyanigy asm("ldi r28, 0x20; ldi r29, 0x00; ld r24, Y");-nek. Ezeeobbi 1 oracilus, ezutobbi pedig 3 vagy 4 :) De hogy miert az rejtely...  

Fontos megjegyezni, hogy az STM8x processzorok "extended" utasításkészlettel rendelkeznek, mig az AVR "reduced".

OFF: Az STM8x számomra a Z80 idézi sőt. (Én épp ezért szeretem.) Így nagyon elegáns kis assembly handlert írtam, az UART -ra. Sajnos korlátok vannak a változók átvételében az assembly és a C között.
Persze ez sem mindig elégséges. Pl. a "tiny-usb" ami egy ATtiny85 -ön (de lehet kisebb is) valósítja meg az USB HID kommunikációt, az úgy tűnik nem tud működni az STM8x pont az utasítás készlete miatt. Semmi sem tökéletes.

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

Fontos megjegyezni, hogy az STM8x processzorok "extended" utasításkészlettel rendelkeznek, mig az AVR "reduced".

Igen, nem ismerem ezt az MCU-t, de valoban ilyen CISC-light jellegunek tunik az utasitaskeszlet ;)

Sajnos korlátok vannak a változók átvételében az assembly és a C között.

Mgen... a gcc inline assembly-je elegge agyfaszosnak nez ki elsore, de valojaban pont ez az elonye hogy a valtozo-atadasok meg az ilyesmik egysegesen legyenek kezelve. Lehet hogy az SDCC ezt nem csinalja annyira jol es/vagy hatekonyan...

Pl. a "tiny-usb" ami egy ATtiny85 -ön (de lehet kisebb is) valósítja meg az USB HID kommunikációt, az úgy tűnik nem tud működni az STM8x pont az utasítás készlete miatt

Ez inkabb azert van/lehet mert a CISC-light jellegu instruction pipeline miatt sokkal nehezebben becsulheto hogy egy-egy utasitas hany oraciklusig fut le (noplane foleg ha memory wait cycle-k is kerulnek bele, amik az AVR-nel gyakorlatilag nem leteznek, ott nincsenek I/O wait cycle-k). Es ez a tiny-usb stack az nagyon-nagyon arra van kihegyezve hogy iszonyatosan pontosan tudjuk hogy melyik utasitas mennyi ido alatt fut le :) 

Ami meg mukodhet az egy ures while tehat while(status); vagy while(!status);, hogy ha lehet tudni, hogy biztosan lesz neki nulla vagy nem nulla erteke. Nyilvan kod memoriat ez is hasznal.

Igen, noha ez is kapcsolodik a feladatkorhoz de a kolleganak itten nem erre van szuksege. Inkabb csak egy interrupt flag acknowledgement-re, amit mikrokontrollertol fuggoen persze de eleg sok esetben egy sima input (regiszter ertek beolvasasa) is ki tud valtani.

Meg ez a while ( ... ) konstrukcio is tud csunyasagokat csinalni hogyha a status kifejteseben nem volatile-kent van deklaralva az adott I/O regiszter ;)