Kezdem sejteni, mi a probléma. Az, hogy még mindig oprendszer fölött gondolkodsz, ahol 523 mélységben hívják egymást függvények, s ott ilyen előfordulhat.
Ezzel szemben mikrokontrolleren van olyan, hogy mindösszesen 2 - tehát kettő - a stack mélysége, vagy 8, esetleg 16. Szóval azért nem fog elromlani, mert vagy emlékszel, melyik az a három hely, ahonnan a módosított rutint hívod, vagy rákeresel a nevére CTRL-F-fel.
Azaz büntetlenül megváltoztathatom egy szubrutinom paraméter átadását is akár, mert pillanatok alatt megtalálom az összes hívást.
Értem, hogy operációs rendszer fölött, kész library-kat használva ez nem járható út, de többen, akik ezzel foglalkozunk, mondjuk nektek, hogy ez más műfaj, mint magas szinten programozni. A problémák, a hibalehetőségek is egészen mások.
Én még csak kész library-kat sem használok. Egyetlen include van a forrásom elején, ami az adott MCU regisztereinek, bitjeinek a nevét include-olja. Innentől kezdve egy üres semmi az editorban. Én így kezdek neki a kód írásának, s nem lesz nagyon bonyolult. Jellemzően néhány száz vagy néhány ezer assembly sor.
Mondok két lehetséges hibát. Az egyik, hogy egyetlen bit 1-be vagy 0-ba írása read-modify-write módon történik. Miközben egy port 5-ös bitjét 1-be állítod, beolvasod az egész port-ot, 1-be állítod az érintett 5-ös bitet, majd visszaírod.
Ha a kimeneti latch-ben mondjuk a 2-es biten 0 volt, a port bemenetként van programozva, a bemenetén magas logikai szint, tehát 1 van, úgy az 5-ös bitet 1-be állító utasítás beolvassa az egész portot, köztük a 2-es biten lévő 1-et is, majd a visszaíráskor szépen ki is írja a kimeneti latch-be az 1-et. Még nincs baj, mert a 2-es bit bemenet. Ha most kiforgatod ezt a bitet - tehát az eddigi nagy impedanciás bemenetből kis impedanciás kimenetet csinálsz, amelyik a kimeneti latch tartalmát fogja hajtani -, kimenetként magas szintet fog hajtani, holott korábban vélhetően azért volt 0 a kimeneti latch-ben, hogy alacsony szintet hajts majd a 2-es biten. Mindez egy figyelmetlenül használt bit állító utasítástól, aminek látszólag semmi köze sem volt a 2-es bitedhez. Tehát más logikai szint lesz a kimeneteden, mint amit oda írtál, s a kódban látszólag nincs olyan utasítás, amelyik azt a bitedet felülírná!
Hasonlóképp hiba, ha portra írás utáni utasításban olvasod ugyanazt a portot, például épp egy ilyen read-modify-write típusú utasítással, ami ráadásul felületesen szemlélve kizárólag írásnak tűnik. Azért gond, mert a 4 órajeles gépi ciklus második órajelében olvas, a negyedikben ír, így a kimeneten a következő utasítás olvasásáig még nem lett stabil a megváltozott logikai szint, ha túl hamar olvassuk azt vissza, különösképp, ha a lábon van kapacitív terhelés is. Szebben szólva nem lesz betartva a setup time-ra előírt követelmény. Így aztán nem az jön vissza a portról, amit az imént kiírtunk, hanem a korábbi állapot. De lehet, hogy csak némely biteken.
Ez a hiba viszont nem fog előjönni, s nem is hiba, ha a mikrokontrollert lassan hajtod, mondjuk 4 MHz-ig. Ha ennél gyorsabban járatod, vagy úgy kell elhelyezni a portot író utasításokat, hogy köztük legyen valami, vagy NOP-ot kell közéjük írni, vagy nem a portot, hanem a lath-et kell írni, de járható az is, hogy tükörregisztert csinálsz neki RAM-ban, ott bűvészkedsz, s az eredményt mindig csak írod a portra.
Aztán sok szerencsét ahhoz a szimulációhoz, ami összehozza, hogy 6 MHz-ig minden jól működik, nagyobb órajelfrekvencia esetén viszont hiába kapcsolsz egy port bitet 0-ból 1-be, néhány száz ns múlva visszabillen 0-ba. Viszont bőven van még tartalék sebességben, mert mondjuk 32 MHz-ről járatható legfeljebb ez a kontroller.
VaZso már említette, hogy a hardware nem software, s nyilván ilyenekre gondolt.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE