[elektro] STM32f4 interrupt : volatile tombok
hg12345
hg12345 at freemail.hu
Wed Dec 11 09:39:42 CET 2013
Nem kipróbálni kell hanem tudni, mivel a C fordító elég nem meghatározott dolog, egy új verziókban lehetnyi eltérés lehet az értelmezésben, ezért az auto cast, (nem) volatile ami nem egyértelmű az optimalizáció értelmezésében változhatnak a verziók szerint!
A volatile nem ATOMIC utasítás generál, azt kell figyelembe venni, a fordítási egységedben optimilázálja változódat, fordító joggal hiheti azt hogy nem változott? Mi van mögötte... egy load/store tipusú processorban van néhány egyenértékű szabadon használható regiszter, az ARM esetében 12db ilyen regisztered van. A uC úgy próbál optimalizálni, hogy minél kevesebb memória művelet legyen, ezek lassúak a belső regiszter eléréshez képest. Vagyis azokat a változókat amiket gyakran használ és nincs kivéve az optimalizáció alól, azokat a függvényen belül program szempontjából átlátszó módon a belső regiszterekben tárolja.
Egy olyan ciklus esetén ami egy más helyen írt változóra vár, ha a függvény meghívása során, egyszer betölti a regiszterbe és utána ezt másolatot használja akkor ez soha nem fog megváltozni. Ennek a változónak volatile módosítót adsz, akkor ez nem történik, meg minden hivatkozás során végig csinálja a standard C beolvasást vagy kiírást....
Egy nagyméretű tömb esetén, ha nem csak egy elemét használod akkor ezt alapból nem tudja megcsinálni a forditó, nincs annyi regisztere :-)
IT! is ugyan olyan program (függvény) mint bármi más a programodban! Nem is kell másképp meghatározni az CORTEX uC-nél. Egyetlen pici különbség van, hogy minden gyengébb pioritású függvény futását a saját futási idejére felfüggeszti, de ezt teljesen láthatatlan módon. (idöben tovább tart). A felfüggesztés miatt kell figyelni a közösen használt adatokra, de ez hasonlóan más fordítási egységben használt közös adatokra is igaz.
Nem értem a megoldást,
Egy részből nehéz megérteni az egészet.
Van három programod és két buffered,hogy kihasználja a programot adatokat azt a dac_buf_state dönti el?
1, töti a buffert (IT)
2, szüri a buffert
3, kiolvassa a buffert(IT)
A két IT beíró és kiíró egy IT kezelés?? Azért egy a program?
Ha már gyorsítani akarsz, akkor index kezelést tedd át int (int32_t) valamivel gyorsabb, mert nem kell konverziót végezni a 32 bites uC-nek. Az ARM mindent 32 biten végez, csak a tárolás lesz a meghatározásnak megfelelő, de ez kiolvasáskor és tároláskor plusz feladat ad uC a váltás. (nem igazán észre vehető a különbség).
Ezzel a megoldással a memóriával se tudsz sprórolni, mert amig ALING 4 a default beállítás minden változót 32 bitre igazitva tárol, ha sporolni kell akkor tedd elé a PACKED módosítót, de gondolom nem kell sporolni a memóriaval
Egyébként nem lehet, hogy a kattogás a szürő inicializálási progbléma, folyamatosan kéne szűrni, és a új buffer átadásakor valami miatt nem folyamatos a szűrés.
Nekem érthetőbb lenne a kezelés három pufferrel (persze már írtam) egy puffeben mindig csak egy program dolgozna (beolvasó, szürő, kiíró) nem kell semmilyen módosító, csak egy kis plusz program ami 3 programnak a buffer strukturákra mutató pointert kiosztja.... Ha ez megvan akkor egy pillanat és át tehető DMA-sra.
Pal Lukacs <ekegep at yahoo.com> írta:
>Szia !
>
>Eloszoris koszi a valaszt !
>
>Igy nez ki:
> struct DAC_BUF
> {
> float32_t left[DAC_BUF_MAX_L];
> float32_t right[DAC_BUF_MAX_R];
> uint16_t index_L;
> uint16_t index_R;
> enum {DAC_BUF_WRT, DAC_BUF_RDY} dac_buf_state ; //writabble, readyabble
> } ;
>
>
>volatile struct DAC_BUF dac_buf_1_inst, dac_buf_2_inst;
>
>
>Ki fogom probalni, hogy nem adok volatile modositot.
>Tudom hogy kikapcsolja az optimalizaciot,..az IT miatt tettem a tomboket es a tobbit volatilere, mert az IT irja, olvassa.
>
>IT-ben:
>
> switch(dac_channel_state)
> {
> case DAC_CH_L:
> dac_channel_state = DAC_CH_R;
> //...adat kivesz
> if( dac_buf_1_inst.dac_buf_state == DAC_BUF_RDY)
> {
> if(dac_buf_1_inst.index_L <= (uint16_t) (DAC_BUF_MAX_L - 1) )
> {
> out_data = dac_buf_1_inst.left[dac_buf_1_inst.index_L++] ;
> }
> else{
> dac_buf_1_inst.dac_buf_state = DAC_BUF_WRT;
> dac_buf_1_inst.index_L = 0;
> dac_buf_1_inst.index_R = 0;
> dac_buf_2_inst.dac_buf_state = DAC_BUF_RDY ;
> }
>
>
>...
>stb.
>
>
>Udv
>Szabi
>
>
>
>
>On Tuesday, December 10, 2013 5:30 PM, hg12345 <hg12345 at freemail.hu> wrote:
>
>Hi,
>
>Ezzel a volatile-vel jól megkevered magadat.
>A volatile a kiveszi az optimalicáióból a felhasznált változó kezelését. (olyan mint ha -O0 fordítanád)
>leginkább HW kezelés megadásánál kell használni, nehogy csak egy részet olvassa vagy írja a változónak, perifériának.
>Illetve olyan változóknál, ahol a fordító nem érzi (látja) hogy a kiértékelés közben az értékét változtatja. Ez esetben csak gyorsítás miatt még a feltétel előtt beolvassa és a feltétel kiértékelése közben már nem.
>(egy külső bitre való várakozás e hiány végtelen ciklust okozhat)
>
>Az IT és a nem it-s program közösen használt változóira, ha egyszerre irhatják... inkább az ATOMIC kezelés a fontos. Ez azt jelenti hogy írás vagy olvasás közben a vezérlés nem vehető el a programtól! Sokan azt hiszik, hogy ez triviális egy globális IT tiltással, de ez ennél tovább mutat. Ezt igazából SW nem megoldható, vagy támogatja a HW vagy nem.
>Az optimalizáció okozhat meglepetéseket fordítás közben, és erre nem mindig a volatile kulcsszó a megoldás. Ha szükséges érdemes utána nézni a __schedule_barrier(),__force_stores(), __memory_change() beépített fordítási utasításoknak, és hasonlóan a ARM belső buffer/cache ürítő utasításoknak. Valószínüleg nem itt kell keresni a problémát.
>
>Esetedben a tömb pointereket kell volatile-ként definiálni (szerintem az is felesleges), de a adattárolás biztos nem. (ha nem használsz optimalizációt, akkor a volatilenek nincs hatása!)
>
>Amit írtál:
>
>volatile struct adc_buf adc_buf_inst1, adc_buf_inst2;
>
>ezt milyen fordító eszi meg?
>struct {
> int adc_buf_inst1; //int és real azonos tárolási terület
> int adc_buf_inst2;
> } adc_buf_t;
>
>adc_buf_t adc[1024];
>
>valami ilyesmire gondoltál? (ha struct elé irod a volatile-t akkor ez teljes elem kezelés nem lesz optimalizálva, ha csak a tag elé akkor az a tag nem lesz optimalizálva)
>ez esetben a feldolgozás lehet pointeres vagy indexes, de a fordító mivel érzékeli, hogy nem ugyan azt írod olvasod a következő feldolgozási ciklusban, minden olvasáskor vagy íráskor új értéket fogadni a változódnak. Nem kell volatile!
>
>
>
>
>
>Pal Lukacs <ekegep at yahoo.com> írta:
>>Sziasztok !
>>
>>HW float szamolja a dolgokat. Ellenorizve, mukodik az FPU.
>>
>>Nem 12 bit, 24 ADC, 16 DAC :)
>>Kimertem a szures idotartamat. ~25ms
>>
>>Ha igy szamolok, hogy 1/48kHz (mintaveteli freki) = ~20us, ez szorozva 1536-al (ennyi a tomb merete) ez kb 32ms. Ebben benne van az is hogy az IT-k kozben hozzak be az adatot, tehat beleszakitanak a szuresbe.
>>Tehat amig megtelik a masik puffer, addig megtortenik a szures is, es meg ido is marad.
>>
>>A szuro algoritmusoknak tomb cime van megadva. (CMSIS DSP library)
>>
>>Kerdes:
>>Van-e hatranya sebesseg szemontjabol annak, hogy a tomb(ok) (left/right) es a hozza tartozo indexek, meg allapotok strukturaban vannak tarolva ?
>>A valtozo deklaralasoknal pedig volatile-t az elotag.
>>
>>Tehat: volatile struct adc_buf adc_buf_inst1, adc_buf_inst2;
>>Igy remelem az egesz valtozo a strukturan belul volatile lesz?
>>
>>Udv.
>>Szabi
>>
>>
>>
>>
>>On Tuesday, December 10, 2013 1:06 PM, hg12345 <hg12345 at freemail.hu> wrote:
>>
>>Hi,
>>
>>az STM32 eleve 32bites (int) rendszer egy beolvasás és egy kiírás 32 biten történik.
>>Ha a lebegö pontos változódat real ként definiáltad, akkor az méretre azonos egy int-tel vagyis ezen nem múlok a sebesség. Ha double ként annak a megfelelő long long ez 2x32bit tárolódik.
>>A pointer (index) számításban lehet különbség, mert több belső ciklust használ el a címzésre, ez elérésben is különbség van, mert két beolvasás (kiírás) kell, de ezt is lehet optimalizálni, ha engedélyezed a blokkos ki és beolvasást, akkor kevesebb utasítás lehívás lesz.
>>
>>Milyen sebességgel veszed a mintákat, képtelenségnek tartom, hogy STM34F4xx uC egy ~40Khz 12bites adatfolyam kiüsse :-(
>>
>>A tömböt érték vagy pointerként adod át ? :-)
>>
>>
>>
>>
>>Pal Lukacs <ekegep at yahoo.com> írta:
>>>Sziasztok !
>>>
>>>Lehet hogy hulye kerdes,...a float adat elerese memoriaban tobb ido mint az int elerese?
>>>
>>>Mert en az adat behozas utan egybol konvertalom (int to float) es ugy irom, olvasom a memoriaba (memoriabol).
>>>
>>>
>>>Udv.
>>>Szabi
>>>
>>>
>>>
>>>
>>>
>>>
>>>On Sunday, December 8, 2013 12:12 PM, Pal Lukacs <ekegep at yahoo.com> wrote:
>>>
>>>Hi!
>>>
>>>Vegulis mindegy milyen hosszu a tomb, ha egy adatot meg tud szurni addig amig jon a masik, akkor barmekkora hosszu tombot meg tud szurni, amig megtelik a masik puffer.
>>>Itt csak azert kellett tomb, mertdecimalni , interpolalni kell, es nem mindegy hogy mekkora hosszu az adatsor.
>>>
>>>
>>>
>>>On Sunday, December 8, 2013 11:04 AM, hg12345 <hg12345 at freemail.hu> wrote:
>>>
>>>Hi
>>>sokkal jobb a ping-pong buffer
>>>1, DMA-val is kezelhető,
>>>2, 1.5K nem memória foglalás
>>>3, a szűrő algoritmus gyári megírt és csak a pointert kell átadni :-)
>>>
>>>De szerintem célszerű lenne 3 fix méretű tömböt lefoglalni a heap-en vagy fixeni, és
>>> ezeket a tömböket cirkulárisan használni... Gondolom a tömb mérete határozza meg a hang késleltetését... A tömb méretét akkorára kell választani, hogy a szűrés tudjon vele végezni míg az következő szűrendő mennyiség beérkezik. (ez a szűk kapacitás, de ha növeli a felhasznált tömbök számát, ez ezen nem tud segíteni, csak a verseny helyzet esetén később fog adatot veszíteni, a folyamatos késlekedés növekedés mellett)
>>>
>>>egyiket tölti a DMA
>>>másokban számol a szürő
>>>harmadikat kiküldi a DMA
>>>
>>>
>>>"Móczik Gábor" <pm_levlista at progzmaster.hu> írta:
>>>>2013.12.07. 18:41 keltezéssel, Arnold Fuzesi írta:
>>>>> Lehet cserelgetni a
>>> buffer kezdocimet is, ugy gyors. Csak a kettos buffereles memoriazabalo, cirkular buffer jobb kihasznalast ad.
>>>>
>>>>Na jó, de jelen esetben mit érsz el buffer cím cserélgetéssel?
>>>>
>>>>Ugyanaz, mintha circular lenne, csak még egy plusz pointert cserélgetsz
>>>>az rd/wr-en kívül, valamint jobban "kvantált" az anyag, csak diszkrét
>>>>buffernyi darabokban férsz hozzá, a circ. bufferben meg tetszőleges
>>>>hosszban, folyamatosan akár.
>>>>
>>>>Doublebuffer olyan esetben lehet jó, amikor nincs annyira ráhatás a
>>>>kiolvasó folyamatra, pl. képernyőn megjelenítés. Ha nem a video drivert
>>>>írod, hanem valami magasabb szintű rétegben vagy, nem tudod mikor fog
>>>>kelleni a kijelzőnek egy adott sornyi pixel, jobb ha egyben odaadod
>>> az
>>>>egész képtartalmat, aztán majd kiírja amikor akarja, te meg a háttérben
>>>>összeállítod a következő képet.
>>>>
>>>>-----------------------------------------
>>>> elektro[-flame|-etc]
>>>>
>>>
>>>-----------------------------------------
>>> elektro[-flame|-etc]
>>>-----------------------------------------
>>> elektro[-flame|-etc]
>>
>>-----------------------------------------
>> elektro[-flame|-etc]
>>-----------------------------------------
>> elektro[-flame|-etc]
>
>-----------------------------------------
> elektro[-flame|-etc]
>-----------------------------------------
> elektro[-flame|-etc]
More information about the Elektro
mailing list