This shows you the differences between two versions of the page.
so2:teme:tema2 [2017/03/22 22:03] adrian.stanciu [Detalii de implementare] |
so2:teme:tema2 [2020/03/29 21:18] (current) constantin.ghioc [Resurse] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Tema 2 - Driver UART ====== | ====== Tema 2 - Driver UART ====== | ||
- | Termen de predare: Marți, 12 Aprilie 2016, ora 23:00 | + | * Termen de predare: **Sâmbătă, 12 Aprilie 2020, ora 23:00** |
Line 18: | Line 18: | ||
Să se scrie un modul de kernel care să implementeze un driver pentru portul serial (''UART16550''). Device driver-ul trebuie să suporte cele două porturi seriale standard dintr-un PC, ''COM1'' şi ''COM2'' (''0x3f8'' și ''0x2f8'', de fapt întreg range-ul de ''8'' adrese ''0x3f8-0x3ff'' și ''0x2f8-0x2ff'' specific celor două porturi). În afară de rutinele standard care trebuie implementate (''open'', ''read'', ''write'', ''close''), driver-ul trebuie să aibă suport și pentru schimbarea parametrilor de comunicație cu ajutorul unei operaţii ''ioctl'' (''UART16550_IOCTL_SET_LINE''). | Să se scrie un modul de kernel care să implementeze un driver pentru portul serial (''UART16550''). Device driver-ul trebuie să suporte cele două porturi seriale standard dintr-un PC, ''COM1'' şi ''COM2'' (''0x3f8'' și ''0x2f8'', de fapt întreg range-ul de ''8'' adrese ''0x3f8-0x3ff'' și ''0x2f8-0x2ff'' specific celor două porturi). În afară de rutinele standard care trebuie implementate (''open'', ''read'', ''write'', ''close''), driver-ul trebuie să aibă suport și pentru schimbarea parametrilor de comunicație cu ajutorul unei operaţii ''ioctl'' (''UART16550_IOCTL_SET_LINE''). | ||
- | Driverul trebuie să folosească înteruperi atât pentru recepție cât și pentru transmisie, pentru a reduce latența și timpul de utilizare a procesorului. De asemenea, apelurile ''read'' și ''write'' trebuie să fie blocante. Temele care nu respectă aceste cerințe nu se iau în considerare. Este indicat să folosiţi în cadrul driver-ului un buffer de citire și un buffer de scriere pentru fiecare port serial. | + | Driverul trebuie să folosească înteruperi atât pentru recepție cât și pentru transmisie, pentru a reduce latența și timpul de utilizare a procesorului. De asemenea, apelurile ''read'' și ''write'' trebuie să fie blocante. <html><span style="color:red;">Temele care nu respectă aceste cerințe nu se iau în considerare.</span></html> Este indicat să folosiţi în cadrul driver-ului un buffer de citire și un buffer de scriere pentru fiecare port serial. |
Un apel read blocant înseamnă că rutina de read apelată din user-space se va bloca până la citirea a **cel puţin** un octet (buffer-ul de read din kernel este gol și nu se pot citi date). Un apel write blocant înseamnă că rutina de write apelată din user-space se va bloca până la scrierea a **cel puţin** un octet (buffer-ul de write din kernel este plin și nu se pot scrie date). | Un apel read blocant înseamnă că rutina de read apelată din user-space se va bloca până la citirea a **cel puţin** un octet (buffer-ul de read din kernel este gol și nu se pot citi date). Un apel write blocant înseamnă că rutina de write apelată din user-space se va bloca până la scrierea a **cel puţin** un octet (buffer-ul de write din kernel este plin și nu se pot scrie date). | ||
Line 29: | Line 29: | ||
Transferul de date între diversele buffere reprezintă o problemă de tipul [[http://en.wikipedia.org/wiki/Producer-consumer_problem| Producător-Consumator]]. Exemple: | Transferul de date între diversele buffere reprezintă o problemă de tipul [[http://en.wikipedia.org/wiki/Producer-consumer_problem| Producător-Consumator]]. Exemple: | ||
- | *dacă se scrie dintr-un proces în dispozitiv, procesul este producător și dispozitivul consumator; procesul se va bloca până există loc în buffer-ul consumatorului; | + | *dacă se scrie dintr-un proces în dispozitiv, procesul este producător și dispozitivul consumator; procesul se va bloca până există cel puțin un loc liber în buffer-ul consumatorului; |
*dacă se citește dintr-un proces de la dispozitiv, procesul este consumator și dispozitivul producător; procesul se va bloca până există cel puțin un element în buffer-ul producătorului. | *dacă se citește dintr-un proces de la dispozitiv, procesul este consumator și dispozitivul producător; procesul se va bloca până există cel puțin un element în buffer-ul producătorului. | ||
==== Detalii de implementare ==== | ==== Detalii de implementare ==== | ||
Line 44: | Line 44: | ||
*numărul întreruperii asociate cu COM1 este 4 (''IRQ_COM1''), iar numărul întreruperii asociate cu COM2 este 3 (''IRQ_COM2'') | *numărul întreruperii asociate cu COM1 este 4 (''IRQ_COM1''), iar numărul întreruperii asociate cu COM2 este 3 (''IRQ_COM2'') | ||
*[[http://elf.cs.pub.ro/so2/res/teme/uart16550.h| header-ul]] cu definițiile necesare pentru operațiile speciale; | *[[http://elf.cs.pub.ro/so2/res/teme/uart16550.h| header-ul]] cu definițiile necesare pentru operațiile speciale; | ||
- | *un punct de pornire în implementarea rutinelor de read/write este [[http://elf.cs.pub.ro/so2/wiki/_media/laboratoare/lab04/exmodullincase.zip| exemplul]] de character device driver de conversie upper-case; singura diferență este că trebuie să folosiți două buffere, unul pentru read și altul pentru write; | + | *un punct de pornire în implementarea rutinelor de read/write este [[http://elf.cs.pub.ro/so2/res/teme/case.zip| exemplul]] de character device driver de conversie uppercase/lowercase; singura diferență este că trebuie să folosiți două buffere, unul pentru read și altul pentru write; |
+ | *puteți folosi [[http://lwn.net/Articles/347619/|kfifo]] pentru buffere; | ||
*pentru citirea/scrierea datelor din/în porturi nu trebuie să folosiți funcții amânabile (puteți să faceți totul din întrerupere); | *pentru citirea/scrierea datelor din/în porturi nu trebuie să folosiți funcții amânabile (puteți să faceți totul din întrerupere); | ||
*va trebui să sincronizați rutinele de read/write cu rutina de tratare a întreruperii pentru ca rutinele să fie blocante; este recomandat să folosiți [[http://ocw.cs.pub.ro/courses/so2/laboratoare/lab04?&#sincronizare_-_cozi_de_asteptare|sincronizare cu cozi de așteptare]]; | *va trebui să sincronizați rutinele de read/write cu rutina de tratare a întreruperii pentru ca rutinele să fie blocante; este recomandat să folosiți [[http://ocw.cs.pub.ro/courses/so2/laboratoare/lab04?&#sincronizare_-_cozi_de_asteptare|sincronizare cu cozi de așteptare]]; | ||
Line 51: | Line 52: | ||
*pentru a-l dezactiva trebuie recompilat kernel-ul, fie punând driver-ul ''serial'' ca modul, fie dezactivându-l cu totul (pe mașina virtuală este deja făcuta această modificare); | *pentru a-l dezactiva trebuie recompilat kernel-ul, fie punând driver-ul ''serial'' ca modul, fie dezactivându-l cu totul (pe mașina virtuală este deja făcuta această modificare); | ||
*''Device Drivers --> Character devices --> Serial driver --> 8250/16550 and compatible serial support''. | *''Device Drivers --> Character devices --> Serial driver --> 8250/16550 and compatible serial support''. | ||
- | *puteți folosi [[http://lwn.net/Articles/347619/|kfifo]] pentru buffere. | + | |
===== Testare ===== | ===== Testare ===== | ||
- | Pentru simplificarea procesului de corectare a temelor, dar și pentru a reduce greșelile temelor trimise, corectarea temelor se va face automat cu ajutorul unor [[http://elf.cs.pub.ro/so2/res/teme/2-uart.zip|teste publice]]. Indicații despre utilizarea suitei de teste se găsesc în fișierul ''README'' din cadrul arhivei. | + | Pentru simplificarea procesului de corectare a temelor, dar și pentru a reduce greșelile temelor trimise, corectarea temelor se va face automat cu ajutorul testelor publice care se găsesc în noua infrastructură. Pentru testarea locală, folosiți următoarele comenzi: |
+ | |||
+ | <code> | ||
+ | $ git clone https://github.com/linux-kernel-labs/linux.git | ||
+ | $ cd linux/tools/labs | ||
+ | $ LABS=assignments/2-uart make skels | ||
+ | # dezvoltarea temei se va efectua în directorul 2-uart/ | ||
+ | $ make build | ||
+ | $ make copy | ||
+ | $ make boot | ||
+ | </code> | ||
+ | |||
+ | Indicații despre utilizarea suitei de teste se găsesc în fișierul ''README'' din cadrul arhivei. | ||
==== Sfaturi ==== | ==== Sfaturi ==== | ||
Line 78: | Line 91: | ||
==== Depunctări ==== | ==== Depunctări ==== | ||
- | Depunctările generale pentru teme se găsesc pe pagina de [[so2:teme:general| Indicații generale]]. În plus, se vor avea în vedere următoarele elemente: | + | Depunctările generale pentru teme se găsesc pe pagina de [[so2:teme:general| Indicații generale]]. |
- | *-0.3 utilizare incorectă a device-ului | + | |
- | *-0.1 lock și posibilitate de pierdere unlock | + | |
- | *-0.1 down și posibilitate de pierdere up | + | |
- | *-0.1 disable și posibilitate de pierdere enable | + | |
- | *-0.1 utilizare funcții necorespunzătoare la niveluri IRQ | + | |
Line 99: | Line 107: | ||
*documentație despre portul serial găsiți pe [[http://retired.beyondlogic.org/serial/serial.htm | beyondlogic]] sau pe [[ http://tldp.org/HOWTO/Serial-HOWTO-19.html | tldp]] | *documentație despre portul serial găsiți pe [[http://retired.beyondlogic.org/serial/serial.htm | beyondlogic]] sau pe [[ http://tldp.org/HOWTO/Serial-HOWTO-19.html | tldp]] | ||
*[[ http://www.byterunner.com/16550.html | tabela cu registre]] | *[[ http://www.byterunner.com/16550.html | tabela cu registre]] | ||
- | *[[ http://www.ti.com/lit/ds/symlink/pc16550d.pdf | datasheet 16550]] | + | *[[ https://pdf1.alldatasheet.com/datasheet-pdf/view/9301/NSC/PC16550D.html | datasheet 16550]] |
*[[ http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming | documentaţie alternativă]] | *[[ http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming | documentaţie alternativă]] | ||