Fórum témák
» Több friss téma |
Idézet: „// megjött az 5 karakter, esetleg ellenőrzöd?” A HAL_OK-nak nincs köze a vett karakterszámhoz. Ezt a HAL_UART_RxCpltCallback függvénnyel lehet megoldani és egy segédváltozóval, ami a main-ben lekérdezhető. MX példákban megtalálható.
Tudsz egy ilyen példát linkelni.. Köszi előre is.
G0-t használok, de gondolom itt is így van. Egyszerű, ha belenézel az stm32xx_hal_uart.c fájlba. A HAL_UART_IRQHandler meghívja a callback-et, ha beérkezett a megadott darabszám. __weak-ként van definiálva a függvény, beírod a programba:
Közben én is megcsináltam és kipróbáltam, jól működik.
Köszi, már régebben is nézegettem ezt a rutint, de nem értettem pontosan mire is való.
Srácok egy bonyolultabb kérdéssel fordulok hozzátok.
Nem is száz, hogy le tudom írni, de igyekezni fogok. Készítek egy elektromos kerékpárra egy fedélzeti kijelzőt, amely hivatott az aktuális sebességet is mutatni. Az eredeti kínai kijelzővezérlés bedöglött és emiatt meg kellett néznem hogy működik a sebesség mérése. Lényegében a motor egy fázisát beereszti egy osztón keresztül a mikrokontroller egyik lábára, feltételezem, hogy egy timert vagy megszakítást használva a motor impulzusainak számolására és megadva a kerék egy fordulatának hosszát ki tudja számolni a sebességet. Igazából ezen a részen túl vagyok és beállítva egy timer-t külső órajeles módra, majd számolva az impulzusokat ki tudom számolni az aktuális sebességet, de sajna kicsi felbontással. És most a lényeg: Egy kollégám említette, hogy elvileg képes lehet az STM32 mikrokontroller, egy úgynevezett GATED módban való működésre, amely adja a lehetőséget, hogy valahogy kapuzni lehessen a bejövő jeleket és ezzel megmérni a két beérkezett impulzus közt eltelt időt. Ennek meglétével pedig egy viszonylag pontosabb és nagyobb felbontás érhető el, amelyből persze pontosabb sebesség számítható. A kérdés az, hogy van e már itt valaki, aki használt valamilyen hasonló feladatban ilyen beállításokat és hogy miképpen tudom én ezt megvalósítani, ha egyáltalán lehetséges. Most ilyen ráncigálós kis modult használok a próbálgatáshoz, melyben egy STM32F103C8 található. A végleges munkát majd egy 407-es fogja végezni. A bicikli sebesség tartományát, hogy könnyebb legyen 0-100km/h-ra állítanám. (Ha nem felel meg az előosztás esetleg, akkor a sebesség függvényében lehetne azt is állítgatni.) Előre is köszi a segítséget. A hozzászólás módosítva: Júl 19, 2019
Úgy fest ez egy nem túl népszerű beállítás, de úgy néz ki sikerült beállítanom amit akartam, kár, hogy közben megmértem a motorból érkező jelet és kiderült, hogy valami nagyon nem úgy van ahogyan az én képzeltem. (de ez már más kérdés lesz)
Viszont felmerült két kérdése bennem: 1, ha kapuzni akarok egy timer-t, akkor annak mindenképp lesz egy kimenete? 2, nem vagyok biztos benne, hogy jól számolom az időzítést mikor a timer elő és utóosztásait állítom ezért, ha valaki megtenné, hogy leírná nekem a számolás menetét azt megköszönném. Én így számolok stm32f103c8-nál.: 1/7200000 == 13.8nS (0.000000013888) Ha mondjuk akarok egy 500mS-os timer beállítást, akkor így számolnék: 500000/13.88 == 36023 Tehát ha jól számoltam, akkor 1000-es előosztással, 36023szor kell a timer-nek számolnia, hogy pontosan 500mS-onként csorduljon túl. Jól számolok? Azért kérdezem, mert PIC esetében volt egy FOSC/4, itt nincs ilyen?
1, Ezt nem értem. A feladatból nekem az input capture funkció jön le, ahhoz pedig bemenet kell.
2, Több órajel konfiguráció is létezik. A lényeg, hogy a TIM1 az APB2 a többi pedig az APB1 x2 órákhoz vannak kötve. Ha nem kapcsoltál be valamilyen egyéb osztót a timer-ed konfigurációjánál, akkor nagyjából jól számoltál. Azért írom, hogy nagyjából, mert egy gyors áttekintéssel kiderül a 36023-nak kb. semmi értelme és a helytelen kerekítés okozza. A helyes érték a szép kerek 36000 lesz (0,5 * 72 * 10^6 / 10^3 = 36 * 10^3). Egyébként nem olyan ritka beállítás, amit csinálsz. Én pl. IR távirányító jelét dolgozom fel ilyen input capture-al.
Sziasztok!
Fejlesztgeteg egy saját könyvtárat amit lehető legkisebb protolgatással egyik kontrollerről a másikra lehet vinni. Jelenleg épp STM32-re csinálgatom a (UART) könyvtárat és olyan problémám van, ha fut az RTOS a háttérben akkor az UART átküld 2-3 byte-ot majd hardfault-al meghal a kontroller. A könyvtár szálvédett és IT védett ebbe most ha nem muszáj nem keresném a hibát, mert nem itt van a probléma szerintem. A probléma ott történik mikor az UARTn_IRQHandler-e meghívásra kerül és én elkezdem lekérdezgetni az status és az IT engedélyező biteket. Ezeket függvényekkel teszem. A példa kedvéért vegyük azt a függvényt ahol a hiba van
Ahol a _PERIPHERAL_INLINE egy inline __attribute__((optimize(xx))-nek felel meg és ezzel kérdezem le a TXE flag-et a Driver layer-en (az hogy a reg base addr miért így van csinálva az most nem részletezném) és ezzel működik szépen. Viszont, ha én még hozzá rakom, hogy __attribute__((always_inline)) és a globális optimalizáció O0-ra van belőve akkor jön a hardfault, ha viszont átrakom a globális optimalizációt O0-nál nagyobbra megint megy szépen. És ezek csak RTOS meglétekor igazak (a könyvtár tud RTOS-al és RTOS nélküls is futni) nélküle megy minden szépen. Valaki látott már ilyet létezik rá valami magyarázat, hogy miért érdekli az it-t hogy én optimalizációtól függetlenül ezt az egy sort mindig inline szeretném látni? Vagy ez esetleg a fordítónál hasal el? Egy másik kérdés IT-re vonatkozóan a kód szépsége miatt gondoltam csinálok egy táblát ami Callback-et tud tárolni (mbed-es Callback-ből származik az implementációja, tehát nem csak egy pointert tárol) viszont ez, hogy elérje az IT kezelő függvényt a Driver-en belül 1 hívás helyett tesz 3-4 hívást ettől kell féljek? (mert láttam valahol egy doksit ahol két IT közötti váltásnál (tail chaining asszem) spórolnak 12 vagy 6 ciklust (nem tudom pontosan), ha ott volt értelme nem tudom mekkora hiba az előző metodika)
A hardfault-ot kellene kielemezni, hogy mi is történik ott pontosan. Könnyen lehet, hogy valami alattomos dolog van a háttérben (pl. rossz megszakítás prioritás szint és belenyúl a megszakításba a scheduler, kifutsz a stack-ból ha bele kell fordítani a függvényhivást, stb.).
Itt egy kis kód, amit én bele szoktam biggyeszteni a programjaimba (annak idején a saját RTOS-omhoz írtam, bár azóta átálltam FreeRTOS-ra).
A stack frame itt egy Cortex-M4F-es maghoz készült. Értelemszerűen módosítani kell a struktúrát ha máson használod. A változóban elérhető lesz a hiba fellépésekor érvényes regiszter értékek, ennek segítségével jobban behatárolható mi is történt.
Upsz, pici javítás. Az _usageFaultHandler-t nevezd át UsageFault_Handler-re. A _hardFaultHandler-t pedig HardFault_Handler-re.
A helyzet az, hogy én sem értem pontosan, talán itt van a nagy gond.
Lényegében úgy gondoltam, hogy egy timer számlálóját kívülről egy impulzussal lehetett volna inkrementálgatni. Gondoltam, hogy a motor egy fázisáról levett szál, minden mágnes elhaladásánál generál egy impulzust és ez adta volna gyakorlatilag a timer-nek az órajelet. Aztán egy másik timer-t meg úgy állítottam volna be, hogy az előző timer két kívülről kapott impulzusa közt eltelt időt mérte volna. Ebből meg már kiszámoltam volna a sebességet, egyéb adatok tudatában. Mind ezt a hardver intézte volna, valamilyen kapuzással. Ami viszont most szembe jött velem teljesen felborította ezt az elképzelésemet, mert megmértem a motorból érkező jelet a vissza fejtett kapcsolás alapján egy logikai analizátorral és kikapcsolt állapotban a csatolt jelet mutatja, amit nagyon nem értek. És itt a kérdés is, melyik topikban tudnak nekem ebben segíteni, hogy megfejtsük miféle jel jön a motorból és hogy miért... Illetve az órajeles témánál pedig minden perifériának a maximumot állítom, semmit nem osztok külön le. Elvileg 72MHz-van ott ahol annyi tud lenni. A hozzászólás módosítva: Júl 20, 2019
Túlgondoltad. Egy db timerrel megoldható a dolog. Simán be kell állítani a timer-t a kívánt precizitásra. Ezután input capture módban érzékelni kell a jel fel/le futását (igény szerint), megszakítás generálásával. A megszakításban ki kell olvasni a timer aktuális értékét, majd az előző érték-ből és az újból kiszámítható az eltelt idő. Tovább finomítható a kód a túlcsordulás megszakítás használatával (hosszabb idők is mérhetőek).
Nézegettem a mérési eredményeid. Elég nagy zagyvaságnak tűnik. Persze elég kis mintavételezéssel vetted fel, nem tud többet a tied? Az én saleae-m akár 500Ms/s-t is bír.
A megszakítást akartam kihagyni vagy is csak ritkára venni, hogy a főprogramom minél kevesebbszer legyen félbeszakítva. Ezért csak a timer és a kapuzás, valahogy..
Tudna többel is venni az analizátor, de próbáltam nagyobb mintavétellel is, nem volt jobb a jelalak, ez meg így könnyen feltölthető. Könnyebben tudom mutatni, egy 100-200MB-os fájlt nehezebb mozgatni. Csatoltam egy 7MB-os mentést. Ebben az alap látható az első részében, majd egy gázfröccs, és aztán elengedem a gázt. Ez is elég zagyva, egyszerűen nem értem, hogy ez egy kommunikáció vagy csak egy valamilyen random jel. Arra gondoltam, hogy nem e a FET-ek kapcsolgatásának a zaját mutatja az analizátor. A hozzászólás módosítva: Júl 20, 2019
DMA-val kikerülheted a megszakítást. Akkor a DMA vezérlő fogja kiírni a mért eredményt a kívánt memóriaterületre (vagy pl. körkörös pufferbe).
Az a baj a mostani adatokkal, hogy sok impulzus hossza pontosan megegyezik a mintavételezés frekvenciájával, azaz nehéz eldönteni, hogy most zajt látunk vagy jelet.
Csinálok egy 24Megásat. Azt hiszem ez a legtöbb ennél a kicsi analizátornál.
Köszi!
pont CM4F-et használok. Meg is néztem, nem annyira ismerem az ARM-ok lelki világát még nem rég álltam át PIC32-ről. De ez mennyire egészséges, hogy a hardfault-ban a kiolvasott pc értéke 10?
Hmm, nem igazán normális.
Első körben ellenőrizd, hogy a stack frame pointere értelmes helyre mutat-e (nehogy az legyen, hogy vmit kavart a fordítód). Ha igen, akkor nézd meg, hogy mi van a link registerben. Nézd meg vele, hogy milyen utasításból kerültél oda, ahol most vagy. Ha az is hülyeség, akkor lehet, hogy valahogy sérült egy task kontextusa (tárolt regiszter értékek). Ezt a hibát okozhatja stack túlcsordulás (egy task beleír a mögötte tárolt task területére, mert kevés a neki allokált terület). Ha a fejlesztőkörnyezeted és az RTOS-od támogatja, érdemes lenne bekapcsolnod a stack figyelést. Ilyenkor pl Atollic-nál látható mennyi szabad területe van a különböző task-oknak. A másik lehetőség, hogy rosszul állítottál be egy megszakítás szintet. Ez azért fontos, mert ha az ütemező megszakítás megszakít egy másik megszakítást ( ![]()
Itt egy minta két task közti váltásra a saját RTOS-omból. A scheduler beállítja az új stack pointert (meg még csinál pár apróságot, de az most nem számít). A lényeg, hogy látszik, ahogy beleírja az aktuális stack végére a regiszter állapotokat (ez a kód CM3-as), majd ütemezés után az új task korábban mentett regisztereit helyreállítja. És tippem szerint nálad valami itt borul.
A stack méret nem hiszem, hogy problémás lenne 128k van heap-nek belőve a FreeRTOS config-ba és a task ~10k memóriával jön létre az tény hogy a FreeRTOS fölött van egy saját C++ layer ami több memóriát eszik, de 10k egy uart-os driver nem tud megzabálni (a küldött adat egy Hello World char tömbben raktam globálisra raktam a while fölé, hogy a task-ba pakolja így is úgy is hibát okozott).
A stack túlcsordulós dologgal szórakoztunk az egyetemen, hogy van eset mikor az RTOS még "elkapja" és van amikor instant hardfault, de az előbbiek miatt nem tartom lényegesnek. Na az utóbbi pont már sokkal inkább azzal pont úgy voltam nem piszkálom (még a preemtion és a sub priority kicsit zavaros, hogy most melyik mi célt szolgál) a priority-it egyszer feljebb toltam de nem néztem mekkora a scheduler prioritása ezt kipróbálom be rakom legnagyobb prioritásra aztán meglátom. A második válaszod lehet választ is ad miért csak RTOS alatt okoz problémát a dolog. Még a volatile-ra gyanakodtam, de nem igazán hozott semmit (kb be raktam mindenhova), de az alap gondolat miatt mivel szimultán úgy sincsen írás mivel vagy az it tudja írni a változót/változókat vagy az adott listába fűző uarta-ra író függvény (közben az uart it kikapcsolva)
Ez valami fordítási hiba lesz szerintem.
Állítottam a prioritást max-ra akkor is meg volt a hiba. Na mondom akkor jöjjön a global interrupt tiltás engedélyezés. Ez sem működött majd ki vettem az UART-os függvények elöl az always_inline-t és akkor is dobta a hardfault-ot viszont most az interrupt kezelő miatt. A Interrupt:: Disable függvény nem inline (kikapcsolja a globalt megnézni hogy az engedélyezve van-e az it ki kapcsolja majd vissza tér az it bekapcsolt vagy kikapcsolt értékével) az Interrupt::Restore sem inline (megnézi az előzőleg visszaadott értéket és be kapcsolja vagy kikapcsolja az it-t) viszont az itt hívott Peripheral::Interrupt:: Disable/Enable (mások mint az előbb említett függvények csak a register set/clear-t írják emberileg olvasható nyelvre) is always_inline-al van ellátva és az is hibát okoz... Szerintem elengedem ezt az optimalizációs mániát berakom simán inline-ra aztán döntse el a fordító mit akar vele csinálni. A hozzászólás módosítva: Júl 21, 2019
Nem olyan bonyolult a group priority, sub priority kérdése. A magasabb group priority-s megszakítás megszakíthatja az alacsonyabbal rendelkező megszakítás futását. Az azonosak, illetve alacsonyabbak értelemszerűen nem. A sub priority csak azt dönti el, ha több megszakítás is aktiválódott, melyik fog először végrehajtódni (de a group priority ugyanaz, az a fontosabb).
Biztos van olyan helyzet, ahol a sub priority-vel játszadozás hasznos, de én nem szoktam használni. A scheduler prioritását ne piszkáld. A saját megszakításaidnál pedig ne használd a legmagasabb és legalacsonyabb prioritásokat.
Én is úgy láttam, hogy többsége a sub-priority nem használt, csak még sok bennem a PIC32-es logika ott meg hangsúlyos a sub-priority is
Persze az utolsó részt én is tartani szoktam csak akkor használok legmagasabb prioritást, ha valami nagyon nagyon kritikus (pl tápot figyeltem ADC-vel és ennek a komparátor IT-je legmagasabbra volt állítva, hogy "biztos" át tudja kapcsolni az áramkört akkura). De jelen esetben még a fából vaskarika megy úgyhogy mindent lehet és próbálom a library-t f...-ognak is ki tenni, hogy lássam min csúszik el->mit kell át írjak. Fejlemény, viszont nem a fordítás okozza a galibát, hanem a Callback amit nem teljesen értek miért. (publikussá tettem a handlert és be vágtam direkte az IT-be, láss csodát a hiba megszűnt) A működése pár szóban (elég sarkosan): Van fent tartva hely adott class pointer-ének és függvényének és a callback számára egy belső pointer amin keresztül ezeket típussal együtt meg tudja hívni (mert amúgy a Callback nem tudja milyen típusra hivatkozik, csak a függvény típusát ismeri). Ha az IT-ben a Callback-et direkt meghívom és ebben always_inline függvény van akkor HardFault ha viszont a callback-ben tárolt mutatókat kimásolom egy memória területre majd én castolom típusosra akkor jól működik.
Na várjunk csak. Te inline-os függvényt hívtál meg pointerként hivatkozva? Az egyértelmű programozói hiba és kb. semmi értelme.
Nem nem, a pointeren keresztül hívott függvény (ami az interruptHandler-re mutat és az interruptHandler nem inline függvény) hív meg egy always_inline-os függvényt, ha csak simán inline (a belülről meghívott függvény) nincs vele baj vagy ha az optimalizáció be van kapcsolva akkor sem okoz gondot, csak az okozza a gondot ha O0-ban akarok always_inline függvényt meghívni.
Csatti2: volt pár pillanatod rá pillantani a 24MHz-es mintavételű jelsorozatra?
Lehet neked többet mond mind nekem, talán egy kicsit szebb a struktúrája, de nekem nem sokat mond így sem.. Köszi.. A hozzászólás módosítva: Júl 21, 2019
Hát ez elég furcsa. Szemmel látható, hogy jóval sűrűbb középen, gondolom ott gyorsítottál rá.
Milyen motort használsz? Pontosan mit is mérsz és hogyan?
Nézd meg a generált assembly kódot. Valami furcsaság lesz ott.
Mxus 3K turbo.
Az egyik fázisa közvetlen van kivezetve és az megy bele a kijelzővezérlőbe. A kijelző vezérlőn full gáznál a teljes akkumulátor feszültségének 50%-a jelenik meg, a motor amúgy 84v-ról jár, tehát ha tele van az aksi, akkor full gázadásnál 42v jön be azon az egy fázison. Ezt műszerrel mértem. Ez a benő jel egy egyenirányító diódával meg van fogva, és mögötte pedig egy tranzisztorral és néhány ellenállás segítségével minden impulzusnál 3.3v-ot enged a mikrokontroller lábára. Kvázi egy szintillesztő. És az eredményt meg már te is láttad. A felvett adatok a következőt mutatják: Az első 1/3 időben csak az álló motornál kapott jelek látszanak, majd a 2/3-nál húztam egy kis gázt, majd a 3/3-ban ismét az alap állapotot mutatja. A hozzászólás módosítva: Júl 21, 2019
Szóval egy BLDC motor egyik fázisát figyeled. Álló helyzetben rögzíti a kereket a motorvezérlő? Tud fékezéskor visszatölteni?
Megtaláltam aliexpress-en ezt a motort. Két szett Hall szenzor kimenete is van ha jól értettem. Miért nem használod egyszerűen az egyik Hall kimenetet inkább. |
Bejelentkezés
Hirdetés |