23.11.24 02:50 - Ochranny obvod LiPol baterie [3] 09.11.24 12:34 - PCB footprint / landing pattern pr [2] 20.10.24 22:32 - Webové rozhraní k MCU na jednode [9] 02.10.24 10:51 - STM32G431 vlastnosti integrovanéh [7] 29.09.24 13:39 - STM32G031 bez externích součást [10] 26.09.24 14:47 - Spolehlivé logování dat z MCU p [5] 07.09.24 19:00 - CLI pro STM32? [2] 20.08.24 14:35 - Vývoj na jednočipy v Cčku a zá [24] 31.07.24 09:45 - Napajanie modulu z "kolajnic" [38] 23.07.24 21:17 - Predám kalibrátor napätia a pr [3]
Máte nápad, tip, sdělení, zajímavý projekt nebo produkt na zveřejnění, který byste rádi sdíleli s námi na MCU.cz? Dejte nám vědět na media/zavináč/mcu.cz, do soukromé pošty nebo do komentáře.
Dnes jsme pro Vás pitvali digitální osciloskop Tektonix TDS 3032. Jedna se dvoukanálový osciloskop 350MHz se vzorkováním 2,5GS/s s možností bateriového napájení.
K osciloskopu se standardně dodávají dvě sondy P6139A do 500MHz.
Pro výstup z obrazovky či paměti slouží v základu pouze paralelní port nebo 3,5" 1,44MB FDD mechanika, GPIB rozhraní se dodává jako doplňující karta.
Pro příjemnější práci má osciloskop na spodní straně dvě nožičky pro naklonění, bohužel však jen do jedné polohy.
Rameno má aretované polohy
Rozebrání osciloskopu vyžaduje alespoň malou znalost případně delší bádání. Zadní plastový kryt drží pouze jeden šroubek vzadu a na boku je nutné vyndat cele rameno včetně celého aretovacího mechanismu
Po sundání zadního krytu se nám naskytne pohled na vnitřnosti
Zdroj je přišroubován na hlinikovén plechu a obsahuje i obvody nabíjení akumulatoru
Hlavni elektronika je na samostatné osmivrstvém plošném spoji
Vstupní část je kryta plechem, po jeho sejmutí je vidět že plošný spoj je univerzální a je možné ho osadit i pro 4 kanálovou verzi
LCD displej je zasazen do hliníkového rámečku, měnič pro podsvícení je připevněn nad displejem. Samotný displej má rozlišení 640x480 bodů.
Na předním čele se nachází jen tlačítka pro ovládání. Tlačítka okolo displeje mají pružný plošný spoj
Jak klávesnice okolo displeje tak i hlavni klávesnice mají gumová tlačítka
Tlačítka a rotační kodery jsou umístěny na samostatném plošném spoji
Vpravo nahoře jsou vidět konektory pro paměti z doplňujícími (rozuměj placenými) funkcemi
Zadní kryt
V přiloženém archivu jsou obrázky v podstatně lepší kvalitě.
S tými procesormi som nerobil, tak tam by asi bolo potrebné robiť na stacku nejaké hara-kiri, ako uvádzaš.
Otázne je, či by to tam pre riešenie problému prerušenia ktorý tu vysvetľujem, bolo vôbec potrebné.
V každom prípade, tak ako píšem nižšie, pri podobných problémoch a ich riešeniach je treba poznať ten ktorý procesor na úroveň presného fungovania inštrukcií.
Zial knihu o mikroprocesoroch nemam prave po ruke, ze by som si to overil. Ale bol som skalopevne presvedceny, ze aj 8080 ci Z80 uklada na stack nejake registre pri preruseni.
oprava: na 86 se uloží i flags, na 8080 se zakáže přerušení a uloží návratová adresa. (dost ohavně - řadič přerušení musí procesoru podstrčit instrukci RST, ale o tom jsem doteď neměl tušení, to programátor nevidí). Přerušení se musí povolit instrukcí EI a vrací se normálním RET, ale na tohle asi bývalo makro IRET. Andy: O ukládání akumulátoru jsem nic nenašel, ale na Z80 byla instrukce EX AF, AF'. Nefouká větříček odsud?
Z pohledu aplikačního programátora je to na avr|80xx|pic stejné. O zásobník se nestará, při přerušení se uloží návratová adresa, na 80xx se uloží i flags. Při reti|retfie|iret se návratová adresa popne do PC. Při reti|retfie se povolí přerušení nahozením GIE bitu, při iret se popnou flags, čímž se povolí přerušení. Při retfie 1 se navíc obnoví ze stínových registrů. Podstatný rozdíl je v tom, že u avr|pic (harvard) se o naplnění tabulky vektorů stará překladač, kdežto u 80xx (vNeumann) systém. Hnusný je akorát to, že v datasheetu avr jsou vektory pojmenovaný a tají se, kde leží.
Torgeir: Na 8080 sa pri preruseni uklada na zasobnik okrem PC registra aj register A a STATUS register, teda 4 byty. A rozdiel je v tom, ze klasicky ret vytiahne zo stacku len 2 byty, kdezto reti vytiahne tie byty 4. Takze preto treba patricne upravit stack a stack-pointer.
Zdravim, skocim vam do debaty. Je nejaka legislativa, ktora prikazuje mat ochranny obvod (DW01) priamo v placatej lipol baterke (800mAh)? alebo moze byt aj na plosaku zariadenia mimo baterky? Baterka bude sucastou zariadenia pripojena cez maly konektor. Na plosaku bude aj nabijaci obvod (TP4056)
Andy: Trochu sa strácam. GCC prekladá funkcie tak, že na začiatku je v konečnom dôsledku inštrukcia call a na konci je inštrukcia ret. Medzi týmito dvova sa odohrá všetko potrebné a podstatné. Volanie funkcie z funkcie prebieha podľa toho istého princípu.
Pre funkcie volané na základe prerušenia platí to isté, len na konci nie je ret, ale reti. Adresy volaných funkcií z prerušenia sú uložené vo vektore prerušení.
Jediné čo potrebuje je, aby funkcia volaná z prerušenia niekde v sebe volala funkciu (call), ktorá sa ale nekončí ret, ale reti.
Ako by to bolo v prípade 8080 a podobných, prečo by bolo treba manipulovať priamo s údajmi na stacku?
Torgeir: Funguje Ti to na tom AVR bez sahania stacku len preto, lebo INT uklada na stack len navratovu adresu z PC.
Pokial by si zobral iny MCU, napr. na baze 8080 alebo 6800, tak tie ukladaju na stack toho trochu viac a myslim si, ze bez manipulacie stacku sa neobides. To su ale stare procesory.
Z najnovsich 8-bitov, PIC18 uklada vsetky pracovne registre do INT-shadow-registrov a na stack dava tiez len navratovu adresu.
Len predtým stačilo (ATmega) v priebehu vykonania rutiny z prerušenia ručne nastaviť opätovné povolenie toho prerušenia cez príslušný bit, ktorý sa inak sám nahadzoval po ukončení prerušenia a všetko šlo ako malo. Pre rodinu AVR to už neplatí a jediné čo pomôže je vykonať inštrukciu reti. Možno je to bug procesora (ale nenašiel som v errata), možno nie. Je to jedno, lebo som našiel riešenie.
A dávam ho tu do pozornosti každému, kto by na podobný problém narazil.
Horac: áno, NAKED rieši tú istotu, že sa funkcia nezačne nejakým push, ktorý by sa inštrukciou reti() v tele funkcie následne nespároval s nejakým pop.
Andy: Netreba mi nič pošahať na stacku. Ešte to tak
Skrátka tento typ procesora nie je ochotný vyvolať to isté prerušenie, pokiaľ sa od jeho predchádzajúceho volania neuskutoční reti/reti().
Preto v rámci mojej obsluhy prerušenia potrebujem zavolať funkciu (call), ktorá nemá nič iné na starosti, iba sa vrátiť cez inštrukciu reti ani nie ret, aby bolo opätovné vyvolanie od udalosti prerušenia možné.
Samozrejme, že je všetko bezpečne pod kontrolou a principiálne v mojom prípade nemôže prísť k rekurzívnemu zahlteniu procesora.
Torgeir: vypadá to tak, v interrupt.h je spousta maker, které vektor chtějí. A taky spousta balastu pro doxygen, čili se nedivím, že si to radši napíšeš v assembleru.
No ja som to pochopil tak, ze potrebuje real-time task switch managera. Ten musi posahat data na stacku a zavolat standartnu funkciu obsluhy periferie ako by to robil v poll-rezime. a pred tym nez urobi return z funkcie musi opravit data na posahanom stacku. A to na tom AVR nejde asi urobit inak, len cez asm.
Ale sahat na stack je dost nebezpecna hra a asi by som skusil hladat iny sposob ako obabrat ten blokujuci int-kontroler.
V mojom prípade nie. Prekladač chce konkrétny vektor periférie zo zoznamu definovaných vektorov, prislúchajúcich konkrétnej periférii. Inak sa program nepreloží.
Aj mi to príde vcelku logické a neočakával by som opak, keď je pred funkciou "__interrupt " a prekladač pre konkrétny procesor pracuje so zadefinovanou množinou pomenovaných interruptov.
No jo, ale co se myslí tím "Naviac by sa tým obsadila nejaká hw periféria s ISR"? Přece obslužnou rutinu překladač přeloží, i když na ni nenastavím žádný vektor.
A samozrejme použitie tej funkcie v C je veľmi nebezpečné, lebo tu by nejaký prekladač mohol mať báječný nápad, preventívne postrkať na začiatok volania funkcie nejaké push registrov. No po narazení na inline funkciu reti() by sa už príslušné pop nerealizovalo a oheň je na streche.
Našťastie GCC v mojom prípade tak nespravil, no nemusí to byť garantované za hociakých okolností.
Takže žiadne C, ale v tomto prípade čistý asm s jedinou inštrukciou.
void fn_reti(void) { reti(); } ale to stále nič nemení na tom, že reti() je len cez inline asm zapísané v súbore interrupt.h ako
# define reti() __asm__ __volatile__ ("reti" ::)
Akurát, že prekladač C-čkovú funkciu správne preloží ako
void fn_reti(void) {
reti();
be8: 18 95 reti bea: 08 95 ret
a načo mať v programe zbytočnú inštrukciu "ret" na ktorú aj tak nikdy nepríde? To teda radšej ten asembler. Ale ak je potreba písať v "čistom" C-čku, tak proti gustu žiaden dišputát
Znovu upozorňujem, že píšem o konkrétnej rodine procesorov, ktorá je uvedená nižšie.
by síce fungovať mohla, neskúšal som, ale je úplne kontraproduktívna z dôvodov, ktoré píše Praktik. Naviac by sa tým "obsadila" nejaká hw periféria s ISR, ktorú treba naviac obslúžiť a tak či tak je procesorovo závislá a to všetko len preto, aby sa robila "hluchá" práca.
Čo je zložité na samotnom asembleri?
v mojom prípade je to v súbore:
nieco_nieco.S
PUBLIC_FUNCTION(fn_reti)
reti END_FUNC(fn_reti)
vo funkcii ISR(), tam, kde potrebujem povoliť prerušenie v prerušení
praktik: je to prázdná funkce, která by měla končit RETI, jak chtěl Torgeir. Neřeším, k čemu to potřebuje, řeším, že to jde udělat bez assembleru. 8085 a 86 mají i softwarová přerušení, kde se žádná obsluha řadiče konat nemusí a bylo by chybou, kdyby ji překladač vkládal automaticky.Nutno zmínit, že zrovna tohle jsou procesory, které při přerušení pushnou flagy a při IRET je popnou.
Ale ani to nestačí. To přerušení vyvolala nějaké periferie (např UART signalizuje, že přijal znak). Pokud tu periferii neobsloužíte (nepřečtete ten znak z UARTU), to přerušení od perifere tam visí dál a po ukončení ISR se znovu vyvolá stejné přerušení. Takže tu periferii stejně musíte obsloužit (a kde jinde, než v tom přerušení?).
Torgeir: s RETI to není tak jednoduché. U většiny procesorů dělá víc práce než pouhé RET. Většinou obnovuje i flagy, případně další registry, takže musí být v zásobníku i nějakých pár bytů navíc, než pro RET. Ale pro návrat z ISR nestačí jen RETI. Většina procesorů má nějaký více či méně inteligentní řadič přerušení, který se po vyvolání interruptu "zablokuje" a další INT nepřipustí. Zakže tomu řadiči musíte říct, že byl INT obsloužen a může vyvolat případné další přerušení. V řesení od gp to za vás udělá překladač. Pokud chcete použít vlastní rutinu s RETI, tak musíte řadič přerušení obsloužit sám...
Torgeir a gp: a k čemu by vám bylo dobré takové "prázdné" ISR? Přijde interrupt, odskočíte, nic neuděláte a vrátíte se a pokračujete v hlavním programu. Nikde poznámka, že k INT došlo a k jakému. To jste ten interrupt vůbec nemuseli aktivovat...
E-Ryc: Nikto to tu predsa za všeobecnú pravdu nevyhlasuje.
Uvádzam konkrétnu rodinu MCU, kde to funguje. Celý môj príspevok bol o tom, že ak by niekto vo "svojej" rodine MCU na podobné obmedzenie narazil a potreboval by ho obísť, mohol by si preveriť funkčnosť riešenia, ktoré úspešne na konkrétne uvedenej rodine MCU prevádzkujem.
Oficiálny postup doporučovaný výrobcom je používať oficiálne inštrukcie. Ich správanie je presne zadefinované. Je na programátorovi, aby inštrukcie procesora buď iba vlastnými silami alebo za pomoci nejakého prekladača kombinoval tak, aby dosiahol požadovaný výsledok.
Ja se hadat nebudu, pro svoje "projekty" se asemblu uspesne poslednich 20 let vyhybam...
Verim, ze na nekterych (vetsine) platformach to opakovane RETI bezpecne bude, ale asi bych si netroufnul to vydavat za obecnou pravdu (predpokladam, ze to neni "oficialni" postup doporucovany vyrobcem cipu).
Nedo..be A je jedno, aký prekladač je použitý, lebo tá krátka funkcia končiaca sa RETI musí byť napísaná v asembleri. Predpokladám, že žiaden príčetný prekladač to totižto takto ani nemôže preložiť.
Zavolanie z prerušenia "prázdnej" funkcie ukončenej RETI, uloženie žiadnych registrov nespôsobí. A aj keby, návratom z tejto funkcie sa tie registre vždy musia korektne (pri písaní v asm tak "ručne") obnoviť. Z hľadiska návratu hodnoty PC zo zásobníka je jedno, či sa funkcia končí príkazom RET alebo RETI.
Dôležité je, že návrat cez RETI, aktivuje prerušenia.
Z hľadiska hodnôt registrov je jedno, či sa funkcia končí strojovou inštrukciou RET, alebo RETI.
Nemá to žiaden vplyv na push a pop registrov. V mojom prípade sa POP a PUSH robí samostatnými strojovými inštrukciami.
RET a RETI spôsobia iba návrat hodnoty PC zo zásobníka.
Torgeir: radši si ověř jak přerušení u daného MCU pracuje, bo pokud vím tak některé procesory při vstupu do přerušení a jeho ukončení automaticky ukládají a obnovují některé registry. Nesměl bys dané registry používat.
No tak u STM32 (jestli myslis normalni Cortex-ovy jadra) staci zapsat do BASEPRI pozadovanou minimalni prioritu preruseni aby se klidne znova udelalo. N
Sú MCU, ktoré nepovoľujú opakované prerušenie, pokiaľ predchádzajúce nie je ukončené a to ani po resete príznaku daného prerušenia v rutine prerušenia.
Šľak ma ide trafiť nad takým nezmyselným obmedzením. Však viem čo robím, keď potrebujem, aby mi prerušenie pracovalo v kontrolovanej rekurzii. Nemá zmysel polemizovať či to vôbec treba. Áno, je to treba. Občas veľmi.
A v určitých prípadoch to nenahradí ani spustenie ďalšieho IRQ.
Našiel som také riešenie pre MCU typu AVRxxxDBxx. No mohlo by fungovať aj pre STM32xxx
V prerušení treba zavolať funkciu, ktorá nemusí robiť vôbec nič, ale nevráti sa inštrukciou RET, ale inštrukciou RETI. Samozrejme, že funkciu je treba spraviť v asembleri.