Tema 2 - Driver UART

  • Termen de predare: Sâmbătă, 12 Aprilie 2020, ora 23:00

Scopul temei

  • consolidarea noțiunii de device driver
  • citire documentație hardware și urmărirea funcționalității dorite în documentație
  • lucrul cu întreruperi; folosire de funcții neblocante în context întrerupere
  • folosirea buffer-elor; sincronizare
  • module cu parametri

Enunț

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.

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).

Schemă buffer-e

Transferul de date între diversele buffere reprezintă o problemă de tipul 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ă 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.

Detalii de implementare

  • driverul va fi implementat ca un modul de kernel cu numele uart16550.ko
  • driverul va fi accesat ca un device driver de tip caracter, cu funcționări diferite în funcție de parametrii transmiși modulului la încărcare:
    • parametrul major va specifica majorul cu care trebuie înregistrat dispozitivul;
    • parametrul option va specifica modul de funcționare:
      • OPTION_BOTH: va înregistra și COM1 și COM2, cu majorul dat de parametrul major și minorii 0 (pentru COM1) și 1 (pentru COM2);
      • OPTION_COM1: va înregistra doar COM1, cu majorul major și minorul 0;
      • OPTION_COM2: va înregistra doar COM2, cu majorul major și minorul 1;
    • pentru a afla cum se pot pasa parametri în Linux, consultați tldp
    • valorile implicite sunt major=42 și option=OPTION_BOTH.
  • numărul întreruperii asociate cu COM1 este 4 (IRQ_COM1), iar numărul întreruperii asociate cu COM2 este 3 (IRQ_COM2)
  • header-ul cu definițiile necesare pentru operațiile speciale;
  • un punct de pornire în implementarea rutinelor de read/write este 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 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);
  • 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 sincronizare cu cozi de așteptare;
  • pentru ca tema să poată funcționa este nevoie ca driver-ul serial implicit să fie dezactivat:
    • cat /proc/ioports | grep serial va detecta prezența driver-ului implicit pe regiunile unde sunt definite COM1 și COM2;
    • 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.

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 testelor publice care se găsesc în noua infrastructură. Pentru testarea locală, folosiți următoarele comenzi:

$ 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

Indicații despre utilizarea suitei de teste se găsesc în fișierul README din cadrul arhivei.

Sfaturi

Pentru a vă mări șansele de a obține nota maximă, citiți și respectați coding style-ul kernelului Linux descris din documentul Coding Style.

De asemenea, folosiți următoarele tool-uri de analiza statică pentru a verifica codul:

checkpatch.pl

  •  /path/to/linux-4.9.11/scripts/checkpatch.pl --no-tree --terse -f /path/to/your/src-file.c 

sparse

  •  sudo apt-get install sparse 
  •  cd /path/to/linux-4.9.11 
     make C=2 /path/to/your/src-file.c 

cppcheck

  •  sudo apt-get install cppcheck 
  •  cppcheck /path/to/your/src-file.c 

Depunctări

Depunctările generale pentru teme se găsesc pe pagina de Indicații generale.

În cazuri excepționale (tema trece testele prin nerespectarea cerințelor) și în cazul în care tema nu trece toate testele se poate scădea mai mult decât este menționat mai sus.

Submitere

Arhiva temei va fi submisă pe vmchecker, în conformitate cu precizările din pagina de reguli.

Din interfața vmchecker alegeți opțiunea Driver UART, aferentă acestei teme.

Resurse

Resursele temei se găsesc și în repo-ul so2-assignments de pe GitHub. Repo-ul conține și un script Bash care vă ajută să vă creați un repository privat pe instanța de GitLab a facultății. Urmăriți indicațiile din README și de pe pagina de Wiki dedicată pentru git.

Întrebări

Pentru întrebări legate de temă puteți consulta arhivele listei de discuții sau puteți trimite un e-mail (trebuie să fiți înregistrați). Vă rugăm să urmăriți și să respectați indicațiile de utilizare a listei.

Înainte să puneți o întrebare verificați că:

  • ați citit bine enunțul temei
  • nu este deja prezentată întrebarea pe pagina de FAQ
  • nu se poate găsi răspunsul în arhivele listei de discuții
so2/teme/tema2.txt · Last modified: 2020/03/29 21:18 by constantin.ghioc
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0