Fórum témák

» Több friss téma
Fórum » PIC - Miértek, hogyanok haladóknak
 
Témaindító: G-Lex, idő: Jan 9, 2006
Lapozás: OK   1249 / 1249
(#) killbill válasza Wezuv hozzászólására (») Hé, 9:45 /
 
A gyakorlati haszna az, hogy nem neked kell foglalkozni azzal, hogy az osszes feladathoz tartozo fuggvenyedet ciklukusan meghivd az egyetlen foprogrambol, es az mind vizsgalgasson valami timer allapotot, vagy pollozzon hardware biteket, hogy van-e dolga vagy nincs. Azert, mert ez a tipikus mikrocsip megoldas (sajnos volt szerencsem kinlodni ezekkel), attol ez meg nem jo. Az igazi multitasking lenyege pont az, hogy a kulonbozo feladatokat kulonallo processekben irod meg, es a kernel majd mindig annak adja a CPU-t, akinek kell. Persze egy cooperative kernel eseteben ez csak akkor mukodik jol, ha a processzek nem sokaig foglaljak egyhuzamban a processzort, de ez a fenti fociklusos mindent hivogatos modszernel is igy van. Vannak esetek, amikor egy process megis nagyon sokaig csinal valamit, es ezzel feltartja az osszes tobbi processzt. Erre tobb megoldas is van. Lehet hasznalni preemptive kernelt, de azzal sok egyeb macera van. Lehet olyat csinalni, hogy a hosszan tarto muveletet valahogy feldarabolod tobb reszre, vagy csak beleteszed, hogy x idonkent adja fel a CPU-t. De a legtobb esetben egy-egy esemenyre reagalni nem tart sokbol. Es termeszetesen allapotgepek kellenek, de azok mindenkeppen kellenek. Azok nelkul nem nagyon lehet programozni.

A fix idoosztas egy mas teszta. Meg valamikor 1991-ben kellett ket egymastol fuggetlen z80 gepre irt programot osszeraknom egy joval nagyobb sebessegu, de a z80-nal sw kompatibilis processzorra. Kezenfekvo volt, hogy 2ms-os valtassal hol az egyik, hol a masik kod futott. Ebben az esetben ez jo megoldas volt, de normalis korulmenyek kozott ezzel az a baj, hogyha az egyik programnak semmi dolga nincs, mert var valami bejovo adatra, akkor is lefoglalja a processzort a 2ms idore, mikozben a masiknak szuksege lenne a CPU idore. A multitaskolas lenyege, hogy mindig az a process kapjon idot, akinek szuksege van ra. Ha egy process elmegy varni valamire, akkor o addig nem hasznal el processzor idot, amig be nem kovetkezik az az esemeny, amire var.
(#) Wezuv válasza killbill hozzászólására (») Hé, 9:56 /
 
Na jó, de ha a process nem kér időt, akkor nem is fordítódik rá a szelete, valamint ha hamarabb végez, akkor visszaadja a szálat.
Abban egyetértek, hogy a későbbiekben már sokkal kevesebb idő a fejlesztés és kényelmesebb, legalább is annak tűnik. De biztosan megmaradnak azok a lehetőségek is, amik speciálisak, hardver közeliek, vagy csak azok, amiket a kernel enged?
Nézted, van RTOS a harmony-ben, lehet, hogy kipróbálom!
(#) killbill válasza Wezuv hozzászólására (») Hé, 11:03 / 1
 
Ez megvalositas fuggo. Az en kernelemnel (nem en irtam) minden lehetoseged megmarad. Egy jo cooperativ kernel csak annyit csinal, hogy amikor (az en esetemben) meghivod a BZ_EventWait() fuggvenyt, akkor a kernel megnezi, hogy melyik process READY, es ezek kozul a legnagyobb prioritasunak adja a CPU-t. De valaszthatok round robin schedulingot is, amikor is nincsenek process prioritasok, csak korbe korbe megy a READY processzek kozott. Alapvetoen az egesz 'signal'-okra epeul. A szignal az egy bit egy 32 bites szamban. Minden bit egy szignal. A process csak szignalra tud varni, minden mas (szemafor, lock, message) szignalokra epul. Minden processhez tartozik egy leiro, amiben benne van az, hogy milyen szignalra var eppen, es hogy eddig milyen szignalokat kapott. Namost ha var az 1-re, de csak a 8-at kapta, akkor az a process nem READY. Ha megkapja az 1-et, akkor mar READY-ve valik, es a legkozelebbi BZ_EventWait() kernel hivas latni fogja, hogy a process futokepes, es ha nincs magasabb prioritasu READY process, akkor meg is kapja a CPU-t. De ettol meg ugyanugy vannak megszakitasok, ez minden egyeb. Ez csak a szalak futtatasahoz ad egy nagyon kenyelmes kornyezetet, de nem tilt meg semmit, nem korlatoz semmiben. A signal kuldo fuggvenyeket termeszetesen lehet megszakitasbol is hivni.

Egy preemptiv kernelnel, amikor A process egy signalt kuld B processznek, akkor a kernel megnezi, hogy ettol B process READY-ve valt-e, es ha igen, akkor mar inditja is B-t, ha az magasabb prioritasu, mint A. Namost, mivel signalt megszakitas is tud kuldeni, ezert egy preemtive kornyezetben egy processz futasat ilymodon egy magasabb prioritasu process meg tudja szakitani. Ennek elonye, hogy nem a tobbi process donti el, hogy egy magasabb prioritasu mikor futhat. De hatranya, is van boven. Sokkal jobban kell a kozos eroforrasokra vigyazni, az egyebkent nem javasolt globalis valtozokat volatile-nak kell deklaralni. Meg aztan van a prioritas inverzio nevu problema, ami megintcsak bosszanto.
(#) Wezuv válasza killbill hozzászólására (») Hé, 12:52 /
 
Ez nagyon "szép", tetszik! A process, ami még nem READY, hogyan kapja meg a szükséges szignálokat? A szignálok vizsgálata a kernel feladata, a kernel dönt, hogy READY-e a process a megfelelő szignálok esetén? Azt, hogy milyen szignálra vár a process, a legutóbbi futásnál adja át a kernelnek? A szignál mögött lévő adatokat hogyan kapja meg a process? (azt hiszem nem kérdezek meg mindent, mert megharagszol! )
(#) usane válasza cross51 hozzászólására (») Hé, 13:43 /
 
Hello!

Megint volt egy kis időm játszani az PIC32MM-el. Összehasonlítottam a kódrészletedet az enyémmel. A konklúzió, hogy dual edge módban megy az SCCP nálam is. Eddig a módokkal nem játszottam. Illetve az MCCP-n igen, de az SCCP-n nem. Mind a két dual edge mód megy, buffered és unbuffered is. A center aligned mód viszont nem megy az SCCP-n és azzal próbáltam, az MCCP-n viszont az is megy. Átnyálaztam az adatlapokat megint, de semmi utalást nem találtam amit kihagyhattam volna. Kihagytam még valamit, vagy ez már tényleg bug?
(#) killbill válasza Wezuv hozzászólására (») Hé, 14:07 /
 
Idézet:
„A process, ami még nem READY, hogyan kapja meg a szükséges szignálokat?”
Ugy, hogy egy megszakitas vagy egy masik futo process kuld neki signalt: BZ_EventPost(pid, signal);
Amikor egy process meghivja a BZ_EventWait(sig) fuggvenyt, akkor a sig parameterben mondja meg, hogy melyik signalokra var. Itt egy nagyon egyszeru pelda, amiben van egy timer megszakitas, ami minden processznek kuldi a SIG_TIMER szignalt, es egy billentyuzet szkennelo process, ami ezt a TIMER signalt hasznalja idozitesre. Ezen felul lehet meg neki kuldeni STOP es START szignalt, csak a pelda kedveert.
  1. my_signals.h:
  2.  
  3. #define SIG_TIMER      (1<<0)
  4. #define SIG_START      (1<<1)
  5. #define SIG_STOP        (1<<2)
  6.  
  7. ----------------------------------
  8. timer.c:
  9.  
  10. #include <my_signals.h>
  11.  
  12. // 1ms timer interrupt rutin
  13.  
  14. void  timer_isr(void)
  15. {
  16.   // elintezi a timert
  17.   ...
  18.   // minden processznek elkuldi a SIG_TIMER signalt
  19.  
  20.   BZ_EventPost(PID_BROADCAST, SIG_TIMER);
  21. }
  22.  
  23. ---------------------------
  24.  
  25. buttons.c:
  26.  
  27. #include <my_signals.h>
  28.  
  29. #define STKSIZE 400  // 400 byte stack ennek a processnek boven eleg
  30.  
  31. static int port;            // ide kell kuldeni az eventeket
  32.  
  33. static void process(void);
  34.  
  35. /*
  36. * Elinditja a billentyuzet szkennelo processzt. A p parameter az a message port,
  37. * ahova a billentyu eventeket kuldeni kell.
  38. */
  39. void  ButtonsInit(int p)
  40. {
  41. static char stack[STKSIZE] __attribute__((aligned(8)));
  42.  
  43.   port = p;
  44.  
  45.   BZ_ProcSpawn(PID_BUTT, stack + STKLEN, process);
  46. }
  47.  
  48.  
  49. /*
  50. * Ez maga a szkennelo process
  51. */
  52. static void process(void)
  53. {
  54. int s, run, new;
  55.  
  56.   run = 0;
  57.  
  58.   for(;;){
  59.     /*
  60.      * Ez a harom signal erdekel minket
  61.      */
  62.     s = BZ_EventWait(SIG_TIMER | SIG_STOP | SIG_START);
  63.  
  64.    if(s & SIG_STOP)
  65.      run = 0;
  66.  
  67.   if(s & SIG_START)
  68.       run = 1;
  69.  
  70.   if(s & SIG_TIMER && run){
  71.  
  72.     // szkenneli a billentyuket
  73.     ....
  74.     // ha van uj lenyomas, elkuldi a megfelelo uzenetet
  75.  
  76.     if(new)
  77.        BZ_PortSend(port, MSG_NEWKEY, new, 0);
  78.   }
  79. }
  80.  
  81. ------------------
  82.  
  83. main.c:
  84.  
  85. #include <my_signals.h>
  86. #include <everything.h>
  87.  
  88. void main(void)
  89. {
  90.    ...
  91.    TimerInit();
  92.    ButtonsInit(PORT_MAIN);
  93.    ..
  94.    egyeb initek
  95.    ..
  96.    // bekapcsolja a billentyu szkennelest
  97.    BZ_EventPost(PID_BUTT, SIG_START);
  98.    for(;;){
  99.      s = BZ_EventWait(SIG_....);
  100.      ...
  101.    }
  102.  }
  103. }
(#) pajti2 válasza killbill hozzászólására (») Hé, 20:16 /
 
Még mielőtt bármiféle állást foglalnék mikrovezérlőkre való kooperatív / preemptív kernel ügyben, egy olyan kérdésem lenne, hogyan tudod biztonságosan meghatározni egyes alkalmazás modulok maximális verem igényét?
(#) killbill válasza pajti2 hozzászólására (») Hé, 21:06 /
 
A par posttal ezelott emlitett modszer megfelelonek bizonyult. Ha egy processz osszes lehetseges allaoptan atment mar, akkor annal tobb stack nem nagyon kellhet neki. Mivel nem hasznalok nested interrupt-ot, attol sem kell tartanom. Szoval latom, hogy az adott processz mennyi stack-et hasznal, amire rahagyok meg valamennyi biztonsagi tartalekot, es kesz. Nincs MMU, hogy page fault-ot kerjen, ha tulcsordult a stack... Igazabol semmi mas modon nem tudod megoldani, ha nincs HW tamogatasod. Allokalsz annyit, amennyi biztonsaggal elegendo, es remenykedsz, hogy eleg is lesz. Egy C programnal nem lehet elore kiszamolni a stack igenyt. De visszakerdezek. Egy "hagyomanyos" mikrocsipes kornyezetben, ahol azt se nagyon tudja a programozo, hogy egyaltalan hova van beallitva az SP, ott mi garantalja, hogy eleg a stack? Beallitja a RAM vegere, aztan novekszik visszafele, amig ossze nem er a bss-sel vagy a heap-pel (?).
(#) pajti2 válasza killbill hozzászólására (») Hé, 22:16 /
 
És azt az esetet hogyan tudod stabilan érzékelni, hogy a processzek valamennyi lehetséges állapoton átmentek már?

Ha az alkalmazásba nem akarsz preemptive kernelt építeni, nincsen stack szabdalódás, a stack-et csak az alkalmazás egészére méretezed, és akkor akármekkora ráhagyást is követsz el, azt csak egyszer teszed meg. Mondjuk adsz a firmware egészének 10 kbyte-ot a 120 modulra összesen, és azt méricskélés nélkül is tudom, hogy nem fogja átlépni. Viszont ha 120 modulra egyesével akarom odaadni a 10k-t, az egy kicsit ciki lesz.
(#) Wezuv válasza killbill hozzászólására (») 7:47 /
 
Idézet:
„Ugy, hogy egy megszakitas vagy egy masik futo process kuld neki signalt:”

Valószínű, csak fogalmazási zavaraim vannak, de ha egy process vár, akkor nem küldhető "neki" semmi, mert nem tudja ellenőrizni, mert egyik része sem fut. Ezért gondoltam és kérdeztem, hogy a szignálokat bizonyára a kernel dolgozza fel és ha azok rendben vannak, akkor indítja a várakozó processt. A kernelnek viszont tudnia kell, hogy a process mire vár, amit bizonyára a process fog átadni. Valamit nem jól értek?
Köszönöm a példát, maga az eljárás az világos, csak az nem, hogy melyik részhez tartozik (process, kernel)!

A verem alatt a hardveres stack-et értitek, ahová a szubrutin hívások, megszakítások esetén lerakódik a visszatérési cím és egyéb infók? Vagy a közös RAM területet, amit elosztasz a processek között?
(#) killbill válasza pajti2 hozzászólására (») 8:41 /
 
Idézet:
„És azt az esetet hogyan tudod stabilan érzékelni, hogy a processzek valamennyi lehetséges állapoton átmentek már?”
Ha egyszeru a processz, akkor konnyen. Ha nagyon osszetett, akkor sehogy. De azert a stack fogyas nem olyan szelsoseges dolog, hacsak nem hasznalsz rekurziot. A tobbeves tapasztalat szerint 1k stack meg soha semminek nem kellett. En sem mericskelem, csak latom. Ha a sw megy orak ota, csinalt mar mindent, amit csinalnia kell, akkor eleg nagy valoszinuseggel allithatjuk, hogy sokkal tobb stack nem fog nekik kelleni, mint amennyit eddig elhasznaltak. Szoval tenyleg nem ertem, hogy mit akarsz. Van 6-8 processzem, mindegyik kap parszaz byte stack-et es nincs vele semmi baj. Plusz van az exception stack. Es ennek az egvilagon semmi koze nincs ahhoz, hogy preemptiv vagy kooperativ. Pont ugyanugy hasznaljak a stacket.
(#) killbill válasza Wezuv hozzászólására (») 8:50 /
 
Idézet:
„Valószínű, csak fogalmazási zavaraim vannak, de ha egy process vár, akkor nem küldhető "neki" semmi, mert nem tudja ellenőrizni, mert egyik része sem fut.”
Nem ellenoriz a processz semmit. Pont ez a lenyeg, hogy nem az altalad megirt kod (process) csinalja a multitaskot, hanem a kernel. A kernel ellenoriz. Amikor meghivod a varakozast (EventWait() ), akkor abban megmondod a kernelnek, hogy mi(k)re varsz. Az EventWait() es EventPost() fuggvenyek a kernel reszei.
A stack az stack, igen az a stack (verem), ahova a processzor a regisztereket meg egyes processzorokon a visszateresi cimet menteni tudta. Mert pl. az ARM vagy a PIC32 is, ha jol emlekszem, alapbol csak egy regiszterbe teszi bele a visszateresi cimet szubrutin hivasakor, es ha a szubrutin nem hiv tovabbi szubrutint, akkor a vegen csak a regiszterben levo cimre ugrik vissza. Ezzel megsporol ket teljesen felesleges stack muveletet. Ha megis hiv szubrutint, akkor elmenti a stack-be ezt a regisztert.
(#) Wezuv válasza killbill hozzászólására (») 9:15 /
 
Ha új processzt akarsz felvenni, akkor változtatni kell a kernelen, (pl. stack kiosztás beállítása, processz belépési cím, ilyesmi)? Vagy van valamilyen protokoll egy új processz regisztrálására, pl. a processz kér annyi stack-et amennyit jónak gondolsz?
(#) pajti2 válasza killbill hozzászólására (») 11:50 /
 
Idézet:
„Van 6-8 processzem, mindegyik kap parszaz byte stack-et es nincs vele semmi baj. Plusz van az exception stack. Es ennek az egvilagon semmi koze nincs ahhoz, hogy preemptiv vagy kooperativ. Pont ugyanugy hasznaljak a stacket.”

Khm, a stack ugyanolyan használatát ugye te sem gondoltad komolyan? Szerintem egy kernel mag fejlesztés könnyítő eszköz, és erősen a megítélésének az alapja, hogy folyamatos fejlesztési logisztikában végső soron könnyít vagy nehezít rajta.

Kicsit tegyük tisztába a fogalmakat. Itt egy cikk is róla: What are “co-operative” and “pre-emptive” scheduling al...ithms?

Kooperatív kernelnél a vezérlés feladása "önkéntes", és ha jön is valami hw irq, a visszatérés mindig a beszakítási ponthoz tér vissza. Nem tud a verem összegubancolódni a taskok között, éppen azért lehet firmware egészére összefüggő közös stack, amit a C32 fordító önként is be fog állítani neked a teljes fel nem használt ram területére. Külön asm betétek sem kellenek a C programba, lehet homogén a forráskódod.

Preemptive kernelnél alkalmasint nem visszatérés van, hanem átváltás a taskok között erőszakos vezérlés elvétellel, és lévén olyankor a stack a taskok között kajak össze tudna gubancolódni, azért is kell külön verem. A regiszterek mentését is saját asm rutinnal kell csinálnod, a C32 fordító nem fog hozzá támogatást adni - nem tud. Egyesével kell a stack méretet adnod a moduloknak, a forráskódod nem lehet majd homogén C rutinok esetében.

Volt már eset valami japán autógyár vackával, amikor a firmware moduljainak elnézték a stack méretét, egymásra futottak, elkallódott az automata sebességváltó vezérlése, és a kocsi extrában gyorsítani kezdett. 4-en haltak meg.

Jelenleg éppen keresem, van-e a 32-es magokban stack limit regiszter cpu megszakítást generálni, ha a verem éppen túlcsordulna, és nem találom azt az adatlapot, ahol ír róla. Az legalább egy eszköz lehetne a verem használat kitesztelésére máshogyan is, mint hogy egyszer csak misztikus jelenségek kezdenek el történni.
(#) killbill válasza pajti2 hozzászólására (») 13:02 /
 
Az teny, hogy a kooperativ kernelnel a megszakitasok ugyanoda ternek vissza, de a processz valtasok maskepp mukodnek. Egy kooperativ kernel eseten pontosan ugyanugy szukseg van minden processznek kulon stack-re. A processzek stack-je meg kell maradjon akkor is, amikor eppen masik processz fut. Ha csak egy kozos stack lenne, akkor ha az A processz betesz a stack-be 10 byte-ot, aztan atadja vezerlest (egy kernel hivassal) B processznek, aki szinten beletesz 20 byte-ot, aztan visszaadja a vezerlest az A processznek egy ujabb kernel hivassal (es itt a lenyeg, hogy nem returnnel), akkor az A processz altal latott stack megvaltozott, hiszen az SP 20 byte-tal arrebb van, mint amikor meghivta a kernelt. Ezert kell minden processznek sajat stack. Nem veletlen, hogy a processz valtast (context switch) a kernel vegzi, es ez joforman nem all masbol, mint a stack-ek cserelgetesebol. Gondold csak vegig.

A linkelt oldal elmeleti dolgokrol szol, szo nincs benne stack-rol. Amugy meg a fene meg is ette az egeszet, ha a stack pointert C fordito allitja be... A stack hasznaltsagot ugy lehet a legegyszerubben merni, hogy feltoltod a kijelolt stack teruletet egy bizonyos mintazattal, es kesobb megnezed, hogy ebbol mennyi valtozott meg. Ez nem egy 1000%-os megoldas, de sw-bol nem nagyon van mas modszer. Viszont arra tokeletes, hogy lasd, hogy a kodod a valo eletben mennyi stack-et fogyaszt es ez alapjan biztonsaggal tudjal neki stack-et allokalni.
(#) killbill válasza Wezuv hozzászólására (») 13:10 /
 
Az altalam hasznalt kernel, az kb. 30 db C fuggveny meg egy 20 soros assembly rutin, ami a process valtast csinalja. A processzek stack-jeit te allokalod statikusan, es egy kernel hivassal inditod el az uj processzeket. A peldamban lathatod a BZ_ProcSpawn() hivast a ButtonsInit() fuggvenyben. Ennek a hivasnak atadod, a PID-et, ami a Process Identifier, azaz a processz azonosito, atadod, hogy melyik fuggveny legyen a processz es hogy hol van az altalad allokalt stack (vege). Az en kernelemben a PID-ek 0-tol szamozodnak, es egyben a processz prioritasat is meghatarozzak. Komolyabb, nagy kernelekben mint a Linux, ott a pid dinamikusan generalodik, de ott mondjuk egyszerre tobbszaz processz is fut, nalam meg altalaban 10 alatt.
(#) Wezuv válasza killbill hozzászólására (») 13:26 /
 
Nekem tetszik a megoldás, a korlátai ellenére is. A stack egymásra csúszás veszélye elvben megvan, de szerintem is meg lehet határozni a minimum szükségest és azt növelni biztonságosra. Nem valószínű szerintem se, hogy egy program, ami "mindent" megcsinált a tesztek alatt, ami a feladata, egyszer csak többet kérne. A rekurzív függvényhívásokat, gondolom kerülöd, vagy korlátozod...

Viszont nem lehetne egy olyan megoldást használni, ami kidobná a processt, ha túllépné a keretét, majd újra indítaná? A hibát jelezné a kernel és pontosabban lehetne hangolni a méretet. Azért lehet, hogy atomreaktort (és autót) nem vezérelnék ilyen megoldással, de amúgy nem hiszem, hogy túl nagy veszélyt hordozna a megoldás. Egy sima egyszerű program futtatásakor is előfordulhat, hogy a stack túlcsordul és azt is meg kell oldani, akkor is, ha csak 8 mélységű...
A hozzászólás módosítva: 13:33
(#) killbill válasza Wezuv hozzászólására (») 14:04 /
 
Idézet:
„Nekem tetszik a megoldás, a korlátai ellenére is.”
Igazabol a semmihez kepset nincsenek korlatai. Maximum vonzatai mint peldaul a processzenkenti stack. De ezt leszamitva sokkal kenyelmesebb programozasi kornyezetet ad, mint ha neked kellene a feladatok kozott elosztani a processzor idot.
Idézet:
„A rekurzív függvényhívásokat, gondolom kerülöd, vagy korlátozod...”
Igen, a rekurzio ehes fajta, de ha tudom, hogy milyen melysegig fog menni, akkor azert saccolhato a fogyasztasa.
Idézet:
„Viszont nem lehetne egy olyan megoldást használni, ami kidobná a processt, ha túllépné a keretét, majd újra indítaná?”
Ha nincs HW-es tamogatasod (MMU), akkor nem lehet. A PIC16-ban hasznalatos SPLIM regiszter sem ad 100%-os biztonsagot, mert a stack-et a magasszintu nyelvek mint a C, nem csak push utasitassal irjak, hanem indirekt cimzessel is, amikor mondjuk a lokalis valtozokat kell elerni a stack-en.

Viszont a processzt ujbol elinditani felesleges, mert ha egyszer tulcsordult a stack-je, akkor ujbol ez lesz, akkor meg minek.

Sajnos ma mar vindozzal is vezerelnek atomreaktort, ugyhogy en mar epitem a betonbunkert. De a komoly rendszerek eseteben valoban erdekes kerdesek ezek az elore meghatarozhatatlan dolgok. Biztos vannak modszerek, amikkel egy adott program memoriaigenyet lehet szamolni, nem tudom. Nekem vannak sw-eim, amik evek ota mennek es soha nem volt veluk semmi akadas, pedig 24/7-ben mennek ezerszam (pl. EXIT lampak Auszrtaliaban).
Következő: »»   1249 / 1249
Bejelentkezés

Belépés

Hirdetés
Frissek
2017. Feb, 21. Kedd
15:13:09
Jelenleg 523 fő olvassa az oldalt
Online tagok:
Lapoda.hu     XDT.hu     HEStore.hu