Table of Contents

Tema 2 - GPS Tracker (2024)

Obiective:

  • construirea unei distribuții Linux minimaliste;
  • configurări de bază Linux;
  • servicii de sistem Linux;
  • dezvoltare aplicații IoT;
  • utilizare interfață serială (UART/TTY) pe Linux;
  • optimizări de spațiu;

Pentru a rezolva tema, este recomandat să folosiți mașina virtuală SI 2024 cu toate uneltele necesare gata instalate!

Enunț

Dorim să realizăm firmware-ul pentru un dispozitiv IoT de monitorizare GPS (emulat printr-un script Python) folosind un Raspberry PI (de asemenea, emulat folosind qemu).

Pe scurt, va trebui să realizați o imagine incorporabilă cu Linux ce va implementa o aplicație de achiziție a datelor de la un senzor GPS conectat printr-o interfață UART (protocolul textual NMEA pentru GPS, detalii mai jos) și expune pe rețea un server HTTP cu o pagină web de vizualizare a datelor capturate.

Exemplu de frontend web (aspectul nu contează, dar puteți să faceți ceva drăguț dacă aveți timp/chef):

Cerințe

Imaginea Linux de bază:

Pas inițial: realizarea unei imagini de bază de Linux (kernel + rootfs) ce va fi folosită ca punct de plecare / suport pentru programele & serviciile cerute de restul cerințelor:

Sistemul trebuie să conțină următoarele configurații de bază (ne ajută pe noi, în special, să automatizăm partea de testare):

Rezolvarea acestei cerințe este OBLIGATORIE pentru obținerea oricărui fel de punctaj (altfel nu avem ce testa ⇒ 0p)!

Inb4: veți avea de customizat rootfs-ul. După cum va trebui să separați fișierele / codul / scripturile sursă de imaginea binară obținută ca rezultat al procesului de build (care poate fi semi-manual sau complet automatizat – ce preferați), recomandăm organizarea unui overlay – subdirector al temei unde includeți DOAR fișierele de configurație / surse ce doriți să apară în imaginea finală ce le vor suprascrie pe cele implicite.

Pentru rootfs-ul construite prin tehnică de package-based bootstrapping, puteți copia ulterior acest overlay folosind cp -ar sau rsync -a.

Pentru BuildRoot, citiți recomandările oficiale de customizare (folosiți OVERLAY, e cel mai ușor + elegant).

+ citiți enunțul până la capăt pentru a vedea cerințele finale!

Compilare Kernel

Avertisment / important: din păcate, kernel-ul de la raspberrypi/linux NU ESTE PREA COMPATIBIL CU qemu! Deci evitați (vedeți mai jos, folosiți mainline-ul lui Torvalds)!

Recomandăm folosirea kernelului mainline, descărcabil de pe https://kernel.org/ (sau Github, torvalds/linux). NU LUAȚI MASTER-ul sau alte branch-uri experimentale! Folosiți un branch/tag de versiune (e.g., v6.12).

La configurarea kernelului, va trebui să setați parametrul LOCALVERSION la valoarea -si-<prenume.nume> (folosiți username-ul de pe Moodle în loc de placeholderl <prenume.nume>, e.g. -si-florin.stoian!). Vedeți aici variabilele implicate, TLDR: nu uitați să dezactivați LOCALVERSION_AUTO pentru a putea set versiunea voastră custom!

Au fost testate versiunile v6.12 și v6.6, compilate atât automat prin buildroot (însă se configurează mai special, vedeți mai jos), cât și manual. Așadar, aveți două opțiuni de compilare:

Pentru o testare rapidă a sistemului rădăcină, puteți folosi imaginea vmlinuz-test inclusă în scheletul de temă în scheletul de temă (atenție: nu a fost testată pe distribuții Debian cu systemd!).

1. Compilare manuală

Pur și simplu se descarcă codul sursă torvalds/linux de pe git (ori din GitHub release, arhivă .tar.gz mult mai mică) și să dă make ca în laborator (nu uitați să modificați LOCALVERSION!)!

NU uitați ARCH=arm64 și configurația inițială a arhitecturii, defconfig (pe mainline NU există bcm27*_defconfig)!

Pentru a a nu avea probleme cu copierea/instalarea modulelor externe (e.g.: mmc, să nu vadă rootfs-ul, sau să nu se încarce automat driverul de rețea usb-net), recomandăm dezactivarea modulelor de kernel, adică MODULES=n din menuconfig – acest lucru va face integrarea tuturor driverelor în imaginea de kernel și va omite copierea lor pe sistemul rădăcină (în <rootfs>/lib/modules).

2. Compilare automată prin Buildroot

Pentru cei care folosesc buildroot, aveți opțiunea de a compila kernelul Linux (în menuconfig, aveți BR2_LINUX_KERNEL cu toate opțiunile de descărcare necesare).

Însă procesul de adaptare a configurației de kernel necesită pași + documentare suplimentară (still pretty much recommended!):

Precizări comune la compilarea kernelului

Deși e prezent în defconfig (în caz că vreți să optimizați), nu uitați să includeți driver-ul pentru dispozitivul serial ce emulează dispozitivul GPS, model FTDI FT232H.

În final, la rularea prin qemu, trebuie să folosiți device tree-ul care începe cu bcm2837-, deoarece rulați kernel-ul mainline. Vedeți explicația aici sau aici. DTB-ul îl puteți compila voi (din kernel: make dtbs, sau, la Buildroot, aveți setare în meniu) sau prelua din altă parte (cât timp funcționează).

Dacă nu vedeți nimic la bootarea kernelului, înseamnă că ori e imaginea proastă (și este dificil de dat seama). Asigurați-vă că aveți parametrii kernel de earlycon corecți pentru varianta de Raspberry PI emulată. Dacă vedeți mesaje inițiale în consolă, însă se blochează, atunci înseamnă că parametrul console= al kernelului este incorect (încercați alt dispozitiv serial).

Dacă aveți probleme cu kernelul și/sau nu rulează corect în qemu, atunci puteți omite / include un kernel pre-compilat, însă cu depunctare (-10p). Însă va trebuin să scrieți în README ce ați încercat și ce rezultate ați avut!

HTTP Server / Web UI:

Dorim ca sistemul să expună un server HTTP pe portul 80 o interfață web minimalistă care să prezinte, în timp real, datele de la GPS primite (lat/long + dată/timp) prin UART:

* Sistemul va trebui să ruleze un server http ce va asculta pe portul 80;

Serverul trebuie să pornească automat la boot (ca daemon). Majoritatea distribuțiilor folosesc systemd ca init și manager de servicii, deci va trebui să creați un astfel de descriptor pentru aplicația web.

În BuildRoot și Yocto aveți mai multe opțiuni de init system-uri, la alegere: Busybox (cel mai light dintre toate, se scriu scripturi sh), SysVInit (aka rc.d/runlevels) sau SystemD (mai popular și bine documentat, însă trebuie compilat și poate adăuga ~1-2h în plus la timpul de compilare, depinde de puterea de calcul a sistemului).

Pentru Buildroot, dacă folosiți un interpretor / limbaj care necesită dependințe externe, citiți secțiunea Adding Packages. Pentru Python aveți incluse deja o mulțime de biblioteci populare. Pentru Golang, citiți secțiunea Infrastructure for Go packages a manualului. În general, pentru cei care doresc să folosească un limbaj compilat, este util ghidul general de generare a pachetelor compilate pentru build system-ul lui standard.

Datele de la GPS le veți prelua de la un alt serviciu, descris în subsecțiune următoare. Dacă nu doriți să rezolvați acel task, puteți să prezentați pur și simplu câteva date de test (i.e. hardcodate) în interfața Web.

GPS data acquisition daemon:

Pe lângă serviciul web, va trebui să dezvoltați un daemon de achiziție a datelor de pe un dispozitiv serial (emulat prin QEmu ca usb-serial model FTDI FT232H, vizibil în guest Linux ca /dev/ttyUSB0);

<hint> Fiind serială emulată, baud rate-ul configurat nu contează! (merge aproape orice e standard).

Instalați picocom în imagine pentru depanare facilă!</hint>

Format date GPS

Dispozitivul serial emulat va trimite informații codificate în ASCII folosind standardul NMEA, câte o linie per tip citire, un mesaj fiind terminat prin secvența newline CRLF (i.e. \r\n).

Exemplu date:

$GPGGA,115357.00,4419.000,N,02636.013,E,1,12,0.92,15.2,M,32.5,M,,*69
$GPGSA,A,3,25,24,07,17,03,01,27,14,30,26,29,12,1.56,0.92,1.25*00
$GPGSV,4,1,15,08,04,320,58,29,00,328,47,06,67,141,51,11,66,056,66*7D
$GPGSV,4,2,15,01,48,001,68,07,85,075,16,30,69,342,59,17,40,340,16*71
$GPGSV,4,3,15,03,62,124,05,14,04,320,40,25,44,340,66,12,46,287,06*71
$GPGSV,4,4,15,26,35,180,68,24,46,202,49,27,90,060,36*4E
$GPGLL,4419.000,N,02636.013,E,115357.000,A,A*56
$GPRMC,115357.000,A,4419.000,N,02636.013,E,10.500,90.0,151224,,,A*6D
$GPHDT,90.0,T*0C
$GPVTG,90.0,T,,M,10.5,N,19.4,K*51
$GPZDA,115357.000,15,12,2024,0,0*51

Va trebui să filtrați aceste date (e.g., să extrageți coordonatele GPS și data/timpul și să le convertiți într-un format prezentabil în interfața web).

Vedeți aici un tutorial al formatului NMEA 0183. Este suficient să parsați/preluați doar tipurile GGA (latitudine/longitudine) și ZDA (dată + timp UTC), însă ar fi nice to have și informațiile despre viteză / vector de deplasare.

Pentru testare, veți porni manual script-ul ce generează astfel de date în paralel cu qemu!

Este recomandat să faceți parsarea liniilor tolarabilă la erori (e.g., să nu crape daemon-ul când primesc un fragment parțial al unui senzor, doar să îl ignore), altfel riscați să fiți depunctați dacă se ajunge la vreun race condition!

Instrucțiuni pentru rularea imaginii folosind QEmu

Ca și punct de pornire, puteți descărca un schelet inițial cu scripturi + structură recomandată (v0.1). Aceasta conține:

Trimitere

Deoarece Moodle nu acceptă dimensiuni foarte mari, soluția temei va fi împărțită și trimisă în două moduri (vă rugăm să respectați convențiile de denumire cu exactitate!):

Arhiva cu binarele (.tar.*z pls; se acceptă gz și xz) trebuie să conțină (obligatoriu: să folosiți strict aceste denumiri de fișiere):

Pe Sharepoint, dați link CĂTRE FIȘIERUL ARHIVEI, NU CĂTRE UN ÎNTREG DIRECTOR!

Noi avem scripturi care automatizează descărcarea, veți fi depunctați dacă nu urmați aceste convenții! Ar trebui să meargă descărcate automat punând &download=1 la finalul URL-ului ;)

Arhiva cu fișierele sursă (.zip pls) OBLIGATORIU să conțină:

Puteți folosi Makefile-ul din scheletul temei pentru generarea acestor două arhive, însă este recomandată verificarea manuală a arhivelor după generare!

Nu vor fi punctate temele care nu au hash-ul SHA256 al arhivei încărcat pe Moodle sau cele al căror hash nu corespunde cu arhiva downloadată de pe platforma de hosting la momentul corectării (este folosit și pentru a verifica upload / modificări apărute după deadline)!

Notare

Din 100p total, aveți:

Bonus:

Imaginile care nu au au fost construite personal sau nu rulează deloc (cu excepția unor greșeli minore) nu vor fi punctate!

Precizări

Resurse