Přerušení v Linuxu

_Jenda

  • ****
  • 433
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #15 kdy: 24. 07. 2020, 19:59:54 »
Blokujici zarizeni se da vytvorit jedine napsanim ovladace konkretni periferie (konkretniho cipu).

Tazatel chce jenom implementovat "user space driver", protoze vyvoj a ladeni je mnohokrat jednodussi. Pokud je srozumen s reakcni dobou / latencema a nevadi to dane aplikaci, tak bych to taky tak preferoval.
Těžko může implementovat jenom "user space driver", když chce funkcionalitu, kterou žádný (?) existující kernel driver nemá.
Podle mě chce mít v user space program, který bude čekat na signál od zařízení (čekáním na interrupt), a když přijde, tak zařízení přečte (pomocí existujícího jaderného SPI).


RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #16 kdy: 24. 07. 2020, 20:15:18 »
SPI i I2C jsou master/slave zbernice, a jinak nez pollingem se s takovyma periferiema neda bavit. Pokud chce zarizeni neco rict, muze trpelive mlcet, az dostane slovo (polling), nebo se ozvat dodatecnym, out of band, signalem - prerusenim, na zaklade cehoz vyvola pozornost mastera aby ho zkontroloval.
Jasne, ale tohle je/bude v jádře, ne v userspace.

Blokujici zarizeni se da vytvorit jedine napsanim ovladace konkretni periferie (konkretniho cipu).

Tazatel chce jenom implementovat "user space driver", protoze vyvoj a ladeni je mnohokrat jednodussi. Pokud je srozumen s reakcni dobou / latencema a nevadi to dane aplikaci, tak bych to taky tak preferoval.
Těžko může implementovat jenom "user space driver", když chce funkcionalitu, kterou žádný (?) existující kernel driver nemá.

Pokud jsi root, tak v userspace si muzes napsat ovladac k cemu chces (klidne vyuzivajici mmap/dma) - samozrejme je tam silne omezeni, ze jedinym uzivatelem daneho zarizeni bude autorova aplikace, protoze to konecne pristupove API bude viditelne jenom pro userspace, vyjma par pripadu, ktere maji udelanej zpetnej tunel do jadra (napr. FUSE).

Treba to preruseni z gpio - viz strana 15:
https://elinux.org/images/c/c8/Userspace-drivers-csimmonds-elce-2018_Chris-Simmonds.pdf
A celkove obsluhu jednoducheho zarizeni lze pak udelat i v bashi.

Psat ovladac do jadra ma smysl jedine kdyby to zarizeni spadalo do existujicich trid zarizeni, ke kteremu existuje standardni linuxove API (napr. typu framebuffer, disk, komunikacni port, atd) a prave zarizeni, ktere je unikatni ze nic takoveho v jadre neni, se hodi spis na psani userspace driveru.

Typicky priklad pouzivajici userspace drivery - flashrom (kazdy model SPI flashky se implementuje trocha jinak) a taky je zpusob jejich pripojeni velice variabilni.

Re:Přerušení v Linuxu
« Odpověď #17 kdy: 24. 07. 2020, 20:24:56 »
Psat ovladac do jadra ma smysl jedine kdyby to zarizeni spadalo do existujicich trid zarizeni, ke kteremu existuje standardni linuxove API.
Já jsem dotaz pochopil tak, že to je přesně ten případ. V kernelu už základ SPI je, chci si tam jenom dodělat ten mechanismus probuzení userlandu.

RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #18 kdy: 24. 07. 2020, 20:34:21 »
Psat ovladac do jadra ma smysl jedine kdyby to zarizeni spadalo do existujicich trid zarizeni, ke kteremu existuje standardni linuxove API.
Já jsem dotaz pochopil tak, že to je přesně ten případ. V kernelu už základ SPI je, chci si tam jenom dodělat ten mechanismus probuzení userlandu.

To co je v jadre neni zadnej "zaklad" SPI, ale plnohodnotny SPI driver. SPI je zbernice a nemuze resit kazdou periferii - stejne jako mas treba PCI, PCIe, atd. Ovladace PCI karet taky nejsou rozsirenim zakladu PCI driveru... jenom ho vyuzivaji jako jednu z komunikacnich cest.

Tazatel ale nenapsal co je to za periferii, takze se nechme prekvapit.

Btw pokud by na RPI nebo jinou platformu chtel psat ovladac ktery vyuziva spi/int z kernelu, tak spravna cesta by byla sparovanim onoho driveru na patricny SPI port a GPIO / interrupt skrze device tree, a to neni uplne vec pro zacatecnika.

Re:Přerušení v Linuxu
« Odpověď #19 kdy: 24. 07. 2020, 21:38:01 »
jenom ho vyuzivaji jako jednu z komunikacnich cest.
No dyt.


Re:Přerušení v Linuxu
« Odpověď #20 kdy: 26. 07. 2020, 08:54:46 »
Např. pokud by původní problém byl v tom, že nějaký hardware pomocí SPI pushuje hodnoty v nepravidelných intervalech a on na ně chce reagovat (soft)realtime, tak nepotřebuje žádné interrupty, bohatě mu stačí blokující znakové zařízení...

SPI i I2C jsou master/slave zbernice, a jinak nez pollingem se s takovyma periferiema neda bavit. Pokud chce zarizeni neco rict, muze trpelive mlcet, az dostane slovo (polling), nebo se ozvat dodatecnym, out of band, signalem - prerusenim, na zaklade cehoz vyvola pozornost mastera aby ho zkontroloval.

Blokujici zarizeni se da vytvorit jedine napsanim ovladace konkretni periferie (konkretniho cipu).

Tazatel chce jenom implementovat "user space driver", protoze vyvoj a ladeni je mnohokrat jednodussi. Pokud je srozumen s reakcni dobou / latencema a nevadi to dane aplikaci, tak bych to taky tak preferoval.

Joahaa! konečně chápu zadání, díky...

Treba to preruseni z gpio - viz strana 15:
https://elinux.org/images/c/c8/Userspace-drivers-csimmonds-elce-2018_Chris-Simmonds.pdf
A celkove obsluhu jednoducheho zarizeni lze pak udelat i v bashi.

Strana 15 nedořekla jedno sladké tajemství: poll() je třeba volat na pseudosoubor "value" v tomtéž adresáři.
A k tomu terminologická vysvětlivka: syscall poll() nedělá hloupé olizování, ale čeká na událost (aneb hlavně že jsme zmátli nepřítele.)

Trochu jsem se začetl, tady jsou k tomu nějaké další střípky:

https://www.kernel.org/doc/Documentation/gpio/sysfs.txt
(hledejte klíčové slovo "edge")

https://blog.frantovo.cz/c/355/GPIO%20v%C2%A0Raspberry%20Pi%20jako%20soubory

https://www.raspberrypi.org/forums/viewtopic.php?t=7509

...a jenom velmi na okraj (popravdě tam o IRQ není vlastně nic):

https://www.ics.com/blog/gpio-programming-using-sysfs-interface

Takže správný postup by měl být, použít standardní SPI API pro SPI komunikaci a GPIO API pro čekání na interrupt.

Chápu to tak, že kernel musí obsahovat obecné GPIO API a specifický ovladač nebo nějaký definiční soubor (v rámci device tree?) pro RPi, takže ví, jak IRQ nakonfigurovat a když přijde, tak ho umí taky třeba ACKnout, což bych z user space dělal asi dost těžko... prostě ten interrupt se na nejnižší úrovni musí obsloužit a ACKnout v kernelu (aby se nezacyklil) a pokud tato podpora v kernelu existuje, tak user space dostane už jenom výslednou relativně nezáludnou událost. BTW, asi chápu, proč jsou ty GPIO interrupty edge-triggered (nikoli level-triggered).

RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #21 kdy: 26. 07. 2020, 09:55:32 »
Takže správný postup by měl být, použít standardní SPI API pro SPI komunikaci a GPIO API pro čekání na interrupt.
Bingo!

Kdyby to chtel psat in-kernel jak by to rad Mirek, tak se z toho patlani spravneho DT s interruptem zblazni:
https://blog.stabel.family/raspberry-pi-4-device-tree/

Chápu to tak, že kernel musí obsahovat obecné GPIO API a specifický ovladač nebo nějaký definiční soubor (v rámci device tree?) pro RPi, takže ví, jak IRQ nakonfigurovat a když přijde, tak ho umí taky třeba ACKnout, což bych z user space dělal asi dost těžko...

Tak nejak.. delat polling interrupt flagu a acknout ho z userspace jde, pokud mate privilegia na pristup na dane adresy (mmio) nebo io porty, ale v ramci moderniho OS nemate sanci nastavit vektor preruseni, i kdyz vite kam ho zapsat, tohle musi resit kernel - protoze ten jedinej ma persistentni virtualni adresy (v x86 cs selektor).

Pred GPIO interruptem existoval navrh na IRQ API, kde v kernelu je kratky handler a jinak to funguje znova skrze poll():

https://lwn.net/Articles/127698/  (stejny zpusob pouziti, skrze poll)


Re:Přerušení v Linuxu
« Odpověď #22 kdy: 26. 07. 2020, 10:04:41 »
Kdyby to chtel psat in-kernel jak by to rad Mirek
Já jenom dodám, že o tom prakticky nic nevím, takže jenom čistě laicky mi přišlo, že když mám v kernelu připravený základ, je snazší nad ním napsat nějaký tenký wrapper a vyexportovat si jednoduché jednoúčelové zařízení, se kterým už pak práce v userlandu bude triviální.

Spíš jsem se ptal, proč by se to tak udělat nemělo, rozhodně jsem se s tebou o to nechtěl hádat, na to jsem fakt v téhle oblasti úplný laik :)

RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #23 kdy: 26. 07. 2020, 10:10:58 »
Kdyby to chtel psat in-kernel jak by to rad Mirek
Já jenom dodám, že o tom prakticky nic nevím, takže jenom čistě laicky mi přišlo, že když mám v kernelu připravený základ, je snazší nad ním napsat nějaký tenký wrapper a vyexportovat si jednoduché jednoúčelové zařízení, se kterým už pak práce v userlandu bude triviální.

Spíš jsem se ptal, proč by se to tak udělat nemělo, rozhodně jsem se s tebou o to nechtěl hádat, na to jsem fakt v téhle oblasti úplný laik :)

Si to jednou zkus - problem neni napsat kod - ten udelas treba jednou (pokud jsi sikovnej a neudelas tam moc chyb), ale pak pro kazde zarizeni kde to bezi (rekneme RPi, Beaglebone, a ruzna cina) musis vytvorit ty upravy DT - coz je softwarova analogie k toho jak si ty dratky v hw pripojil.

Na tyhle jednoduchy veci nefunguje plug & play (to se nahrazuje tim DT) a kdyz se podivas na situaci kde PnP funguje (USB) a presto se voli psani userspace driveru (skrze libusb,libhid) - musi ti byt jasne ze psat neco v userspace je omnoho jednodussi. Muzes si volit jazyk, chyby ti nezpusobi pad OS, muzes resit veci interaktivne. Snad tohle postaci..

Re:Přerušení v Linuxu
« Odpověď #24 kdy: 26. 07. 2020, 10:17:07 »
Si to jednou zkus - problem neni napsat kod - ten udelas treba jednou (pokud jsi sikovnej a neudelas tam moc chyb), ale pak pro kazde zarizeni kde to bezi (rekneme RPi, Beaglebone, a ruzna cina) musis vytvorit ty upravy DT - coz je softwarova analogie k toho jak si ty dratky v hw pripojil.
DT trochu znám, před nějakýma cca dvěma lety jsem s ním musel cosi řešit v Buildrootu s custom kernelem.

Na tyhle jednoduchy veci nefunguje plug & play (to se nahrazuje tim DT) a kdyz se podivas na situaci kde PnP funguje (USB) a presto se voli psani userspace driveru (skrze libusb,libhid) - musi ti byt jasne ze psat neco v userspace je omnoho jednodussi. Muzes si volit jazyk, chyby ti nezpusobi pad OS, muzes resit veci interaktivne. Snad tohle postaci..
Tohle mi nepřijde jako pádná argumentace ze dvou důvodů:
1. předpokládám, že tazatel to chce pro jedno zařízení a jednu desku, že to je nějaký custom projekt
2. důvody, proč se různé věci dělají spíš v userspace, můžou být úplně jiné a v daném případě neplatné

Takže tohle mě moc nepřesvědčilo. Kdybys řekl "věř mi, mám to vyzkoušené, tohle je lepší cesta", mělo by to pro mě (od tebe) větší váhu :)

RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #25 kdy: 26. 07. 2020, 10:30:50 »
Takže tohle mě moc nepřesvědčilo. Kdybys řekl "věř mi, mám to vyzkoušené, tohle je lepší cesta", mělo by to pro mě (od tebe) větší váhu :)

Ale ony neexistuji univerzalni duvody proc se neco musi prave tak a ne jinak - nastesti v Linuxu a OSS obecne mame moznost volby, jak veci delat ruznymi zpusoby

Jeden duvod, se kterym jsme se setkali u psani nasich ovladacu pro V4L2 - ze kernel-space je dost nestabilni co se API tyce, takze pokud chces udrzovat svuj driver v kernelu, musis tomu venovat omnoho vice casu. Ale zrovna u V4L2 se tomu neda vyhnout a driver musi byt v kernelu.

S kazdou verzi kernelu je sance, ze se ti tvuj driver rozbije, a musis sledovat kam ten vyvoj speje - treba i co se tyce zpusobu reseni preruseni - tech zpusobu jak preruseni obslouzit je snad pet ruznych (od jednoduchych callbacku, po kernel thready ktere usinaj do pristiho preruseni)

Re:Přerušení v Linuxu
« Odpověď #26 kdy: 26. 07. 2020, 21:22:53 »
Chápu to tak, že kernel musí obsahovat obecné GPIO API a specifický ovladač nebo nějaký definiční soubor (v rámci device tree?) pro RPi, takže ví, jak IRQ nakonfigurovat a když přijde, tak ho umí taky třeba ACKnout, což bych z user space dělal asi dost těžko...

Tak nejak.. delat polling interrupt flagu a acknout ho z userspace jde, pokud mate privilegia na pristup na dane adresy (mmio) nebo io porty, ale v ramci moderniho OS nemate sanci nastavit vektor preruseni, i kdyz vite kam ho zapsat, tohle musi resit kernel - protoze ten jedinej ma persistentni virtualni adresy (v x86 cs selektor).

Pred GPIO interruptem existoval navrh na IRQ API, kde v kernelu je kratky handler a jinak to funguje znova skrze poll():

https://lwn.net/Articles/127698/  (stejny zpusob pouziti, skrze poll)

Díky za ten odkaz... moc hezké čtení, v podstatě to shrnuje všechny moje námitky :-)

User space chápu jako prostor, který je od hardwaru naschvál poněkud izolován, běží nad nějakou abstrakcí stroje s jednotným softwarovým rozhraním. User space je prostředí relativně lenivé, pokud se týče doby odezvy a její garance, ale na druhou stranu nijak děsivé pro programátora - a v zájmu stability systému toho user space zas tak moc nesmí.

ACKování IRQ je věc, kterou se patří dělat v "IRQ kontextu", což je z hlediska plánování procesů/tasků atd. poměrně vyjímečné místo s výsadními právy, zejména vysokou prioritou běhu, např. tam může být zakázáno další přerušení (nebo lze znovu rekurzivně přerušit jen IRQ linkou o vyšší prioritě). Pointa je v tom, že kromě ACKnutí interruptu standardním způsobem hostitelovu řadiči přerušení (tzn. charakteristicky pro danou platformu počítače) mívají jednotlivé periferie svá vlastní pravidla, jak je třeba v dané periferii HW-specificky zašťourat, aby (v kontextu naší debaty) dočasně zmlkla, tzn. aby po návratu obsluhy přerušení (ISR) nebyla obsluha volána okamžitě znovu toutéž periferií. Viz level-triggered IRQ na PCI, tam se snad ani nic "genericky" neACKuje. Druhá varianta je, že pokud IRQ řádně neACKnete HW-specifickým způsobem, periferie už nikdy další interrupt nepošle (toho bych se bál u edge-triggered IRQ) - ale tato varianta je obecně snad méně časově kritická, a zrovna tenhle druh ACKu by se dal odložit do nějaké té "obsluhy druhé úrovně" (ACK je proveden nějakým relativně standardním = řádně plánovaným taskem, v kernelu nebo i v user space).

Chci říct, že ISR kontext a user space jsou dost protichůdná prostředí. ISR kontext má přednost i před kernelovými tasky. Naopak mít v user space zakázané interrupty? Z toho mám trochu husí kůži... Plánovač procesů potřebuje povolené interrupty ke svému provozu. Nemám teď úplně jasno, jak "drahý" je odskok do normální kernelové obsluhy IRQ, vs. co by znamenalo, mít obsluhu navíc v adresním režimu user space (jestli by ten context switch byl nutně těžkotonážnější).

V tom historickém kontextu na LWN se správně píše, že se věc komplikuje u sdílených IRQ linek, a že ohledně zmíněného HW-specifického ACKování v samotné periferii byl i nějaký návrh, toto pro jednodušší případy popsat nějakým structem, který by se dal předat při inicializaci user-mode driveru z user space do kernelu, a generická obsluha (ISR) v první linii v kernelu by podle tohoto "receptu" provedla základní držhubný ACK, aby se interrupt mohl odblokovat (například pro další  periferie sdílející tutéž linku). Pokud mohu soudit, neujalo se to...

Tzn. request_irq(IRQ,*obsluha) podle mého patří právem do kernelu, v user space bych se tohoto nedožadoval :-) Mimochodem v kernelu request_irq() nezapisuje přímo do tabulky vektorů, se kterou pracuje CPU LAPIC - kernel má jednotnou super-obsluhu, která se zavěsí na všechna IRQ obsluhovaná LAPICem, a teprve tahle superobsluha volá obslužné rutiny (callbacky) registrované jednotlivými drivery (kernelovými moduly). Je to pravda už hodně dávno, co jsem to ve zdrojákách našel - snad se na tom moc nezměnilo :-) Dovedu si představit, že tahle superobsluha umí čítat počty interruptů (pokud to nedělá hardware LAPICu) a mám pocit, že přímo tahle superobsluha umí po ukončení "užitečné" obsluhy taky zavolat plánovač, tzn. v tom případě není pravda, že je plánovač probouzen pouze konkrétním časovačem (a procesy, které se procesoru dobrovolně vzdají tím, že usnou/zablokují se).

Hergot to jsem zase ujel...

jfila

Re:Přerušení v Linuxu
« Odpověď #27 kdy: 31. 07. 2020, 19:18:22 »
Děkuji za rozsáhlou diskuzi, chtěl jsem využít to co už v jádru je, ovladač SPI i obsluhu přerušení. Jak diskutující popsali,  údržba a ladění jaderného ovladače mě připadá příliš kanónovrabcově. Ale pokud bych pokračoval, tak bych to možná udělal. Podobně to má udělaný například ovladač pro CAN SPI řadič. Ale zatím se snažím pouze o userspace.

RDa

  • *****
  • 989
    • Zobrazit profil
    • E-mail
Re:Přerušení v Linuxu
« Odpověď #28 kdy: 31. 07. 2020, 19:45:24 »
Jaky cip/zarizeni to je, co se snazis obslouzit?

jfila

Re:Přerušení v Linuxu
« Odpověď #29 kdy: 31. 07. 2020, 20:27:00 »
Začal jsem tlakoměrem  a vlhkoměrem. Teď bych třeba RFID po SPI.