AVR kontrollerek programozása

Fórumok

Kezdek összezavarodni :(
Minden különösebb gond nélkül eljutottam oda, hogy képes vagyok (most épp) egy ATmega16A assembler programozni - avrdude, jtag ice1 (kínai ocó) és avra.
Ahogy kicsit elkezdtem "bonyolultabb" dolgokat kódolni, rögtön eljutottam oda, hogy debuggolni kellene. Elvileg a jtag erre alkalmas. Fel kellett csapni a avarice "konnektort" a avr-gdb -hez - miután megadtam a device -t ez is elindult. Akkor jött a meglepi ahhoz, hogy debuggoljak a program elf formátumban kell hogy legyen - az égetéshez az hex a tuti. Itt viszont kiderült, hogy az avra nem tud ilyet :( Kopp. Zsákutca? Nem lehet ezt valahogy megoldani? Olyat nem találtam hogy "hex 2 elf", legfeljebb "hex 2 bin".
Előzőleg, már feltettem az arduino csomagot - vettem néhány arduino kompatibilis (klón) mütyürt és ezzel tudtam gyorsan kipróbálni - működik-e egyáltalán. A lényeg hogy fenn van a az avr-gcc avr-as és tartozékai. Ha jól értem ez letudja forgatni az assembly fájlomat, de csk össze-vissza panaszkodik:

avr-gcc -mmc=atmega16 ize.asm
ize.asm: file format not rcognized; treating as linker script
ize.asm:3: syntax error

A harmadik sor - megjegyzés :(
Megpróbálom átrágni magam az avr-gcc parancssori kapcsolóin - eléggé ijesztő - de ha valaki tudja a megfejtést azt megköszönném.
Már vagy tíz éve programoznak AVR kontrollereket Linux alól, csak nekem nem sikerül? :(

AVR UART teszt forrás:
http://pastebin.com/PKAwk6EY
"Ugyan az" csak tiszta assembly, avra fordító:
http://pastebin.com/SkXdPF1K

Friss forrás kód: http://pastebin.com/HHgUuEEZ
Friss "Makefile": http://pastebin.com/W72mZ2Qf

OFF:
Az már most jól látszik, hogy kénytelen leszek a C felé mozdulni. Az AVR processzorok RISC jellegű utasítás készletének köszönhetően a legegyszerűbb apróságok lekódolása is három-négyszer annyi utasítást igényelnek, mint mondjuk az MCS51 család (ami nem risc). Viszont (az én tapasztalatom szerint) vagy inline assembly vagy külön assembly modulok jól jönnek az időkritikus helyeken. Nem akarnám feladni az assemblert teljesen.

Hozzászólások

Szerintem avr-objcopy kell neked. Én nem szoktam assemblyben dolgozni, de a gcc kimenete alapvetően elf (vagy exe), ebből az objcopy csinál ihex-et (vagy srec-et), gondolom visszafelé is menne neki.

Amúgy az assemblyt szerintem nem igazán célszerű használni már. Gyakorlatilag az egyetlen előnye, hogy garantáltan tudod mennyi idő telik el két utasítás között, de ritka az olyan eset, hogy egy-két us hiba nem fér bele, ha meg belefér, akkor jobb a timereket használni. Ha mégis ilyen kell akkor ott az inline assembly, ami egész jó cucc, csak van egy-két kellemetlen hülyesége, meg elsőre teljesen átláthatatlan a paraméterkezelése.

Assembly-t nem könnyű programozni. Sajnos csalóka, mert az elemi utasításokat könnyű megtanulni, de ahogy az ember nekiáll egy nagyobb programnak, megérzi az assembly hátrányát.
A látszólagos tanulási előnyt intenzív tanulást feltételezve már a második héten lekörözi a C.

Nem beszélve arról, hogy húdejó ha tud az ember X processzort assembly-ben programozni. Aztán kap egy másik architektúrát és ... minden előlről?

Brian Kernighan, Dennis Ritchie és Ken Thompson ezt megtapasztalták 45 évvel ezelőtt. Lett is belőle egy frankó C nyelv és Kernighan & Ritchie -féle The C Programming Language könyv, ami azóta is referenciamű.

Assembly helyett a C a mikrovezérlőkre sokkal praktikusabb. Akár átláthatóság, akár más mikrovezérlőcsaládok programozására való áttérést tekintve is.

Startnak AVR-hez ezt még német nyelv ismerete nélkül is merem ajánlani:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Példaprogramokat tanulmányozd, másold ki, fordítsd le, próbáld ki.

Nagyjából egyetértek, de finomítanám.
Az architektúra megismerése megkerülhetetlen. Szerintem akár a PC -re sem lehet úgy szoftvert írni, hogy nem ismered az architektúrát.
Az assembler azért tud hasznos is lenni, de csak azért hogy "kitöltsd" a C library megfelelő eljárásait. Vannak esetek, ahol a kód optimalizálás során jutsz el oda, hogy kell az assembly - persze kicsi és gyors rutinok számára - pl. interrupt kiszolgálás.
A C akár nevezhető szimbolikus/univerzális assemblernek, illetve az ott kidolgozott eljárások jó keretet adnak milyen eljárásokra is lehet szükséged a program felépítése során.
Az említett honlapot köszönöm már megtaláltam és tényleg hasznos.

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

Egy jól megírt c kódnak nem kéne lassabbnak lennie egy jól megírt assemblynél, főleg nem kicsi és gyors rutinokhoz. Azt mondjuk el tudom képzelni, hogy valaki jobban optimalizál monduk ciklust mint a gcc, de az esetek nagyrészében még azt is meg lehet csinálni c-ben.
Bár a jól megírtsághoz kétségtelen, hogy ismerni kell az architektúrát, legalább annyira, hogy hány bites az ALU és meddig tart egy memóriaművelet.

Szerintem az assembly jobban olvasható, persze mikrokontroller esetében. Nyilván tökéletesen alkalmatlan az assembly nyelv magas szintű, alkalmazás rétegben történő programozásra. Ugyanakkor olyan esetben, ahol 8 bit * 24 bitre, és 8 bit * 16 bitre külön szorzó rutint írok, mert az utóbbi IT-ben fut, időkritikus, az előbbire meg szükség van a számábrázolás miatt, akkor nagyon nincs kedvem egy '*' jellel leírni a szorzást.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

De ehhez minek assembly?

value = variable24bit * variable8bit;

value = (uint16_t)variable16bit * variable8bit; /* castolás csak akkor kell, ha variable16bit igazából nagyobb, de te tudod, hogy befér 16 bitbe. */

Oké, az első a általában 32 bites szorzásra fordul, de a modernebb gcc-k pl már tudnak 24 biten számolni.

Az olvashatóság meg megszokás kérdése, de azért a c-t szerintem többen tudják olvasni, mint az assemblyt. Főleg, hogy utóbbi nagyon platformfüggő.

Na, de épp azt mondom, hogy kétféle szorzó rutinnak kell lenni, nem library-ból előhúzni egyet, betölteni a paramétereket, szorozni, elvenni az eredményt.

A 16 * 8 bitesnél követelmény, hogy gyors legyen, konkrét példámban 213 gépi ciklus. A 24 * 8 bitnél meg az, hogy beleférjen a 24 bites szám, és véletlenül se használja ugyanazon regisztereket, mint a másik, mert az IT-ben fut, ez meg nem, és a regiszterek mentésére nincs idő.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Oké, arról nem volt szó, hogy nincs idő push/pop-ra, így értem. De az rossz érv, hogy kétféle szorzás rutin kell, ezt c-ben is nagyon könnyű megcsinálni. És meglepne, ha a 16 bites szorzás c-ből megírva nagyon eltérne a te 213 ciklusodtól, max néhány százalék szerintem.

Nem vitatom, manapság nagyon jók a fordítók. Van ebben egy szubjektív elem is a részemről: szeretem kézben tartani a dolgokat, bit szinten látni, mi történik. Én még az az őskövület vagyok, aki Z80 assembly-vel kezdtem a számítástechnikát. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ez mondjuk jogos. :) Kommentelés segíthet. Bár tény, amikor írom, annyira benne élek, úgy érzem, önkommentelő az egész, hiszen annyira logikus, de ne tudd meg, fél év múlva saját kódom esetében sem értem, hogy ez meg hogyan működik. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Átérzem a dolgot, én is állandóan "túloptimalizálom" a dolgokat, viszont x64 esetében - főleg ha használom a fordító "különc" képességeit is -, nagyon ritka esetben tudtam sokkal gyorsabb kódot írni, mint a fordító (de első blikkre kb 10-15%-ot tudtam ráverni, de ezt is csak azért, mert én !pontosan! tudom hogy mit szeretnék, ő meg max kitalálni tudja).
Persze egy mikrokontroller megint más, ott c-ben nem tudod garantálni a 100%-ig pontos időzítéseket, kénytelen az ember asm-hoz nyúlni

// Happy debugging, suckers
#define true (rand() > 10)

Amúgy ha ennyire ki kell valamit optimalizálni, akkor lehet esetleg érdemes más mcu-t választani. Tudom, van olyan eset, hogy erre nincs lehetőség, meg klassz érzés büszkén elmondani, hogy 32B RAM-ban megcsináltam azt amihez másnak néhány k kellett, de ha a megrendelő szempontjait nézed, őt ez marhára nem érdekli, és 2$ alatt lehet kapni 100MHz-es Cortex-M4-eket.

A példámban nem termékfejlesztés szerepelt, hanem hobby. Néhány szempont:

- nagyon alacsony fogyasztás, tehát feleslegesen ne legyen nagy a fizikai órajel

- nagy sebesség, mert PWM-mel kellene hangot lejátszani. Alacsony sebesség esetén a felbontás illetve a mintavételi frekvencia csökken

- memória mérete, hogy olcsó legyen a kontroller

- mivel egy darab, lehessen kapni DIP tokban

Nyilván mások a prioritások, ha prototípus készül, amelyből gyártmány lesz. Az első két szempont ellentmondásának az a feloldása, hogy a lehető legalacsonyabb órajel mellett a legtöbb művelet végződhessen el, tehát optimális legyen a kód.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Olcsó, gyors, kis fogyasztás ---> 8 bites őskövületek helyett az olcsó ARM Cortex M0 a barátod. Órajelét a legtöbb esetben a 8 bitesnél alacsonyabbra választhatod, hiszen sok 16, 24, 32 bites műveletet egyben ledarál, nem pedig egy rakás 8 bites utasításból pakolja össze.

Létezik DIP tokban? Nyilván az is szempont volt, hogy ne kelljen fejlesztői környezetet venni hozzá, mert ugye nem azzal ér véget a történet, hogy a kód lefordult, és előállt a hex file. Valahogyan a kontroller flash memóriájába bele kell gyömöszölni a bináris tartalmat.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Minden tiszteletem ellenére kérlek vedd észre, hogy a felület szerelt alkatrészeké a főszerep. A DIP tokos cuccok szinte csak a deszkamodellekhez használatosak. Régi szép és daliás időkben ez volt a technológia, de manapság a "produktum" az felület szerelt.
Az adapter lapok (SMD - DIP) jelentik a megoldási lehetőséget. A sorozat (ha lesz) azt meg hagyd a profikra. Egyébként számtalan kisebb-nagyobb arm processzort lehet egy kis lapra szerelve, már órajel és reszet áramkörrel, néhány ezer forintért kapni.
Ami inkább fontos, hogy a fejlesztéshez "fel kell állnia" számos dolognak és még bele is kellhet tanulni (ami idő).
Sok éve, számos okból arra a következtetésre jutottam, hogy olcsóbb egy használt (márkás) ócska PC -t befogni. Pl. csináltam GSM/GPRS - soros illesztőt olyan GSM modulokkal aminek nem volt IP stackje - akkoriban egy ilyen beágyazott modul 100 eFt vagy afölött volt - én meg anyagárban kihoztam 20 eFt -ból plusz egy kis szoftver. Természetesen ha valami hiba volt, komplettül cseréltem a ládát. Igaz hogy sokat fogyasztott és sok helyet foglalt, de évekig működött halál megbízhatóan néhány ponton, bevágva a szekrény aljába. A fejlesztési idő alig egy hónap.
OFF: A régi regula úgy szólt, hogy ha kell még valamilyen funkció végy elő egy relét. Aztán jöttek a csövek, majd a félvezetők. Én ezt odáig vittem, hogy végy egy PC -t :) Fejlesztés szempontjából olcsó és roppant gyors megoldás. Üzemeltetés szempontjából már nem annyira jó a megoldás, e az esetmeben jól működött.

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

Azért engedtessék meg, hogy ne csak és kizárólag termékfejlesztés történhessen sorozatgyártáshoz. Az munka. Meg van az, amikor otthonra kell valami. Az meg hobby. Ez utóbbinál erősen szempont, hogy ne kelljen nyákot gyártatni, mert az igen drága kis darabszám esetében. Tehát mi marad? A DIP tokos mikrokontroller. És máris megbukott az a javaslat, hogy nagy erőforrású, 32 bites processzort válasszon az ember, C-ben programozzon. Minek? Teljesen jó a 8 bites kontroller assembly-ben megírt kóddal.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A mikrokontrollernek a speciális, egyedi igények megvalóstása a feladata legtöbbször. Ezt 1 %-nak gondolni nekem szokatlan. Elképzelem, amint egy < 200 Ft árú mikrokontroller helyett R-Pi-t építek a falon egy szürke dobozba > 10 000 Ft-ért, amelyik fénycső késleltetett kikapcsolását intézi, de egyéb apró feature-ei is vannak. Nem mindegy, hogy nyákon megy busz, ezért zavarérzékeny a szerkezet, vagy minden chipen belül van. A fogyasztás is egy külön kaland.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Persze, lehet összerakott cuccokat használni, ezért van a net tele minőségileg, khm. tudod
Viszont egy led villogtatásához ne használjunk már egy raspberry-t, mert erre a célra tökéletesen megfelel egy halom kommersz alkatrész. De jó, legyen, villogtassunk programozottan, de nem fogok 15k-t fizetni egy olyan cuccért, amit egy ~100 ft-os dologgal is megcsinál az ember

// Happy debugging, suckers
#define true (rand() > 10)

alma-körte. Az ATmega328-pu csak negyed annyi mint amennyit irtal (1$, ez kerül az arduino-kba is, nem a sima). 5$-ert viszont valoban van arduino (az smd tokos atmegaval szerelt, nem a dip tokos). Ha az smd vonalat nezem, akkor mar 0.5$ kornyeken hozzajuthatok egy atmegahoz, szamomra felesleges sallang nelkul.
Panelt igy is ugy is gyartani kell, nem szeretem a sundisznot, igy meg csak beletervezem, beforrasztani meg legalabb +1 perc a fejleszesi idohoz;)

// Happy debugging, suckers
#define true (rand() > 10)

Amiket én néztem, azok a komplett board-ok, nem csak a procik. Előnye ahogy leírtam, nem kell forrasztgatni, össze van rakva, ki van tesztelve. A hátránya, mint
ahogy azt is leírtam, hogy nem biztos, hogy pont azt adja, ami az embernek kell. Prototypingra, sőt, gyakran full fejlesztéshez is egyre többször ilyen boardokat
látok, főleg sw-eseknél, akik nem akarnak forrasztgatni, nyákot tervezni, stb.

Mint mondtam, sok arm, avr és pic processzorral szerelt kis kártyát lehet kapni készen, ehhez már "csak" az adott feladathoz szükséges perifériát kell oda tenni. Ezek a kis board -ok olyan árakban vannak, hogy a DIP tok cinezésével foglalkozni is vétek.
(Egyébként most éppen egy DIP tokos ATmega16A áll az asztalomon de bread boardba dugva, sajnos a kvarcot kénytelen voltam egy kis panel "morzsára" cinezni, így tudtam mellé dugni)

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

Ha megveszel egy kész nyákot, azon éppen az a hardware lesz, ideértve az analóg részeket is, amelyeket megálmodsz magadnak? Én nem hiszek ebben. :) A geometria, konstrukció is illeszkedni fog oda, ahova beépítenéd? Rögzítő csavarok, hűtés, ha kell, minden? Ez biztos?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Hááát. Csalódtam benned :) Régen úgy mondtuk, hogy "Jééé egy doboz! Mit építsek bele?"
A tréfát félretéve, ez ahhoz hasonlít hogy a szoftvert honnan építsük? - alulról felfelé, vagy felülről lefelé. Tekintve hogy az smd cucc milyen kicsi, az egyedi nyák gyártás, vagy próba panelre forrasztgatás/huzalozás mennyi időt vesz igénybe ...
Szerintem fordítva kell felülni a lóra, azaz kereskedelemben kapható cuccokhoz kell idomulni és nem fordítva - persze ez nem kívánatos kompromisszumokat is behoz.
Tisztelem az elszántságod, de érdemes először körülnézni, kicsit számolni és aztán dönteni, mi is az amit neked kell megcsinálni és mi az amit meglehet, érdemes megvenni.

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

+1. Ha minimál idővel akarunk dolgozni, akkor tényleg a célhoz legközelebbi hw-t érdemes megvenni, és max a plusz board-ot megcsinálni, a kettőt meg összekötni. Persze
hobbi projektnél aztán ráér az ember szöszölni az ilyesmivel, de én akkor is inkább csinálnék egy prototipust, aztán ha működik frankósan, utána kezdenék el nyákot tervezni...

http://uk.farnell.com/nxp/lpc810m021fn8fp/mcu-32bit-cortex-m0-30mhz-dip…
:)
Igazából valami filléres devboardot kerestem, mert ezek lényegében mcu+programozó eszköz+raszteres tüskesor+néha kristály, szóval lényegében olyan jól használhatók próbanyákkal mint egy dip tokos mcu, de ezt dobta ki az internet elsőre.

Szerk: Amúgy én is valószínűleg valami avr-rel fognék hozzá pillanatnyilag bármilyen hobbiprojektnek, hacsak nem lenne cél valami új mcu család megismerése, legyen akármennyire rossz is a célra, mert azt ismerem, és sokkal gyorsabban haladok vele. Csak itt annyira elkalandoztunk, hogy nem is tudom már, hogy hobbi vagy munka.

"- nagyon alacsony fogyasztás, tehát feleslegesen ne legyen nagy a fizikai órajel"
Ez egy mítosz. Az órajel nem mond semmit, se a gyorsaságról, se a fogyasztásról.
1. Lehet hogy egy MCU-nak 4 órajel kell ugyanahhoz a művelethez, amihez a másiknak 1 órajel is elég.
2. A feladatot a gyorsabb MCU gyorsabban végzi el, így többet tud aludni.

A tipikus alkalmazások esetén pedig - ahol az idő nagy részében időzítetten alszik, illetve megszakításra vár az MCU - sokkal fontosabb az alvási módokban való fogyasztás (és hogy meddig mehetünk le az alkalmazásunkban). Ráadásul ez esetben jobb lehet a nagyobb órajel (lásd 2.)

"- nagy sebesség, mert PWM-mel kellene hangot lejátszani. Alacsony sebesség esetén a felbontás illetve a mintavételi frekvencia csökken"
Szinte minden normális MCU-ban van hardveres PWM lehetőség, ehhez nem kell nagy "sebesség". Főleg hang előállítására.. kHz vs MHz

"- memória mérete, hogy olcsó legyen a kontroller"
Ez hobbi chipeknél és kis tételben igaz. Azonban a memória mérete az árban csak adott családon belül jelentkezik (és ebben is csak bizonyos darabszámig). Egy ilyen kis chip gyártásánál általában fontosabbak a feature-ök, a lábszám és a méret.. Például a most megjelent - csak a flash memória méretében eltérő - STM32F042F4P6 és STM32F042F6P6 között kemény 17 Ft különbség van :) Az egyik 16 kB, a másik 32 kB flash memóriával rendelkezik.

"- mivel egy darab, lehessen kapni DIP tokban"
Ha meg akarod kímélni magadat (mert mondjuk van munkád és legalább McDonalds órabéren dolgozol), akkor 1-2 darabra inkább veszel boardot.
Például: http://www.ti.com/ww/en/launchpad/launchpads-msp430.html
Vagy például 3 db: https://store.ti.com/EZ430-T2012-MSP430-USB-Stick-F2012-Board-P955.aspx
Hozzá a programozó/debugger egység: https://store.ti.com/EZ430-F2013-MSP430-USB-Stick-Development-Tool-P800…
Ezeket ingyen osztogatták konferenciákon, például nekem is onnan van.

Miért mítosz? Amikor egy komplementer mos-fet pár átkapcsol, lesz egy olyan időpillanat, amikor egyik csatorna ellenállása sem végtelen, tehát áram folyik rajtuk. Továbbá a gate-csatorna kapacitást is fel kell tölteni, a töltéshordozók odajuttatása szintén áramot jelent.

Statikusan nem folyik áram, fogyasztás sincs. Tehát minél gyakoribbak az eszközben az átkapcsolások, minél gyorsabban járatod, annál többet fogyaszt.

Az 1 órajel természetesen nem igaz. Az valójában sok órajel, csak pipeline-okat használnak, az utasítások átlapolva kerülnek végrehajtásra. Tehát az az ára a dolognak, hogy több tranzisztornak kell átkapcsolni egy-egy órajel alatt.

A kHz vs. MHz azért hibázik egy picit, nem? 7.5 kHz sávszélességhez kell legalább 15 kHz mintavételi frekvencia. 10 bites felbontás esetén ehhez a számlálót nagyjából 16 MHz órajelről kell járatni. Másfelől viszont a PWM regiszterét 15 kHz-cel kell etetni, de addig a hozzá szükséges adatot el kell hozni memóriából például egy SPI buszon, némi kódnak futnia kell, mert csak tudnia kell, hol a vége, esetleg adódhat más teendője, hiszen hang generálása közben sem állhat le az élet, stb.

Írtam, ne csak a sorozatgyártást vegyük ide, hanem a kis szériájú, egyedi hobby projecteket is.

Az általad linkelt nyákok szerepét nem igazán látom. Jó akkor, ha valaki meg akar ismerni egy CPU-t, de semmire nem mégy vele, ha konkrét elképzelésed van, hiszen nyilván nem az a hardware van a nyákon, amit szeretnél, amit terveztél. A nyák geometriája, rögzítő furatok sem épp oda fognak esni, ahova kellene.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

OK, folyik áram, nagyrészt a tokozás szennyeződésén. :) Szóval van, csak kicsi.

Félreérthettél. SPI-t a memória eléréséhez írtam. ADC ugyan van, de most DAC kell. Mellesleg az ADC meg zajos, ha megy a CPU core.

10 bites PWM-hez 1024-ig kell elszámolni egy ciklusban. Ha ebből van másodpercenként több, mint 15000, akkor ebből kb. 16 MHz jön.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A tényleges megvalósításban a PWM mögé raktam egy passzív 4-ed fokú szűrőt, amelyet numerikusan méreteztem.

Egyedi darabnál szempont az is, hogy ne kelljen sokat forrasztgatni, szóval a PWM erre jó megoldás volt nekem. Mindegy, nagyon elkanyarodtunk. Az eredeti mondandóm az volt, hogy szerintem mikrokontrolleres környezetben van létjogosultsága az assembly programozásnak.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ez érdekes! Mit csinálsz? Sleep a mag amíg mérsz? Esetleg esetben sample end hold?
Mekkora a zaj? - % vagy bit? Milyen feltételekkel mérted?

OFF: Mindig csodálkoztam, hogy a PC hangkártya, a régi TV tuner kártyák hogy nem szedik össze a zavarokat. A PC bele egy pokol. Mi lehet ha egy 5x5 mm morzsán van minden?

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

A mérés idejére sleep teljesen jó lenne, ha közben nem lenne más dolga a CPU-nak. De van. És akkor már - erről a katalóguslap is ír - zajos lesz a konverzió. Chipen belül lesz zajos, nem a hozzávezetésen. Mivel épp hangról van szó, tapasztaltam. Nem is kicsit, nem az LSB 1 bitnyi hibájában testesül ez meg.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Tapasztalatom szerint tempóban egy jól megírt C kód szélsőséges esetben minimum 80%-át hozza a nagyon kioptimalizált assemblynek. Nem szélsőséges esetben 95%-át, de alább bemutatok egy esetet, amikor a C ráver a mezei assembly programozóra.

Assembly-t olvasni tudni viszont tényleg hasznos, ahogy a proci hardver utasításkészletével és annak idejeivel is katalógus szinten érdemes lehet összebarátkozni.

Például:
- van-e a prociban barrel shift, vagy csak sima shift?
- van-e külön add és adc (carry-vel) vagy carry feltétel vizsgálat kell (feltételvizsgálat + inc : PIC16Fxx http://ww1.microchip.com/downloads/en/DeviceDoc/40300C.pdf 111. oldal)
- van-e benne hardverszorzó?
- van-e benne hardverosztó és modulóképző?

Ha írok egy algoritmust az adott mikrovezérlőre, ezt időkritikus esetben figyelembe kell venni.
Annó réges-régen volt ilyen problémám (C64 - mai 8 bites mikrovezérlőnél sokkal lassabb procija), ahol a pixelmemória számításhoz 320-szal kellett gyorsan szoroznom.

Mivel nem volt annak sem hardverszorzója, ezért ha lazán szoroztam volna, igen fájdalmas lett volna. De tudtam hogy nincs szorzó.
Így C szintaktikával leírva:


  er = x;    // *1
  er <<= 2;  // *4
  er += x;   // *5
  er <<= 6;  // *5*64 = *320

És ez akárhogy nézem, 8 bites architektúrán shiftenként 2 órajel (shiftL, shiftH), barel shift hiányában er <<= 6; ---> ez 12 órajel.
Összeadás pedig add lo és adc hi (utóbbi automatikusan carry-vel csinálta), 2 órajel.
Összesen belátható hogy a fenti kódrészt ha arra az architektúrára normális C fordító fordítja, 20 órajeles blokként illeszti be és a végén még +2 órajel hogy visszategyem ugyanazon interfész regiszterbe. Ez tehát összesen 22 órajel.

És mi ebből a tanulság?
- nem programoztam egy sort se assemblyben, hordozható maradt a kód
- mégis tudom, mi lesz normális esetben az elvárható kód --> "gcc -O2 -S" és ellenőrizni tudom.
- ezt azért tehetem meg, mert ismerem a proci assembly utasításait, időzítéseit.
De nem írtam egy deka kódot sem a munka során assembly-ben, csak hordozható C-ben.

És végül nézzük meg, mi lesz belőle AVR8 architektúrán:

unsigned short szor320(unsigned short x) {
    unsigned short er;
    er = x;    // *1
    er <<= 2;  // *4
    er += x;   // *5
    er <<= 6;  // *5*64 = *320
    return er;
}

Az igazság pillanata: avr-gcc -O2 -S 320.c # 320.s fájlban az assembly


        .file   "320.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
        .text
.global szor320
        .type   szor320, @function
szor320:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        mov r18,r24     ; ez a rész az   er = x;  (x értéke  r25:r24 duplareg)
        mov r19,r25     
        lsl r18         ; ez a rész az   er <<= 2;
        rol r19
        lsl r18
        rol r19
        add r18,r24     ; ez a rész a    er += x;
        adc r19,r25
        mov r24,r18     ; itt érdekes dolgot játszik, ugye innentől  er <<= 6; jön
        mov r25,r19
        clr __tmp_reg__ ; mi ez?
        lsr r25         ; és miért jobbra? Balra kértem 6-ot
        ror r24
        ror __tmp_reg__    ; és már látszik, hogy legyőzött a C fordító ...
        lsr r25
        ror r24
        ror __tmp_reg__
        mov r25,r24        ; helyére rakja a felső és alsó byte-ot (r25:r24 a visszatérő).
        mov r24,__tmp_reg__
        ret
        .size   szor320, .-szor320
        .ident  "GCC: (GNU) 4.8.1"

A C nyelv és fordítója együtt legyőzte ismét az assembly ötlettáramat. Miért nyert a C-ben írt kód tempót az én elképzelésemhez képest?
Mert a GCC ahelyett, hogy szolga mód er <<= 6; -ot csinált volna, ahogy én írtam volna assembly-ben, helyette jobbra shiftelt 2-t és a kieső biteket __tmp_reg__ -be rakta és ebből lett az alsó byte, az eredeti alsóból pedig a felső.

Tehát a C 114 %-os tempót adott már itt az én eredeti assembly elképzelésemhez képest. Viszont hogy mégis belekössek: a végén ha r25:r24 helyett ideiglenesen r24:r25 inverz sorrendet használt volna a fordító, az utolsó előtti mov utasítás elhagyható lenne. Hurrá, egy utasítást mégis kézzel ki tudtam nyerni!!!

Viszont a C fordító leleményessége nélkül alapból sokkal lassabban futó kódot raktam össze.
Tehát van amikor a C fordító okosabb a "mezei" assembly programozó logikájánál.

Nézzük az alábbi kódot, tehát nem adjuk a fordítónak meg, hogy hogyan csinálja


unsigned short szor320(unsigned short x) {
    return 320*x;
}

avr-gcc -O2 -mmcu=attiny13 -S 320-szorzat.c # nincs hardverszorzó az attiny13-ban

Ebben az esetben az assembly-t megnézve gyakorlatilag azonos az előzőekben írt shift, add, shift módszerrel a kapott kód. Egy különbség: attiny13-nak is van már movw utasítása (2 byte-ot másol)

avr-gcc -O2 -mmcu=atmega48 -S 320-szorzat.c # van hardverszorzó az atmega48-ban

A C fordító által kiadott kód lényegi része:


szor320:
        ldi r18,lo8(64)  ; a 320
        ldi r19,lo8(1)
        movw r20,r24     ; r25:r24 --> r21:r20
        mul r20,r18      ; alsó-alsó szorzat, eredmény: r1:r0
        movw r24,r0      ; r1:r0 --> r25:r24-be
        mul r20,r19      ; alsó-felső szorzat
        add r25,r0       ; r25-höz hozzáad
        mul r21,r18      ; felső-alsó szorzat
        add r25,r0       ; r25-höz hozzáad
        clr r1
        ret              ; r25:r24 az interfész

Ezt ugyanilyen hatékonysággal írtam volna meg assembly-ben, talán a "clr r1" maradt volna ki. Eredmény gyakorlatilag ugyanaz, ellenben fárasztóbb assembly-ben megírni. Sőt a tévesztésből eredő problémákat, hibakereséseket is nézve sokkal szerencsésebb a C.

Egy ismerősöm kizárólag ASM-ben tolja az AVR-t. Kérdeztem tőle miért. Hát mert neki fekete doboz a C, másrészt példának hozta a bájt tükrözést, hogy ahhoz is milyen jól jön a carry bit és C-ben ötlete sem lenne hogyan lehet megoldani, példának ezt írta:


  ldi        r25, 0x80
rev_byte:
  rol        r24
  ror        r25
  brcc       rev_byte
  mov        r24, r25
  ret

mert ez rövid és szép. Csak éppen ha jól számolom 37 ciklus körül van. Ugyanez C-ben:


unsigned char reverse_byte(unsigned char n)
{
  n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
  n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
  n = (n >> 4) | (n << 4);
  return n;
}

Amit erre fordított az avr-gcc:


000048dc <reverse_byte>:
    48dc:	98 2f       	mov	r25, r24
    48de:	99 0f       	add	r25, r25
    48e0:	9a 7a       	andi	r25, 0xAA	; 170
    48e2:	86 95       	lsr	r24
    48e4:	85 75       	andi	r24, 0x55	; 85
    48e6:	98 2b       	or	r25, r24
    48e8:	89 2f       	mov	r24, r25
    48ea:	88 0f       	add	r24, r24
    48ec:	88 0f       	add	r24, r24
    48ee:	8c 7c       	andi	r24, 0xCC	; 204
    48f0:	96 95       	lsr	r25
    48f2:	96 95       	lsr	r25
    48f4:	93 73       	andi	r25, 0x33	; 51
    48f6:	89 2b       	or	r24, r25
    48f8:	82 95       	swap	r24
    48fa:	08 95       	ret

Ez "hosszú" és "csúnya", de ha jól számolom pont 50%-al gyorsabb a fenti rövid és szép kódnál... Egyébként ahogy észrevettem sokaknál az ASM-ben kényelmes Carry bit az egyik fő gátja annak, hogy átszokjanak C-re. Nyilván kell néha az ASM de a kód nagyrészét minden esetben kényelmesen meg lehet írni C-ben, ami akár hordozható is lehet 8/16/32-bit között. Nem sok értelmét látom annak, hogy egy kód 100% ASM legyen.

A példáddal csak az a problémám, hogy összehasonlítasz egy optimalizált C kódot egy olyan assembly-vel, amelyet egy assembly-ben programozni nem tudó ember írt. Miért ne jutna eszembe, hogy a 6 balra léptetés 8 biten valójában 2 jobbra léptetés, csak az eredmény egy byte-tal feljebb kerül? Vagy miért ne jutna eszembe, hogy 4 valamerre léptetés egy swapf és egy maszkolás?

A C-ben az a rossz, hogy nem tudod, mi történik, mivé fordul a kód. Éppen erre írtál példát. Ez nem gond, ha bőségesen vannak erőforrásaid, de ha szűken mérnek futásidőt, memóriát, akkor szerintem az assembly a jó megoldás.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

"A C-ben az a rossz, hogy nem tudod, mi történik, mivé fordul a kód." ...

1. a C-ben írt szoftverek mégis jól működnek mikrovezérlőn, pedig nem szokás assembly szinten átnézni. Hihetünk a fordítónak.

2. Hidd el, nem lesz 80%-os hatékonyságnál rosszabb a kihozatal látatlanban sem. A 95% körüli hatékonyság normális C fordító esetén valószínűsíthető. A projekt bukása ha ettől a pár %-tól függ, akkor az elején igen rosszul volt felmérve a szükséges mikrovezérlő. Estem bele sajnos én is ebbe a hibába. Azóta inkább fölé lövök - bár kemény 100 Ft többletkiadást jelent a kisszériás fejlesztés darabjainál.

3. Van hogy mégis tudni akarom. Akkor jön a "gcc -S" illetve az "objdump -d". És rábólintok, hogy 90% feletti hatékonyságú a generált assembly, amibe nem célszerű kézzel beletúrni olyan áron, hogy ezzel megnehezíteném az újabb mikrovezérlő családok felé való jövőbeli hordozhatóságát.

Úgy érzékelem locsemegével vagyok korban. A programozást a Z80 line-by-line programozásával kezdtem. Nekem is jobban fekszik az assembly.
Anno amikor az első DOS I386 processzorra írt C programomban kellett interrupt rutint kezelnem, egy hazánkban alig ismert de igen jó compilerrel, megpróbáltam interrupt handlert írni C -ből. Visszanéztem a közbülső assembly kódot és rosszul lettem. Nem emlékszem már pontosan mi is nem tetszett, de az a kód nagyon sz'r volt. Próbáltam a compiler "#pragma" utasításait használva javítani a kódon, de nem tudtam vele az elvárásaimnak megfelelő kódot készíteni. Akkor tanultam meg vegyíteni a C -t az assembly -vel. A végeredmény stabil és gyors kód lett.
A program karbantarthatóságát illeti, elővettem egy csaknem 20 éves projektemet, amit 51 -es architektúrára írtam - GPS -t kezelt, soroson kommunikált, mért térerőt és az eredményt kipakolta egy 4x16 karakteres LCD panelra. A dokumentáltsága olyan, hogy egy hét alatt szerintem bárki megérti aki jártas az architektúrában - memória és IO térkép, jó sok komment és folyamat ábrák. A karban- és kézben- tartható programok titka az, hogy a fejlesztés idejének majdnem a felét a dokumentálás teszi ki. "Az ihlet" sodrában az ember csak úgy lapátolja a kódot, viszont néhány nap késleltetéssel érdemes újra átnézni a kódot. Egyrészt ilyenkor rájöhetünk, hogy néhány "ötlet" mégsem olyan jó, másrészt akkor látszik, hogy mi az amit első ránézésre nem értünk - na oda kell a komment, egy jegyzet vagy akár egy kis folyamatábra. Néhány nap távlatában még könnyű felidézni mit és miért is csináltunk.
Az assembly kód olvashatósága azért nem jó, mert nagyon belelehet veszni a részletekbe. Amit C -ből elintézel egy sorral a mögött lehet akár kétoldalnyi assembler, amiről tudjuk hogy az áttekinthetőség határát súrolja.
Biztos hogy a C nem annyira kihegyezett mint az assembly lehet, szokványokat, szabályokat alkalmaz, lehetőleg úgy hogy az többször felhasználható legyen.

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

Nézem az objcopy man -ját (ezt dobja a rendszer a "man avr-objcopy" -ra).
Azt mondj hogy object fájl tartalmat másol másik object fájlba? Az elf tudtommal végrehajtható formátum, vagy tévedek?
BFD formátum, S-record mik ezek? Kell ez nekem?
Igen én is hardwares vagyok ;)

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

"Azt mondj hogy object fájl tartalmat másol másik object fájlba? Az elf tudtommal végrehajtható formátum, vagy tévedek?"
Hát, objectnek linkelés előtt szokás nevezni ugye a lefordított file-t. De az objcopy tud linkelés utáni kimenetet is kezelni, gondolom tartalmilag nem igazán van ezek között különbség, legalábbis statikus linkelésnél (ami nyilván alap mcu-nál). De ez nekem is nagyon ingoványos terület egyáltalán nem vagyok biztos, és végül is csak elnevezés, szóval nem létkérdés.
"BFD formátum, S-record mik ezek? Kell ez nekem?"
BFD: valami GNU formátum, igazából nem tudom én se, nem kell neked. Azt hiszem a gcc komponensei mindenképp ezt használják belül bináris formátumnak.
S-record: Ejnye, hát milyen hardveres vagy te, hogy még nem hallottál a Motorola S-record-ról? :) (olyan mint az ihex, csak más).

Rövid keresgélés alapján szerintem:
avr-objcopy --input-target=ihex --output-target=elf inputfile.hex outputfile
De most tesztelni nem tudom.

Valami workaround nem jó? Teszem azt, ha valahol jár a programod, egy lábra impulzust küldesz, ezzel triggereled az oszcilloszkópot, vagy kigyújtasz egy LED-et, vagy soros portra üzensz. Tehát nem debuggerrel, hanem kreatívan, ahogyan debugger nélkül keres hibát az ember.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Mondjuk én is így szoktam debuggolni, pedig van egy avr dragonom. De valahogy sose működött megbízhatóan az avr-gdb+avarice+ddd hármas, breakpointoktól mindig összeomlott, anélkül meg max végtelen ciklus felderítésére jó.
Viszont időkritikus dolgoknál szerintem csak a gpio+logic analyzer/scope működik jól, a soros port lassú, a jtag meg ha jól emlékszem csak 1MHz-es main clockot tud csinálni, én meg szinte mindig 8/16MHz-t használok. Mondjuk a debugwire-t nem ismerem.

No igen, a debuggerrel az is gondom, hogy a legtöbb alkalmazás időkritikus egy mikrokontrollerben, tehát debugolhatatlan statikusan.

Tegyük fel, valami FSK adatfolyam jön, amit memóriába kell tenni. Ebben statikusan hogyan keressek hibát, mert az az adatfolyam valós időben ömlik befelé? Vagy billentyűzet pergésmentesítése. De bármi, ahol vannak hardware-es időzítések. Legyen mondjuk triac-os fázishasításos teljesítmény vezérlés. Na, ezt statikusan hogyan debugolja az ember, hozzátéve, hogy galvanikus kapcsolatban van a mikrokontroller a hálózati 230 V-tal?

Ne érts félre, nem vitatkozom veled, épp egyetértően írtam.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Triakos fázishasítós dimmert pont debuggoltam soros porton :)
Ha jól emlékszem mondjuk eleinte csak gyengeáramon, kézzel adva neki az impulzust, aztán meg leválasztó trafóval.
Az meg egyébként nagyon ritka, hogy valami annyira időkritikus, hogy debuggolhatatlan mondjuk soros porton. Az esetek 90%-ában elég, ha az időkritukus részben pár változóban eltárolom az érdekes változókat, aztán a nem időkritikus részben dumpolom.

Pont ezt csinálom. Először a fuse beállításokkal piszmogtam - 16MHz külső kvarc és valahogy nem azt láttam amit szerettem volna. Ráadásul, a kis USB -s jtag valami timeout hibával nem tudja írás után visszaolvasni a fuse -kat, csak ha egy újabb paranccsal kiolvasom és akkor már jól ketyeg a proci - ez a kis nüansz elég sok időt elvett az életemből.
A lényeg, hogy pont a legegyszerűbbnek tűnő perifériával, a timer -el kezdtem építkezni. Elértem azt hogy szépen 1 ms újra húzza magát, így szép 1 ms -os felbontású, egyenlőre csak 16 bites tick számlálót hozzak létre a ramban (lehet jobban járnék valami regiszterrel, de egyenlőre legyen így). Az interrupt rutin "lelke" így néz ki:


LDS    R24, LOW(TICK)
LDS    R25, HIGH(TICK)
ADIW   R24, 0x01
STS    LOW(TICK), R24
STS    HIGH(TIWK), R25

Ez a néhány sor intézi a 16 bite incrementálást, jól is működhet, az alsó bitet nézegetve szinkronban billeg a timer kimenetével.
A "fő hurokban" felpiszkálok egy 16 bites időzítőt, aminek az értékét a TICK számláló és egy konstans értékkel töltöm majd figyelem (minden körben megnézem), hogy a TICK értéke mikor lesz ennél több:


MAIN_LOOP:
LDI   XL, LOW(TICK)
LDI   XH, HIGH(TICK)
LDI   YL, LOW(TIMERA)
LDI   YH, HIGH(TIMERA)
LD    R16, Y+
LDD   R17, X+
SUB   R16, R17
LDD   R16, Y
LDD   R17, X
SBC   R16, R17
BRCS  NOT_YET
;-----
LDI   XL, LOW(TICK)
LDI   XH, HIGH(TICK)
LDI   YL, LOW(TIMERA)
LDI   YH, HIGH(TIMERA)
LD    R16, X+
LDI   R17, LOW(WAITA)
ADD   R16, R17
ST    Y+, R16
LD    R16, X
LDI   R17, HIGH(WAITA)
ADC   R17, R16
ST    Y, R16
;-----
SBIC  PINA,2
CBI   PORTA, 2
SBIS  PORTA, 2
SBI   PORTA, 2
NOT_YET:
SBIC  PINA, 0
CBI   PORTA, 0
SBIS  PORTA, 0
SBI   PORTA, 0
RJMP  MAIN_LOOP

Hát itt kicsit többet kell zsonglőrködni van egy 16 bites compare és egy 16 bites összeadás. A WAITA értéke pillanatnyilag 10 (decimál) azaz 10 ms billegnie kéne a PORT A 2-es b bitjének. Nagyjából szinkronban a timer0 kimenetével. A "MAIN_LOOP" pedig (talán) 2 MHz billegteti a PORT A 0 -ás bitjét. A TICK = 0x0060 és a TIMERA = 0x0062 -vel - sram alja.
A hiba ott van hogy a PORT A 2 -es bitje meg sem moccan :(
Én nem látom a hibát :( Jól jönne a debugger.

OFF: A 16 bites aritmetikai műveletekből jól látszik, hogy ez kiabál a C -ért, mert assembly -ben ezt már leírni is egy életmű.
Egyébként semmi bajom a C -vel, rengeteg programot írtam már vele, amik sok éven át működtek és működnek kielégítően. De valahogy az egy chipeseknél úgy gondoltam ez túlzás.
Nálam mindig is az olyan feladatok csapódnak le, ahol nem mindegy hány órajel is megy el. A szkóp régi jó barátom :)
A C -s példa programocskákban az első ami szembejött a "delay" - na ne, persze ha van egy kernel aki közben egy tucat más dolgot futtat amíg "delay" akkor rendben van de amúgy ez nagyon gáz. Egy 16 MHz -en ketyegő kontroller nekem ne lóbálja a lábát.

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

Életemben nem piszkáltam még AVR-t, de egyelőre nem világos a dolog, igaz, nem is ismerem a hardware-t.

Biztos, hogy az SBIS argumentuma PORTA akart lenni? Gondolom, a PINA változód 2-es bitjének negáltját másolnád a PORTA 2-es bitjére, csak szerintem rossz bitet tesztelsz másodjára.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Elírás, így helyes:


SBIC  PINA,2
CBI   PORTA, 2
SBIS  PINA, 2
SBI   PORTA, 2
NOT_YET:
SBIC  PINA, 0
CBI   PORTA, 0
SBIS  PINA, 0
SBI   PORTA, 0
RJMP  MAIN_LOOP

A kimenetnek beállított PORTx kimenetén megjelenő szint kiolvasásához a PINx bitet kell olvasni. (Elsőre én is beleszaladtam abba hogy a PORTx bitet olvastam és nem működött a dolog. Ez a kód a helyes és gyakorlatilag bitenkénti "toggle" műveletnek felel meg a GPIO porton).

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

Gondolom az eddigiekből sejtitek, nincs sok tapasztalatom asm-mal, de ezt nem teljesen értem:

SBIC PINA,2
CBI PORTA,2
SBIS PINA,2
SBI PORTA,2

Jól értem, hogy ennek az a feladata, hogy a PORTA 2-es bitjét váltsa minden lefutáskor? Mert nem feltétlenül azt csinálja, ha a CBI és az SBIS között befut egy interrupt, akkor az simán elég késleltetés lehet, hogy feltöltse a kapacitásokat, és egy lefutásban kapcsolja oda-vissza a pint (sőt azt se tartom kizártnak, hogy elegendően nagy külső felhúzó áramforrás segítségével akár még az interrupt se kell, elég az utasításbetöltés)

Nagyon lassan olvasok asm kódot, szóval nem olvasom el teljesen, viszont nem látom a DDRA írást...

Leírnád a konkrét feladatot? Kezdek kíváncsi lenni, eddig nem látok benne olyat, ami asm-ért kiáltana.

"De valahogy az egy chipeseknél úgy gondoltam ez túlzás."
Túl vagyunk már azon, hogy csak pár byte memória van az mcu-kon, viszont egy csomó hátrányt hoz az asm: Nehezen cserélhető alatta a platform, nehezen olvasható, nehezen debuggolható... (mondjuk a ddr regiszter írás pont úgy kimaradhat c-ben is)

"A C -s példa programocskákban az első ami szembejött a "delay" - na ne, persze ha van egy kernel aki közben egy tucat más dolgot futtat amíg "delay" akkor rendben van de amúgy ez nagyon gáz. Egy 16 MHz -en ketyegő kontroller nekem ne lóbálja a lábát."
100%-ban egyet értek, főleg, ha sleep-et is tud. Gyors játékoknál jó a delay, de én se szeretem használni.

Nem a teljes kódot írtam le - pl. az alap beállítások, mint stack pointer vagy épp a port kimenetbe állítása lemaradt.
Valójában a topicot NEM a 8 bites RISC architektúrájú AVR mikrokontrollerek programozásának rejtelmeiről akartam indítani, hanem a Linux alapon - leginkább a Debian disztribúció alkalmazásával - létrehozható fejlesztői környezet felépítéséről van szó. A "kreatív" debuggolási módszerekből elég jó vagyok - ugyan sok éve nem piszkáltam egy chipeseket, pont azért mert keserves a hiba keresés.
A feladat csupán "ismerkedés" az utasítás készlettel és ha lehet akkor hasznos kód részletek kidolgozása. A szoftver timer-tick számláló egy alapvető funkció, nem csak az egy chipeseknél - nézzétek meg a libc -t ha valaki nem bízik a szavamban.
A következő lenne az USART és így az RS232, ahol kapásból kell pl. FiFo, ha FiFo akkor cím aritmetika (egy chipeseknékl a cirkuláris buffer a kedvenc), de mielőtt ilyen "finomságokba" kezdhetnék, máris elbuktam egy igazán egyszerű cím aritmetikán, illetve rögtön látom, hogy hiába van jtag nem tudom kihasználni :(
Egyébként rengeteg fejlesztő eszköz és platform van az AVR -ekhez.
Assembler: avra és avr-as
C/C++: avr-gcc és sdcc
Debuggolás: avr-gdb és a velejárók
Aztán a platformok: ATMEL/GNU, Arduino vagy rtos. (Ezek kicsit összecsúsznak de mind eléggé más ahhoz hogy el kelljen dönteni melyiket is használjuk és mire)
OFF: Már a 80 -as évek végén, amikor intenzíven dolgoztam az 51 -ekkel arról "álmodoztam" hogy in circuit emulátorral mennyivel gyorsabb és megbízhatóbb lehetne ez a meló. Az akkoriban elérhető ilyen jellegű eszközök, horrorisztikus árban voltak - nem volt olyan fejlesztés, vagy perspektíva ami azt a költséget indokolhatta volna. Mostanára ez gyökeresen megváltozott, fillérekért elérhető eszközök vannak eleve úgy felépítve, hogy lehessen őket debuggolni. Én pedig nem tudom használni? Mostanában egyre gyakrabban az az érzésem, hogy nem az általunk írt szoftverekben kell keresnünk a hibát, hanem a használt eszközökben, platformokban és oprendszerekben. A Linux -nál ezt még el is fogadnám, hisz zömében nagyon lelkes emberek, a szabadidejük feláldozásával építik.

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

Én úgy dolgoztam, AVR-re, hogy a kód jelentős része C, és 1-2 dolog volt csak ASM-ben. Bare metal írtam a programot (bár utólag lehet, hogy az rtos-nek lett volna értelme), ami minimális HW illesztés kellett, azt datasheet-ből, és példák alapján csináltam.

De a legjobb trükk az volt, hogy úgy írtam meg a programot, hogy a vas elérését egy HAL (Hardver Abstraction Layer) mögé tettem (ennek az absztrakciós szintjét a projekt válogatja, hogy hova kell tenni). Hordozható C kódot írtam (ez ma már nem nagy kunszt, lényegében annyi, hogy uint8_t és tsai-t kell használni), és a HAL rétegre írtam egy szimulátort C-ben PC-re. Ezen szimulátor környezetben lehetett debuggolni, illetve unit teszteket, meg integrációs teszteket csinálni. Iszonyatosan felgyorsította a fejlesztés idejét ez a módszer - a csippen debuggoláshoz képest - és a minőséggel is elégedett volt a megrendelő. Csak a HW elérést kellett így a csippen fejleszteni, azokat pedig egymástól viszonylag függetlenül lehetett tesztelni. Azért elő kellett venni a szkópot is, azt nem úsztam meg :-).

Jtag mondjuk ilyen, én is azt hittem, hogy minden gondomat megoldja majd amíg ki nem próbáltam :)
Amúgy ha c-re átváltasz valószínűleg jobban jársz, ha nem a debian által adott gnu-s avr toolchaint használod, hanem leszeded az atmel oldaláról, rengeteg patchet raknak bele, mert a gnu iszonyú lassan fejlődik nekik.

A timer interrupt helyes kezelése az egyik legbonyolultabb rész, ezen kell a legtöbbet gondolkodni, hogy jó legyen. Ráadásul mivel a kellemetlen esetek véletlenszerűen jönnek elő, ezért debuggolni sem nagyon lehet. Csak az összes időzítési eset végiggondolásával lehet jóra megcsinálni. (Esetleg szimulátorban végig lehetne pörgetni az összes esetet, és bizonyítani, hogy jól működnek. De ez repülőgépirányító szintű dolog már, nem hobbiprogramozás.)

Annyira nem triviális dolog, hogy az első Arduino verziókban is hibásan volt ez, ha jól emlékszem pont akkor javították, amikor elkezdtem foglalkozni ilyenekkel. A friss változatban érdemes megnézni, hogy mit csinál a micros() metódus. És akkor a konkrétumok:
* A több bájtos számlálót (TICK) interruptból növeled. Ezért a main loopban előfordulhat, hogy a két bájt kiolvasása között üt be az interrupt, ilyenkor hibás lesz a ramból kiolvasott TICK érték. Ezért a TICK kiolvasást CLI/SEI párossal kell körülvenni. Ebben az interrupttól védett részben kell a TIMERA regisztert is kiolvasni.
* A TIMERA kiolvasásakor előfordulhat, hogy a TIMERA már átfordult, de a TICK-nek még az inkrementálatlan verzióját olvastuk ki. Ezt úgy lehet csekkolni, hogy ki kell olvasni az overflow interrupt flaget is a TIMERA kiolvasása után. És ha az overflow interrupt flag aktív, és a kiolvasott TIMERA érték már az overflow határ után van (azért kell mindkettőt ellenőrizni, mert ezeket sem egyszerre olvassuk ki, ezek sem feltétlenül összetartozó értékek), akkor a kiolvasott TICK értéket inkrementálni kell.

És ha ez még nem lenne elég, akkor a fast PWM mód is bekavarhat, azt nem tudom fejből, de itt van elemzés róla: http://forum.arduino.cc/index.php/topic,70045.0.html

Amit leírtál abban teljesen igazad van, köszönöm!
Nem fogalmaztam eléggé precízen. Nekem egy ilyen tickes számlálós időzítési lehetőség egyenlőre bőven elég akár 10-20% hibával. A lényeg hogy amíg el nem éri a beállított időt ne aktiválódjon valami (pl. külső eszköz beállítása után ki kell várni, akár 20s míg hozzá nyúlhatsz újra, ezt delay -el megvalósítani tűrhetetlen)
Ha precízebb időzítés kell akkor nincs mese be kell építeni az interrupt rutinba és még ott is gondolkozhatsz az interruptok prioritásán és a futási idejükön. Ugyanakkor blokkolni a teljes interrupt rendszret életveszély lehet.
A kódomra visszatérve (amit eredetileg nem is akartam kiteríteni, annyira kiforratlan) nem hogy egyszer, kétszer kihagy, hanem meg sem mozdul. Mivel nincs komoly pontossági igény, elég ha azt látom hogy az idő lejárt.

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

Ha éppen egy nagy átforduláskor fordul elő az inkonzisztens kiolvasási hiba, akkor nem 10-20% lesz a hiba, és nem feltétlenül később történik meg aminek adott idő után kellene, hanem akár előbb is. Nem lehet úgy dolgozni, hogy "én tudom, hogy ez így rossz, de nekem most megfelel". Illetve lehet, de nagyon hamar instabil lesz minden.

Abból, hogy "félúton" a kiolvasások között vált a tick számláló, mi is történhet? Mondjuk az alsó 8 bit még az inkrementálatlan értéket mutatja, míg a felső 8 bit az inkrementáltat, ami akár 256 msec hibát okozhatna 0xFF és 0x01 (amihez a 0x00 alsó 8 bit tartozik) - jogos!
Ez így tényleg sz'r!
Mint mondtam ez csak amolyan "ujj gyakorlat", a hiba elég gyorsan kibukott volna. És továbbra sem magyarázza, hogy miért nem aktiválódik a timer soha. Arról már nem is beszélve hogy kell használni a jtag -et. Hogyan kellene debuggolni.

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

Nekem generál .elf-et. Eclipse alatt próbáltam, az "AVR Eclipse Plugin"-nal.
Ha érdekel, írj egy emailt, elküldöm a makefile-t, és kimazsolázhatod.

A gdb-nek valahogy meg lehet mondani, hogy a szimbólumokat melyik ELF-ből vegye.

Én így csináltam régen:

C -> ELF -> bin

A bin-t lehet égetni, a gdb pedig nagyon örült az ELF-nek.

Fuszenecker Róbert

Igen. Minden jel arra mutat, hogy fordítva ültem a lóra!
C -ből kell indulni. Ott inkább a hex formátum kinyerése a macerásabb, itt viszont elf -et nem kapsz.
Még lehet töprengeni hogy avr-gcc vagy sdcc, de úgy tűnik az avr-gcc verziót sokkal jobban támogatják.
OFF: Kénytelen leszek bemenni az akolba :( A példák, leírások és egyebek mind az ATMEL/AVR stúdióra hivatkoznak, méghozzá a windowsos verzióra. Persze itt is felmerül a kérdés, hogy melyik verziót is. A legfrissebb a 6.2 ami már az arm támogatást is tartalmazza, viszont jó esély van rá hogy a kínai klón jtag -net nem. Valamiért a 4 -es AVR Stúdiót emlegetik, ami kompaktabb és nem támogatja az arm és xmega chipeket. Azt hiszem megpróbálkozom a 6-ossal - ez előre mutató.

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

A formátumok között - bizonyos megkötésekkel - kiválóan konvertál az objdump.
Szerintem assemblerrel is ELF-et generálsz, tehát ha az assembly a kedvenced, használhatod azt is.

Egy ideig én is mindenféle házi megoldásokkal dolgoztam, de később beláttam, hogy egyszerűbb (és végeredményben olcsóbb) valamilyen kész megoldást használni.

Sok sikert a fejlesztéshez!

Fuszenecker Róbert

Megoldva? - nem igazán :( Nem Linux a megoldás.
Elővettem a jó öreg XP -t és megkíséreltem feltelepíteni az ATMEL Studio 6.2 -t. Nem sikerült, valami MS Individual Console 10.0 telepítése során egy "$shtdwn$.req" nem másolható a "Rendszrgazda .. temp/" könyvtárba, megpróbáltam kézzel - nincs jogosultság de olvasni sem tudja? Zavaros. Kicsit googleztam de nem találtam erre a hibára semmi használhatót. Megint felmerül a kérdés mit szabad és mit nem a "Rendszergazda" -nak.
Amikor megkaptam a JTAg -et össze-vissza keresgéltem a neten és végül lehúztam egy olyan file-t ami tartalmazza a CH340 (soros-USB konverter) chiphez tartozó drivert - ilyen van a JTAG -ben - és benne egy AVR Studió 4.17 build 666 verziót.
Kicsit mókoltam vele, és voila debuggolok :D
Problémák:
Valamiért nem tudtam beállítani, hogy a target nem ATMEG16 hanem ATMEGA16A? - pedig benne van a listában, de nem engedi kijelölni.
Valamiért a target board/cpu feszültség 6,2V lett, 5V helyett.
Ami a "programocskámat" illeti, már a disassembler is megmutatta volna, hogy rossz értékek töltődnek az X, Y regisztere párokba 0x0060 és 0x0062 helyett 0x6060 és 0x6262 - ez így eléggé érdekes.

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

De igen - AVR Studio 4.17 build 666
Mint azt írtam, ezt a JTAG driverével (CH340) együtt húztam le.
Ki fogom próbálni, az utolsó 4.x hivatalos verziójával is, de a JTAG ICE (látszólag) teljesen jól működik. Kapcsolódik, az AVR Stúdió felismeri mint "JTAG ICE", kiolvassa a fuse beállításokat és megállítja a program futását, pont ott ahol akartam. Még nem töltöttem le vele programot, így azért még van miért aggódni.
Viszont úgy tűnik, a "JTAG ICE" mint olyan nem támogatja a az ATmega16A csak a simát. Papír forma szerint ezek teljesen kompatibilisek.

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

ASMFLAGS += -x assembler-with-cpp -mrelax

ezeket add meg gcc-nek és akkor lefordítja asm-et
mondjuk lehet hogy kicsit at kell írnod, nem tudom

objcopy tud utána elf-ből hex-et meg minden mast csinalni

egyébként meg hasznáj C-t szvsz

Újra tervezés!
Még mindig XP -re, csak a "kopasz" HU PROF SP3 -ra sem tudtam feltenni a 6.2 ATMEL Stúdiót - a hiba ugyanaz amit már írtam $shtdwn$.req fájlt nem lehet másolni (rendszergazdiként). Nyilvánvalóan ez a verzió már NEM támogatja az XP -t - érthető, elfogadom.
Elővettem a "hivatalos" utolsó 4.19 verziójú AVR Stúdiót. Működget de inkább orrán-száján elszáll. az egyik próbálkozásomnál egyenesen törölte a flash -t. A probléma egyértelműen a JTAG és a szoftver kapcsolatában látszik. A JTAG klón USB driverével lehúzott 4.18 build 666 (ez is elég érdekes) már elég jól működik. Viszont van ott egy readme fájl amiben a WINAVR 2010x verziójának telepítését javasolják. Feltettem - én úgy látom ez a Linux (és a Debianon is) fellelhető AVR toolchain windows verziója. Ráadásul az egyébként általam is kedvelt "Programmers editort" is mellé teszi. Kész vagyok :( Most már nem tudom milyen rendszerben (Linux vagy windows) folytassam a "munkát" (ez egyenlőre inkább hobby vagy nosztalgia projekt).
Sok olyan hozzászólót, hozzászólást látok akik sikeresen programoztak, programoznak AVR -t. Kérlek áruljátok el végül is ti milyen rendszeren, milyen eszközökkel teszitek ezt?
Szeretnék már tovább lépni, de nagyon utálnám, ha félúton megint abba szaladok bele, hogy megrekedtem.

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

Linux alatt dolgozom, bár főként 32 bites mikrovezérlővel. Időnként viszont "nosztalgiázok".
A mikrovezérlők C programozáshoz elég számomra a szintaktika kiemeléses text editor, a többi C tudás és mikrovezérlő PDF-je. A C tudással nincs gond. :)

Egyszerű és nagyszerű Makefile írást célszerű megtanulni. Így nagyobb, sok C fájlt tartalmazó projektek megvalósításával sincs gond ( make / make clean ). Adott mikrovezérlőre szabott IDE nekem nem kell, sőt utálom. De ez ízlések és pofonok kérdése.

Kódletöltés: parallel porton avrdude segítségével. Laptopomon már nincs parallel port, a nagy dögöt meg nem akarom a raktárból elővenni.
Ezért legutóbb Raspberry PI-ről töltöttem le: http://forum.xham.org/index.php?topic=183
Mellesleg a kommunikációs teszt kódot is a Raspberry-re SSH-zva írtam a Midnight Commander belső szövegszerkesztőjének használatával és ugyanezen a Rapsberry-n avr-gcc -vel fordítottam.

Tetszik!
Tehát a kódolás mondjuk avr-gcc és mondjuk geany - szeretem a szintaktikai kiemelést és ez jobban látszik mint a Midnight Commander.
Égetéshez jól működik a JTAG -em (mondjuk még az eeprom -al nem próbálkoztam, de ha a flash megy ez sem lehet akadály).
A makefile régi jó barátom - utálom a bináris izéket, amit a fejlett IDE -k használnak - régebben ezek sokszor megkínoztak.
Valaki használ SDCC?

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

JTAG és bárminemű kódletöltő cucc helyett ---> Raspberry tüskesora. Erre voltam kíváncsi, ezért ugrottam neki 2 éve ennek. Tehát:

- Rpi-re SSH-val bejelentkezni
- Rpi-n futó text editor
- Rpi-n futó avr-gcc
- Rpi-n futó avrdude kódletöltő
- Rpi tüskesoron csak maximum drót felhasználásával "in circuit seriall programming"

Amire nem léptem tovább: ugyanezt az "RPi mint in circuit serial programmer" megoldást ki kellene kísérletezni PIC32 és ARM Cortex Mx mikrovezérlőkre, ideális esetben C fordítóval mindennel.

Én is Linuxon fejlesztek 8 bites AVR-ekre. Arduino-ra csinálom a prototípusok nagy részét, ehhez nem kell programozó ugye. A termékbe gyári AVR égetővel égettem avrdude programmal parancssorból. Eleve azért választottam az AVR-t (először PIC-kel próbálkoztam, de MS only fejelsztőkörnyezete volt, ezért dumpoltam), mert ez jól használható szabad eszközökkel is.

Én Eclipse-et használtam szövegszerkesztére, de a C/C++ builder nélkül, tehát tisztán szövegszerkesztő üzemmódban (csak azért, mert alapból Java-t szoktam programozni, és ezért szeretem az Eclipse-t. Igazából csak a keresés a fájlokban funkciót használtam extraként, amit azért sok program tud). A build, és az égetés pedig parancssorból ment szkriptből, nincs függőségkezelés, mindig mindent fordítottam - így sem tart túl sokáig egy mai gépen: avr-g++ -szal csinálok binárist egy lépésben (.S végződés esetén ASM-et is fordít), avr-objcopy (ez csinál hexet), avrdude.

Egy fenti hozzászólásban leírtam, hogy a programom jelentős része platformfüggetlen C, a platformfüggő részek egy HAL mögött vannak, így PC-n lehet tesztelni a program nagy részét. Ezt mindenképpen érdemes használni. Még real-time programoknak a nagy részét is lehet így tesztelni virtuális órával és időzítőkkel - pl szabályzót csináltam már így.

On-chip debuggert nem használok pont azért, mert előre sejtettem, hogy nem egyszerű összerakni. A program low-level részeit a program módosításaival, serialon küldött trace-szel (ahol lehetett), és szkóppal (ahol más lehetőség nem volt) fejlesztettem. 1 eset volt, ahol a paltformfüggetlennek álmodott rész nem pontosan ugyanúgy működött, mint PC-n de ezt könnyű volt behatárolni a hibajelenségből következtetve. Valami aritmetikát benéztem, hogy a köztes eredmény ábrázolása platformfüggő volt - kasztolással lehetett javítani.

Igen, a build szkriptjeimet eredetileg az Arduino-ból "loptam" ki - valahogy rá lehet bírni, hogy loggolja, hogy mit csinál. Pont ugyanezeket, amiket fentebb leírtam.
Az arduino programok is valójában "sima" C programok, csak valami csavar van az include-olás körül, meg van egy beépített main függvény, ami a setup/loop-ot hívja.
Annyi extra van még az Arduino-ban, hogy nem kell "égetni" a programot, hanem egy bootloader van a csippen gyárilag (az EEPROM címtartomány egyik végén), ami reset után egy rövid ideig fut, és ha ezalatt az USB-serial-on keresztül elkezdődik az új program feltöltése, akkor azt beírja az EEPROM-ba (a címtartomány másik végére). A bootloaderrel kevesebb hely van a programodnak, és egy kis késleltetéssel indul a program. De ha kell ki lehet szedni a bootloadert is egy rádugott programozóval valahogy.

Én még otthon hobbizom az AVR-kel, illetve az új projekteben már STM32-t használok.

Nálam is nagyon hasonló a kialakítás, én is linuxon fejlesztek, de ugyanígy lehetne windows-on is.
Én az atmel által készített avr-gcc csomagot használom, amit innen tudsz letölteni http://www.atmel.com/tools/atmelavrtoolchainforlinux.aspx
A Code::Blocks nevű IDE-t használom a kódturkálásra, könnyen bekonfigurálható(fordító beállítás, külső makefile-vel való fordítás, stb...).
A programozás szintén avrdude, illetve az USB-s AVR-nél az dfu-programmer. Mindkettő parancssoros.
Debuggolást én is soros trace-szel vagy egy mini USB-s logikai analizátorral oldom meg.

STM32-es kontrollerek esetében szinte ugyanez van, csak a programozó más.

Nagyon szeretem, hogy bármilyen targetre fordítok a környezet ugyanaz. Igazából az ökoszisztéma amit kialakítottam magamnak mind AVR, mind STM32 volnalon, nagyszerűen működik mind windows mind linux alatt, köszönhetően a cross-paltform megoldásoknak.

A Debian -ba eleve ott vannak ez a toolchain, csak úgy tűnik darabokban. Viszont, ott van az Arduino ami szinte minden elemet tartalmaz. Viszont az avarice + avr-gdb a debugger backend az elkülönül.
Viszont ott van az avra (AVR assembler) ill. az SDCC (Small Device C Compiler).
Tulajdonképp ez már szinte zavarba ejtő.
A Debian Wheezy avr-gcc 4.7.2 verzió, avr-as 2.20.1.20100303 és az avr-libc 1.8.0-2

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

Az SDCC valójában NEM támogatja az AVR processzorokat! - valamit benéztem. Sok szó esik róla a neten de úgy tűnik ez nem egy hivatalos "branch".
Nem kell tovább "kutakodni" az avr-gcc a nyerő.

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

A C előnyeihez mégegy szösszenet, bár most mikrovezérlő helyett látványossága miatt x86 (ivybridge) processzorra írom a példát:

Példa#1: maradékképzés

unsigned short modulo(unsigned short x, unsigned short y) {
        return x % y;
}

eredményeképpen

modulo:
        movl    %edi, %eax
        xorl    %edx, %edx
        divw    %si
        movl    %edx, %eax
        ret

Ez eddig oké, assembly-ben is kb. így kódoltam volna le.

Példa#2: maradékképzés fixen 110-zel (de más, nem 2^N hosszal is megnézhető).

unsigned short modulo(unsigned short x) {
        return x % 110;
}

Erre fordul:

modulo:
        movl    %edi, %eax
        movl    %edi, %edx
        shrw    %ax
        movzwl  %ax, %eax
        imull   $38131, %eax, %eax
        shrl    $21, %eax
        imull   $110, %eax, %eax
        subl    %eax, %edx
        movl    %edx, %eax
        ret

Érdemes elgondolkozni azon, hogy miért a több utasításból álló kódot választotta a C fordító ez utóbbi esetben és ha keresünk 100 assembly-ben többé-kevésbé jártas programozót, vajon egy x % 110-re melyik megoldást fogja a többség lekódolni?

Bárhonnan nézem a dolgot, assembly kódot közvetlenül írni csak nagyon speciális esetben érdemes és akkor is csak az időkritikus részét. Minden egyéb esetre egy jól átgondolt C kód lefordítása gyakran a trükkökkel gyorsabb kódot adhat mint a magunk által egyszerű gondolatokkal írt assembly.

Kérdésnek kérdés hiszen nem x86-ból indultunk ki, hanem mikrovezérlőből.
Ha az ember megörököl egy 1995 előtt kifejlesztett architektúrát, akkor tényleg lehet szempont.
Például: http://ww1.microchip.com/downloads/en/devicedoc/41190c.pdf
Összesen 1020 utasítást tudsz belepaszírozni ebbe. Szerencsére egyre ritkább eset, hogy ilyenbe kell a "világmegváltó" programot belefejleszteni. Az ebbe való reális feladat C-ből fordítva is belefér.

Ma már egyre kevésbé kérdés, a mai korszerű mikrovezérlőkben több száz kB (többükben 1..2 MB) programmemória van már. Még a 8 bitesek legnagyobbjainak programmemóriája is meghaladja a 100 kB-ot.

http://www.atmel.com/devices/ATMEGA2560.aspx
http://www.atmel.com/devices/ATxmega384C3.aspx
http://www.microchip.com/wwwproducts/Devices.aspx?product=PIC18F27K40

De az alapkérdés: ha méretre kell optimalizálni: gcc esetén "-Os", ahol s mint size.
Az előbbi hosszabbra eresztett gyors futású kód ilyen módon lefordítva:

modulo:
	movl	$110, %ecx
	movl	%edi, %eax
	xorl	%edx, %edx
	divw	%cx
	movl	%edx, %eax
	ret

Mai trendek szerint nem a megfelelő méretű programmemória a szűk keresztmetszet általában, hanem a mikrovezérlő értelmes fogyasztás melletti számítási teljesítménye.
- a maximális órajel, ha valamit nagyon számolni kell
- illetve a futási idő minimalizálás, majd rögvest mikrovezérlő altatás (lásd: energiagazdálkodás)

Ezért a gcc esetén a "-Os"-nek egyre kevésbé van jelentősége, a "-O2" optimalizálásnak annál inkább.

De azt szerintem te is látod, hogy a technológia nem arra halad, hogy optimalizáljuk addig a kódot, amíg belefér 1020 utasításba...
Éppen munkahelyet váltok, keresésnél elsődleges szempont volt, hogy modern, 32 bites mcu-kkal dolgozhassak, mert a 8 biteseknek (amiken most dolgozom) szerintem néhány éven belül csak marginális szerepük lesz (szenzor->busz konverzió meg hasonlók pl). 32 bites mcu meg nem nagyon van 32k flash nélkül, és filléres pluszköltségért van 100k+.

A technológia minden irányban halad. Most épp a 32 bit és a mixed signal.
Az biztos hogy a mi körülményeink között nem lehet leragadni.
Egyébként csak azt tudom mondani ami c kontra assembly, amelyikkel előbb éred el a kívánt/elvárt eredményt. A 8 és 32 bites chipek közt árban már nincs komoly különbség. Talán ha sok ezres szériát kell csinálni, de ez mifelénk nem jellemző.

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

29 éves beágyazott c fejlesztő vagyok munkahelyváltás közben. Mivel még legalább 10 (de lehet 20) évig szeretnék beágyazott fejlesztő maradni, ezért engem most nagyon nagy mértékben befolyásol, hogy mennyire piacképes a tudás. Az assembly szerintem már nem igazán az. Hamarosan a 8 bites platformok ismerete se lesz az.
Másrészt eddig open source platforfüggetlen SDKn dolgoztam (tinyos), csomószor kellett mások kódján dolgozni. A csúnyább kódokkal így is nem egyszer jutottam el oda, hogy ezt inkább megcsinálom rendesen nulláról. Belegondolni is rossz, mi lett volna, ha assemblyben lett volna (főleg, hogy msp430-valamin és atmega128*-on is működik a rendszer).

Szerintem otthon, a négy fal között mindenki abban programozza a mikrokontrollerét, amiben akarja :) De egy olyan projektre, amit még évekig támogatni kell (akár cégnél vagy open source projektben) felelőtlenség assemblyt választani.

A példa nem igazán idevágó. Az egychipes processzorok, különösen a RISC architektúrájúakat egy x86 -al hasonlítgatod? - az assembly helyett légyszives a mögötte lévő mikroprogramot megnézni, akkor lehet összehasonlítani. Szerintem itt érkezünk el arra a pontra, hogy miért is jó a C jelen esetben - sokkal kevesebb kódsorral, humanoid számára jól olvasható szöveget kapsz.
Épp csak elkezdtem az avr -t programozni, azonnal írtam pár makrót, ami tulajdonképpen a CISC felé mozdítja a mnemmonikot - miért írjak két sort ha egy is elég egy 16 bites regiszter feltöltéshez. Na igen de akkor dugig leszel egy kupac még nehezebben értelmezhető makróval ...
A "vita" megint oda vezet, hogy mivel tudsz gyorsabban és hatékonyabban dolgozni? - az assembly mnemmonikkal vagy a C nyelvel. Hát amit jobban ismersz.
Ettől még ha kell használhatsz assembly kódot inline vagy külön fájlban, ha ez megéri, mint ahogy a libc is alkalmaz néhány assembly modult.
Ami kicsit elszomorít, hogy annak ellenére, hogy már a chip architektúrájába beépítik a hiba keresési lehetőséget, még mindig ott tartunk, hogy ezek nem túl megbízhatóak és vagy drágák, azokhoz a feladatokhoz képest amit elénk tesznek.

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

Kezdődnek a kínjaim :(
Azon igyekszem, hogy az eddig assemblyben írott kis timer piszkálómat, c és assemblyben vegyesen (van egy c és van egy S fájl) megírjam. Eddig csak PC környezetre írtam c programokat (mondjuk azt jó sokat), nincs gyakorlatom, hogy néz ki ez egy egychipesen.
Szeretném a tick számlálómat magam elhelyezni a memóriában (ATmega16 1K RAM), méghozzá a legelején 0x0060. Van ennek itt egyáltalán értelme? Lehet inkább egyszerűen egy ilyen deklaráció:


volatile uint16_t   tick_counter

Már ez is kicsit homályos, hogy az uint16_t helyett miért nem jó az "unsigned int". Ha én akarom (ha lehet/szabad egyáltalán) elhelyezni a kis 16 bites számlálómat, akkor azt hog kéne:


volatile uint16_t   *tick_counter;
// Aztán valahol a kódban:
tick_counter = 0x0060ul;

Súgjatok, egyenlőre nem látom mi a helyes megoldás, pedig bújok jó néhány példa programot.

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

Szerintem nem érdemes azzal foglalkozni, hogy a memóriában melyik címen található meg a változód. Arra figyel a compiler, linker, hogy a megfelelő helyre kerüljön, hacsak nincs valami különleges célod vele.

A másik a uint16_t mindíg egy előjel nélküli 16 bites számot takar, míg az "unsigned int" az architektúrafüggő. Az "unsigned int"-ről a szabány csak azt mondja, hogy ez egy minimum 0-65535 értékű változó, de ez lehet nagyobb is.
Például írsz egy architektúra független kódot, amiben a változó unsigned int. Ez az avr-gcc esetén egy 16 bites változó lesz a valóságban, míg egy ARM Cortex-Mx processzor esetén már 32-bites is lehet a fordító beállításától függően. Ezért érdemes ilyen beágyazott környezetben ezeket a konkrét típusokat használni, mint az uint16_t és társai, ez biztosítja, hogy a mindíg ugyanakkora lesz a változód maximális mérete.

A C automatikusan rendeli a változóhoz memóriacímet, nem kell ezzel törődnöd. Mindössze azzal, hány bites változót akarsz és mennyit?
pl. unsigned short bigyo[10];
Az AVR8 timerrel kapcsolatos példakódjait az induláshoz itt megtalálod:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_…

Kösz! - látszik hogy sosem kellet ilyet használnom.
Fellapoztam a jó öreg Kernighan&Ritchie (második kiadás 1994) de csak annyit értettem, hogy ezzel a deklarációval a compilert arra utasítja, hogy ne optimalizáljon? Homály.
Egy biztos semmi köze ahhoz hogy RAM vagy FLASH esetleg EEPROM!
(Az tévesztett meg, hogy a "const" deklarációval emlegetik - mint újdonság és ANSI)
De akkor vajon miért látom ezt számos példaprogramban? Mit optimalizálhat ezen a compiler?

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

http://www.geeksforgeeks.org/understanding-volatile-qualifier-in-c/

Vegyünk egy egyszerű estet:

uint8_t flag = 1;

void IRQ_handler(void)
{
if (flag == 0) flag = 1;
else flag = 0;
}

int main(void)
{
for(;;)
{
if (flag == 1)
{
//do something
}
}
}

Ezt a kódot ha optimizálva fordítod kioptimalizálja a flag változót és nem fog működni a programod. Ellenben ha a flag változót a volatile-nek deklarálod a fordító tudja, hogy az valahol máshol megváltozhat és nem optimalizálja ki.

IO regisztereknél még azért fontos a volatile, mert különben lehet "késleltetve" fog lefutni a kód. Pl ezt:

uint16_t *register = 0x0060;
*register |= 1 << 3;
_delay_us(3);
*register |= 1 << 4;

Kioptimalizálhatja a fordító erre:

uint16_t *register = 0x0060;
_delay_us(3);
*register |= (1 << 3) | (1 << 4);

A példa lehet, hogy rossz, mert a _delay_us lényegében volatile assembly ciklus, és elképzelhetőnek tartom, hogy ez arra kényszeríti a fordítót, hogy az előtte és utána következő részeket külön optimalizálja, de a lényege szerintem látszik a dolognak, hogy miért jobb io regisztereket volatile-lal használni.

No igen. Ezek azok a dolgok amik egy assembly kód esetén fel sem merülnek.
Nem is lesz olyan könnyű erre "átszokni".
Vajon mennyit változik az optimalizáció compilerről-compilerre úgy hogy közben architektúrát is váltunk? Lehet, érdemes szoftver "hibáknál" kikapcsolni az optimalizációt, és ha ez segít újra gondolni a kódot?

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

Néha valóban segít, de félrevezető lehet.
Nagyon gyakori bug pl hogy egy változó írva van interruptból és "main programból" is (vagy ha van valami os szerűség, akkor interrupt és task kontextusból), és az írás sorrendje nem mindegy (ha mondjuk 8 bit architektúrán egy 32 bites változó, akkor végképp, ott az is előfordulhat, hogy a task már 2 byte-ot megírt mikor jön az irq). Ilyenkor ha letiltod az optimalizálást, sokkal lassabb lesz a kód, és ez "megjavíthatja" a bugot.

Na jó, de az nem hinném, hogy nyelvfüggő, ha valakinek nem jut eszébe, hogy valaminek atomikusnak kell lennie. Én utálok IT-t tiltani egyébként, szerintem nem szép. Inkább csinálok egy flag-et, amellyel jelzem, hogy az adaton dolgoznak, most ne piszkáld. Szóval az illető változó módosítását zárolom. Meg persze úgy szervezem a programot, hogy ezt meg lehessen tenni. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ilyesmire is gondolok. IT-ből:

- sok byte-os változó növelése
- set new data valid flag.

Alap szintről:

- ha new data valid, akkor adat kiolvaása, majd clear new data valid flag.

Védetlenül nem szoktam ilyesmit hagyni, bár lehetnek olyan szinkron mechanizmusok, hogy adott részen biztosan nem jön IT.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ezek már a multitask problémaköre. (Itt azért az AVR -el még nem tartok.)
Szemafor, mutex és testvérei. Ha már az ilyen "trükköket" próbálgatunk - még nem mélyedtem el teljesen az AVR utasításkészletében - eddig nem találtam atomikus test-and-set utasítást. Ti tudtok ilyet?
Mit lehetne erre használni - azonkívül hogy teljesen tiltom az összes irq-t amíg az utasítások lefutnak?

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

pl. a MCS51 utasításkészletében van olyan, hogy DJNZ - azaz decrement jump non zero - amivel csak az a hiba hogy előbb set és csak aztán test.
A multitask működtetéséhez (vagy irq és main loop) hasznos - tesztel és ha szabad a pálya "lefoglalja" azaz set majd elvégzi a dolgát. Mindezt atomikusan, azaz más task (irq) nem szakíthatja meg.
Amibe még szintén nem mélyedtem el az az AVR interupt prioritásokba, azaz ha egy változót más interruptból is piszkálsz attól is védekezni kellhet. Az egész kicsit akadémikus, de tényleg nagyon hasznos egy ilyen típusú utasítás.

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

Ha szeretnéd kiküszöbölni a figyelmeztető üzeneteket:

volatile uint16_t *tick_pointer = (uint16_t *)0x0060L;

Szerintem a linker szkript -- ha nem kell tömegével ilyesmit csinálni -- alkalmasabb erre, mert szétválasztod a kódot és a linkelést.
Hozzáteszem, aki a kódba számot ír (kivéve #define-nál, 1, 0, esetleg 2, 8), azt hamar vissza kell engedni a munkaerőpiacra :-)

Fuszenecker Róbert

Mivel magamat munkáltatom (majd 20 éve), nem azt nézik milyen programot is írok, hanem hogy működik-e.
Egyébként, volt olyan amikor belenéztek a forrásba, és elcsodálkoztak azon hogy minden konstans külön van definiálva.
Itt és most minél rövidebb annál jobb, annál áttekinthetőbb. Ha ez egy sok fájlból összeálló projekt akkor az ilyen konstansok "halálos" veszélyt jelentenének.
Valaki felemlegette a castolást - hát ezekről is lehet regényt írni. Néhány kis programocskám sok gcc -t megértek, szinte minden váltáskor, a fordítás során jöttek a warningok - nyirbálják a C szabadságát, de ettől még ugyan úgy sok a hibás program ;)
OFF: Épp most voltam egy látszerész szaküzletben amíg összerakták hogy mi és mennyi is lesz vagy ötször kiakadt a program.

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

Egy kis zűr!
Debian Wheezy 64 bit alatt a jtag -em (ami egy kínai klón CH340 chipen alapszik) jól működik mint "jtag1" (baudrate = 115200). Viszont Jessie 64 bit, timeout errorokat dobál!? Hiába veszem vissza a Baudrate -t a hiba marad.
Mit lehet még megpiszkálni?

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

Már megint egy akadály :(
Próbálok c -t assemblerrel keverni. Lefordul. Az assemblyben írott rutinokat látja és használja a C - működik.
Kivéve az interrupt rutint :(
A www.nongnu.org/avr-libc oldlon található egyszerű példaprogramot követve:


.global  TIM0_COMPA_vect
TIM0_COMPA_vect:
  // program
  reti

A disassemby listában ennek a vectornak nyoma nincs "reset" vectoron kívül minden "__bad_interrupt".
Hogy lehet rávenni hogy a vektor oda mutasson?
SZERK:
Rájöttem :) A példa más procikra vonatkozik, nekem a ATmega16(A) -hoz a TIMER0_COMP_vect kellett - rögtön helyre került. Most már csak ara kéne rájönnöm, részben miért is működött a kód?

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

Ha már ilyen lendülettel dolgozol assembly-ben, kíváncsi vagyok hogy hány %-kal lesz gyorsabb az interrupt kódod a C-ben írt és "avr-gcc -O2" módon fordítotthoz képest.

Indulási segítségül egy C példa: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_…

Szóval egy óra! Tetszik, kár hogy nem tudok németül.
Nem tudom gyorsabb lesz-e. Viszont amikor azon töprengtem, hogy az adott architektúrával, mi az ami jó - gyors és hatékony - akkor döntöttem egy sima tick számláló mellett, és az optimumot én is az 1 ms -re számoltam (16 MHz órajel mellett).
Viszont ha már ilyen összetett rutint kell írni, akkor csak ha nagyon muszáj csinálnám assembly -ben. Ebben az esetben még azt is megpróbálnám, hogy mielőtt assembly kódot írok, megnézem mit is fordít a gcc és ha azon találok fogást, akkor ugrok neki assembly -vel.
Ebben a "gyakorlatban" pont az volt a fontos, hogy a C és assembler forrás, fordítása linkelése stb. Ha ezt tudom hogy kell akkor mindent megfogok tudni oldani amit egy ilyen kaliberű chippel meg lehet/érdemes oldani.
Nem tudom, hogy ez az assembly vs. c miért is ekkora próbakő? Biztos vannak olyan műveletek, ahol jól jöhet egy kis assembly, de ha nem teszed és működik, akkor nem mindegy. Ami szimpatikus, hatékony azt használd.
Ahogy egyre jobban mászok bele ebbe a történetbe látszik, hogy a kód még az AVR sorozaton belül is nehezen hordozható. A kis c és assembly is néhány processzorral számol, a de már tele van #ifdef variációkkal.
Úgy hogy a c itt nem feltétlenül a hordozhatóság miatt jó, inkább aki nem szeretné a processzor bikfa nyelvezetét megtanulni az gyorsabban tud dolgozni, ráadásul, ott van egy kupac kész library amit felhasználhat.

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

avr-gcc -O2 -mmcu=attiny2313 pelda.c -S
és már látod is, mit fordított.

Amit máshogy írtam volna a példában: 8 bites architektúra lévén figyelni célszerű arra hol elég egyetlen összegzés és hol kell 2 db 8 bites.

volatile unsigned int millisekunden; // itt kell a 16 bit, oké
volatile unsigned char sekunde; // 8 bit elég: 0..59
volatile unsigned char minute;  // 8 bit elég: 0..59
volatile unsigned char stunde;  // 8 bit elég: 0..23

ezzel sok felesleges összeadás kizárható.
És az IRQ-t is így írnám:

ISR (TIMER0_COMPA_vect) {
  if (++millisekunden >= 1000) {    //  >= hülyevédelem miatt.
    millisekunden = 0;
    if (++sekunde >= 60) {
      sekunde = 0;
      if (++minute >= 60) {
        minute = 0;
        if (++stunde >= 24) stunde = 0;
      }
    }
  }
}

Amit fordított belőle:

__vector_13:
        push r1
        push r0
        in r0,__SREG__
        push r0
        clr __zero_reg__
        push r18
        push r24
        push r25

        lds r24,millisekunden
        lds r25,millisekunden+1
        adiw r24,1
        sts millisekunden+1,r25
        sts millisekunden,r24
        cpi r24,-24
        sbci r25,3
        brlo .L4
        sts millisekunden+1,__zero_reg__
        sts millisekunden,__zero_reg__
        lds r24,sekunde
        subi r24,lo8(-(1))
        sts sekunde,r24
        cpi r24,lo8(60)
        brlo .L4
        sts sekunde,__zero_reg__
        lds r24,minute
        subi r24,lo8(-(1))
        sts minute,r24
        cpi r24,lo8(60)
        brlo .L4
        sts minute,__zero_reg__
        lds r24,stunde
        subi r24,lo8(-(1))
        sts stunde,r24
        cpi r24,lo8(24)
        brlo .L4
        sts stunde,__zero_reg__

.L4:
        pop r25
        pop r24
        pop r18
        pop r0
        out __SREG__,r0
        pop r0
        pop r1
        reti

Olyan túl sok felesleget ebből sem lehet kihagyni. Talán egy-két utasítást. Illetve ha például dedikáltan X regisztert csak IRQ-ban használod, sehol máshol a programodban, akkor nyerhetsz időt, hiszen nem kell rá push/pop. Viszont a teljes programodban ügyelni kell akkor, hogy ne használd ezeket a regisztereket.

Nyilván utasításkészlettől is függ, de az inc helyett 0xff kivonása lehet, hosszabb, bár nem tudom. A másik, hogy a 16 bites számlálót lehet, egyszerűbb két 8 bites szorzatára bontani, bár nem biztos. Pl.: 20*50, 10*100, 5*200, 4*250, 40*25, 8*125. Ez utóbbi első számlálója mehet úgy, hogy inc, and 7, ha 0, kezeljük a másik számlálót.

Ha az ember C-ben írja a kódot, az ilyen lehetőségek eszébe sem jutnak, mert nem érzi úgy, hogy eszébe kell jusson bármi is.

A +1, vizsgálat 60-ra is lehet úgy, hogy -59, +60, aztán ha nincs átvitel, clear. Persze, ha CISC a CPU, akkor mindenre van utasítás, de ha RISC, akkor jól jönnek ezek a gondolatok.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Inkább csak zárójelben.
Van olyan AVR mc amelyikben nincs RAM és így stack sem. Azért ezeket C -ből programozni elég tűrös - ezt említi az avr-libc doksi is.
Persze ilyenkor mindig felmerül, hogy kell-e ilyen pici cuccot használni.

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

Bizony, a core i7 és java előtt is volt számítástechnika. ;)

Érdemes a MC14500B Handbook-ot végiglapozni! Abban az időben - különösen a fogyasztása miatt - kifejezetten megfelelt ipari rendszerekhez.
Ugyanebből a korszakból a 8X300 - a kedvencem. Ugyan szélesebb a busz, de csak 8 utasítása van! Persze némelyik utasításához manapság kisebb c programot kellene írni. :) Legjobb tudomásom szerint rakétairányításra is használták.
Az egyik kollégám így dolgozott: "Egy pixel alatt 12 feladatot kell végrehajtani, és ez alatt 8 órajelem van... (némi számolgatás)...Tehát a processzor 16 bites, az utasítás hossza 22 bit." Így készült a bipoláris/bitszelet videoprocesszor 300 ic felhasználásával. Az ALU 4db 74181, a program 1kszó. Kevesebb alkatrész kellett volna, ha van pl. AMD Am2900 bitszelet processzor.
Még érdekesebb az Apollo Guidance Computer. Az alap verzió 4100 NOR kapuból épült, 8 feladatos realtime, két nyelven programozták - egyszerre. Ilyennel repültek a Holdra. Igen jó cikket találhatsz az utánépítéséről is.

Hát, ezek azok a dolgok, amiről egy java programozónak élete végéig fogalma sem lesz. Viszont nem igaz az a tétel, hogy led villogtatáshoz raspáj kell meg linux és perl.
Annak idején egy realtime interfészt oldottam meg 1db Z80 felhasználásával. Az öregebbek lehülyéztek, utánaszámoltak - kiderült, hogy költségben bármilyen más megoldáshoz képest legfeljebb 30% az ára, helyfoglalása, stb. Pedig 2 interrupt is volt, stack sehol, viszont a regiszterek bőségesen elegendők voltak az adattároláshoz, dekódoláshoz. Hol a hiba?

Szerintem inkább a hardware volt a gond, hiszen az egychipesekkel ellentétben a Z80, kopaszon csak buszokat kezel, semmi periféria - PIO, SIO és CTC - plusz órajel, reszet és némi interrupt logika. Szép nagy nyák kellett hozzá, míg most lehet a feladatot egy néhány száz forintos, gyufás skatulya arduino kártya elintézné.

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

Én PIC-et használok, persze Z80-on tanultam valaha, a '80-as években. :)

Ugyanakkor nem értem, mi az értelme a kész nyáknak. Utána szalagkábellel vagy tüskesorral illeszted ahhoz a nyákhoz, amin a hardware-ed van? Nem egyszerűbb eleve a hardware-be tervezni a mikrokontrollert? Ez utóbbi esetben épp megfelelő képességű eszköz, megfelelő lábkiosztással, környezettel, sallang nélkül lesz rajta.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Mert nem maximumra törekszünk, hanem optimumra. Ha kell 3 darab eszköz, ami be lesz rakva egy polc mögé, akkor arduino, összeköt, bedobozol, ennyi. Ha fontos az, hogy a lehető
legkisebb méret legyen, esetleg adott formába/helyre kell belepakolni a dolgokat, akkor érdemes lehet saját nyákkal játszani, de ez mindig plusz mérnökóra, ami viszont drága. (nyák tervezés, marás, összerakás, tesztelés, második-harmadik-negyedik verzió elkészítése, stb.)

Lehet tiszta lyuk nyákon drótozgatni is. Továbbra is az a gondom, hogy egy ilyen kész nyákon nem pont az van - miért is lenne? -, amit szeretnél. Egyszerűen nem az a hardware, hiszen a gyártó nem láthatta, mit akarsz majd a jövőben megvalósítani.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ezért hívják ezt mérnöki munkának, és nem sufnituningnak. Megnézed a feladatot, megnézed, hogy lehet adott paraméterek mellett leghatékonyabban megoldani, és úgy oldod meg.
Lehet, hogy sokkal egyszerűbb, ha leveszel a polcról egy kész ardunio-t, hozzácsapsz egy 3$-os modult (kamera, hőmérő, i2c vezérlő, lcd vezérlő, stb.) összekötöd, és megoldotta a problémát, lehet dobozolni, van úgy, hogy nyákon drótozgatsz, szerelsz, mérsz, akármi. Ezzel sincs semmi gond, bizonyos helyzetben nyilván ez a célravezető.

Hogy miért is támogatom általában a modulokra építkezést? Pont azért, amiért az esetek 99%-ban nem irunk 0-ról egy operációs rendszert, driver-t, fordítót, grafikus könyvtárat, böngészőt, térképkezelő könyvtárat, hanem használunk egy valaki által megcsinált, kitesztelt könyvtárat (terméket).

Lehet, csak nincs mindenre kész megoldás. Valahogy így képzelem, amikor software-es kezd el hardware-t „fejleszteni”. :) Vegyünk egy kamera modult, egy CPU modult, egy hőmérő modult, egy központi modult, aztán dugdossuk őket össze. :( Szerintem ez se nem olcsó, se nem hatékony, még csak nem is mondanám feltétlen stabilnak, viszont tény, hogy egy délután alatt összerakható. Munka nincs vele, de legalább iszonyú számítási kapacitással, software és hardware apparátussal villogtathatunk egy LED-et akkora jitter-rel, hogy jobb esetben nem vesszük észre.

Ezzel szemben én tipikusan másképp gondolkodom: mekkora hőmérséklet-tartományt kell mérnünk, milyen gyakran, mekkora hibával, zajjal, mekkora jitter-rel kell annak a LED-nek villognia, mennyi helyet foglalhat a cucc, mennyit fogyaszthat, és így tovább. Aztán ehhez kezdek hardware-t tervezni, egyáltalán mérési elvet, módszert választani, A/D konverziós eljárások közül a megfelelőt kiválasztani, megépíteni, eldönteni, hogy kvarcról, vagy chip-en belüli RC-oszcillátorról jöjjön az órajel, és így tovább.

Nyilván, ha van igény valamire, gyorsan kell megcsinálni, s az árrés elbírja, lehet legózni. Viszont ha van idő és valóban cél hardware-t akarunk csinálni, illetve speciális a feladat, akkor egyedi hardware kell. Triacos fázishasításos teljesítmény vezérlőt sem hiszem, hogy eleve kész mikrokontrolleres modulokból raknék össze, pl. azért sem, mert szerintem nincs megfelelő soros kapacitást tartalmazó tápegység modul készen, triac varisztoros védelemmel, miegymás. Ezeket méretezni kell.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nemá'! Van abban ram elég. :)
Egy trükköt kellett kitalálni: Az stack pointert kellett fix értéken tartani, mert ha körbeér belekaszál a memóriába ágyazott io-ba. No, ezért az interrupt ismert helyen érkezhetett, és a végén fix helyre kellett ugrani.
Az egész program 228 bájt+4x128 táblázat, amelyben az interfész parancsainak hossza és tulajdonsága van leírva: hossz, dekódolás/figyelmen kívül hagyás. Valószínűleg egy PIC sem tudná rövidebben megoldani.

Szóval a szerkezet egy két irányú soros-párhuzamos/párhuzamos soros átalakító, némi dekódolással és ütközés kezeléssel. Az egyik oldalon egy 8085+8237 dma (stb.) CDROM vezérlő, a másik oldalon egy Thomson CD30 optomechadeck. (CD olvasó :)

Z80-nak óriási jelentősége volt a maga idejében. Viszont processzor volt, nem mikrokontroller. Egy PIC-kel szívesebben dolgozom, mert ez utóbbi kontroller, benne találhatók a memóriák, perifériák. Ráadásul a PIC teljesen statikus design, a Z80-nak volt alsó órajel frekvencia korlátja is, nem csak felső.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

:)
No, ezért dolgoztunk 8085-tel, mert egy rendes vezérlésnél az 5 huzalozott vektoros interrupt nélkülözhetetlen. A PIC persze statikus, mert CMOS. A 8080..Z80 meg még NMOS. Bár volt egy NSC800, ami egy olyan Z80, ami 8085. ;) És CMOS, de nincs 30 éves se.
Ebben a "statikus design"-ban az a szokatlan, hogy hiányzik a HALT utasítás. Nem én voltam az első aki kereste! Mert a sleep, vagy a loop ugyanoda szívem szerint nem ugyanaz, mint amikor a processzor "nem csinál semmit".
Szóval a Z80 idejében is volt mikrokontroller. Pl. a 8035/8048, vagy a 6805 (asszem). Biztosan találkoztál vele, mert régebben minden billentyűzet ilyenekkel működött. A 8035 maszkprogramozva soros kontrolerré vált. Tehát a vázolt Z80 megoldás helyett olcsóbb lehetett volna.
De! Az akkori időkben a projekt 3-6 hónapig tartott, az anyagrendelési normaidő meg 13 hónap. Már ha szerencséd van... Így maradt a "fiókból fejlesztés". Vagy a saját fiókodban volt, vagy mástól kértél kölcsön. Éppen ezért, amikor egy komoly fejlesztés befejezése után a főnökünk elgondolkozva belépett és megszólalt: - Vajon miért nem cmos processzorral dolgoztatok? Az kevesebbet fogyaszt! - Nem ütöttük meg, mert úriemberek vagyunk. :))

A HALT miért hiányzik? Z80-on csak annyi az értelme, hogy végtelen ciklusban fetch-el, ezáltal frissíti a memóriát, már feltéve, hogy DRAM-okat illesztettek hozzá. Aztán egy IT vagy NMI vet véget ennek.

A sleep ezzel szemben tényleg elaltatja a CPU-t. A perifériákat persze nem. Ha meg valakit ez valamiért bánt, ott a végtelen ciklus, ahogy írtad is.

Egyelőre nem látom, abból, hogy a Z80 NMOS, miért következik, hogy nem mehet az órajele DC-től. Inkább az lehet, hogy bizonyos dolgokat dinamikusan, pl. egy gate-csatorna kapacitásban tároltak átmenetileg.

Szerk.: sohasem fogom megérteni, abban mi a pláne, hogy noha az R regiszter 8 bites, a 6-osról a 7-es bitre nem képződik átvitel, tehát csak az alsó 7 biten inkrementálódik a DRAM sorcíme frissítéshez.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A HALT számomra azt jelenti, hogy a cpu megszakításra várakozik. Tehát nem szoktam meg pl. a sleep módban indított AD indítást. A DRAM kimaradt az életemből. Akkoriban általában 8k-s cmos ramokat szoktunk használni - már ha adatokat is kellett tárolni. A legnagyobb munkaterület akkoriban talán 96 bájtra rúgott. :)
A dynamic logic miatt nem lehetett DC az órajel.
Kerestem egy Z80 DRAm kezelést leíró cikket is. A Z80 Refresh "Limitations" cím allatt találod kérdésedre a választ.

Nem teljesen értem. Az egy dolog, hogy 128 soros RAM-ra számítottak, de ha nem kell neki a 7-es bit, úgy sem kezd vele semmit. Aztán, ha mégis 256 soros a RAM nagyobb frissítési ciklusidővel, akkor meg miért ne lehetne átvitel az R regiszter MSB-jére? Ne a CPU gyártója találja már ki, milyen memóriát illesztenek a processzorhoz, pláne, hogy azt az átvitelt megvalósítani szerintem nem nagy kihívás.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Részben igazad van.
De.
A DDR3 kezelését szintúgy nem oldották meg! ;)
Ami számodra a "CPU gyártója", szóval mögötte komoly tervezési munka áll. Nem egy CPU-t, hanem rendszereket szoktak tervezni. Lehet leleményes mérnökökre, rendszergazdákra, stb. bízni a rendszereket, de a komoly gyártók másképp csinálják. Mindig az adott kor technológiájának megfelelő eszközcsaládot bocsátanak a felhasználók rendelkezésére. Magyarul egy rendszer megvalósításához felütöd a katalógust és összeírod a megrendelendő elemeket.
Persze az egyes funkciókat a későbbiekben mindig javítják. Vagy nem.
A választ megtalálod itt.

Jé. Az odáig tiszta, hogy az IR-ből az I vektor ne íródjon felül, már csak az nem világos, miért nem egy bittel feljebb maszkolták ki az átvitelt. Hozzáteszem, csak felületesen néztem át a linket, nem olvastam el mélységében az egészet. Ha jól emlékszem, INC I, DEC I utasítás nincs, tehát ez sem lehet az oka.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az új nemzedék (lassan 30 éve vagyok a szakmában, azaz egy emberöltő) nehezen tudja elképzelni a "régi idők" megoldásainak hatékonyságát.
Mostanra elvagyunk kényeztetve a különféle olcsóbbnál, olcsóbb SBC és SoC megoldásokkal, és a fejlesztés is jóval hatékonyabb mint mondjuk 20-30 éve volt. Viszont nem lehet és szabad a múltban ragadni.
Persze RPI -vel LED -et villogtatni elég nagy pazarlás, de szigorúan véve ezt a "feladatot" egy NE555 vagy bármi másból felépített astabil multivibrátor is elintézné, így ezzel példálódzni elég nagy csúsztatás. Mostanában több Arduinó klón lapot vettem az eBay -en, a "blink" izé teszt elfogadhatónak tűnt a működőképesség ellenőrzésére.
Apropó! Most az Arduinó programozási nyelve c/c++ vag valami módosított nyelvjárás? Azt látom, hogy az avr-gcc az alap, de gondolom a sok makró miatt beszélnek róla úgy mint külön programozási nyelv.

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

Arduino tényleg C, viszont a hasznos és minden Arduino által támogatott mikrovezérlőre egységes függvényekkel "kedveskedik".
http://www.arduino.cc/en/reference/homePage -- jobb oldali oszlopát lásd példának.
Nem kell kitökölnöd, hogyan kell adott mikrovezérlőn az A/D értékét kiolvasnod. Stb.

Ahogy az USB stack-kel sem kell mikrovezérlőcsaládonként külön-külön foglalkoznod és a TCP/IP stack-kel sem. Eltérő mikrovezérlőcsaládnál is egységes függvényhívással éred el a célod.
Lásd még: http://www.arduino.cc/en/Reference/Libraries

Ez fura, én szeretem kitalálni, mi hogyan legyen. Valahogy jobban az az érzésem, hogy kézben tartom a dolgokat.

Szerk.: Közben módosítottál. A TCP/IP, USB már elég összetett ahhoz, hogy ne kívánja az ember mindig elölről kezdeni.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Előnyök is hátrányok. Ahogy jó kérdés, hogy mikor dönt az ember:

- bare metal programming (amit írtál te is)
- Arduino szolgáltatásait használva programozni
- RTOS és klónjai felett programozni
- Linux programozás (SBC-jelleggel)

mellett. Ez mind-mind feladattól függ. TCP/IP stacket írtam annó bare metal módszerrel, Ethernet kontroller lekezelésétől DHCP-n, ICMP-n keresztül az UDP-ig jutottam el. Az adott 8 bites mikrovezérlőből kihozva a maximum > 90%-át (C nyelv).
Viszont a TCP állapotgépet inkább a Linuxét használom szívesen, vagy Lantronixot.

Szóval van az a feladat, amikor nem a "bare metal" irány a kifizetődő. Azonban van olyan feladat ahol éppen a "bare metal programming" a célravezető.

A Digispark kickstarter -el nem próbálkoztál? Sajnos még nem tudtam rájönni, hogy tudom a Wheezy Arduino -ba beilleszteni :( Mondjuk nem foglalkoztam vele sokat.

OFF: Olyan jó kis cuccok vannak, úgy érzem magam mint egy gyerek a cukorkás boltban. Ezeket nem szabad kihagyni. Egyébként az ATtiny85 DIP tokban is kapható.

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

Assembler kontra C
Még mindig az ujjgyakorlatoknál tartok. A topik első harmadában mutattam a timer interrupt kiszolgáló assembly rutint:


.global TIMER0_COMP_vect
TIMER0_COMP_vect:
        PUSH    R24
        IN      R24, _SFR_IO_ADDR(SREG)
        PUSH    R24
        PUSH    R25
//------
        LDS     R24, (tick_counter)
        LDS     R25, (tick_counter) + 1
        ADIW    R24, 0x0001
        STS     tick_counter, R24
        STS     tick_counter+1, R25
//------
        POP     R25
        POP     R24
        OUT     _SFR_IO_ADDR(SREG), R24
        POP     R24
        RETI

Most (nem)csak kíváncsiságból megcsináltam C -ből:


ISR (TIMER0_COMP_vect)
{
  tick_counter++;
}

Nagyon bonyolult lett :) Ime az assembly lista:


ISR (TIMER0_COMP_vect)
{
  7c:	1f 92       	push	r1
  7e:	0f 92       	push	r0
  80:	0f b6       	in	r0, 0x3f	; 63
  82:	0f 92       	push	r0
  84:	11 24       	eor	r1, r1
  86:	8f 93       	push	r24
  88:	9f 93       	push	r25
  tick_counter++;
  8a:	80 91 60 00 	lds	r24, 0x0060
  8e:	90 91 61 00 	lds	r25, 0x0061
  92:	01 96       	adiw	r24, 0x01	; 1
  94:	90 93 61 00 	sts	0x0061, r25
  98:	80 93 60 00 	sts	0x0060, r24
}
  9c:	9f 91       	pop	r25
  9e:	8f 91       	pop	r24
  a0:	0f 90       	pop	r0
  a2:	0f be       	out	0x3f, r0	; 63
  a4:	0f 90       	pop	r0
  a6:	1f 90       	pop	r1

Összesen, 4 push/pop felesleg van - azaz 8 ciklus. Az esetek jó részében ez elhanyagolható, de van néhány amikor nem.
Még nem túrtam bele eléggé a kód befolyásolás lehetőségeibe, de nem tudom jó ötlet-e C szintről beletúrni. Az r0,r1 a avr-libc által használt regiszterek, így ha bővül (valamiért) az interrupt kiszolgáló rutin és ebben használatba veszi a regisztereket akkor baj is lehet.
Azaz ha valamilyen esetben nem elfogadható a 8 ciklus veszteség, akkor inkább assemblyben írnám meg az interrrupt rutint.

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

Ezt leszámítva is évekkel ezelőtt többször is megrágták már ezt a témát, hogy annak ellenére, hogy az r0/r1 regiszter tabu a gcc-nek ettől még ISR-ben ne generálja a felesleges kódrészt. A viták vége mindig az lett, hogy nem módosítják emiatt gcc-t, illetve a szokásos lezárás: a gcc opensource, akinek nem tetszik módosítja. De egyetlen ISR miatt nem kell dobni a C-t. :)

Kis időzítés a fenti példánál:
- hasznos utasítás: 14 illetve 19 utasításidő. Ez annyi mintha 16 MHz és 21,7 MHz órajeligény lenne.

Az arány valójában nem ennyire szélsőséges. Nézzük az ATmega1284P leírását.
http://www.atmel.com/images/doc8059.pdf
5.7.1 Interrupt Response Time
fejezet.

The interrupt execution response for all the enabled AVR interrupts is five clock cycles minimum.
...
A return from an interrupt handling routine takes five clock cycles.

Az arány tehát 24 illetve 29 utasításidő. Ez így már annyi, mintha 16 MHz-es órajel helyett 19,3 MHz órajel kellene neki. Pár sorral bonyolultabb interrupt-ban megvalósított feladat esetén ez a különbség még kisebbé válik.

Ugyanakkor látszik, hogy több, de a legtöbb esetben** nem ez fogja ellehetetleníteni a feladat teljesítését, hanem az hogy eleve alulméretezett mikrovezérlő családot akar használni a projekt megálmodója.

** egyetlen hely, ahol az ASM kötelező volt: hardver támogatás nélküli USB low speed eszköznél, de ott is csak az egyszerű GPIO-ról a csomagot levevő/ráadó rutinnál. A többi mehetett C-ben. Ma már ez is kikopófélben, ilyen esetben egyszerűen legalább full speed USB hardvertámogatás elérhető számos 8 bites mikrovezérlőkben is.

UART kezelés. Megörültem, amikor a WEB -en megtaláltam a Fleury által írt library -t. Lehet korai volt. Szimplán egy terminálból, 9600 baud -on "rákönyökölök" a billentyűre és kiakad mint az elemes mackó :(
Most keressem a hibát vagy írjak egy újat?
Akármilyen pici is ez a cucc (16MHz órajel nem is olyan kicsi ebben a műfajban) ilyet nem szabadna csinálnia.

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

Segítség: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART
(A német nyelv ne zavarjon, a példakódok átgondolása elég.)

És egy teszt:


#include <avr/io.h>

uint8_t uart_poll(char *ch) {
    if (UCSRA & (1<<RXC)) {
        *ch = UDR;
        return 1;
    }
    return 0;
}

És ami lett belőle (avr-gcc -O2 -mmcu=atmega16 -S rxteszt.c):


uart_poll:
        sbic 0xb,7
        rjmp .L5
        ldi r24,0
        ret
.L5:
        in r18,0xc
        movw r30,r24
        st Z,r18
        ldi r24,lo8(1)
        ret

Ha csak ezt nézem, 9600 bps esetén 10 kHz-es órajelről le kell vennie "van új karakter?" vizsgálattal együtt a karaktert. Abban a lib-ben más van elrontva. Például hogy valami blokkos eseménnyel lefogja a mikrovezérlőt és addig nem veszi át a karaktert.
Célszerű ezért a karakter levételt IRQ-ba tenni és ciklikus pufferbe begyűjteni a levett karaktereket. A valós program pedig ebből a pufferből veszi át ilyen módon már karaktervesztés nélkül, ahogy ideje engedi.

Nyilván a polling nem opció.
A Fleury féle handler pontosan azt teszi, hogy interruptból kezeli a vételt és az adást, külön-külön cirkuláris FiFo -ból. Anno én ilyet írtam 51 -re, szerényebb memória igénnyel (16 + 16 byte a FiFo -nak) de hát csak 128(?) byte -om volt.
Amúgy is kicsit hiányos a library illetve a kód java (már a szöveg) az arról szól, hogy a különféle kontrollereket lekövesse. Engem az annyira nem zavar, az ATmega16 -ra írt kód a nagy többségre megfelel, ha mégis kell inkább újraírom, mint azt a töménytelen és nehezen követhető if izét beletegyem - persze elegáns, de sokat ront a kód olvashatóságán (és úgy tűnik a használhatóságán is). Csak azt hittem hogy ezt megspórolhatom :(
Az ISR rutinok assemblyben írása járhatóbbnak tűnik (nekem), itt rafinált címzésre é egyebekre nincs szükség, csak hatékony és megbízható kódra. A többi "sallang" mehet C -ben.
MÁS: Az "inline" direktívát kétféle képpen is lehet emlegetni, úg mint inline assembler és olyan (általában rövid és "frappáns") rutin ami nem call hívással épül be hanem közvetlenül fordul bele a kódba, ott ahol említésre kerül. Megvannak ezek a lehetőségek azt avr-gcc -nél is? Keresnem kell valami jó példákat ezekre.

SZERK: Az "inline assembler" nem opció! Mintha hieroglifákat kellene olvasnom :( Ha ez nem mindennap kell (miért kéne) akkor nem szabad használni, napokig tart az értelmezése.

OFF: C -ben és assembly -ben is törekszem arra, hogy egy rutin egy oldalra beférjen. Egy ilyen assembly rutin értelmezése nem lehet túl megerőltető, azaz még kezelhető és érthető.

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

Az nem neked szolt, hanem hg2ecz-nek, csak ha az overe valaszol, akkor mar nem tudja szerkeszteni (lockolja) a hozzaszolast, o meg pont azt kerte tole, hogy szerkessze.

Ha irsz egy C kodot, hupra masolaskor kiszedi belole a html tag-nek hitt darabkakat (honfoglalaskori drupal verzio sajatossaga).
Szoval ha latsz valahol egy ilyet: #include ures ize, azt jelenti, hogy onnan valamit kiszedett a drupal (feltetelnel hasonloan, i-vel indexelt tombnel meg doltbetus lesz).
Erre javasolta azt az offolo, hogy inkabb irjon &amplt;-t, mert abbol pont < lesz.
#include &amplt;akarmi.h&ampgt; => #include <akarmi.h>

--
What's worse than finding a worm in your apple?
Finding a U2 album on your iPhone.

Ez egyre furcsább!
Találtam még egy libraryt (persze szintén minden jót minden jóhoz Thomas Buck) és a mellékelt teszt program ugyanúgy viselkedik - ha "rákönyökölök" egy billentyűre szinte rögtön kiakad!? Lehet hogy ez valami hardware probléma? Nem értem, hogy lehet ilyet használni?

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

Látod, ezért jó, ha assembly-ben mindent magadnak implementálsz. Csak a hardware van és te, semmi bizonytalanság. Illetve ami van, az kizárólag hardware-es eredetű lehet, vagy saját ostobaság, de ki van zárva más ámokfutása.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ismered a medvés & vadászos viccet?
Ott fennt is javasolták, de lásd be, ennyi idő alatt kétszer megírhattad volna!
No, és a könyökön kívül van más hardver element is a szerkezetben? :)

Kezdeti lépésnek a vétel legyen interrupt, és ha más különleges kívánalom nincs, a program fő hurkában az adás legyen polling!

(Fojt koev)

Nem szeretem ismételni magam, de ez továbbra is furcsa.
Elővettem egy még egyszerűbb, inkább csak példaként leírt UART kezelést, ami csak az avr-libc által nyújtott alapszolgáltatásokat nyújtja (baud beállítás, bit test stb.) Íme a "kód":


#define F_CPU           16000000UL      // ATmega16A external crystal 16MHz
#define BAUD            9600
...
void main()
{
 ...
 init_asy();
  sei();                                // Enbale all interrupts
  //---
  while ( 1 )                           // Loop forever
  {
    PORTA = PINA ^ 0x80;                // Toggle port A pin 7
    //---
    if ( bit_is_set(UCSRA,RXC) )
    {
      aux = UDR;
      if ( bit_is_set(UCSRA,UDRE) )
        UDR = aux;
    }
  }
}

void            init_asy(void)
{
  UBRRH = UBRRH_VALUE;
  UBRRL = UBRRL_VALUE;
  #if USE_2X
    UCSRA |= _BV(U2X);
  #else
    UCSRA &= ~(_BV(U2X));
  #endif
  UCSRC = 0b10000110;                   // 1000.0110 - UCSRC for 8n1
  UCSRB = 0b00011000;                   // 0001.1000 enable Rx and Tx
}   // end init_asy

Azaz semmi interrupt, semmi assembly trükk - szimplán ha jön valami, leveszem és ki is küldöm, ha engedi a hardware.
Így is fennakad a szeme. Kicsit tovább bírja mint az interruptos verzió, de akkor sem OK. Ezt én nem tudom elhinni, hogy ez csak így kiakad. Ráadásul most még azt sem látom "hova" akad ki ha kiakad?
Töprengek, de azt sem látom, hogy egy ilyen hiba esetén mit és hogyan tudna segíteni a jtag. Nem látok mást, csak tovább olvasgatom a doksit.
Egyrészt, az avr-libc a ki nem használt, nem élesített interruptokat a "bad_interrupt" rutinba küldi, ami egy "jmp 0x0" ami a reszet.
A PORTA 7 bitjének piszkálása is leáll. Hova tűnik a proci? (Reszetre persze magához tér).

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

Továbbra sem értem, de találtam valamit.
Valójában a kódba már "beleszőttem" az eddig jól működő (tesztként) timer kezelő rutinkáimat. A teljes kódot (most már inkább) a pastebin -re : http://pastebin.com/vf21UEUH
Az interrupt rutinok nem, viszont a teszt kód zavarja a működést - ha ráengedem a 2. és a 3. timerrre (100msec és 1sec) akkor lefittyen, ha csak azt elsőt használom (10 msec) akkor nincs probléma, nem akad ki.
Lehet az a gond, hogy ha nem veszem el időben a karaktert (sem overflow sem overrun hibát nem figyelek) és nem kezelem le a hibát akkor elszáll?
Ha a timer figyelést kiterjesztem a többi kis timerre, akkor megnyúlik a lekérdezési idő és nem érek oda időben, hogy levegyem a karaktert, "kiáll" hibára. Viszont akkor sem értem miért áll le a teljes ciklus - azaz a processzor "otthagy". Nagyon szokatlan viselkedés.

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

Én biztosan nem fogom olvasni helyetted a doksit. Viszont ami oda van írva, azt illik komolyan venni. Tehát, ha nem specifikált az, hogy nem kezeled a hibát, akkor kell kezelni. De lehet hardware-es gond is. Például az MCU Vss és Vdd lábai közé ugye tettél hidegítő kondenzátort rövid hozzávezetéssel? Tehát kis belső impedanciát képviseljen nagyfrekvencián. Mondjuk 100 nF jó is lesz.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Jelenleg az egész egy forrasztás mentes kísérleti panelen van.
A betáp 10mkF kezdődik és ám legyen bedugtam még 2db 220n (az volt kéznél). De szerintem ha elmegy 16MHz -es kvarccal, akkor nem lehet túl nagy baj :)
Engem is meglepett mennyire jól tűri ezt a felállást a cucc - 1 usec négyszög teljesen jól néz ki a szkópon, ahogy a nagy könyvben megírták.
Itt valami szoftver bukta van talán, hogy kezelni kell a túlszaladásokat.
De jó lenne tudni, hol jár kiakadt állapotában a poci. Lehet hogy valami sleep -be megy?

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

Nagyobb kapacitás elméletileg kisebb impedanciát jelent ugyanazon a frekvencián, csak ugye a gyakorlat más. Az elektrolit kondenzátorok induktivitása és belső ellenállása nagyobb, mint a kisebb kapacitású multilayer kerámia kondenzátoroké. A rövid hozzávezetésnek is ez a lényege. 10 cm vezetéknek már igen tetemes induktivitása van. Már úgy értem, a látszólag csekély induktivitáson keletkező feszültség jelentős lehet az igen nagy di/dt értékek mellett.

A forrasztásmentes lap már eleve rosszul hangzik. Legalább egy multilayer kerámia kondenzátort forrassz a Vss és Vdd lábak közé.

Az a viszonylag nagy kapacitású elkó a bemeneten édes kevés, nem pótolja a hidegítést közvetlenül a táplábakon. A másik, hogy port lábon közvetlenül kapacitív terhelés ne legyen.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A "betáp" egy 10mkF tantál kondi - elég jó minőségű. Most felkerült (közvetlenül) a proci mellé 2 db 220nF + 2 db 33nF kerámia.
A "madzag" hossza az továbbra is gond - egy LEd -et feltettem "villogtatási célokra" 270 Ohm keresztül és a szkópon jól látszik, ha bekapcsol ck. 100mV változás van a többi amplitúdóban (több láb is megy).
Lehet a vége az lesz, hogy 9-12V -ról fogom járatni, a panelen közvetlenül egy 7805 lefogva 5V -ra és szűrve.
Mindezek ellenére nem hiszek abban hogy ez lenne most a probléma oka.

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

Bocs! Úgy gondoltam, hogy van egy antik, áteresztő tranzisztoros (a jó öreg 723 chippel vezérelve) labortápom - 2x30V 1A + 5V/1A. Jelenleg az 5V/1A ágról megy. A szűrésével nincs gond.
De áttérnék valamelyik másik ágra (vagy a fiókból egy analóg dugasztápra) és azt stabilizálnám közvetlenül a breadboard bemeneténél.

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

Szerintem meg nem. Tiltja a vallásod, hogy soros induktivitást tégy a 7805 bemenetére, persze, a bemeneten legyen közvetlen hidegítés.

Nokia táppal az a bajom, hogy nem a nyákra tesszük jó eséllyel, stabil tápot pedig nem kellene hosszabb vezetéken, melynek van induktivitása, ellenállása, vezetni.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Bizony tiltja! Konkréten nem Nokia, hanem D-Link 5V/2A tápot használok. Feszültsége 5,08V. A hosszú vezetéket - ha szükségesnek látom - áthurkolom egy 3cm átmérőjű impulzuszavar szűrésére használt ferriten. A deszkamodell megfelelően szűrt, de csak alapfunkciókat tesztelek. Utána jön a kísérleti áramkör, ahol a PIC már saját magának biztosítja a kapcsolóüzemű tápot. A 7805 nem jöhet szóba, mert vagy kisfogyasztású akumulátoros táplálású szerkezetről van szó, vagy nagyfogyasztású akkumulátoros szerkezetről :), ahol minden más melegszik, tehát kerülni kell a plusz hőtermelést.
Ennek a kis tápnak hajszál pontosan ugyanaz a kapcsolása, mint a boltban kapható "ipari LED tápnak", tehát a minőségét ismerem.
Mindössze egy biztos tippet szerettem volna adni. A 7805 már többször is szívás tárgya volt, még LSTTL korszakban. Itt, amikor néhány utasítás sem működik megbízhatóan, nem kellene új tápot feltalálni! Bemész a boltba, és 1500-ért kezedben van egy működő kísérleti táp, amely kis helyen elfér.

Bizony, bizony.
Ha már ilyen tájékozott vagy, bizonyára találsz a nagy kék interneten egy olyan görbét, ahol a 7805 ripple rejection szerepel - akár 10uF tantálkondenzátorral szűrve. Szóval ha megtaláltad eme analóg erősítő határfrekvenciáját, már csak össze kell vetni a mikrokontroller órajelével.
Mivel ez itt nem egy nagyfrekvenciás szűrő méretező topic, ezért a javaslatom megfelelő az esetleges táphiba elhárítására. Ennek ellenére a 7805 működhet ma, de biztosan tudjuk, hogy komolyabb előkészületek nélkül alkalmatlan a feladat ellátására.

Őőő... izé. A kapcsolóüzemű táp meg eleve holtidős tag. Szóval mindkettőbe kell valami passzív szűrős megoldás feljavítandó a nagyfrekvenciás tulajdonságokat. Igen nagy frekvenciákra megoldja a hidegítés, a lassabb eseteket meg kiszabályozza a 7805 erősítője.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

+1
Nem osztom bucko averzióját a 7805 -el kapcsolatban. Persze, ha kihagyod a szűrőkondikat és csak úgy szőrén beteszed, vagy egy marék LS TTL IC-t akár tápsínes nyákon meghajtasz vele 800mA felett akkor készülj a legrosszabbakra. Az én esetemben nincs ilyen igénybevétel. 1 db LED a legkomolyabb terhelés.
A kapcsoló tápról is működik, de amit a vackaim között találtam, az csinos szöszöket termelt, ami valójában csak engem zavart a szkópos mérések közben.
Általános szabály, hogy a zavarokat nem szabad megtermelni, akkor nem kell őket szűrni :)

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

:)
Az averzió mögött azért van 30 éves fejlesztőmérnöki tapasztalat is.
Amit egyikőtök sem olvasott el (ez így a fórumokra jellemző - osztjuk az észt, osztán olvasni meg nem tudunk): a 7805 10kHz felett igen rosszul szűr. Ha kihagytad a nagyfrekvenciás szűrőt a hálózat felé, akkor az olcsó trafó kapacitíve átengedi a "Kossuth Rádiót". Ezt a zavart nem fogja meg sem az elkó sem a 100nF kerámia, sem a 7805. És belekerül(het) az áramkörödbe. Az adatlap 10uF tantálkodenzátorral közli a rossz hírt. :(
Ezért írta valaki egyik topicban, hogy ma működik, aztán egyszer csak nem... Hát pl. ilyen okok miatt. Mondjuk a szomszéd bácsi bekapcsolta a régi tévéjét, ami az egész lakótelepet ellátja megfelelő zavarszittel. :)
Tényleg van egy kis probléma az alacsonyabb frekvenciákon. Alább láthattok egy nem szokványos "injected in-phase ripple" technikával gerjesztett, de fix frekvenciájú kapcsolóstápot. A piros karika egy méretezett EMI filter, a nyíl a kapcsolótranzisztort mutogatja. A "hűtőborda" a 18um vastagságú fóliából lett kialakítva. Üzemi frekvencia 160kHz, kimenő feszültségek: 5V + 5V galvanikusan leválasztott stabilizálatlan. A tápot mikrokontroller vezérli.

A szkóp (10mV/div és 4ms/div) azt mutatja, hogy normál helyzetben kicsivel több mint 10mVpp a zaj. Az ennél kicsit nagyobb beszakadás az előforduló terhelésnél nagyobb terhelésugrás teszt. Ennek alapján a tápegység legfeljebb 40mVpp zajt termel. (Hát izé, nem voltak a boltban kisebb kondik.) A kisebb cikcakkok az I2C és soros vonali kommunikáció miatt van.

A konstrukció lényege:
- A főnök vásárolt egy dobozt.
- A főnök vásárolt egy akkut, ami belefér a dobozba.
- Aztán terveztem egy áramkört, ami legalább 10 órát kibír egy töltéssel. :)
Persze a leglényegesebb: elöl-hátul fojtó, Kossuth Rádió meg a váróteremben ücsörög. ;)

Szerintem elbeszélünk egymás mellett. A kapcsolóüzemű táp eleve képtelen kiszabályozni a nagyfrekvenciás komponenseket, lévén, a ciklusidején belül kellene ezt tennie. Éppen ezért, meg azért, mert igen nagy zajt termel, benne van szűrés. Mégis mi a fene akadályoz meg abban, hogy LC szűrőt építs egy 7805 köré? Kapcsolóüzemű tápnál megteszed, mert muszáj, analóg tápnál nem teszed meg, majd ujjal mutogatsz rá, hogy de hiszen ez sz.r!

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nem is értem. Mindenki azzal cseszeget, hogy elavultak az ismereteim. :(
Ha megfigyeled, a 7805 lassanként 40 éves konstrukció. A világ értelmesebb fele nem használ analóg tápot. Nem csak a költségek csökkentése miatt, hanem a kapcsoló üzem funkciógazdagabb, és jobb üzemi paraméterekkel rendelkezik.
Az általam forgatott 1983-as Siliconx katalógusban már 100..500kHz-es megoldások is vannak, pedig akkoriban elég gyenge fetek voltak. A mai táp ic-k tipikusan 1..6MHz-en működnek. Ha úgy gondolod, hogy ezek a megoldások több zajt termelnek, vagy lomhábbak a 7805-höz képest, akkor tévedtél!

A zavarszűrőt meg lehet tervezni, de boltban is kapható megfelelő alkatrész. Aztán képzeld el: zavarszűrő, puskástrafó, egyenirányító, kondik, 7805, hűtőborda -> breadboard. Reszelhetsz hozzá dobozt is. Egy amatőrnek praktikus?

A fentiek helyett egy kész táp - azt jelenti nem teszem meg, mert a gyárban már megtették. És nem kerül egy puskástrafó árába sem.

Igen. Csak egyet felejtesz el, de félő, inkább tudatosan. A Nokia tápot nem a nyákra teszi a kísérletező kedvű kolléga, hanem a már stabilizált tápot vezeti fél méter vezetéken. Szerinted ez normális? Ugyanaz a gond vele, mint az USB portról kinyert táppal, amennyiben 5 V-os hardware-t működtetnek vele. Aztán megy a pislogás, hogy brown-out reset volt.

Szerintem a szabályozónak a felhasználás helyéhez igen közel kell lennie, hiszen a visszacsatolási pontnál biztosítja a közel nulla impedanciát a szabályozó.

Számomra már az is egy rémület, amit R-Pi-vel csinálnak. 5 V-ot adnak neki valami külső tápról.

Két lehetőség van, ami szerintem elfogadható. Az egyik, hogy az áramkör megcsinálja magának a 3.3 V-ot, mert ennyiről működik, s nem túl fontos, hogy az 5 V annyi-e, mekkora rajta a zaj. A másik, hogy beletesszük a fél méter kábelt, de akkor 4 vezetékes legyen, azaz a szenzor vezetékek a cél helyről vigyék vissza a szabályozóba a szabályozandó feszültséget. Ez már szebb, de csak óvatosan, mert ha elfogy a fázistartalék, oszcillálni kezd, s vége mindennek.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az öreg tápegységes kolléga úgy tanítota, hogy egy panelen a bemeneti szűrés hivatott megszüntetni a 10 cm vezeték által felszedett zavart. Ennek ellenére nem kell négyhuzalos megoldás, mivel nem precíziós vagy nagyáramú a táp. Ennek ellenére van olyan LDO szabályzó (pl. Texas LP3961), ahol van "sense" bemenet. Számold ki a vezeték ellenállását, és meg fogsz lepődni. (Ez nem vonatkozik a kici kinaji usb vezetékekre, mert ott a keresztmetszet közel 0.) Lehet még feszülségesés zavarimpulzus miatt. Erre a ferritgyöngy a megoldás. Keress egy USB illesztési leírást! Némi tanulmányozás után kiderül, hogy az USB tápot, adatvezetéket csak úgy bekötöm, aztán miért akad le mégis...

Az USB meg minden szempontból szívás. A brown-outot kísérletezgetés közben célszerű lekapcsolni!

Tehát 2db lényeg van:
- Az áramkör bemenetét kell megfelelően szűrni. Ez a "megfelelően" kicsit homályos. Ezért a következő lényeg.
- A bementen kialakuló feszültség alsó és felső értékének a kívánt értéken belül kell maradnia.
Pl. a TTL táp 5V+-5%, azaz a tápfesz+zavar minden esetben a 4,75..5,25V tartományban jó, ezen kívül nem garantált a helyes működés. Így elméletilag az 5,0V+0,5Vpp zavar esetén kifogástalanul működik az áramkör. Ebből a keretből azonnal ki lehet kerülni, ha hiányoznak az egyes tokok tápfeszültség lábaira kötött hidegítések. Ugyanis a kapuk átkapcsolásakor keletkező áramimpulzus kicsit kisüti ezeket a kondenzátorokat, míg az így keletkezett feszültséglökést megfogja a tápvezeték induktivitása.

(Dolgoznom kéne, ezért írok egy gyakorlati példát ;)

Hi-lo FET rc csillapítótagot hangoltam. Az egyik konfigurációban a két eszköz egymás mellet - a járulékos induktivitás 21nH, a másiknál szemben - 42nH, azaz +36mm hossz. Az egymás melletti hangolása sikeres volt. A szemköztinél elhelyeztem a tagot, megszűnt a lengés. Megmértem a másik oldalt, és "nem látta" a csillapítást. Közben volt egy fojtó! (A jel emelkedési sebessége: 12V/70ns.) A megoldás igen durva: mindkét oldalra be kellett szerelni a csillapítót.

Természetesen az esetleges analóg perifériákra más előírás vonatkozhat. Tán ezért van az AVR-en is két tápcsatlakozó.

Itt a 16MHz órajel a lényeg, mert azt csak 4,5..5,5V tartományban garantálják.

Nagyon színvonalas lesz ez a topic. Köszönöm!
Tudom és vallom a mikroprocesszorok szentháromságát:
- táp
- reszet
- órajel
Ha ez a három dolog rendben van akkor már nagy bej nem lehet. bucko révén, tudni vélem, hogy az annyira kívánatos i2c, spi stb. szintén nem olyan egyszerű, hogy "rácinezem osz't kész".
Mindazonáltal, az adott feltételek mellett nem hiszem, hogy itt most ezzel volna gond. Ha belegondoltok, hogy bizonyos Arduino lapokon van egy proci, és a PC USB táplálja nagy hiba ezzel nem lehet. Persze amikor beleépíted valami kütyübe, mellé teszel egy valamiféle tápot, akkor lehetnek meglepik, de itt és most nem hiszem, hogy ez lenne a problémám forrása.

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

Igen érdekesen programozol C-ben! ;)

TIMSK = (0 << TOIE0); // Disable Timer0 overflow interrupt
Ezt így kell írni helyesen:
TIMSK &= ~(1 << TOIE0); - gondolom van ilyen: bit_clear(TIMSK, TOIE0)
avagy
CBI TIMSK, TOIE0

TIMSK = (1 << OCIE0); // Enable timer 0 compare match interrupt
Ezt így kell írni helyesen:
TIMSK |= (1 << OCIE0); - gondolom van ilyen: bit_set(TIMSK, OCIE0)
avagy
SBI TIMSK, OCEI0

Ökölszabály: bitmaszk érték sosem 0, mert akkor nem mondtad meg melyik bitet maszkolod!

if ( timi_array[1] <= 0 ) ....
Ha gondosan végzed az inicializálást, akkor elegendő az egyenlőség vizsgálata. És vajon az uint mikor lesz negatív? :)

A volatile azt jelenti, hogy a fordító felkészül a változó a külső tünemények által történő módosítására. Így az interrupt tiltása a változó vizsgálatakor felesleges!

Szóval ezidáig úgy tűnik érdemesebb az adatlapot gondosan elolvasni, és asm-ben programozni. Mert akkor előbb tudod meg mit csinálsz.

"Lehet az a gond, hogy ha nem veszem el időben a karaktert (sem overflow sem overrun hibát nem figyelek) és nem kezelem le a hibát akkor elszáll?"
Az adatlap szerint (19.7.4 Receiver Error Flags):
"The USART Receiver has three Error Flags: Frame Error (FE), Data OverRun (DOR) and Parity Error (PE). ... None of the Error Flags can generate interrupts."
Valamint az adat olvasása előtt kellene vizsgálni a hibát, mert utána törlődik. Azaz "figyelni" nem lehet, csak olvasni. Persze ez itt nem számít.

"Ha a timer figyelést kiterjesztem a többi kis timerre, akkor megnyúlik a lekérdezési idő és nem érek oda időben,..."
A 16MHz periódusa 62,5ns, a soros port karakter ideje ebben az esetben kb. 1ms. Szóval hol kószálnál 33000 órajel alatt?

A táplálásról írja a AVR042: AVR Hardware Design Considerations: "Looking at the datasheet for an Atmel AVR microcontroller, one can be fooled to believe that power supply is not critical." :)
Ráadásul ez a dokumentum ground plane táp és földelés szűréséről beszél!
A gyakorlatban bármelyik kimenetre kötött néhány száz pF kapacitás (ugye a 10^12 Ohm bemeneti ellenállású FET :) hatására túllépheted az adott kimenetre engedélyezett áram maximumát. Szkóppal mérni szinte lehetetlen, analizátorral sem tudod igazán triggerelni. Viszont tápfeszültségen keletkező tüske miatt a processzoron belül átbillenhet egy flip-flop, így a konstrukciótól függően valamely bit vagy beállítás megváltozhat.

Hát ennyit a breadboard előnyeiről!

A 16MHz meg csak a 4,5..5,5V tartományban garantált...

Nem néztem meg a kódját, de ezek szerint alaposan bugos volt. A nullát taszigálhatja balra, akkor is nulla marad. Az 1 esetében jobb a helyzet, csak cserébe tiltotta a többo IT-t.

A 33000 órajel magyarázatra szorul szerintem. Jól írtad, csak a fentebbi számokból ez nem nagyon látszik. Egyrészt 9600 8N1 esetével kalkuláltál, nem 1 ms-mal, másfelől az első karakter után a következő shiftelésének idejét is számoltad. Ez lehet akár helyes, de ha a legutóbb átvett karaktertől nézzük, akkor csak picivel több, mint 16000 órajel van.

A leírásod alapján amúgy az sejlik, hogy a maszkolások lettek csúnyán elszúrva, tehát olyan bitek is visszatörlésre kerülnek, amelyekhez nem kellene nyúlni.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Természetesen 2 karakter, mert a második éppen most siftelődik be. Persze ez is lényegtelen, mert overrun esetén (rákönyököl) is mindig lesz egy karakter az UDR-ben. Legfeljebb néhányat elveszít.

Valójában ebben a programban nem állnak azok a bitek, amiket visszatöröl. De azért csak katonásan!

A hidegítés meg nagyon nem játék!

A második karakternél látszik, hogy két órajel H szintje gyakorlatilag hiányzik az "időben". A 5us zsugorodott 167..375ns értékre. A hiba oka, hogy az egyik kimenet hajtotta a 160kHz-es tápegység FET bemenetét. A max. kimenőáramot az megengedett értékre korlátozó ellenállást sorba kötve a jelenság megszűnt.
Ez volt a drótozott kapcsolásban, és jött az smd, ground plane (öreg profi tervezte), mlcc mindenhol. És megint bejött ugyanez. A hiba oka: kifelejtettem néhány kétirányú I2C meghajtón a lábakra szerelt szűrést. A buszmeghajtó 3 logikai szinttel dolgozik, gyakorlatilag az él alján dönti el, hogy ő most adó vagy vevő. Ez néhány ns hosszú glitch-ként jelentkezik, amit gyakorlatilag lehetetlen mérni.
Nem is ez a (nem ló! :)) csemege az egészben, hanem a jelenség. A glitch az SCL vezetéken keresztül, a mikrokontrolleren belül nullázza az I2C BRG-t, amit maga a mikrokontroller nem vesz észre, nem jelzi a státuszban, így szoftver úton nem javítható. A buszon lógó perifériák "nem értik" a túl rövid H szintet, várnak a további órajelekre, ezért a busz leakad. (PIC18F14K22)

Még egy szó a C és a volatile kapcsolatáról. Ilyet még csak multithread könyezetben használtam. Bár a jó fordítónál felesleges volt, mert felismerte és megvédte a thread-en belül és kívül használt változókat. Mikrokontroller esetén érdemes kicsit gondolkodni, mivel lassú és kevés a memória. Pl. van e szükség a 10 és 100 értékek 32 bites tárolására. Mindezeket 1 bájton tárolva nincs szükség az interrupt tiltására, vagy a volatile védelemre, és még a kód is kisebb, gyorsabb lesz.

Ezt kis szösszenetet nagyon köszönöm, tanulságos!
Az áramkorlátot a FET vezérlésében biztos nem hagyom ki (hacsak nem használok valami array -t ahol eleve benne lehet). Viszont, hogy az i2c lábait is kell szűrni, ez valószínűleg nem jut az eszembe, amíg néhány álmatlan óra után, végső kétségbeesésben ki nem próbáltam volna. Tény hogy a néhány 100KHz sebesség mellet pl. hidegítő ferrit gyűrűket iktattak be minden vezetékhez (pl. Centronics).
A volatile dologról mint írtam nincs jele hogy a fordító bármit is tenne az interrupt védelmében.

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

Nnneem!
A ferrit csövecske nem "hidegít". Ilyen paraméterei vannak: pl. 23 Ohm 100Mhz-en.
Ez a tulajdonság pont arra jó, amikor nagyfrekvenciás zavar, avagy akár egy roppant gyors impulzus hatására fellépő gerjedést kell elcsípni. Ekkor a "egyszerű drót" hirtelen ellenállásként viselkedik és gyorsan lecsillapítja a rezgést. Tipikus rezgőkör egy FET valamely kapacitása és a hozzá vezetett vezeték induktivitása.

Az I2C buszt nem szabad szűrni, hanem a rákötött (kétirányú) buszmeghajtót kellett a gyártó specifikációjának megfelelően hidegíteni. Ugyanis amíg azon tétovázott, hogy adjon vagy vegyen, elbillent és megrántotta a tápot. Mármint a sajátját, ezért rövid időre tévedésbe esett. :) Szóval megrántotta az SCL vezetéket, ami elrátotta a CPU I2C BRG-t. Kész dulakodás és tömegverekedés!!

Az interfészekre rakott ferritgyűrű a külső zavaroktól is véd. Néhány centi vezeték kiválóan veszi a Kossuth Rádiót! Zavarvédelem híján meg mindenféle rejtélyes körülményekről pusmognak a "szakemberek". :)
Aztán egy IBM szerver meg mégsem érzékeny a körülményekre! Hát nem érdekes?

A volatile nem az interruptot védi, hanem az interrupt alatt megváltozott értékek hatásaitól óvja meg a programot.
Pl.
Változó = 0x00ff (két bájt)
Beolvasod a felső bájtot = 0
Interrupt -> Változó++ -> 0x0100
Beolvasod az alsó bájtot = 0
Következésképp a Változó==0

A másik alapeset, ha a programod többször felhasználja ugyanazt a változót. Nem mindegy, hogy az elején regiszterbe töltöd és azt használod végig, vagy többször töltöd be - másodjára az interrupt/függvény által megváltoztatott értéket. Ilyenre van pl. a "#pragma isolated_call", amivel kijelented: sietek, de garantálom, hogy a hívás nem módosítja az általam használt változókat, igy nem kell menteni (megvédeni) őket.

Node!
A volatile csak konzisztens forráskódnál működik! Ha C-ben védendőnek deklarálod, és kézi asm betéet használsz, a fordító nem ismeri fel, hogy a 0x1234 címről olvasott bájt megegyezik a "volatile char X" értékkel!

Ami a bitmaszkos műveleteimet illeti pirulok! Teljesen jogos, javítottam!
Sosem használtam, szerettem ezeket bitműveletes dolgokat C -ből, itt az ideje megbarátkozni velük ;)
Ami a volatile dolgot illeti a fordító nem tesz be semmilyen védelmet, arra az esetre ha vizsgálat közben ( timi_array[2] <= 0 ) rászaladsz a timer interruptra. Így nem látom hogy készül fel a "külső tüneményekre".
A <= vizsgálat szimplán reflex, a fordító egyébként or utasítással állítja be a flageket majd brne (Branch if Not Equal) utasítással vizsgál/ugrik, nem panaszkodik az uint -re.
A tápfesz mint fentebb írtam 5V (egy analóg tápból).

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

Köszönöm a tippeket és segítséget. Sajna, a helyzet mit sem változott :(
Továbbra is leakad a proci, ha egynél több "timer" vizsgálatot beiktatok.
Ráadásul nem látom, nem tudom, hogy tehetném láthatóvá hova is megy el a processzor. A kódban NINCS olyan hurok amibe beleragadhatna. Ha a stacket futtatom túl? - talán ez de akkor is (általában) vissza áll valahogy az eredeti állapot. Pillanatnyilag, csak a timer0 compare/match interruptja él, de nem abban cirkulál, amikor "leakad" akkor oda sem megy be.
Azon gondolkodom, hogy vajon, tudok-e a "__bad_interrupt" kezelőt át tudom-e írni - valami bitet ott megmozgatnék.
Erős a hw hiba gyanúja, de ha nem nyúlok a soroshoz, a timerkék tökéletesen működnek. Ha csak egy timerkét kezelek/vizsgálok akkor sem látszik a hiba (volt hogy egy órára magára hagytam a PC -vel).
Misztikum :)

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

Javítottam a buta bitmanipulációs hibáimat, leforgattam - a hiba maradt.
Cseréltem a pastebin -ben a kódot és csatoltam az assembly listát: http://pastebin.com/vf21UEUH
Nagyon tanácstalan vagyok, ez a hiba teljesen értelmetlennek tűnik.
Megnéztem az áramot (alapesetben, LED nélkül, "fogadókész állapotban) 43mA ha lefittyen akár 49mA -ig is felfuthat. A Timer0 compare/match kimenete PB3/(OC0/AIN1) kiakadt állapotban is 1ms szép 50% kitöltésű négyszöget produkál. A teszteléshez használt port A lábak különféle állapotokban állnak, azaz sem a timer compare/match interrupt nem jut érvényre, sem a "fő" hurok nem ketyeg, illetve a timer teszt rutin is "hallgat".
Hol jár a proci esze?
Azon morfondírozok, hogy nem "bicegtetni" fogom a portot, hanem a kód meghatározott pontjairól kiteszek egy pozíció számot, legalább azt megtudom hogy mindig ugyanott akad el vagy sem, mi az utolsó "lehelete".

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

Ha jól látom, 1-et levonsz a timer számlálódból. Ha nem negatív, visszatárolod az eredményt, ha negatív, átugrod a tárolást. Nem tudom, mit szerettél volna. Valóban az a cél, hogy ha eléri a nullát, ne számoljon tovább? Tehát alap szintről majd újra inicializálod?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Pontosan.
Talán mondtam párszor, hogy ez most még inkább ujjgyakorlat. Így itt és most azt próbáltam meg hogy lehet néhány számlálót csinálni, egyszerű ütemezési feladatokhoz úgy, hogy az interrupt kezelő rutin kicsi és hatékony maradjon, kihasználva az utasítás készlet sajátosságait.
Így lett 1ms és 16 bites a számláló, az interrupt rutin a státusz regiszteren kívül csak az R24 és R25 regisztereket használja (a bit piszkáló csak teszt, szépsége hogy nem használ semmilyen regisztert).
Köszönöm, hogy ránéztél!

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

Most nem váltogatom a port biteket, hanem a különféle pontokon más-más számot teszik ki. Változó hosszan tűri az UART (30 -tól akár 512 karakterig) de mindig a "test_timer" rutin legvégén (mielőtt visszatérne a fő hurokba) áll meg az élet. Olyan mintha a stackel történne valami.
Megpróbálom újra húzni a stacket, a fő hurokban, teljes interrupt tiltás mellett.
IGEN! A fő hurokba a következőt tettem:


cli();
SP = 0x04FF;
sei();

Azóta stabil.
De hol vagy hogy az ördögbe száll el a stack?

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

Sajnálom, már vagy ötször olvastam de nem értem a bejegyzésedet :(
A végtelen ciklus egy átlagos megoldás az állapot automatára.
Sokkal izgalmasabb, hogy hogy tud elszabadulni a stack pointer?
Nem látom ennek lehetőségét a kódban sehol.
Mindenesetre most kipróbálom az "inline" típust :)

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

Ugzan nem okoz gondot, de eleve furcsa, hogy a stack-en feleslegesen tart egy visszatérési címet. Valami ilyesmi

call main
jmp exit

exit:
cli
stop:
jmp stop

Amolyan meta nyelven írtam. Elvileg, ha kijönne a main-ből, visszatérés után IT-t tiltana, majd egy végtelen ciklusban pörögne.

Amúgy minek stack-en tárolni a main-ből való visszatéréshez tartozó címet? Egyáltalán mennyi hely van a stack-en? Milyen mélységben használhatod?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Aha! Leesett. Te az assembly listát nézed.
A szóban forgó részt NEM én írtam, az avr-gcc kreálja, nem tudom miért jó ha megjegyzi ezt a címet vagyis szubrutinként hívja meg az általam írt programot ...
Nem értem mire (lehet) jó ez.
Közben azt is kipróbáltam, hogy a "test_timers" rutint mint "inline" definiáltam - a hiba így is megszűnik.
Ez egy őrület!

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

Csak ámulok!
Szemem kiesik, de nem találok hibát.

A C fordító 045f-re állítja a stack értékét.
A 04ff nem tudni hova címez! :)

PORTA = PINA ^ 0x80; -> PORTA = PINA - 0x80;
in r24, 0x19
subi r24, 0x80
out 0x1b, r24
Félrefordította a fordító?

Olvasgatom az adatlapot, de nincs ötletem. Ilyen akkor fordulhat elő, ha a cpu extrém alacsony órajellel megy, vagy lebeg egy interrupt bemenet. Az utóbbi a bad interrupt vektorok miatt nem valószínű.

A biztonság kedvéért tiltani kellene az összes nem használt interruptot.

Egy kis kiegészítés.
timi3_zero:
//------ Toggle port A pin 0
SBIC _SFR_IO_ADDR(PINA), 0
CBI _SFR_IO_ADDR(PORTA), 0
SBIS _SFR_IO_ADDR(PINA), 0
SBI _SFR_IO_ADDR(PORTA), 0
//------
Talán ezért az inline mizéria.
Ezt cseréld ki a kedvemért: PORTA = PINA ^ 1;

Az assembler közepén C szöveg? - ilyet lehet?
Az a négysoros "novella" azért jó, mert nem használ semmit, csak a portot meg jó sok proci ciklust :)
A 0x04FF csak elírás és csak itt.
A legfurcsább (számomra) hogy a stack pointer mászik el, semmi olyat nem látok ami ilyet okozhatna. Mondjuk a végtelenített main loop elé még nem tettem markert - ez lesz a következő.
Aztán elmélyedek a szóról-szóra átvett make fájlomat, lehet ott valami hiba van, bár az assembly listában sem látszik hiba.

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

Izé - visszakozom, de csak félig.
Amit ott kiegészítésként írtam, azt hittem C-ből fordult. De nem, hanem inline.
Pontosítok: Úgy néz ki, mintha C-ből asm() direktívával került volna be.
Ezt csinálja:
- törli a PORTA.0 bitjét, ha 1 = 0 vagy 1->0 azaz mindig 0
- beállítja a PORTA.0 bitjét, ha 0 = 0->1 vagy 1
Ez egy két órajelnyi impulzus. Jól látom?

Helyette:
CBI _SFR_IO_ADDR(PORTA), 0
NOP
SBI _SFR_IO_ADDR(PORTA), 0
Ezt még én is értem! ;)

Dejszen ott az asm lista! Kicsit egyszerűsítsd le, fordítsd le, majd kezdjed visszaírni C-be.
Itt tértem át én is tiszta asm-re! (Nincs szmájli!!)

Nem ez nem egy pulzus, ez a PORTA = PINA ^ 1 - azaz ahogy írtam minden alkalommal ha rászalad az interruptra fordít a biten.


//------ Toggle port A pin 0
SBIC _SFR_IO_ADDR(PINA), 0 ; branch if IO bit is clear
CBI _SFR_IO_ADDR(PORTA), 0 ; clear IO bit
SBIS _SFR_IO_ADDR(PINA), 0 ; branch if IO bit is set
SBI _SFR_IO_ADDR(PORTA), 0 ; set IO bit
//------

A "novella" hátránya hogy elég sok ciklusba kerül - 4x2.
Az _SFR_IO_ADDR természetesen kiváltható a megfelelő direkt IO címekkel, de ha már használom az io.h headert akkor ezt kéne "erőltetni" - vagy még sem?
Tulajdonképen ez volt az egyik olyan kód amiből azt a következtetést vontam le, hogy jobb ezt C -ben kódolni ha lehet, mivel egy ilyen egyszerű bit művelet is ennyi gépelgetést igényel. Azért csak elegánsabb a C kód erre. Viszont az interrupt kiszolgáló rutinokat szeretem assemblyben írni - már az első alkalommal eg felesleges push/pop páros belekerült - a c fordító optimalizációja nem mindenható.

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

Nézem a kódot, és szerintem rossz a soros port kezelésed.

Ha van Rx adat, akkor azt kiolvasod, megnézed, írható-e az adó, s ha igen, beírod adásra. Csak ez hibás, mert adatvesztés lehet.

Tegyük fel, az adó épp még küldi az előző karaktert. Bejön az adat Rx irányból, azt átveszed R24-be. Megnézed, üres-e az adó. Mondjuk nem az. Nem írod be a karaktert az adóba - helyesen -, de utána R24-et felülírod, bár ez mindegy is. Kiolvastad a vevőt, nem küldted a karaktert adásba, mert nem vártál Tx empty-re, csak simán eldobtad a karaktert.

Lehet, hogy ezt akartad, de erőst kétlem, mert eléggé esetlegesen fordulhat elő, hogy eldobja a vett karaktert.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ez igaz, de már írtam valahol feljebb. :)
Itt, ebben a tesztprogramban nem fordulhat elő, mert a szerkezet elég gyors, és a TX buffer gyakorlatilag 2 bájt méretű. Mert nem a TXC-re vár, hanem az UDRE-re, ami egy bájttal beljebb van.
Ha meg eldobja a vett karaktert, akkor az kimarad - 10 A betű helyett csak 9 jelenik meg, de nem akad le.
Hacsak...a 9600 baud két irányban eltérő sebességű. ;)

A való világban meg 2 dróton xon/xoff a célszerű.
Szívesen közzéteszem a PIC-es vevő interruptomat, sőt átírom AVR asm-re is. Bár ilyet csak szemüveg nélkül 1 kilóméterről láttam eddig. :)

Köszönöm a felajánlást, de attól tartok a PIC most inkább csak bezavarna.
Mivel ahogy írtam, a fejlettebb, interruptal megvalósított (egyébként szemre teljesen jó) UART librarik rossz eredményt adtak ezért kezdtem egy ilyen csúcs primitív megoldásba, ahol tuti nem lehet valami hurokban elakadni. Ha ez megy akkor jöhet a következő lépés az ISR.
A baj az hogy nem tudom mit gondoljak, miért nem működik ez a dolog nálam? Hogy tud elmászni a stack egy ilyen szinte lineáris programban, ahol a call utasításokat csak azért használtam, hogy a kód áttekinthető legyen. Valami van itt nálam az asztalon ami bezavar, ami a hibát okozza és rá kellene jönnöm mi is az. A létező UART librarikkal is az látszott, hogy akár reszetre futnak, ha folyamatosan "dől" az infó, biztos hogy nem így kellene viselkedniük. Már nem igen tudom mit is gondoljak - mondjuk hozom a formám, egy ilyen egyszerű dologban is sikerül valami extra hülyeségbe beleszaladnom.
Még az jutott eszembe, hogy mindenütt ATmega16 van beállítva, pedig nekem ATmega16A -van. Az adatlap azt mondja ez "drop in" helyettesítő és a simát már nem is gyártja. Lehet mégis van valami kis differencia?

OFF: Már viszket a kezem az ARM -okra de amíg nem jutok dűlőre az AVR -el mit akarok ARM -al? A konklúzióm továbbra is az hogy az AVR, PIC, MSP430 stb. kategóriájú mcu -nak van még bőven jövője, az ARM nem fogja mindenhonnan lemosni, hiába vannak komoly átfedések.

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

Ilyenkor célszerű olvasgatni a CPU-hoz kiadott errata-kat is. Sokszor vannak hardware bugok is, amelyek akár egy nop-pal, vagy valami kerülő úton megoldhatók. Aztán, amit án csinálnék, ha már úgy is USART: mi lenne ha a stack pointert logolnád ki soros portra a vett karakter helyett? Látnád, hogyan változik az értéke.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az ötlet jó, csak elkésett. Már tudjuk, hogy a stack pointer mászik el azt nem tudjuk, értjük hogyan.
Azt is tudjuk, hogy a hiba mindig a "test_timers" futása végén, épp ahol a "ret" utasítás jön, jelentkezik (nem az interrupt rutinban).
Azt is tudjuk, hogy ha a "test_timers" rutinban csak egy timert "testelek" akkor nincs gond (vagy nem jelentkezik) de ha már kettő, akkor baj van ...

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

Mivel ebben a szakmában több alkalommal ért már meglepetés, olyasmi, hogy valami valaminek látszott, de nagyon nem az volt, aminek látszott, én nem mernék teljes bizonyossággal ilyen határozott állításokat tenni. A problémához való kellő alázattal és nyíltsággal történő közelítés eredményes szokott lenni. Mindenképp érdemes bizonyítani azt is, amiről úgy gondolod, hogy az úgy van.

Lehet, logolnám az SP-t a rutin hívása előtt, a rutin elején, végén, a visszatérés után. Aztán bináris kereséssel megpróbálnék rázsugorodni a hibára, annak környékére. (Értsd: kikommentezzük a kód első felét, ettől elmúlik-e a hiba, aztán a másik felét, a hibátlan rész felét, és így tovább. Persze nem pont a felét, értelmes maradjon a kód azért még.)

Ha úgy van meg a hiba, hogy be lett határolva, de nem világos, mi lehet a baj, akkor arra a környezetre próbálj valami szintetikus tesztet írni. Nyilván fantázia is kell hozzá, valamire gondolni kell, hogy mi lehet a baj, mit szeretnél tesztelni.

Specifikáció betartása fontos. Tehát, ha gyorsan járatod a processzort, ahhoz a tápfeszültség szűkebb tartománya szokott kritérium lenni, ezt be kell tartani.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ilyeneken morfondírozok én is.
A hibakeresésnél (csakúgy mint az elkallódott cuccoknál) először a legvalószínűbb helyekkel foglalkozunk, aztán jön a többi. Nem egyszer találtam ott a hibát, ahol a legkevésbé gondoltam volna.
Az is felmerül, hogy át- újraépítem a deszka modellt - gyanús a táp. Ha lehúzom a külső tápot, de rajta van az USB hajtotta jtag (a Vcc nincs összekötve), akkor lemegy a tápfesz illetve a logikai szintek, de a kütyü ketyeg és a frekvencia sem változik - a JTAG kb. 3m kábel végén lóg. Teljesen képtelenül elfuserált állapot és mégis valamennyire működik ;)
Mielőtt "heurékát" kiáltanál, a szoftvert úgy is járattam hogy teljesen lehúztam róla a jtag -et, semmi nem változott.
Aztán van úgy, hogy az "áttöréshez" kicsit pihentetni kell a témát, de itt így is sok a megszakítás.
Az első próbálkozásoknál, mikor beakartam állítani a fuse biteket a 16MHz órajelhez, eltelt némi idő míg rájöttem, hogy a fuse írása utáni olvasás nem tud hibátlanul lezajlani és a proci megáll. Viszont, ha utána egy külön paranccsal kiolvasom a fuse biteket akkor helyreáll, beáll. A flash programozásakor nincs hiba Wheezy -ben, viszont Jessie -ben egyáltalán nem működik :[
Az egész nagyon rágós és nyögve nyelős.

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

Betettem soros "inicializálása" után (init_asy();) közvetlenül, hogy küldjön ki egy csillagot (UDR = '*';). Visszatettem a hibázós kódot - azaz kivettem az "inline" definíciót. Sőt kivettem a "test_timers()" -ből az interrupt tiltást - nem korrekt dolog de egy próbát megér.
Az eredmény az hogy többször is reszetál menet közben (ha nyomom a karaktereket). Ha ez az esemény mindig ugyanakkor történne, akkor valamilyen stack művelet sokszorozódna, mivel azonban ez teljesen véletlenszerű, hogy hanyadik karakter után "dobja be a törölközőt - a reszetet" ez leginkább olyan mintha fejbe írná a stack regisztert.

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

A bit_set illetve a bit_clear az avr-libc -ben nincs.
Találtam az avrfreaks oldalon: http://www.avrfreaks.net/forum/set-bit-c?page=all
Egy kupac makrót, így az utasítás így néz ki:
bit_clear(TIMSK,BIT(OCIE0)) ill. bit_set(TIMSK,BOIT(OCIE0))
A nop mint utasítás létezik az avr-libc -ben az avr/cpufunc.h headerben van definiálva a _NOP()
Betettem, nem jött be :(
OFF: Jó züllést!

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

Így igaz! És itt-ott használja is a compiler. De ezek a bit manipulációs makrók úgy tűnik nem :(
Viszont hogy ebbe belekérdeztél, ránéztem a _NOP() makró definíciójára.


#define _NOP() __asm__ __volatile__("nop")

Mindehhez azt írja, hogy ez arra lehet jó, hogy a compiler egy utasítást ne optimalizáljon ki, így ez mindig jó breakpount a debuggernek.
Azt viszont még nem tudom, hogy az sbi vagy a cbi utasításhoz szükséges két operandust (IO regiszter cím és bit szám) hogy lehet egy ilyen makrón belül átadni. Ráadásul ha ilyen egyszerű akkor miért nem került bele az avr-libc -be?

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

No, nemá!
Ha van bit_is_set(), akkor van bit_set() is!
Itt a kódod:
PORTA = PINA ^ 0x80; // Toggle port A pin 7 PINA ^ (1 << PA7)
//---
if ( bit_is_set(UCSRA,RXC) )
{
aux = UDR;
if ( bit_is_set(UCSRA,UDRE) )
UDR = aux;
}

A NOP -> AVR-gcc->asm szintaxist kell követni!
A problematika a következő.
Abban a pillanatban, amikor a timer overflow interruptot engedélyezed (unmaskolod) a következő utasítás a RET.
Ha sok timit vizsgálsz, akkor nagyobb a valószínűsége, hogy a maszkolt interrupt alatt áll be a timer Compare Match. Ekkor az engedélyezés pillanatában csak egy RET van hátra, mikozben ez alatt az interrupt készülődik a 19-es vektorra. Itt lehet a hiba.
Ezért kell a NOP, ami az eseményeknek kifutást enged. (idézőjel, idézőjel)

Ezzel mit vélelmezel? Szerintem bármely pillanatban jöhet IT kérés, akár ret előtt, akár utána. Ha előtte jön, az IT által stack-re tett visszatérési cím a ret utasításra fog mutatni, ha utána, akkor pedig a már eleve az mentődik a stack-re, ahova a ret visszatért, azaz amit épp az imént szedett fel a stack-ről.

Ettől függetlenül lehet hardware bug, ha erre utalsz, de akkor azért elég nagy a baj szerintem.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Igen, valami hardware bugot akartam kizárni.
Az interrupt maszk bitjeit nem szabad így kezelni! Igaz, én javasoltam a C szintaxist, de hibás.
Beolvasom a maszk regisztert - és itt a hiba, mert közben meg is változhat a maszk - és a változatlan értéket írom vissza. Ez itt csak elvi hiba.
A többi lehetséges ok, hogy a specifikáció szerint (én ugyanis végigolvastam):
- egy utasítással előrébb olvas a proci
- interrupt után mindig végrehajtódik egy-két utasítás az újabb interrupt előtt
- hasonlóan a picekhez itt is elvi kapcsolási rajzot közölnek pl. az interrup logikáról
- akár az outputként konfigurált interrupt bemenetek is okozhatnak interruptot.
Nem vagyok szkeptikus ;) , de picen is táláltam már több bugot, illetve a leíráshoz képest ellentétes működést. Perszehogy nem dokumentáltam. :( Csak "körbeprogramoztam".
Téhát igazad van: ha jól működik, akkor jól működik. Meg nekem is: ha mégsem akkor nem. :)

Még pic esetén is égnek áll a hajam, amikor indul a mintaprogram, és beállít néhány bitet, amit használ. És csak azt!

De ez a téma már alább folytatódik.

Most néztem a doksiját, úgy csinálja, mint a PIC. Tiltja a GIE-t, törli az IT flag-et, de az egyedi mask bitet nem piszkálja, így az nem lehet a hiba, amit írtál. Viszont egy nagyon durva bugot találtam, egy önálló hozzászólásban leírom...

Szerk.: elsőre úgy láttam, nem menti a STATUS regisztert az ISR-ben, de igen, csak szokatlan, hogy in és out utasítással érhető el a 0x3f címen. Töröltem a helytelen hozzászólásom, amely erről szólt.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

1. Fuse-bol kapcsold ki a brown out-ot a teszt kedveert!
2. A resetet huzd fel valami ertelmes ellenallassal a tapra!
Ha valamiert resetel, erdemes lenne megtudni, hogy miert. Csak egy AVR-ed van keznel? Ha van tobb, megprobalhatnal egy masik peldanyt. Vagy ha van masik, hasonlo labkiosztasu uC-d (vagy akar eltero is lehet, ha konnyu portolni), megprobalhatod masikkal is. Igy a HW hibat ki tudod zarni.
Milyen fuse van beallitva? (Gondolom kulso orajel a soros miatt)
Hol van a legujabb forras?

--
What's worse than finding a worm in your apple?
Finding a U2 album on your iPhone.

A brown outot kipróbálom (bár szkeptikus vagyok).
A RESZET inkább képletes, valójában visszakerül a main program elejére? Inkább olyan mint a "jmp 0" - NINCS hw reszet.
Utoljára lfuse = 0xFF és hfuse=0x99
A gyári beállításokhoz képest csak annyi a változás, hogy 16MHz külső kvarc.
A kód valójában nem változott érdemben és itt van: http://pastebin.com/vf21UEUH

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

De igen! - pontosan azt akartam, hogy akármi is legyen NE lehessen végtelen ciklusban bitet tesztelgetni/várni.
Egyébként teljesen igazad van, ha nem tudja kiírni akkor az elvész.
Próbálok megismerkedni az AVR USART -al, minden ilyen konglomerátumnak meg van a maga nyűgje, ha nem kezelhető teljesen korrektül (túl sok az adat, túl gyors a forrás) akkor azzal is kell tudni számolni.

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

Amit még nem írtam le (és nem is nagyon értek) az a make végén megjelenő memória felhasználási lista(?):
asy-test.elf :
section Size addr
.text 452 0
.bss 8 8388704
.stab 3900 0
.stabstr 2076 0
.comment 17 0

Total 6453

A .bss 8 érthető - 4x2 bájt a timerkéknek és a tick számlálónak de mi az az eszement cím érték?

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

Fejlemény: "felülírtam" a "BADISR_vect" rutint, úgy hogy tudjam ott van.


ISR(BADISR_vect)
{
  while ( 1 )
  {
    PORTA = PINA ^ ax40;
  }
}

Az eredmény, hogy továbbra is rászalad a 0-ás címre (reszet), aztán mikor "kiakad" akkor valójában itt köt ki. Most már csak azt kell kitalálnom, melyik interrupt is az.

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

+1
Ez az, ami nagyon kínos: az összes használt/nem használt ki- és bemenetet (analóg inputot, stb) ISMERT állapotba kell helyezni. Ugyan specifikált a reset utáni állapot, de tegyük fel nem hisszük el.
A reset oka minden további nélkül lehet egy véletlenül input-ként maradt port, ami interrupt forrás lehet.
Mottó: Az áramkör része az oszcilloszkóp. Kívánságra írok élő példát is. ;)

Az összes általam megtekintett példában, uart kezelő librariban NEM foglalkoznak a többi interruptal, rábízzák az alapbeállításra, amit az avr-gcc belegenerál - ezt kell átnéznem.
Az egyedi interruptok tiltása/engedélyezése szétszórtan itt-ott az SFR -ben vezérelhető, reszet után alapból tiltva vannak.
Az alapszimptóma, hogy a stack elszabadul, viszont a kódban nem látok erre okot - nincs "páratlan" push/pop. Marad hogy felülíródik - valahogy.
Akkor viszont az is lehet, hogy nem csak a stack pointer érintett, hanem az SREG vagy bármi az SFR -ek közül.
KÉRDÉS: Jól értelmezem? Az SFR és a munka- regisztereket kétféle képpen lehet címezni: IO és memóriaként - azaz az SFR -ek a memória alján megjelennek a 0-5F ig terjedő tartományban? Mert ha így van akkor azt kell megnéznem hol lehetek képes belepiszkítani a regiszterekbe.
Mondjuk a furcsa az, hogy az uart kezelő librarykhoz csatolt teszt programok is ilyeneket csinálnak? (ott is megfigyeltem hogy újraindult a program.
OFF: Itt a tavasz! Indul a telek szezon - megyek és leharcolom a füvet .)

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

"rábízzák az alapbeállításra" :)
Ez a nagy tévedés! Itt nincs BIOS, nincs operációs rendszer, a C fordító nem helyezi el a loadert a program elejére. Ez egy mikrokonroller, amit kizárólag Te programozol!!
Ha véletlenül a 0 vektorra ugrasz, az nem reset. Abszolút semmit nem tudunk a processzor, a ram és a perifériák állapotáról!

A C fordótó a következő kodot helyezte el a reset vektorra:
- SREG törlése - ezzel a globális interrupt is törlődik
- SP beállítása a MAXRAM értékére
- a BSS törlése - mind a 9 bájt :)
- call main

Az R0-R31 regiszterek az adatterület 0-1f tartományába is elérhetők.
Pl.: sts 0x0001, r0 - az R1-et másolja az R0-ba, csak kicsi szószátyárabban.
A SFR-ek a 0-3f tartományban érhetők el, amely az adatterület 20-5f tartományában is elérhető.
Az SBI CBI utasításokat a 00..1f IO regiszterekre lehet csak használni.
A ram az adatterület 0x0060 címén kezdődik.

A programodat ilyen szempontból is átnéztem, és nem találtam hibát.

Viszont fentiekből következik, hogy csak félig volt igazam. :)
A PORTA fogadja a set_bit() utasítást (SBI -> IO), mivel 0x20 alatt van. Ezzel szemben a TIMSK regiszterbe töltendő, ahol kényelmesebb az SBR utasítást használni.

A korábbi offodra csak annyit tudok mondani, hogy sem az ellenállás, sem a mirokontroller nem fog kihalni. Egészen addig, amíg úgy tudod elképzelni, mint egy ügyesebb és takarékosabb hardvert, addig van értelme. A 80-as évek végén állítottam fel egy szabályt: Három vagy több RC tag helyett megéri mikroprocesszort használni. (Ez az én kis Moore törvényem ;)
Alant látható egy olyan áramkör, ami a fürdőszobában a villany leoltása után 2 vagy 4 percig még járatja a ventillátort. Megépítéséhez 2db 555, néhány kapu, flip-flop stb. kellene. Így meg egyszerűbb volt, és egy villanykapcsoló dobozában elfér. A program 100 szó. Nem kellett hozzá nokia töltő sem. Ha HV típusú mikrokontrollert raktam volna bele, akkor még 3 alkatrésszel kevesebb lenne.
(Hogy mennyi értelme van, az most nem képezi a vita tárgyát! :)

Általában én is így állok a kérdéshez. Ugyanakkor kész, „gyári” ventilátorban az alábbit találtam.

Feszültségosztót követően dióda, ez tölt egy elkót. Elkóval párhuzamosan ellenállás, ez lassan süti ki, ha a világítást a fürdőszobában, sloziban lekapcsolták. Itt jött egy CD4001 kapu inverterként, helyesebben erősítőként, már-már komparátorként használva. Utána ez meghajtott még két párhuzamosan kötött invertert. Így az erősítés igen nagy lett, tényleg komparátor lett belőle. A párhuzamosítás a terhelhetőség miatt volt. A végén ellenállás, majd egy TO-92-es tokban lévő triac, amelyik a ventilátor motorját kapcsolta.

Az RC taggal történő időzítéstől én is falnak megyek, de lássuk be, annyira mindegy, hogy 11 vagy 13 percig pörög az a ventilátor. Nyilván egy PIC12F508-cal királyabb megcsinálni, pontosabb is lesz.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nem javul a helyzet. Azoknak az uart kezelő librariknak is működnie kellene, nem hiszem, hogy ennyire elbaltázottak lennének. Egyre inkább a hardware -re terelődik a gyanú. Rengeteg opcióm van fiókban (felület szerelt ATmega16A + átalakító panel, Arduino klónok ATmega328 és ATmega2560 ill. ATtiny85) nekem a DIP tokos ATmega16 volt a legszimpatikusabb (nosztalgikus).
Ami a késleltető áramkörödet illeti, biztos nem lesz belőle nagy sorozat (valljuk meg ez egy igen költséges megoldás), viszont sokkal gyorsabban elérted az eredményt, mint a CD4xxx tákolással.

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

Ha a fejlesztés költségét beleszámolod, akkor drága. Ugyanakkor egy pici mikrokontroller manapság igen olcsó, néhány száz forint. Jó, tudom, egy CMOS kapuáramkör meg talán néhány tízből is kijön. A mikrokontroller viszont rugalmasabb. Nem kell elkót cserélni, ha jelentősen változtatni szeretnél az időzítésen.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ilyenkor szoktam idézni a medvés és vadászos viccet. :(
Két komment ideje alatt áttölthetted volna a programot bármelyik eszközödbe. Így azonnal ki lehet zárni a hardware hibát.

"Ami a késleltető áramkörödet illeti, biztos nem lesz belőle nagy sorozat (valljuk meg ez egy igen költséges megoldás)"

Ez egy elég nagy tévedés!
A fejlesztési irányelv itt konkrétan: 1-2 ezresből kijöjjön. Egy elektronikai alkatrészbolt felett lakom, csak leugrottam. A ventillátor adott volt, ezért alsó hangon a megtakarítás 6000Ft. Amit nem számoltam, az a fejlesztési költség. Ennek java része a leválasztó trafó hiányából adódott - kellett egy móricka áramkör és szimuláltam, hogy jól helyettesíti-e a 230 voltos feszültséget.
Ez a befektetés a későbbiekben majd megtérül.

"Nagy sorozatban" - legyen ez most > 10db - az árak változnak.
- A nyomtatott áramkör valószínűleg ugyanannyiba kerül.
- A 4011 és a PIC12609 között kb. 170Ft a különbség.
- A PIC12HV609 ugyanannyiba kerül, és ekkor a TL431 és 2 ellenállás (vagy zener) kimarad.
- Tegyünk be inkább egy zenert, és legyen egy PIC10F200. A fenti különbség 50Ft.
(Belefér, mert a program 3 bájt memóriát használ. Szinte egy kis vindóz! ;)
- A kb. 1000Ft-os SSR helyett 37Ft-os triak. Ennek a meghajtásához feleannyi áram kell, így a fő puffer mérete a felére csökkenthető - azaz olcsóbb.

Tehát a különbség lényegében 50Ft, amiből bőségesen megvehetnéd a 4011 időzítéséhez szükséges kondenzátorokat.
Node!
Az áramköröm nem egy késleltetett kikapcsoló, mint a 4011-es megoldás.
- Az áramkör inaktív, csak lekapcsolt villany esetén működik.
- A ventillátor a lámpával együtt kapcsolódik, de a lámpa lekapcsolása után kezd el késleltetni.
- Nullátmenet kapcsoló.
- Ha a fürdőszobába csak rövid ideig tartózkodsz, nem indul a késleltetés!
Szóval ennek az utóbbi kis fícsörnek a megvalósításához - 50Ft-ból - azért jól kösd fel a gatyát! ;)
Viszont a hat állapotot megvalósító végesállapotú gép, 2 interrupt simán belefért a 100 szóba. És ennek a fejlesztési ideje lényegesen kevesebb, mint egy ezt korrekt módon leíró áramkör megtervezése.
Kérdés?

"Két komment ideje alatt áttölthetted volna a programot bármelyik eszközödbe." Való igaz, de az Arduino -ban még több a kérdőjel mint a válasz. Az Arduino (egyenlőre) csak azért lett letöltve, hogy a gyanús vasakat gyorsan ellenőrizni tudjam.
MÁS: A sorozatot 10-50e db -ra gondoltam - pl. a távol keleti gyártósorok kapacitásai. Ott 50 fillér is számít, nem hogy 50 Ft.
A nullátmeneti kapcsolás feature -ről az előzőekből nem szúrtam ki - bölcs dolog. (Kár hogy nem osztottad meg a kapcsolási rajzot, abból talán kiderült volna) Engem is érdekelnek ezek a kis gadget -ek, különösen a nullátmeneti kapcsolás - nálam a világítással van a gond a párom gyűlöli lekapcsolni a világítást - a gardrobe -ban felszereltem egy kereskedelmi mozgásérzékelős cuccot, de nagyon nyűgös a beállítás és relés.

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

De azért csak van olyan eszközöd, amibe be tudod tölteni azt a 0x200 bájtot. :)
Apropó: A soros hardverről még nem meséltél.

Ha lesz időm indítok egy blogot erről az áramkörről. A nullátmenet detektálásának igénye triviális: ha nincs, akkor villany sincs! :)

Világításra első tippem: 11W kompakt fénycső. Az éves fogyasztása + avulása kevesebb. Vagy az asszony nyakába egy 5 kilós bányászlámpa. :)

A sorozat, meg 50 fillér... Először is azt mutattam be, hogy a hirtelen épült 2000Ft-os áramkör itt, ma 500Ft körül előállítható. Kínában, nagy sorozatban ez 250Ft körüli. Bár nagy sorozatban a difi kevesebb mint 15 dollárcent (megnéztem az árakat), de ez egy másik áramkör, ami sokkal többet tud!
Az az igazság, hogy a kínaiak is gyártanak jó cuccokat. Viszont megvizsgálva a webáruházak kínálatát igen érdekes következtetésre jutottam. Ugyanazokat lehet ott is kapni, mint itthon. Persze, mert az itthoniak is onnan szerzik be. :) De többnyire csak az amatőrök által használt "népszerű" dolgokat árulják. Ugyanakkor új fejlesztés esetén néha korszerűbb dolgokat találok...
A népszerű meg így néz ki: A kolléga beszerzett egy OLCSÓ AVR, PIC stb. RELÉPANELT. Az adott szituációban ugyanazt a feladatot egy-egy borzasztóan drága 27Ft-os fettel oldom meg. :( Azért cmos processzorral dolgozva mindig előjön a probléma: még a tranzisztortól is sajnálom a bázisáramot! ;)

A soros hardware csak egy kis kínai cucc egy MAX2332 5V -ról járatva.
(Megint nem tudok abban hinni, hogy ez a gond.)
Kompakt fénycső? - ahol lehet azt használom, de a gardobe kivétel - 360cm belmagasságnál a 11W nagyon sovány - most 4x40W halogén. Ott szokott vasalni is, szóval kell látni.
Én is furcsállom, hogy pl. a szilárd test relék nem tartalmaznak nullátmeneti kapcsolót. Nem igen tudok olyan fogyasztóról akit ez megzavarna, viszont szinte mindenek megnöveli az élettartamát (nem kicsit) és a hálózaton jelentkező zavarok is jelentősen csökkennek.
A CD4xxx már idétlen idők óta létezik - az a kapcsolás lehet már 20 éve létező megoldás,amikor még az egycsipesekkel nem snúroztunk.
Az eBay -en kapható cuccokkal azért vannak/lehetnek problémák. Tapasztalatom szerint, az egyedi alkatrészek zöme drágább mint a hazai boltokban. Kivételt képez ha itthon meg sem kapod. Viszont a kész kis nyákok jóval olcsóbbak, de nincs rajta ÁFA és VÁM illetve a hazai kereskedő haszna. Viszont kapsz rá korrekt elszámolható számlát - azaz hobby.

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

Hát akkor töltsd be valamibe a programot!

4x40W? Ismerek olyat, akinek 40000 fölötti a villanyszámlája! :(

Ez a relé nullátmenetes, viszont csak a (már nem kapható teljesítményű) izzolámpák élettartamát növeli, és zavart is termel.

Az alkatrészekkel az a baj, hogy tényleg Farnell, Mouser a megoldás, ha még idén dolgozni kell vele. Hűtőbordát a németek árulnak, és méretre is gyorsan legyártják. Kész fojtót - amerikai alapanyagból - a lengyelektől. Ha magad akarod tekerni, akkor GBP a megfelelő valuta. :) Nemeccerű az élet!

A trafónál kicsit ködösen fogalmaztál, de a fényképen látszik, hogy szerencsére nem voltál olyan elvetemült, hogy effélét használj. :) Úgy számoltam, kb. maximum 25 mA DC áll rendelkezésedre.

A nullátmenet kapcsolás vonatkozásában gyanúsan méregetlek, de egyelőre nem szólalok meg, mert nem fejtetted ki. Arra utalok, hogy elterjedt az a tévképzet, hogy milyen jó mindent feszültség nullátmenetnél bekapcsolni, pedig dehogy. Kapacitív és rezisztív terhelést igen, de induktív terhelésen a tranziens közel a legnagyobb lesz akkor, ha feszültség nullátmenetnél kapcsolják be. Induktív terhelést a feszültség csúcsának közelében kell bekapcsolni, hiszen állandósult állapotban ilyenkor van az áram nullátmenet, tehát ilyenkor nem lesz az áramnak csillapodó DC komponense, továbbá a vasmagot sem visszük telítésbe, ezzel igen nagy áramlökést úszunk meg.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Igen, csak az egyutas egyenirányítás miatt a fele. A pufferben éppen annyi marad, hogy legfeljebb két félperiódus alatt be tudja kapcsolni a triakos, infraleddel leválasztott ssr-t.

Az induktivitás hiszterézissel rendelkezik. Ha szerencsétlenül pont felmágnesezve kapcsolod ki a vasat, majd ugyanolyan polaritással be, az rövidzár. A tirisztor/triak és a nullátmenet megoldja, mert pont a legalacsonyabb áramnál kapcsol ki (< tartóáram), és közel feszültségmentesen kapcsol be - ami ugye igen kis áramot akar megindítani. Ebben az esetben csak a remanencia határáig marad felmágnesezve a vas.
A tirisztorék meg zavart termelnek, ezért nem alkalmazzák pl. hifi erősítőben. Helyette egy soros ellenállással indul a hálózati trafó, amelyet a szekunder feszültség megjelenése után egy relé áthidal. (Ezért a szünet, majd kattanás bekapcsoláskor.)
A tranziens pont nem azonos az állandósult állapotban kialakult helyzettel!

Nem tudom, hogy meg akartál-e érteni, azért újra mondom, mert picit elbeszélünk egymás mellett. Nem a remanenciáról beszéltem, bár valóban létezik az is. Pusztán arról, hogy induktív terhelést hülye ötlet feszültség nullátmenetkor bekapcsolni, mert az áramnak lesz egy exponenciálisan csökkenő DC komponense, amelyik hozzáadódva az AC-hoz, elvileg maximum 2-szeres, gyakorlatban 1.8-szoros gerjesztést okozna, de mivel telít a vas, goromba áramok alakulnak ki.

Tehát induktív terhelést éppen a feszültség csúcson lévő bekapcsolással kimélünk.

A tranziens nem állandósult, ezt nem is állítottam, csak annyit, hogy elő lehet állítani azt az állapotot, mintha éppen az állandósult állapot egy adott pillanata lenne bekapcsoláskor. Ez az a pillanat, amikor az induktivitás energiamentes, azaz az áram rajta nulla, a feszültség pedig a csúcsérték közelében van.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Csak egész halkan. Az induktív terhelést nem kellene valami kapacitással kompenzálni? Persze létezik központi fázis javítás, de kicsit drágább mint egyedileg, a terheléshez igazítva kompenzálni.
Ha pedig kompenzálva van az induktív terhelés, akkor már megint más a tranziens folyamat.

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

Kiszúrnál magaddal. A párhuzamos rezgőkört nem tudod jó pillanatban bekapcsolni. A kondenzátor miatt muszáj lesz feszültség nullátmenetnél, de emiatt a lehető legrosszabb tranzienst kapod az induktivitáson. Épp azt, amiről írtam. A meddőt ebben az esetben a triac előtt kompenzálnám, de néhány 10 VAr meddőnél nem kell kompenzálni. Mégis minek?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Igazad van. De. :)
A valóságban ritkán kapcsolgatsz ideális induktivitást.
Az adott áramkör egy 20W körüli ventillátort kapcsolgat - nagy az ellenállása. Meg adott a nullkapcsolós ssr is.
Nagyobb motor esetén a felpörgés a kritikus. Egy 10A terhelésű ssr specifikációja szerint 1 félperiódusra 80A-ig terhelhető, amely exponenciálisan csökken: pl. 30s után még 15-20A is lehet.
A kétszeres szorzó "csak" kb. egy reverzálásnál fellépő terhelésnek felel meg. Ugyanakkor a szerencsétlenül maximálisan felmágnesezett (telítés felé) trafó ugyanolyan irányú gerjesztés esetén biztosan telítésbe megy. Még durvább lehet a szabályzás nélküli, eleve túlgerjesztett porszívómotor. (Kivétel az ún. ruszkiporszívó. :)
A jó hír pedig az, hogy mikrokontroller+triak esetén kimérheted a terhelést, és az optimumra állíthatod a bekapcsolást.

A kétszeres szorzó "csak" kb. egy reverzálásnál fellépő terhelésnek felel meg.

Ez ugyan nem tudom, hogyan jött ki, de a kétszeres szorzó csak akkor igaz, ha lineáris marad az induktivitás, ami nem valószínű, mert telítésbe fog menni. Ez onnan jön, hogy ideális induktivitást feszültség nullátmenetnél bekapcsolva az árama szinuszos lesz, de egy csúcsértékkel eltolva. Azaz két csúcsérték lesz a maximuma, az áram nulla értéke pedig egyben a legkisebb érték is. Nem abszolútértékben, hanem előjelesen.

(A reverzálásról: erősen optimista a feltételezésed. Egyik önálló labor témámban véges differenciák módszerével számoltam villamosgép tranziens viselkedését. Nem kétszeres az, a helyzet sokkal rosszabb.)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az az ötletem támadt, hogy ki kéne deríteni mi okozza a resetet. Erre tökétesen alkalmas a MCUCSR regiszter.

A HW inicializálás legelejére illesztd be ezt a kódot:

uint8_t mcucsr_status = 0x00;
mcucsr_status = MCUCSR;
MCUCSR = 0x00;

Ezttán a program futása közben, ahol jónak látod kiirathatod a regiszter tartalmát egy porton, vagy UART-on keresztül.
Ennek a regisztenek a leírását megtalálod a datasheet-ben és rögtön látod mi okozta a resetet.

Ha 0x00 kapsz az azt jelenti, hogy nem reset volt. Ez általában azt jelenti, hogy valahol memóriaszivárgás és a stack túlcsordul, vagy olyan interrupra ugrasz, ami nincs lekezelve.

Két dolgot lehetne kipróbálni:
Az első, hogy az interrupt rutin elején letiltod a global interrupt engedélyezést, majd a végén visszaengedélyezed.

A második kicsit macerásabb, de lehet ki kéne deríteni melyik interrupt "tüzel" esetleg mindegyikhez irni egy rutint, ami portlábon kiad egy számot ilyen esetben és elmegy végtelen ciklusba. Vagy nem használt interruptokat nem __bad_interrupt-ra kéne ugrasztani, hanem csak sziplán egy ret utasítással rögtön vissza kéne térni.

A "bad interrupt" kezelőt már magamra rántottam - innen vettem észre, hogy aktiválódik (nem konkretizáltam alapból, reszet után az egyedi interruptok le vannak tiltva).
Ha feljebb megnézed olyat is csináltam, hogy a globális interrupt tiltása mellett a main -ben elhelyezkedő végtelen ciklusban "újrahúztam" a stacket és a hiba eltűnt. Tehát a szimptómák, el stackelődés és olyan interrupt(ok) keletkeznek amihez hozzá sem nyúlok, elvileg tiltva vannak.
Valahol szimplán "fejbe írom" a regisztereket.
Most visszaléptem a kályhához, elővettem a timer piszkálómat, és próbálok rájönni mit szúrok el.
Úgy tűnik hogy valamin átsiklottam, mert most azt tapasztalom, hogy a timer0 1 msec interrupt "lötyög"? Engedélyeztem a timer0 kimenetét (OC0) és nézem szkópon, szép 2 msec periódus idejű 1:1 kitöltésű négyszöget látok. Viszont a timer0 "compare/match" interruptból billegtetett lábon a négyszög lötyög (az OC0 -hoz képest), nem lehet rendesen beszinkronozni. Itt valami nem gömbölyű :(
SZERK: Úgy tűnik minden 6 -ik interrupt nem jut érvényre. Ilyet még nem láttam :(

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

Nem lehet, hogy még fut az ISR? Az IT-t kiváltó ok nyugtázását tedd az ISR elejének közelébe, így rugalmasabb lesz a rendszer, hiszen futó ISR alatt már tud pengeni a következő IT kérés. Ha a végén van a nyugta, akkor az eredeti, meg a futó ISR alatti kérelmet is nyugtázhatod, elveszítve az IT kérést.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Kösz a tippet. Kár hogy most csak a timer0 compare/match interruptja megy. Nem tiltok interruptot sem. Az ISR -ben mindösszesen, néhány push/pop és az egyik portláb kapcsolgatása van.
Most már nem tudom mit higgyek. Régebben (amikor ezt a kódot írtam) még jól működött.

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

Még ennél is érdekesebb. "Betér" az interruptba, átbillenti a port bitet, majd rögtön vissza - pici alig látható tüske, csak a kettős, késleltetett eltérítés mellett lehet kibökni. Ezt vajon hogy csinálom?
Ráadásul van, hogy a láb épp fenn volt és van hogy lenn.

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

Ha nagy kapacitív terhelésként jelenik meg maga a mérés, elszállhat a kontroller. Most vissza kellene nézni a kódot.

Szerk.: Lehet, kellene egy soros ellenállás a mérőzsinór elé.

Kérés: a mindenkori legfrissebb kódod linkjét a témaindítóba tedd, mert nem vágyom kikeresni sok hozzászólással korábbról.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az éppen használt kód a témanyitóban.
Nem hinném hogy a kapacitív terhelés gondot okozhatna - 100MHz szkóp zsinór 10 -es osztásban.
A "bad_interrupt" amolyan csapdaként szolgál.
Nincs timer teszt, semmi az égvilágon - ez valami hardware sz'rság lehet.

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

Most mit csinál a bad_interrupt? Mert szerintem ott vágja valami fejbe.

Illetve ugye mikor test_timer fut nincs engedélyezve az interrupt. Ott tud úgy elcsúszni szerintem a dolog, Hogy a timer ketyeg a háttérben. Lefut a test_timer, majd rögtön jön az interrupt. Visszalép vizsgálódik, megint letiltódik az interrupt, megint megkésik...

Csak a próba kedvéért előkaptam egy szűz ATmega16A -t, beállítottam a fuse -okat, letöltöttem a "programot". Ugyan úgy működik.

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

Ismét csak a próba kedvéért, visszaállítottam a gyári 8MHz belső oszcillátor módba a chipet. Az eredmény ugyan az, csak nem 1 hanem 2 msec -ként üt be az interrupt. Nem az órajel a gond.
Azon gondolkodom, hogy tudnék egy arduino Pro mini (ATmega328 16MHz 5V) klón befogni egy próbára? Abban van bootloader, de hogy tudom abba betölteni ezt a kódot?

OFF: Nem tudjátok hova lehet képeket feltölteni a pastebin -hez hasonlóan?
Lekaptam mit is mutat a szkóp.

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

Kicsit átírtam a programod a jobb debuggolás értelmében: http://pastebin.com/Mj0HDgXM
Amit módosítotottam az az inicializáslást, és definiáltam összes ISR vectort, hogy lássuk mi a probléma.
Kérlek nézd meg működik-e, és ha hibázik melyik interrupt jön föl.

Működik, csak a "TIMER0_COMP_vect" működik - pont úgy mint az én kódommal.
Kicsit másként "szinkronozódik" de itt is vannak "kihagyások".
MEGJEGYZÉSEK:
(A DDRB = 0x80 hibás - 1 << 3 != 0x08)
Azt meg tudod mondani minek egy konstanst el shiftelni?


int_source = 0x12;
PORTA = int_source << 1;
/* miért nem így */
PORTA = 0x12;

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

Ennél is szebb, hogy ha az ISR rutinba előre/hátra "NOP" -kat szúrok akkor csak kis tüskék vannak interrupt -ból.

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

A compiler optimalizációs opció = S
A téma nyitóban a legfrisebb forráskód mellé, feltettem a "Makefile" -t is.
(Nem sok reményt fűzök hozzá, de ezt használtam minden kísérlethez, így akár itt lehet az eb elhantolva)

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

Valahogy itt is belehet emelni a képeket - hol találom a leírást, hogy ezt hogy is kell csinálni?
Oszcilloszkóp és kapcsolási rajzok mind képek.
Egyébként a kapcsolási rajz, valójában egy semmi - értsd, egy kopasz proci, rajta a 16MHz kvarc + 2 db kondi, egy reszet áramkör egy kondi, egy ellenállás és egy kis nyomógomb, illetve a jtag. Mindez egy forrasztás nélküli breadboard -ba dugdosva. Semmi egyéb extra nincs!

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

A "betáp" egy 10 mkF kondival kezdődik. Utána közvetlenül, ahova a proci tápja be van kötve, be van dugva egy-egy régen jól bevált 220 nF kondi.
Ha tudnám hogy küldenék erről is képet.

OFF: Az ilyen felvetések miatt próbálok valami "korrektebb" kártyát találni a feladathoz. Már megrendeltem eBay -ről egy nagyon hasonló "kiépítettségű" kártyát, ahol mindez be van forrasztva, minden láb kivezetve, plusz jtag és isp csatlakozó illetve a tápon egy kis stab IC. Sajna ez egy hónap mire itt lesz, és az ára is relatíve magas ck. 3 eFt. A másik opció, hogy egy próbapanelre építem ezt a cuccot, de az egy többórás művelet. A szépsége ennek a dolognak pont az lett volna, hogy ilyen "fapados" felállásban is működik. Ha belegondolsz, az összes "nagyfrekis" művelet a tokon belül zajlik. Amivel most próbálkozom az is 1 msec azaz 1 KHz - ez még a "pulzáló egyenáram" fogalmát is alulról súrolja.
Még valami, amióta második lapra került a téma folytatása azóta nincs "Új" marker a bejegyzéseknél. Lehet ez ellen tenni valamit? - kicsit nehéz megtalálni az új hozzászólásokat :(

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

HUP Beszólás kiterjesztéssel van „új” marker.

Ha belegondolsz, az összes "nagyfrekis" művelet a tokon belül zajlik. Amivel most próbálkozom az is 1 msec azaz 1 KHz - ez még a "pulzáló egyenáram" fogalmát is alulról súrolja.

Ezt nem esett jól olvasnom. ;) Ha körbe mész a hurkon, akkor bizony kilépsz a tokból a táplábakon, tehát a nagyfrekvenciás áramok bizony megjelennek a táplábakon. Mivel a hozzávezetésnek van ellenállása és induktivitása, mindenképpen kell hidegíteni, mégpedig rövid hozzávezetéssel, megbízható kontaktussal.

Amit a pulzáló egyenáramról írtál, az két oknál fogva is fájó. Mivel épp a váltakozóáramú komponenst vizsgáljuk, a DC komponens irreleváns számunkra, így mindegy, hogy változó egyenáram - tehát egyenáramra szuperponált váltakozóáram -, vagy DC komponens nélküli váltakozóáram az, amiről beszélünk.

A másik gondom a mondatoddal, az a frekvencia felemlegetése. Igazad volna, ha alapharmonikusunk lenne csak. A helyzet ezzel szemben az, hogy a tranzisztorok ugyanúgy néhány ns alatt kapcsolnak át akkor is, ha másodpercenként ezerszer teszik, meg akkor is, ha milliószor. Neked a néhány ns-ra kell felkészülnöd, amikor a hozzávezetés induktivitásában keletkező feszültség ellen hadakozol.

Tehát amikor az u(t) = L*di/dt összefüggést nézed, akkor a di/dt igen nagy, hiszen nem 1 ms alatt változik valamennyit az áramod, hanem mondjuk 5 ns alatt, aztán nyugton van 999 995 ns-on át.

Szerk.:

K - Kelvin
k - kilo- tehát 1000

Azaz kHz lesz az.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

"HUP beszolás" telepítve. Köszönöm!
A "pulzáló egyenáram" kifejezést a mikrohullámú technikával foglalkozó kollégáktól plagizáltam - viccnek szántam.
Ami most talán a leggyorsabb megoldás, ha egy Arduino Mini Pro -t beáldozok (ATmega328) - vagy le kell mosni a booloadert vagy valahogy Arduinosítani kell a kódot, hogy a bootloder be tudjam tölteni - megint egy kupac hiba lehetőség.

OFF: Eredetileg is ezzel akartam kezdeni, aztán ráébredtem, hogy egy rendes egybefüggő 8 bit portja nincs a '328 -nak. Akkor adtam fejem a '16 -ra, de a korrektebb próba panelre még várnom kell.

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

Már rajta lennék. Sajna kicsit sűrű lett a mai napom, és a holnapi sem tűnik egyszerűnek. bucko posztjaiból kihámoztam, hogy ő hova tette, aztán ha jól értem image -ként hivatkozik rá. Amint leharcolom az aktuális problémákat megcsinálom.

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

Felül a timer kimenete OC0 pin4. Az alsó az interruptban bicegtetett pin.
Ahol "duláz" ott valójában van egy tüske.
Az előbb közbeszólt az Úr azaz a nejem.
A lényeg hogy most az interruptba betettem a PORTB 0 bitjét is - pin1 - és azzal jól működik! - ua. mint a az OC0.
Itt valami el van kódolva, valamit nem látok.
SZERK: Frissítettem a forrás kódot. Tiszta C (semmi assembly) a PORTA bit 1 ugyanolyan "hibás" míg a PORTC bit 0 jól működik - ua. mint az OC0.

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

Ó, hát ennek nagyon egyszerű az oka!

A fő végrehajtó ciklusban lévő

PORTA = PINA ^ 0x01;

sor nem atomikus művelet. Bátorkodom megjegyezni, ez assembly-ben azonnal látszott volna.

Az történik, hogy van egy port olvasásod, az alsó bitet negálod, de csak regiszterben. Becsap az IT, az is olvassa a portot, megforgatod az 1-es bitet ténylegesen. Eddig jó. Visszatérsz IT-ből, befejeződik az alap szinten az értékadás, azaz a regiszterből kiíródik a portra az érték. De melyik is? A 0-ás bitre a megforgatott, de figyelem(!), az 1-es bitre az IT becsapása előtti értéket írod vissza. Ezért van az igen keskeny tüske. Az alap szintről visszaírod az IT előtti állapotot az 1-es bitre.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Igazad lehet amint tudom kipróbálom.
"Bátorkodom megjegyezni, ez assembly-ben azonnal látszott volna."
Így igaz!
Viszont az MC RISC jellege miatt rengeteget kell gépelni - no nem ezt a kis pimf vacakot, hanem a későbbi programot. Mindenképpen érdemes áttérni a C -re. Ráadásul a különféle, "konyhakész" library gyűjteményt nem használni mondhatni bűn.
Ami továbbra is cél, az az ISR rutinok assembly -ben mivel azokat szeretem "szigorúan" kézben tartani.

OFF: Írtam én assembly -ben eleget. 90 körül, Z80 -al túlléptük a 64K keretet - akkor "találtam fel" a cross linkelést, amivel max. 2x64K programot tudtunk összelinkelni. Az akkori idők CP/M csúcsgépén (4MHz Z80A CPU NDK gyártmány), floppy lemezekre a fordítás/linkelés majdnem 1 óráig eltartott:) A 2000 évek során, találkoztam a hadtörténeti múzeumban az egyik ilyen munkaállomásunkkal - ma 2015 -öt írunk és 54 évesen még nem akarok mellé kerülni.
Most az efféle cuccok reneszánszát éljük, csak a spirális fejlődésnek megfelelően egy új szinten, ahol a MC vagy SOIC stb. órajele GHz -ben mérendő. Vissza kell egy kicsit bújnom ebbe a bőrömbe, a PC (szerintem) kezdi kimeríteni a lehetőségeit. És élvezem :D

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

Van valami okod arra, hogy magát a lábat olvasod az output latch helyett? Én a

PORTA = PINA ^ 0x01;

helyett ezt írnám:

PORTA ^= 0x01;

Ha szerencséd van, azzá fordul, amire gondolok, tehát egy olyan EOR utasítássá, amelynek a cél argumentuma a memóriába ágyazott port, a másik regiszterben pedig 0x01 van. Ugye, itt is szívás lehet a C, mert assembly-ben ezt meg tudod csinálni az általam leírt módon atomikus műveletté, de C-ben szerintem csak reménykedhetsz abban, hogy így fordul, és a read és write nem két külön utasításban lesz.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Logikusan ez lenne a korrekt megoldás, hiszen nem a latch "belső oldalát" olvasod, hanem közvetlenül(?) a pin -t.
Már annyi mindent próbáltam, valószínű ezt is. Sőt olyat is csináltam hogy inkrementálom az egész portot. De mivel ha egy másik port lábát "ráncigálom" akkor az egész jelenség eltűnik egyértelmű, hogy az ISR -ben lévő bit piszkálás összevész a fő hurokkal - erre utal a szabályos "össze szinkronozódás" is.
De kifogom próbálni és referálok.

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

Biztos, hogy az a hiba, amit írtam, hiszen látom. :) Ami a latch illetve pin dolgát illeti, a pin olvasása kevéssé jó ötlet, hiszen a lábon kapacitás is lóg, hosszabb a jelút, ha túl gyorsan olvasod korábbi módosítás után, ebből hibás érték is adódhat. PIC-eknél erre fel is hívja a katalóguslap a figyelmet. A latch azonnal olvasható, az ugyanolyan gyors, mint a CPU többi része. A rövidzárral terhelt kimeneti láb esetéről már nem is beszélve.

Az inkrementálás sem segít, hiszen az is fordulhat több utasításra.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Engem általában az érdekel, amit legutóbb a portra küldtem, nem az, amit a hardware hagy megvalósulni. Persze az tervezési hiba, ha zárlat van a porton. Mondom, a sebesség a másik gond.

Ha ragaszkodsz a pin olvasásához, akkor előbb tiltsd az IT-t, az értékadást követően meg engedélyezd.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Te látod a képet, a fórumban vagy csak a linket?
No még egyszer:
[url=http://kepfeltoltes.hu[/url]
OFF: Én ezt nem értem. Egy az egyben azt írtam be amit "Szerkesztési tippek", "Szabadon linkelheted a képedet egy külső címre, az ..." bekezdése megad, behelyettesítve az én képem url -el.
Az én linkem: http://kepfeltoltes.hu/view/150526/F_nyk_p0144_www.kepfeltoltes.hu_.jpg
az url nem is látszik viszont a kép sem :(

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

Kicsit elnyúlt szünet után megint elővettem a témát.
Az új verzió teljesen jól működik, nincsenek "anomáliák".
Viszont most beleszaladtam abba, hogy miért is szűnt meg az SBI ill. az CBI makró a gcc-avr -ben.
Az ezzel kapcsolatos "viták" mintha 2005 tájékán lezajlottak volna. Én úgy értettem, hogy a bitwise műveleteket, ami addig mint makró létezett, kivették mivel a fordító ezt magától is elvégzi. Én ezt nem látom - csak a próba kedvéért a TIMSK beállítását kétféle képpen is megadtam - ugyan azt fordítja. Való igaz, hogy jelen példában ennek nincs jelentősége, de az előző (hibás timer kezelés) pont ezen bukott. Most a kis assembly rutinokkal ez a eltűnt.
Most akkor kezdjem megtanulni az inline assemblert, hogy tudjam használni a bitwise port műveleteket?
Ráadásul, az igazi az lenne ha ezeket az adott helyre beforgatná, mint a makrót. Esetleg írjak egy kupac makrót?
Most beleütköztem a C korlátaiba, vagy csak rosszul használom? Mi van ha mondjuk egy bitfield -et akarok kezelni különféle interruptokból és a főprogramból?
Ráadásul, ez még csak a példában sem túl optimális, hiszen az SBI 2 ciklus, a fordító pedig 3 ciklusra fordította.
Nem értem :(

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

Röviden és tömören leírtad a mai fordítók rákfenéjét! Csak még nem tudatosult és nem jól ejted a szavakat. ;)
Az inline assembler csak speciális esetekben értelmes dolog, már ha tudod mit miért csinálsz.
"... 2005 tájékán lezajlottak volna ..."
Belátható, hogy mikrokontrollert akár sql-ben is lehet programozni és ezzel a módszerrel bármilyen algoritmust is meg lehet valósítani. Csak marha nehezen.
A logikai áramköröket gyártók mindig közlik az ic belső kapcsolási rajzát, tudniillik az ic nem egy elméleti logikai függvény, hanem áramkör. Ami a logikai függvényt megvalósítja. Az AVR leírása sok helyen hiányos, mert megelégednek a működés logikájának leírásával. A PIC esetében szinte mindig közlik a megvalósító áramkört. (Sajnos hozzáteszik, hogy hozzávetőlegesen ábrázolják.)
A fordítót írók jó része valószínűleg nincs teljesen tisztában a működéssel, így az algoritmus esetleg előrébb való a működtetésnél. Ha ismered az áramkört, talán soha nem programoznád úgy... Aztán kezdődnek a beszélgetések, miszerint ezt akartam és a fodító meg úgy fordította. Sokkal egyszerűbb, ha odaírom pontosan azt, amit akartam.
A C egy jó programnyelv, ha ügyes vagy akkor hordozható. (Meg a java is, ha van saját teherautód. :)
Struktúrált assemblernek is hívták, mármint akkor, amikor a struktútált programozás volt újdonság. :)
Esetünkben a C egy szintaxist jelent, de állandóan azt kell sasolni, hogy egy utasításra fordu-e az, amiről hihetnéd. Eközben igen gyakran perifériákra sfr-ekre hivatkozol, amik szintén egy utasítással leírható. A C nem erre készült, és abszolút nem biztosítja a makrózás lehetőségét!!
Milyen hülyeséget írogatok?! Ha majd egyszer a mikrokontrollerek c fordítójába is belekerül a rept, irp, irpc, ifb/ifnb makró lehetőség, akkor lehet vitatkozni. Ezek az utasítások a mikroprocesszor könyezetben programozott feladatokat támogatják, viszont a c számára szemantikailag idegenek. Például egy függvényhívásnál külön lib/makró valósítja meg a változó számú paraméter átadását. Mindössze azért, mert a nyelv nem támogatja. Cserébe a kötöttségekért megkapod a szintaktikai ellenőrzést, és egyúttal egy újabb korlátot.
Egy c fordító biztosítja a loadert - nincs rá szükségünk, a magasszintű függvényhívást - nincs frame pointerünk, egyes esetekben a Neumann modellnek megfelelő stack sem létezik, de mindezeket lehet szoftveresen emulálni. Csupa előny!
Ellenben, ha kitalálod az egy bit billegtetését, akkor azt az utasítássort makróba foglalhatot. Ez kiküszöböli a kód áttekinthetetlenségét is. Más típusú cpu esetén a jól megírt makró - a jól megoldott feladat - hordozható.
Ha idáig eljutottál, nem fogod igényelni azt, hogy minden gondolatodat két zárójel közé rakva büszkén vallhassad: cében programoztam!

Az interrupt programozása más téma. Ehhez tudni kell eseményvezérelt programot írni. Amint ez letisztul, nem okoz gondot a lokális/globális/volatile kezelése. Nagyon nevetséges hozzánemértést tükröző példát láttam: kűlső, gyors és gyakori eseményre szabad-e lebegőpontos műveleteket végezni az interruptban? Alkérdés: szükségünk van-e double értékre, amikor másfél bájtot olvasol ki? Ilyen problémáknál a c-nek elég bonyolult módon el kell magyarázni a változókat. Helyette az asm-hez egy sor helyett több kell. Vajon melyik írja le pontosan a szükséges tevékenységet?

Ön nyert! :)
De ez csak fele az igazságnak!

Hidd el, eléggé körüljártam a témát!
1) Ha már olvastál Microchip dokumentációt ;), még ott is leírják: C-ben lényegesen rosszabb a performansz! (Az egyik Columbo filmben magyarázzák el: Performansz! Tudja, az olyan, hogy a színpadon belehugyozik egy pohárba, aztán megissza. :)))
2) Egy csomó "gyári" függvény hibásan, vagy egyáltalán nem működik.
3) A C fordító helyes szintaktika ellenére ostobaságokat generál.
4) C-ben programozva ki kell szolgálnom a lib író elképzeléseit.
5) Általában nem lehet problémák nélkül abszolút kódot előállítani. (Száz bájtban relokáljon a nénikéd! :))
6) Nem érdekel, nincs időm tesztelgetni, hogy melyik C fordítónak mi a nyűgje, vagy melyik versenyen milyen számban győztes! :)

És sorolhatnám a végtelenségig!

Van kivétel is, amikor komolyabb DSP műveleteket szeretnél végezni, de az már nagyobb gép, nagyobb algotitmus.

Példa egy egyszerűbb esetre: MLX90614 hőmérő. A hőmérséklet 0,02 Kelvin pontossággal olvasható ki 2 bájton.
A PIC18 tartalmaz szorzó egységet, van C fordító, tehát írjuk: double stb. :)
Helyette felvehető egy konstans, ami 27316/2. Ezt levonva a kiolvasott értékből, majd shift jobbra. Így 7 utasítással megkaptuk 0,01 Celsius felbontással az eredményt ugyanabba a két bájtban!
Ennek a példa megmutatja, hogy az a fontos, amit csinálunk és nem a fordító!

Tényleg jó hosszú!
Kicsit azért szeretnék érvelni a C mellett. Ne feledjük, hogy a Linux ami már csaknem egy tucat architektúrán fut (Debian stable) is tartalmaz némi assembly kódot, de elenyésző a C -hez képest. Ezért találták ki a C -t.
A C -hez, számtalan olyan library van készen amit ha magadnak kell megírnod (minden egyes procira külön-külön) akkor sosem lesz belőle produktum (pl. a lebegő- és a fixpontos aritmetika). Nem szeretném ezeket újra írni.
Az avr-gcc -t lelkes emberek csinálták, szabadidejükben és nem is vállalnak rá semmilyen garanciát.
Nem hiszem el, hogy az ilyen alapvető kódok, mint az uart kezelés hibás lenne, de mióta megírták, már több új verzió jelent meg az avr toolchain -ből. Az író megpróbálta a különféle AVR architektúrákhoz illeszteni, de mindet nem próbálhatta ki (mondjuk ez kicsit gyenge érv, mivel az ATmega16 egy régi, alap játékos).
Nem rég alkalmam nyílt i386 -os assembly kód vizsgálatára (nem én írtam), mely már több mint egy évtizede fejlődött - huhhhhh!
Egy-egy eszköz meghajtó megírása OK, de hogy az egész az nagyon durva.
Szerintem okosan kellene a kettőt vegyíteni.
Az én problémám a tudatlanságom és hogy azt reméltem ezeket az alap dolgokat mint az uart kezelés készen, "tálcán" megkapom - tévedtem. A mi szintünkön, a mi feladatainkban a két sorban megírok valamit és a munkát elintézi a már kész engine nem működik - de az is lehet, hogy "begyöpösödtem" és nem tudom ezt a szintet megugrani.

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

Sajna nem tudom mekkora erőforrásokra fejlesztették ki anno a C -t, de biztos hogy közelebb áll a mai egycsipesekhez mint a mostani "monstruózus" asztali PC -k.
Anno amikor sokat foglalkoztam egycsipesekkel, vagy pl. CP/M akkor is sokat agyalogtunk azon mi is lenne a megfelelő fejlesztő és futtató környezet. Első sikeres implementáció a FORTH volt. Én konkrétan nem használtam, de akik ezt implementálták virtuóz módon tudták használni.
Ez volt a "hős" korszak (1980-as évek) most 2015 -öt írunk. (Az ARM processzorokban már nem interrupt de "esemény" kezelés van és DMA)
Nagyot fordult a világ.
Az avr-gcc -n kívül ott van az SDCC - ők viszont leálltak(?) az AVR -ről, mondván azt az avr-gcc elintézi. Én is nekifutottam még az elején (na nem, erőltettem meg magam) de azt láttam hogy már az elf formátum előállítása is zavaros, így tuti nem lehet debuggolni. Ráadásul mindenki az avr-gcc -t használja - sikerrel.

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

A hupon itt van balra a menuben a Unix tortenelem:

1972
1972. január 7: Thompson kézikönyve a B nyelvhez [szöveg]
1972: Ritchie megalkotja a C nyelvet [idézet] [történet] [FAQ] [korai fordító kódja]
1972. március 15 (?): Ritchie Unixos jegyzetei [szöveg]
?: A PDP-11/45 már 256k központi memóriát is támogat
1972: június: A Unix-programozók kézikönyvének második kiadása tíz telepítésről
ír [idézet]
1972. december 6: A 2. Unix-verzió jobbára Thompson munkája, és C-ben íródott [idézet]

Szoval 32 bites gep, max. 256k RAM-mal, lyukszalaggal. A nagyobb, ARM alapu uC-k mar elerik mindenben, orajelben valoszinuleg mar egy attiny13 is (RAM mondjuk keves van benne, es az csak 8 bites).

--
I'm not saying the new Apple Watch will only be worn by wankers but it's not vibration, shock and splash proof for nothing.

Kicsit kiigazítanálak - bár semmiben nem tévedtél! A kérdés volt rossz. ;)
Szó sincs erőforrásokról! A UNIX egy operációs rendszer. Szempontunkból az is lényegtelen, hogy miben írták. Mindössze a kernel szolgáltatások interfésze C.

Lefordítom. Ha valaki a háromlábú processzorra akarja megírni a juniksz putkar függvényt, mert hordozni szeretné az ötlábúra - az egyéb aljasságra is képes! ;) Mint sokadszor írom, figyeljük meg: itt nincs operációs rendszer, nem cél, hogy a "felhasználói program"-ok tömkelegét egységes felületen keresztül illeszteni a kernelhez. A gyakorlat azt mutatja (Lásd ezt a topicot is!), hogy a szedett-vedett lib nem pótolja a mikrokontroller alapos ismeretét!
Mindez másképp van az operációs rendszereken. A device driver, kernel mind elrejtik előled azokat az ismereteket, amitől hardveres helyett szoftveres lehetsz.

Természetesenm lehet írni vagy használni függvénycsokrot (alias lib), és kialakíthatsz egy saját bios/oprendszer hívásos környezetet. Kérdés, hogy nem fontosabb-e ennél ez algoritmus megtervezése, vagy a feladat megoldása?

"Mindössze a kernel szolgáltatások interfésze C." - ez kicsit erős!
Nézz bele a kernel driverek forrásába.
"szedett-vedett lib" - bocs de ez megint erős. Most ezt tapasztalatból állítod? Az avr-libc szedett-vedett? Elszomorítasz.
Három láb? - na ne má' - ATmega2560 100 láb. Persze ha három lábbal is megoldható a feladat ...
"Kérdés, hogy nem fontosabb-e ennél ez algoritmus megtervezése, vagy a feladat megoldása?"
Nem tudom, fontosabb? Eddigi tapasztalataim szerint ha többször felhasználható kódot írtam - plusz munka - mindig kapóra jött hogy elővehettem. Szerintem helye van ennek is meg annak is. A magyarországi viszonylatokat figyelembe véve, ritka az a bizonyos egyedi embedded fejlesztés amit ha jól megcsinálsz ezzel vége. Sokkal gyakoribb ha a jó ég tudja hányszor kell ismét hozzá nyúlni a kódhoz, akkor pedig nem mindegy miben is íródott. A C -ben a az algoritmus jobban olvasható, érthető mint assemblyből kihámozni (hacsak persze nincs nagyon jól megkommentezve, ill. a megvalósított algoritmus jól leírva összekötve a kóddal).

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

Szerintem ebben igaza van bucko kollégának. A mikrokontrolleres feladatmegoldás nem olyan rétegzett, a feladatok sem annyira bonyolultak jellemzően, mint egy PC esetében, az erőforrások sem tolerálják a nagy overhead-et. Éppen ezért jól megírt, általános libek feleslegesen nagyok, bonyolultak, ha meg speciális, akkor semmire sem mégy vele, mert feladatonként egyedi, így épp csak akkor, csak ott használható fel. Értem én, hogy semmi kedved a kontroller katalóguslapját olvasgatni, pedig kellene, s az alapján meg tudsz írni assembly-ben jól működő kódot.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szövegértés!
Ha.
Szíveskednél elolvasni az előző mondatot is, akkor hátha megértenéd mi van odaírva. Idézem:
"Szempontunkból az is lényegtelen, hogy miben írták. Mindössze a kernel szolgáltatások interfésze C."

(Kernel drivert már láttam. Írtam és módosítottam is, de az még 1993-ban lehetett. Utoljára 2 éve kellett kernel forrásba néznem - mit nem tud a linux IDE driver - és megírtam asm-ben. Úgy 20 évet programoztam C-ben AIX-en. Remélem megnyugtattalak! :)

Iderajzolom amit nem értettél meg - függőlegesen jobban kifér:
UNIX
- felhasználói program ->
- putchar makró vagy függvény* (libc) ->
- kernel* (pl. socket, stream kezelés) ->
- kernel driver* ->
- periféria
A * az operációs rendszert és bővítményeit jelenti.

Itt kötelező a libc, mert a kernel és a perifériák elérése gyakorlatilag itt definiált.

Mikrokontroller C
- felhasználói program ->
- libc ->
- periféria

Mikrokontroller ASM
- felhasználói program ->
- interrupt/függvények, definíciók ->
- periféria

Az ASM és C megoldásokban a rétegek száma megegyezik.
Hogy el ne keveredjünk teljesen: Az embedded rendszereket ne soroljuk az utóbbi kettőhöz, mert ott inkább van valamilyen operációs rendszer vagy interfész, így nem közvetlenül programozod a perifériákat.

A hordozható libc => Hordozható==ha megírták arra is. Ez a tény még linuxra is igaz!

A hordozható asm számomra annyit tesz, hogy tudom mi az algoritmus. Így "hordoztam" ugyanazt az algoritmust 80186 asm-ből PIC18-ra. Igaz, "egész estés" projekt volt, de mint írtam:
- már 20 éve kész az algoritmus
- az algoritmus hasonló Fleury-féle libhez
- a "hasonló"==a Fleury-féle libhez jócskán hozzá kellene írni, tehát használhatatlan
- abszolút kódot fordítok - semilyen lib nem jöhet szóba
- másik PIC-re (esetleg pillanatok alatt) alkalmazható ugyanaz a kód

Ugyanakkor a lib helyett lehet makrót használni, így a fenti problémák megoldódnak.

"Három láb" == Irónia. Figyeljük meg: Azért választottam páratlan számokat, mert olyan nincs.
A kicsi számok == pici processzor.

Most éppen olyanon dolgozom, hogy a Fleury-féle lib és hasonlók nem alkalmazhatók. Itt Magyarországon a főnököm biztosan jól tökön rúgna, ha a megoldás helyett egy libpthread-et szállítanék. ;)

Öregszem, szemüvegre is szükségem van! Szívesebben nézek át 60 sor kódot, mint 800-at. Ha nincs kommentezve, akkor is gyorsabban visszafejtem!
8X---
És most jön az ütközési pont: a szedett-vedett lib. ;)
Az AVR nem file szervezésű, mint a PIC. Ezért tényleg elképzelhető, hogy jobb libek vannak hozzá, mivel akár a 68000-es, vagy POWER családnak is hasonló megoldásai lehetnek a sok regiszter miatt. Legalábbis az általános függvények között. De ahogy a kis PIC-hez képest a nagy már "nem olyan PIC" (a 32 bitesben más magot használnak), ugyanúgy a "nagy AVR" is más, mint a mikrokontroller kistestvér. A mikrokontroller meg nem általános architektúra, ezért az általános libek mellett szükség van egyébre is. Bevallom, egyetlen AVR libc nem ment le a torkomon ebéd közben! Mindössze 3 gyártó PIC-C fordítóját dobtam a kukába, méghozzá okkal! Pedig azokat is sokan használják, fórumoznak is róluk becsülettel. :))) Ez tapasztalat.
Aztán, ha a fehér ló seggére megesküszöl, hogy ezzel szemben az AVR libc-t 500 éve szent életű remeték köszörülik - nem úgy,mint a PIC-ét -, akkor hiszek neked! Komolyra fordítva a szót: Láttam már precíz gyártót - pl. Intel, Motorola, IBM stb. - , és láttam csapnivalót - pl. Microchip. Az Atmel lehet, hogy precíz, és akkor szerencséd van!

Viszont a tartós ellenkezésnek a másik oka az, hogy több mint 30 éve programozok, és ekkor az embernek már van egy stílusa. A C és a lib elvesz egy szabadságfokot, de amit ad helyette nem annyira jelentős, hogy érdemes lenne szívni vele. Az inline meg semmit nem ad az asm lehetőségeiből!

Még egy rossz hír :(
Sem a Fleury sem a Gock által írt uart.c nem működik rendesen.
A Fleury verziót csak úgy a teszt programját használva, ugyanott vagyok ahonnan elindultam, újra indul illetve a nem engedélyezett interuptokat is meglátogatja.
A Gock verzióhoz én írtam egy kis teszt programot, a hiba jelenség ugyan az.
Úgy tűnik, ezen is át kell küzdenem magam.

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

Tudom, én vagyok röghöz kötött, de jobban bízom abban, amit magam írok. Nem azért, mert én okos vagyok, aki a library-t írta, az meg ostoba, hanem azért, mert az adott környezetet, célt én ismerem, a speciális igényeket, egyszerűsítési lehetőségeket én látom, és abba jobban illeszkedik az, amit megírok assembly-ben, mint egy általános könyvtári függvény.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Haáát.
Mielőtt ilyen hirtelen véleményt nyilvánítanal, azért inkább nézd meg a kódot! Bár említetted, hogy lusta vagy olvasni. ;)

Kicsit funkcióelemezzüknk! Alapjában véve nem rossz! Ugyanezt a "power of 2" ciklikus bufferelést használom vagy 25 éve. Az algoritmus igen hasonló az enyémhez. (Akkor meg biztosan jó! ;)
Az overhead valószínűleg nem annyira nagy, de nem kezel xon/xoff-ot, és a putc blokkol. Ebben az esetben e kimenő bufferelés absszolút megkérdőjelezhető, és ezért zavaros. Tehát tesztelni jó, másra nem. Annak, aki nem tud adatlapot olvasni és értelmezni, sok mikrokontrolleren akar soros portot tesztelni - egyenesen ideális.

Szóval nem az a kérdés, hogy ki okos vagy ostoba, hanem használható-e ez a lib komolyabb feladat esetén?
Szerintem nem.

Nem tudok mit tenni, muszáj magamnak megírnom. Nem tudom, hogy egy ilyen kódban hol lehet a hiba, miért csúszik félre.
"Tudom, én vagyok röghöz kötött, de jobban bízom abban, amit magam írok."
Megértelek, de nem tudok egyet érteni! Miért kellene ugyanazt a feladatot ki tudja hanyadjára újra írni?
Ha sok ilyen feladatod van, akkor kialakítod a magad eszköztárát, és azt használod (ha optimális ha nem). Tehát valójában ugyanoda kerülsz, csak sokkal hosszabb utat kell bejárnod.
Nem hiszem el, hogy a már meglévő kódok olyan rosszak lennének. Szerintem csak én nem tudom őket használni, más logika mentén épültek fel mint amit én gondolok/képzelek.
Rá fogok jönni! - de lehet, hogy első nekifutásra először magamnak kell néhány dolgot újraírnom.

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

A filozófikus mélységen túl, most inkább azt kell eldöntenem, hogy folytassam. A véleményetekből az jön le, hogy írjak valami sajátot. Nézzem át mit és hogyan inicializál a C és egészítsem ki, esetleg valahogy írjam felül.

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

Nézegettem, szerettem volna Linux -ban dolgozni.
A kínai klón JTAG ICE, egyébként valamiért csak a 4.18 verzióval tud működni :(
De éppen a 4.19 fenn van az egyik gépemen:
AVR macro assembler version 1.77.3 illetve 2.1.42 (nem tudom miért kell két verzió).
Sajnos az *avrgcc* egy dll ennek nem tudom megnézni a verzióját.
Az ATMEL féle assembler különbözik az avr-gcc assemblerétől és az avra ismét egy harmadik - nem egyszerűbb a választás.
Még amikor i386 programoztam, akkor is az első amivel nagyon nem voltam megelégedve (mondjuk DOS alatt) az az uart kezelés. Ott is azt a technológiát követtem, hogy a "handlert" assemblyből írtam, viszont a képernyő kezelés miatt inkább C -hez linkeltem - jól működött.
A tiszta assemblert (avra) azért is adtam fel, mert (ha jól emlékszem) a debuggoláshoz kell a 32 -bites ELF formátum amit gőzöm nincs hogy tudok előállítani az avra készelettel.

OFF: Nem tudom elhinni, hogy a "kevert" technológia nem működhet. Így az algoritmikus feladatokat C -ből a közvetlen hardware kezelést assembly -ből szeretném írni. Ahogy bucko írta "a kernel szolgáltatások interfészeként :) (Pl. szeretnék "megmozgatni" egy 3,2" TFT kijelzőt, ez assemblyből nagyon macerásnak tűnik, különös tekintettel a RISC utasítás készletre.) De ha nem megy akkor feladom.

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

Valamit azért feladni, mert nem úgy megy, ahogy elképzelted?

Assembly-ben sem bonyolult programozni, mivel tudod rétegzetten csinálni a dolgokat. Kis rutinok kezelik a hardware-t, megvalósítják az egyszerű funkciókat, ezek hívásával már igen hatékonyan, szinte magas szinten tudsz programozni.

Több, mint 20 éve csináltam egy frekvencia mérőt Z80 alapon. Assembly-ben implementáltam egy lebegőpontos kalkulátort. Igen, van egy két rutin, ami gondolkodós, mi több, egy lebegőpontos bináris szám kiírása decimálisan, ember számára értékelhető formátumban egyáltalán nem triviális, de megoldottam, tetszett. Valószínűleg kész függvényekkel nem mentem volna semmire, például azért, mert értelmeztem a „végtelen” fogalmát, mint számot, s az azon végzett műveleteket is mind a négy alapműveletre. Ezzel a metódussal megúsztam a hibakezelést. Például a frekvencia nulla, a reciproka, a periódusidő végtelen.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Most aztán tényleg bajban vagyok! Elkezdtem a (magam módján) építgetni az UART handleremet.
Forrás: http://pastebin.com/PKAwk6EY
Három file avr-uart.h avr-uart-test.c és avr-uart-isr.S
Feltettem a vegyes C - assembly listát is, hogy látszódjék mi van.
Sem interrupt se semmi, egyedül a "hibás" interrupt vektort húztam "magamra".
Egy kis setup 9600 Baud 8n1 formátum.
Ha üres az adási regiszter (UDRE) beletömöm a stack pointer alsó felét - folyamatosan "Z" nyomat ck. 1msec.
Ha van adat a vételi regiszterben kiveszem, eldobom.
A kütyüt szembeállítom a PC-n futó minicommal, csak "Z" -ket azaz 0x5A jön. Ha lenyomok egy gombot a minicomban (akár lassan akár "rákönyökölök") kiakad - kiugrik a "main" programból és beáll a csönd.
Legalábbis más magyarázatom nincs ...
Ennél primitívebb teszt programot nem is igen lehet írni - hacsak nem tiszta assembler.
Mi az ördög van itt :(

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

Legyen! A téma nyitóban ott a forrás.
Az eredmény hasonló, de itt most jól látszik, hogy ez a kód az összes regisztert fejbe csapja, beleértve a stacket és az SREG -et. Így ha sokat kap (vételi ágon) beleáll a fals interrupt csapdába.
Alapból a '\' = 0x5C értéket nyomja a PC felé (a PUSH/POP cuccokat még nem vettem ki a rutinokból, bár most megtehetem).
Ha van valami jó ötleted, nagyon örülnék neki.

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

Sajnálom, hogy ez ennyire fáj neked. Egyébként köszöni szépen kitűnően működnek. Ráadásul a probléma szempontjából teljesen irrevelánsak - csak a szkóp kedvéért van.
A kérdés áll, hogy tud egy ilyen űber primitív program ilyen jelenségeket produkálni?
Felülírja a komplett SFR készletet, és végül valamelyik, eredetileg tiltott, interruptban köt ki.
Nem látom az okot :(

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

Azért fáj, mert akkor legalább egy nop kellene, hiszen a port írása után azonnal teszteled azt, de arrafelé igen nagy a jelterjedés ideje, ráadásul lábon kapacitással is terheled. Latch CPU-n belül marad, kevesbb tranzisztoron keresztül ér oda a jel. Mindegy, egyszer elmondtam, téged nem érdekelt.

Ezen felül a toggle szerintem rossz, de lehet, én nézek be valamit. Ha igen, javíts ki!

Teszteled, vajon 0 a port kimenete. Ha igen, skip, ha nem, 0-ba írod a lábat. Eddig jónak tűnhet, de érdemes megfigyelni, akármilyen állapotú volt a láb eredetileg, ezen a ponton mindenképpen 0 az értéke.

Most teszteled, skip, ha 1. Ez sohasem teljesül, mert 0. Tehát nincs skip, 1-be írod, visszatérsz.

Tehát, ha 0 van a porton, 1 lesz, ha pedig 1 van a porton, lesz egy igen keskeny 0 impulzus, de 1 marad továbbra is.

Ha működik, az úgy lehet, hogy a cbi után a jel még nem ér oda, és a korábbi állapot mintavételeződik. Azaz működhet, de az benne a szép, hogy a kód változatlanul hagyásával pusztán attól, hogy lassabban járatod a CPU-t, nem fog működni. Szerintem a megbízható kód nem attól működik, hogy a jel még éppen nem ért oda valahova.

Az elején kell elágaznod, és set vagy clear, de sokkal jobbat mondok: memóriába ágyazott perifériaként eor úgy, hogy a maszkban az illető bit 1, a többi 0, az eredmény pedig abban a latch-ben keletkezzen, amelyik az eor egyik argumentuma, s egyben a port latch.

Ha rosszul írtam, javíts ki, nem ismerem ezt a CPU-t, de nekem most így tűnik felületesen szemlélve a dolgokat.

Szerk.: azt hiszem, megvan, mitől működik, de ezt kihasználni szerintem nagyon aljas dolog. Van egy szinkron mechanizmus PINA felől a doksi szerint, ez egy statikus latch-et és egy élvezérelt tárat jelent egymás után. Viszont ez arra jó, hogy tökéletesen érthetetlen legyen a kód, továbbá, egy nop beszúrásának hatására nem működne, és kitéphetnéd az összes hajad, hogy egy nop, ami nem csinál semmit, hogyan tudja alapvetően megváltoztatni a működést.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Javítottam. Pedig nagyon tetszett :) De igazad van, újra átgondolva az a fura, hogy ez működött. Ráadásul publikusan lett feltéve, ha valaki véletlenül megtalálja és átveszi lesznek meglepetések.
Sajnos a probléma maradt :(

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

Ez a példa is mutatja, mennyire hardware függő az egész. Lehet, ha végigbogarászod a kontroller doksiját, megtalálod a hibát. Attól tartok, gondolsz valamit arról, hogyan kellene működnie, de valójában nem úgy működik, s a mocskos részletek a katalóguslap releváns részeinek alapos tanulmányozása után derülnek csak ki.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A teljes adatlap példa programokból indultam ki.
De persze azért semmi sem zárható ki - most próbálok egy másik alap kártyát összerakni, másik forrásból származó procival.
(Nagyon gyanús ez a történet, még az én tapasztalataimhoz képest is túlzás)

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

Akkor kérlek a lehető legpontosabban írd le mit vársz ettől az uart próbától!
Én azt veszem ki, hogy egy egszerű UART echo programot próbálsz írni, ami nem lehet kiakasztani folyamatos billetyű nyomással.

Pontosan azt amit kihámoztál belőle. És igen az első számú elvárás, hogy ne akadjon ki.
Nem tudok elképzelni olyan soros kommunikációs programot amelyiknek ezt nem kellene tudni elviselni - persze nem lesz korrekt működés de kiakadás semmiképpen nem lehet.

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

ATmega16A DIP 40 -es tokban, 16MHz -es kvarcal (hfuse = 0x99, lfuse=0xff)
Mindössze a PORTA -t használom - teszt célokra a "program" különböző pontjain "toggle". Illetve az USART, asynchron módban, 9600 Baud és 8n1 formátumban (a minicom gond nélkül, helyesen leveszi a karaktereket).

Érdekes, hogy az olyan elterjedt soros kezelő sem megy mint a Fleury által kivitelezett - pont ilyen hibát csinál, azaz vételkor rövid idő után kiakad.

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

A napokban megkaptam az eBay -en vett kis boardot (már egy hónapja gyanús volt nekem ez a dolog):
http://www.ebay.com/itm/ATMEGA16-Development-Board-Minimum-System-Core-…
Rádobtam egy kapcsolóüzemű dugasztápot, kicseréltem a 12MHz kristályt egy 16MHz -re. Lementettem az alapállapotot (fuse és flash) és beégettem a kis tesztejeimet.
Először a timer piszkálót - a fuse -ok átégetése után kitűnően működik.
Az assembler uart tesztet - kitűnően működik - nyoma sincs a kiakadásnak.
Végül a Fleury féle uart kezelőt - hibátlan.
Nyugodtan rákönyökölhetek a billentyűzetre, nem akad ki.
A szkópon jól látszik a táp "zaja" - köszöni szépen jól van.
Hurrá! Vagy mégse? Mi a hiba a másik felállással?
A proci vagy a breadboardos felépítés (kismillió hasonló felállást láttam a neten, még hevenyészettebb mint az enyém volt).
Hogy tudnám ezt kideríteni?

OFF: Azért ez kicsit sok hajszálat elvitt ahhoz hogy csak úgy átlépjek rajta. Elvileg várok még két DIP40 -es ATmega16 -ot egyenesen Kínából, ha azzal is működik akkor a kontroller a hibás. 30 év alatt ilyen nem fordult elő velem.

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

Ha ez így van, akkor az szerkezet ESD áldozata lehetett. A reset után minden jónak tűnik, de valamelyik láb/funkció lebeg és interrupt keletkezik. Ilyet már láttam: Egyszerű fordulat időmérő - egy fordulat egy trigger - elkezdett egyre csűnyábban téveszteni. Mindössze a trigger bemenet nem volt megvédve, így a beépített védődiódák csak egy darabig bírták...

Akkor már két ilyen chipem is van :( ugyan abból a forrásból.
Valami pontosabbat akarok, majd kitalálom.
Az interruptolás az hogy, ha mind le van tiltva globálisan?
Várok még egy cuccot, azon lakatos DIP40-es csatlakozó van, majd összehasonlítom.
Egyébként az új és a breadboard kivitelnél is megfigyelhető, hogy valamennyi tápot akkor is kap a cucc, ha nincs is táp - a JTAG -en keresztül úgy, hogy nincs is összekötve a táp - ég a táp LED és valami működési jelenségek is vannak, dacára hogy 16MHz csak 5V esetén garantált.

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

Azért nem tudok veletek osztatlanul egyetérteni, mert a neten rengeteg olyan fényképet láttam ahol az enyémnél sokkal hevenyészettebb breadboard összeállításokat láttam - állítólag működtek.
Azon is vitatkoztunk, hogy a neten letölthető kódok (pl. Fleury féle soros kezelés) nem lehet ennyire hibás.
A vadító, hogy a minimál tick számlálóm jól működött - miután kicsit helyre raktátok az agyam. NEM volt kiakadás, minden működött ahogy kell.
Viszont, amint a soroshoz nyúltam az egész eltanyázott, de nagyon. Globálisan tiltott interrupt mellett végig firkálta az SFR -t egészen a stack pointerig - ezt nagyjából sikerült (magamnak) bebizonyítanom.
Sajnos egy ilyen chip túl bonyolult ahhoz, hogy egy ilyen anomáliára magyarázatot tudnék adni.
Mindegy, most már tovább tudok lépni, és ha összeállnak feltételek vissza kanyarodhatok ehhez a hibához.
Roppant sok dolog izgatja a fantáziámat az AVR -ek körül.
Köszönöm az eddigi segítségeteket és türelmeteket, számítok rátok!

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

Fura nekem, amit írsz. Egy youtube-os videó, fénykép, akármi bizonyítja, hogy valami működött? Nem a Maxwell-egyenletek? Tudsz bármit is mondani a Te esetedben illetve a fényképen látott esetben a csatlakozások átmeneti ellenállásáról? A hozzávezetések induktivitásáról esetleg? Egyáltalán a stabilizált tápot hol állítottad elő? Csak remélni merem, hogy nem a kontrollertől távol.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Dicséretes hozzáállás, hogy mindent megkérdőjelezel.
Azonban ez indokolatlan többletmunkát okozhat. Én nem "kibernetikus trubadúrt" akartam összerakni, hanem belekóstolni az AVR mc utasítás készletébe. Már sok éve készülnek, nagy sorozatban, kis mc -re alapozott kütyük, igénytelen kapcsolóüzemű dugasztápokkal, kispórolt hidegítéssel, szűréssel. Működik.
Persze ha profi alkalmazásokat kell felépítened, ha csúcsra járatod az eszközt (tulajdonképp pont azt tettem 16MHz órajel a garantált maximum) 24 órás üzemben. Mindezt széles hőmérsékleti tartományokban (-20 ... + 60 °C pl. gépkocsi) akkor sokkal igényesebb kivitelre van szükség.
Az interneten publikált kis asztali cuccok nem túl igényes környezetben jól működnek. Ha nem így lenne nem lenne ennyi különféle kis hobbi projekt ezekkel az eszközökkel.

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

Ez a hozzászólásod maradjon meg az utókornak, igen érdekes fizikai szemléletet hordoz.

Dicséretes hozzáállás, hogy mindent megkérdőjelezel.

Mérnök vagyok, ha úgy tetszik, természetes a gyanakvó hozzáállás, pláne, ha tudjuk az eredményt: nem működik, amit csináltál.

Azonban ez indokolatlan többletmunkát okozhat.

Szeretem ezt a mondatodat, gyöngyszem. Tehát ami többlet munkát okoz, az egyben működési zavart nem okozhat. Csak azok a dolgok okozhatnak olyan fizikai állapotokat, amelyek működésképtelenséget váltanak ki, amelyeket neked könnyű másképp csinálni. Csalódnék Istenben, ha megvesztegethető lenne és ez valóban így működne.

Én nem "kibernetikus trubadúrt" akartam összerakni, hanem belekóstolni az AVR mc utasítás készletébe.

Nem teljesen mindegy, hogy melyik esetben vét hibát a kontroller? Ha hibázik, akkor az a dolog nem fog működni, akár egyszerű, akár bonyolult dologról beszélünk. Tehát bármilyen furcsa, neked egy végtelenül egyszerű hobby projectben is be kell tartanod a szakma alapvető szabályait, ha azt szeretnéd, hogy az működjön, tudniillik a fizikánk egységes, a hobby projectre is ugyanúgy érvényes, mint bármi másra. Nincs kibúvó.

Már sok éve készülnek, nagy sorozatban, kis mc -re alapozott kütyük, igénytelen kapcsolóüzemű dugasztápokkal, kispórolt hidegítéssel, szűréssel. Működik.

Véletlen, mázli, nem stabil. Sőt, lehet, hogy rossz, csak nem vette észre. Lehet, hogy 30 mm-rel rövidebb, 0.2 mm-rel nagyobb átmérőjű vezetéket használt valahol, amelynek így kisebb az induktivitása, ellenállása, mint nálad. Egy pici oxidréteggel kevesebb van a vezeték végén, kisebb az átmeneti ellenállás, stb.

Persze ha profi alkalmazásokat kell felépítened, ha csúcsra járatod az eszközt (tulajdonképp pont azt tettem 16MHz órajel a garantált maximum)

Épp magadat cáfolod. Leírod, hogy ha elmennél a falig, kellene a jól megcsinált környezet, aztán ugyanabban a mondatban azt is leírod, hogy elmentél a falig. Nincs jól megcsinált környezeted. Mi is tulajdonképpen a csodálkozásod tárgya? Az, hogy nem működik? Hogy ez mitől lehet? A fene se érti... :)

Az interneten publikált kis asztali cuccok nem túl igényes környezetben jól működnek.

Nem vagyok meggyőződve arról, hogy ebben a vonatkozásban a fontos és kevésbé fontos dolgok között különbséget tudsz tenni. Ezen felül, ha valami működik, de a körülmények rosszak, az nem biztos, hogy máshol is működni fog, hiszen nem specifikált eset. Például a táp zajára nézvést. Olyan ez, mintha azon keseregnél, hogy valakinek működött 22 MHz-en is, neked meg nem. És? Kellene? 16 MHz a specifikáció. Aztán az már konkrét darab kérdése, melyik meddig bírja a nem specifikált körülmények közti üzemeltetést.

Ha nem így lenne nem lenne ennyi különféle kis hobbi projekt ezekkel az eszközökkel.

Nem látom az összefüggést. Nekem a céges tervezéseim és a hobby projectjeim is egytől egyig működnek. Ez utóbbi akár tiszta lyuk nyákon összeforasztgatva. Viszont mindig odafigyelek a fontos dolgokra, betartom a specifikációt. Ha az élesztés során valami nem megy, magamban keresem a hibát, kidebugolom, kijavítom. Aztán működik.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ezzel most egyet értek. Én mikor valami újjat csinálok, általában meg szoktam állapítani, hogy az áramköreim jobban tudják a fizikát mint én. Ez benne van a fejlesztésben, hogy elsőre nem gondolunk mindenre. A fizika ugyanúgy működik mindenhol. A neten összedobott valamik azért működhetnek, mert valaki kifejlesztette őket és valószínüleg, ha addig nem működött addig javított rajta, míg a funkciót éppen ellátta. Sokszor a minimura tervezett dolgok éppen működnek, egy ideig. De ezt mindíg az adott boardról kell eldönteni tesztek alapján és nem ránézésre.

Ide vág az egyik legkedvencebb íromtól való idézet:

"It is the chief characteristic of the religion of science that it works."
Isaac Asimov

Amit írsz, az a képzavarok tömkelege!
1) A breadboard egy sok kontaktusból álló eszköz. Ilyet használóktól tudom: van olyan típus a mi rögvest kuka! Ez a fényképen nem mindig látszik. :)
2) A mérnöki munka lényege: A feladatnak/előírásoknak megfelelő reprodukálható áramkör előállítása. Ez nem csak a kapcsolási rajzot, hanem az alkatrészek térbeli elhelyezkedését is jelenti. Azaz a dokumentáció soha nem ilyen elemekből áll:
- breadboard
- fénykép
- nekem véletlenül működik
3) Az áramkör megépítését úgy kell kezdeni, hogy
- megismered az adatlapot
- errata
- órajel előállítás
(Ezek egy-egy, a gyártó által megadott dokumentumot jelentenek.)
4) Megépíted az úgynevezett "minimum konfigurációt". Ezt általában a gyártó megadja, de mindenképpen részei a
- megfelelő tápellátás
- hidegítés
- egyes lábak előfeszítése adott szintre
5) A feladat függvényében a bemeneteket határozott állapotba hozod. (Az egyszerű áramköröknél egyértelműen specifikált a nem használt bemenetek kezelése. Mikrokontroller esetén ez nem mindig teljes, de a gyártó feltételezi az alapok ismeretét.)
Az Atmega16 estén egyértelműen leírják, hogy vannak olyan interruptot okozó bemenetek, amelyek aktiválódhatnak még abban az esetben is, ha kimenetként konfiguráltak.
Nyilvánvalóan a nem fix potenciálon levő bemenetek akármit is csinálhatnak. Ez egy teljesen pontos definíció!
Nézd csak meg: az az ármkör (amit készen rendeltél) hány ellenállást és kondenzátort tartalmaz! Vajon mi a szerepük?
6) Az egyéb perifériákat is stabil állapotba kell hozni. (Mint írtam párszor.) Ez feleslegesnek tűnhet, de így tudjuk hol a kályha.
7) Ezek után jöhet a lib! Aki a libet készítette, semmi mással nem foglalkozott csak a soros porttal!
Ha a fenti alapbeállításokat nem tetted meg, nincs garancia a működésére.

Szóval gondolj bele: Tiltott interrupt mellett van interrupt! Akkor vajon melyik fenti pontnak nem tettél eleget?

Még egy dolog a "hevenyészett breadboard összeállításokról". Láttam pár jútyúbos videót is kapcsolóüzemű tápokról. :) Meg én is terveztem, kiviteleztem néhányat. Szerencsére olvasni is tudok, és némelyik gyártó nem csak egyszerű appnote-ot bocsájt ki, de komplett méretezést, szimulációt, hőfényképet, méréseket az így megépített referencia áramkörökről.
A véleményem kb. olyasmi lehetne:
Ismeretes, hogy egy cseh légikisasszony 10km magasból zuhant le (a gép farkával együtt).
De.
Ha valaki azt állítja, hogy ő is leugrott ilyen magasról - többször is.
Hááát, biztosan elhinném! Vagy mégsem?

Szóval hidd el: Egy áramkör működése nem hit kérdése! Minden mérhető és számítható.

Szépen finoman elmondtatok mindennek - nem szívesen megyek ebbe bele.
Az általatok vázolt problémákkal már nagyon régen találkoztam - sokat már el is felejtettem. Talán (számomra) a legfontosabb konzekvencia (amiért részben évek óta kerülöm ezt a témát) az hogy míg a PC -nél egy viszonylag megbízható hardware-el van dolgunk, addig ebben a műfajban (fusi hardware) úgy kell hozzáállni, hogy a hardware NEM megbízható, még akkor sem aha látszólag működik.
OFF: Valaki felemlegette Maxwellt - azért azt se feledjétek, hogy Maxwellt már jócskán túllépte ez a dolog, hiszen az egész a elektronika a kvantum mechanikára alapul, ami CSAK valószínűségekre alapul: Shrödinger macskája és a kedvencem a Heisenberg féle bizonytalanság :D
A breadboard korlátait ki kell ismernem - kell hogy legyen megbízható gyors megoldás a prototípus készítéshez. Az eddigi tapasztalat azt mutatja, hogy a breadboard alkalmazása eléggé korlátozott.
Fenntartom hogy valami nem stimmel az általam beszerzett chipekkel - ez persze NEM zárja ki pl. az ESD problémából fakadó meghibásodást. Nem minden látszik egy 100MHz szkópon, pl. a tranzienseket elcsípni roppant nehéz.
Valaki említette, hogy interrupt létre tud jönni ha a port pl. kimenetnek van beállítva. Ezt akár még el is tudnám fogadni, de én szoftverből, globálisan letiltottam az interruptot - ha ennek dacára a processzor fogadja a tiltott interruptot, az a processzor sz'r, használhatatlan - szerintem.
Mint azt mondtam, számomra most az a lényeg, hogy tovább tudok lépni a témában, az agyamat gúzsba kötő probléma megoldódott, folytathatom a "felderítést".
Most épp azt kellene eldöntenem, hogy melyik irányba induljak a PC vagy más eszközökkel való kapcsolat megteremtésében: soros, USB HID vagy ethernet. Persze, ez feladat függő, tehát érdemes körbejárni mind három variációt.
A másik ezzel párhuzamos felderíteni való, a bootloader alkalmazása, az Arduino csak egy lehetőség ezek közül, ráadásul nem tetszik az IDE és az Arduinóval járó kötöttségek.

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

Nem bántott téged senki, ugyanakkor a hozzáállásoddal, szemléleteddel akadt némi probléma, ezt többen is igyekeztünk helyesbíteni.

Ami azt illeti, én jobban bízom egy mikrokontrolleres hardware-ben, mint egy PC-ben, de ez legyen az én problémám.

A Maxwell-egyenletek szerintem nem mondanak ellent a kvantummechanikának, sőt, a newtoni fizika sem. A BME-n nekünk le is vezették kvantummechanikai alapokon Newton II. axiómáját. A lényeg az, hogy sok részecske viselkedésének átlagából kijön az, ami egy-egy részecskére nem alkalmazható. A törvényeknek mindig van valamiféle értelmezési tartománya, érvényességi feltétele, peremfeltétele, ahol az alkalmazható.

Szerintem USB irányába menj, de felhívom a figyelmed arra, hogy az USB szabvány röpke 600 oldal körül van, ezen felül a kontroller kataóguslapját, az errata-kat is el kell olvasnod, stabil hardware-t építened, ráadásul az USB-hez úgy emlékszem, elég pontos időzítések tartoznak. Mondanám, hogy ha a timer-es, soros portos feladattal gondjaid voltak, akkor lehet, az USB-vel nem kellene próbálkozni, hacsak nem vagy nagyon elszánt, türelmes, alázatos a feladattal szemben.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

"én jobban bízom egy mikrokontrolleres hardware-ben, mint egy PC-ben" - ha te csináltad magadnak, akkor érthető.
"az USB szabvány röpke 600 oldal körül van" - pont ez az gondom nekem is. Ráadásul, nekem mindkét platformon ki kellene tanulni PC oldali interfészt. Egyébként is elég sok rossz tapasztalatom van az USB cuccokkal.
Sokkal gyorsabbnak és hatékonyabbnak tűnik, az ethernet ill. TCP/IP - legalább a PC oldalon minden platformon jól tudom kezelni. Persze itt cél chipekkel akarok dolgozni, nem szeretnék TCP/IP stacket írni 8 bites processzorra (már csináltak ilyet, esetleg implementálható, de itt megint az a kérdés mi is a feladat.
Soros az nem kihívás, itt sem volt az. Rengeteg soros handlert írtam. Ha ez a buta hardware hiba nem lett volna, ez a téma sem bnyúlt volna ekkorára. Az meg már elcsépelt alapigazság, hogy a hibákból tanulunk, nem abból ha minden rögtön működik. (Régen úgy mondták nekem, "ha valami rögtön működik, akkor azonnal szét kell szedni, mert annak biztos valami súlyos baja van!")

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

A "rossz tapasztalat" nem programozási oldalról jött.
Kimondottan mint felhasználó szaladtam bele sokszor különös hibákba. Nehezen azonosítható zavarokba - nem mondod hogy sosem találkoztál olyannal, hogy bedugsz egy sticket és nem látja, nem úgy látja, lassú stb. Tipikus probléma PS/2 billentyűzet/egér USB átalakítóval nem működik és fordítva.

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

Ennek azért oka is van! Maga az USB egy kisfeszültségű és egyenáramú+időzítés elemeket is tartalmazó protokoll. Néha zavarérzékeny és nem vihető messzire. Tök jó, hogy mindent ki-be lehet dugdozni, de pont ez a hátránya is. Nem low-latency interfész, hiába nagy a sebessége. Külön előny a windóz (régi?, mert nekem nincs új) USB eszközkezelése. Néha megtelik, és mindent újra kell rakni. (Kitörölni és újra felismertetni.)

Ennél sokkal profibb a firewire, amely galvanikusan leválasztható, képes címeket kezelni. Ezért is drágább és nem divatos. Viszont használják pl. (profi) zeneszerszámok összekötésére is.

Nem tudom, hogy az ethernet mikrokontrollereknél mennyire ésszerű. Biztosan van olyan távoli összeköttetés, ahol szükség lehet rá. De mindenképpen külön kezelni kell a címeket. Kérdés mit, hányat és hogyan szeretnél összekötni.

Ha jártas vagy a soros kommunikációban, akkor érdemes lenne tanulmányoznod néhány pc megoldásoktól eltérő megoldást is! Pl.:
- RS422/RS485
- I2C
- SPI
- LIN, CAN
- stb.
Ezek azért érdekesek, mert az eszközök összekötéséhez busz specifikus hardver is tartozhat, amit egyes esetekben lehet keverni. Az egyes protokollokhoz létezik célhardver, pl. hőmérő, memória, flash, stb., vagy a buszt megfelelő irányban összekötő/kapcsolgató megoldás.

A soros I2C kezeléshez találtam egy jó szerkezetet. Megépítem, kipróbálom.

Persze az USB -nek komoly korlátai vannak, távolság és zavar érzékenység stb. (Csináltam már olyat is, hogy PC oldalon USB-PS/2 - PS/2 kábel 15m - PS/2-USB - USB egér, és nem kis meglepetésemre működött - viszont akkor nagyon örültem hogy megoldódott a probléma :)
Az általad felsorolt kommunikációk közül most épp az SPI érdekel a legjobban - pont az ethernet vezérlők erről működnek. Ill van egy kis digitális hullámforma szintetizátor panelem, amire nagyon kíváncsi vagyok (pl. szinusz harmonikus torzítás) AD 9850 - es chip. Úgy hogy igen, ide mozdulnék, elsőre jó lenne egy USB-SPI konverter.

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

No igen! Rengeteg jó kis alkalmazása van a PIC mc-nek. De történelmileg az Atmelnél kötöttem ki még a 90 -es évekből. Ráadásul a PIC utasításkészlete, mnemonicja nagyon idegen (nekem).
Egyébként, ha készet akarnék akkor inkább ez:
http://www.ebay.com/itm/All-In-1-USB-to-SPI-I2C-IIC-UART-TTL-ISP-Serial…
Ha pedig PIC és kész, akkor buspirate.
Csak halkan merem bevallani, körül akarom járni ezt a témát. Sok jó SPI alapú chip van, port, ADC, DAC, DDS, ethernet stb. Érdemes beleszagolni, nehogy úgy járjak mint az ATmega16 -al.

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

A PIC azért ilyen, mert "file" szervezésű. Az AVR sok regiszteres, de mindent be kell tölteni és csak a regiszterek között végezhetsz műveletet. A PIC meg egy munkaregiszteres (W), viszont a memória meg a SFR egyenrangú. Csak az a fránya bank select! Most éppen olyannal dolgozom, ahol a memória meg a néhány ;) SFR szét van dobva 32 lapra. A PIC család nagy előnye a választék. Éppen ezért néha nehéz kiválasztani a megfelelő típust. Olyat sikerült találnom, ahol a 28 lábból 19 egy "kapcsoló mátrix" segítségével köthető össze. Tehát ez a 19 láb és kb. 30 funkció, ki- és bemenetek tetszés szerint összerendelhetők. Egy lábra több periféiát is lehet kötni! Még nem próbáltam, de hallatlan előnye lehet akkor is, ha valamilyen bonyolultabb kapcsolás utólag módosítani kell.

A buspirate az tök jó ötlet, opensource meg minden, lehet vele játszani! Munkavégzésre azért olyat szeretek használni, amit a gyártó fejlesztőeszközeivel is lehet használni. Az opensource esetleges, nekem meg sem időm sem kedvem fejlesztőeszközt fejleszteni munka helyett. :( Saját példádon láthatod, hogy milyen nehéz összeszedni s működő eszközkészletet. Én pl. így kezdtem neki:
MPLAB + C
- C kuka
HiTech C
- kuka
MPASM
- kuka
MPLAB X
- kuka
gputils (gpasm) (+MPLAB) => Ez műkodik!!
gpasm szívás -> hup - Szerencsére pont az egyik fejlesztője is hupos. Gyorsan, készségesen javított és a javaslatomra még módosított is!

Mielőtt tudtam volna, hogy ő hupos, úgy javítottam hiányzó utasításokat, hogy írtam bash-ben egy preprocesszort, amelyik a hiányzó utasításokat DB-vel beletette abba a közbülső forrásba, amelyre ráeresztettem az assemblert. Tudom, gány, de remekül működött! :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ravasz, ravasz. ;)
Persze, amikor még bash sem volt, akkor is létezett erre a problémára egyszerű megoldás.
Pl.:


LDHI macro sh
$save nogen
db 28h
db sh
$restore
endm

Ez egy 8085 UNSPECIFIED OPCODE. Használata egyszerűen:


LDHI #data

A listában ugyanez látszik.

Ha már ilyen ontopicok vagyunk. ;)
Tudnál-e tanácsot/ötletet adni, hogy ennél a szerkezetnél milyen szempontok szerint kellene a bankolt memóriát abszolút módban használni?

Nem. :)
Arról van szó, hogy a memória és az SFR-ek 32 bankra vannak szétdobva. (Kb. 80 bájt/bank memória.)
Kérdés:
Ha nem akarok FSR címzést, létezik- valamilyen elegáns/ötletes/trükkös definíciós módszer a lineáris és bankolt memória összehozására?

Pl.:
Az ADRESH, ADRESL a BANK1-ben van. Mellőzendő a bank selectet az itt látszó 80 bájtba celszerű elhelyezni az A/D átalakító eredményét. Ez a 80 bájt a Bank 1/0x0A0-0x0EF tartományban van, míg lineárisan a 0x2050-0x209F a címe. Elképzelhető, hogy két féle címzéssel szeretnék hivatkozni az eredményre.

Tehát abszolút kód esetén hogyan célszerű kezelni ezt a felállást?

Most az Arduino -ra gondolsz? Pont ezen morfondírozok, hogy a bootloader nem lehet akadálya annak, hogy makfile segítségével, saját szájízemnek megfelelő programot írjak. Még eléggé homályos. Nagyon pofás lenne a cucc, ha a "Digispark Kickstarter" -t (ATtiny85) tudnám erre használni. Egy SPI spy -hoz épp jó lenne, viszont amit beszereztem azon lehet, hogy nincs ott a bootloader - ha jól értem ISP programozó kell hozzá (mondjuk USBASP), és az Arduino -ból is egy frissebb verzió (Debian Jessie 1.0.5 - a Digisparkhoz pedig 1.5.x) kell. Ráadásul ha feljebb nézed az avrdude -ból is fel kellett raknom az 5.11.1 verziót, mert a 6.1 -el nem működött a JTAG -em. Kicsit sok az akadály.

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

Valahol már írtam, hogy Jessie alatt az avrdude 6.1 verzióval nem tudom használni a jtag ice klónomat - timeout hibával otthagy.
Wheezy alól, avrdude 5.11 jól működik.
Letöltöttem az 5.11 forrást és ahogy írja az INSTALL (felhasználóként) ./config és ./make - panaszkodik itt-ott de lefordul és ami a lényeg működik.
Az avrdude eredetileg a /usr/local/etc -be kéri az avrdude.conf -ot bemásoltam. Magát az avrdude a felhasználói bin könyvtárba tettem. Becsapós lehet, de működik és ha közben kijavítják akkor használhatom az új verziót - nem zavarják egymást.

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

OFF: Volt egy kis szabi :) Most egy kis megrendelés. A téma nincs elfelejtve, de félre kell tennem és visszatérni a check boxos kattintgatós fejlesztéshez és örülni hogy van. (Amúgy a megrendelt kis ATmega16 panelről kiderült hogy '51 - az is jó de nem azt akartam, mástól rendeltem újat, de az még legalább 2 hét) Viszont, az smd tokos minimál panel kapcsolását sikerült kikunyerálnom a kereskedőből - nem sok különbség van a breadboard felépítésemhez képest (már kapcsolásilag) kivéve néhány kényelmi LED és jumper, ha alacsonyabb feszültségről akarom járatni (a kvarc egy kis IC foglalatban van) - a lényeg hogy az elvártnak megfelelően működik.
Ami az USB - SPI (esetleg i2c) adaptert illeti még vacilálok, hogy esetleg az Arduino Mini vagy a "Digispark Kickstarter" fogjam be. Az utóbbiból mintha hiányozna a szoftver, de azt meg kell nézni egy ISP programozóval, lehet csak "nyűgös" - végül is a soros portra adaptált USB stack (három diódával meg néhány ellenállással) kicsit gyanús. Elvileg HID eszköznek kéne lennie de sem a Linux (Jessie) sem az XP nem ismeri fel. Viszont a minimálisnál is minimalisztikusabb felépítése nagyon izgatja a fantáziámat. Láttatok ilyesmit PIC -re?

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

Ez a "Digispark Kickstarter" érdekes egy valami. (Amúgy erről van szó?) Az ATTiny85 nem tartalmaz hardveres USB-t, ezt "izomból" kell, hogy megoldja. A "sima" PIC-ek ehhez karcsúak szoktak lenni, cserébe ott van egy halom újabb típus, amik már tudnak hardveres USB-t. (Ott még a néhány dióda + ellenállás se kell.) Cserébe talán több a láb, de nem vagyok ennyire MC-ből naprakész.