Cílová skupina: Tato příručka je určena pro architekty firmwaru, vedoucí ODM inženýrů a programové manažery OEM, kteří chtějí pochopit, jak je náš firmware čtecího pera vrstvený, aby jej mohli přenést na nový SoC, vyměnit dodavatele snímače nebo auditovat přenositelnost jimi kupované kódové základny. Předpokládáme, že jste obeznámeni s jazykem C, koncepty embedded RTOS a základními datasheety SoC.
Den, kdy se kupující zeptá „můžeme přesměrovat váš firmware na jiný OID snímač?“ nebo „můžeme to přepracovat pro Rockchip SoC místo Allwinner?“, je dnem, kdy je architektura firmwaru prověřena. Pokud jsou ovladače smotané s aplikačním kódem, odpověď zní „ne, šest měsíců“. Pokud jsou ovladače správně vrstvené, odpověď zní „ano, dva až čtyři týdny“. Naše řada čtecích per o 11 SKU (B1, B2, F8, K7, KF1, L5, P2, Q6, Q8, T2, Y6) je strukturována tak, aby druhá odpověď byla upřímná.
Tento článek vás provede třemi ovladačovými vrstvami — HAL, BSP a aplikační ovladačovou prokladací vrstvou (driver shim) — vysvětlí pravidla závislostí mezi nimi a poskytne konkrétní příklady nákladů na portování u tří reálných migrací, které jsme dodali v letech 2024–2025.
1. Co rozumíme pod HAL, BSP a driver shimy
Slovní zásoba se v oboru liší. My používáme:
- BSP (Board Support Package) — kód, který zná konkrétní PCB. Pin mux, přiřazení GPIO, čísla sběrnic I²C, sekvencování PMIC, profil nabíječky baterie. Nachází se v
bsp/<sku>/. - HAL (Hardware Abstraction Layer) — kód, který obaluje periferii SoC do neutrálního API nezávislého na dodavateli. SPI master, I²C slave, DMA, ADC, audio DAC. Nachází se v
hal/<vendor>/<soc>/. - Driver shim — kód, který adaptuje API periferie nezávislé na dodavateli na konkrétní OID/audio/napájecí IC. Nachází se v
drivers/<component>/. - MCAL (Microcontroller Abstraction Layer) — termín ve stylu AUTOSAR, který používáme pro HAL na SKU s Cortex-M (B1, B2, K7, KF1, P2, Q6, Q8).
Pravidlo je jednosměrné: aplikace → driver shim → HAL → BSP. Nic v HAL nesmí includovat hlavičku z BSP; nic v driver shimu nesmí includovat hlavičku z aplikace. Toto vynucujeme skriptem, který běží v CI a selže build, pokud detekuje zakázaný include.
2. 4vrstvý stack na čtecím peru
Každý firmware čtecího pera sleduje stejnou 4vrstvou strukturu, bez ohledu na SKU nebo OS:
| Vrstva | Ukázkové soubory | Řádky kódu (typicky) |
|---|---|---|
| Aplikace | app/oid_decode.c, app/audio_player.c |
8 000–18 000 |
| Driver shim | drivers/oid_sensor/, drivers/audio_dac/ |
4 000–9 000 |
| HAL | hal/spi_master.c, hal/i2c_slave.c, hal/dma.c |
6 000–14 000 |
| BSP | bsp/<sku>/pinmux.c, bsp/<sku>/pmic_seq.c |
1 500–4 500 |
Linux SKU (F8, L5, T2, Y6) dělí HAL na část v kernel-space a část v user-space. HAL v kernel-space je linuxový ovladač zařízení; HAL v user-space obaluje ALSA, PulseAudio nebo náš vlastní audio daemon. Platí stejné jednosměrné pravidlo.
3. Mapa HAL/BSP pro 11 SKU
| SKU | Dodavatel SoC | Umístění HAL | Velikost BSP | Driver shimy | Aplikace |
|---|---|---|---|---|---|
| B1 | STM32F4 (Cortex-M4) | hal/stm32f4/ |
1 800 LOC | OID snímač, audio DAC, battery gauge | FreeRTOS app |
| B2 | STM32F4 (Cortex-M4) | hal/stm32f4/ |
2 100 LOC | OID snímač, audio DAC, battery gauge | FreeRTOS app |
| F8 | Allwinner A64 (Cortex-A53) | hal/allwinner/a64/ (kernel) + hal/user/audio.c |
4 200 LOC | OID senzor, audio DAC, Wi-Fi/BT, ASR engine | Linux Buildroot |
| K7 | Nordic nRF5340 (Cortex-M33) | hal/nordic/nrf53/ |
2 400 LOC | OID senzor, audio DAC, BLE, TrustZone-M | Zephyr app |
| KF1 | Nordic nRF5340 (Cortex-M33) | hal/nordic/nrf53/ |
2 400 LOC | OID senzor, audio DAC, BLE, TrustZone-M | Zephyr app |
| L5 | NXP i.MX 8M (Cortex-A53) | hal/nxp/imx8m/ (kernel) + hal/user/audio.c |
4 800 LOC | OID senzor, audio DAC, Wi-Fi/BT, ASR, video | Linux Yocto |
| P2 | STM32G0 (Cortex-M0+) | hal/stm32g0/ |
1 500 LOC | OID senzor, audio DAC | FreeRTOS app |
| Q6 | GD32F450 (Cortex-M4) | hal/gd32/f450/ |
2 000 LOC | OID senzor, audio DAC, battery gauge | AliOS Things |
| Q8 | GD32F450 (Cortex-M4) | hal/gd32/f450/ |
2 000 LOC | OID senzor, audio DAC, battery gauge | AliOS Things |
| T2 | NXP i.MX 8M Plus (Cortex-A53) | hal/nxp/imx8mp/ (kernel) + hal/user/audio.c |
5 200 LOC | OID senzor, audio DAC, Wi-Fi/BT, ASR, video | Linux Yocto |
| Y6 | Allwinner A64 (Cortex-A53) | hal/allwinner/a64/ (kernel) + hal/user/audio.c |
4 400 LOC | OID senzor, audio DAC, Wi-Fi\/BT, ASR | Linux Buildroot |
HAL je nejdražší vrstva na změnu. Nový dodavatel SoC znamená zhruba 4 800–6 500 řádků kódu HAL. Nová DPS na stejném SoC znamená 1 500–2 800 řádků kódu BSP. Nový dodavatel OID senzoru znamená 600–1 200 řádků kódu ovladačového shimu. Aplikační vrstva by ideálně neměla vyžadovat žádné změny.
4. Kontrakt ovladačového shimu
Každý ovladačový shim implementuje pevný kontrakt. Například audio DAC shim na každé SKU nabízí:
audio_err_t audio_dac_init(const audio_config_t *cfg);\naudio_err_t audio_dac_start(audio_stream_t *stream);\naudio_err_t audio_dac_stop(void);\naudio_err_t audio_dac_set_volume(uint8_t pct);\naudio_err_t audio_dac_get_status(audio_status_t *status);\n
Struktura audio_config_t obsahuje vzorkovací frekvenci, bitovou hloubku, počet kanálů a ukazatel na DMA buffer. HAL implementuje volání na úrovni registrů I²S nebo TDM. BSP nastavuje pin mux pro I²S0 a napájecí větve PMIC. Aplikace nikdy nepřistupuje přímo k registrům.
Tento kontrakt nám umožňuje měnit dodavatele audio DAC (v posledních 24 měsících jsme dodávali s Maxim MAX98357A, Texas Instruments TLV320AIC23 a AKM AK4633) bez jediné změny řádku aplikačního kódu.
5. Stabilita a verzování HAL API
HAL API je verzováno pomocí sémantického verzování: MAJOR.MINOR.PATCH. Zvýšení MAJOR znamená nekompatibilní změnu; MINOR přidává nová API; PATCH zahrnuje pouze opravy chyb. Aplikační kód je připnut na MAJOR verzi HAL. Aktuální verze HAL jsou:
| HAL | Verze API | Poslední změna |
|---|---|---|
hal\/stm32f4\/ |
3.2.0 | 2025-04 |
hal\/stm32g0\/ |
1.4.2 | 2025-08 |
hal\/gd32\/f450\/ |
2.5.1 | 2025-03 |
hal\/nordic\/nrf53\/ |
4.1.0 | 2025-06 |
hal\/allwinner\/a64\/ |
6.0.0 | 2025-09 |
hal\/nxp\/imx8m\/ |
7.2.1 | 2025-10 |
hal\/nxp\/imx8mp\/ |
7.2.1 | 2025-10 |
Zvýšení MAJOR verze HAL jsou vzácná – v průměru jednou za 18 měsíců. HAL je nejdéle existující část kódu v našem repozitáři firmwaru. Aplikační kód na B2 se od firmwaru 2.4.0 nezměnil, protože HAL API zůstalo stabilní.
6. Migrace BSP v letech 2024–2025: tři reálné případy
V posledních 18 měsících jsme migrovali tři SKU přes hranici BSP. Náklady v každém případě:
| Migrace | Dopad na HAL | Dopad na BSP | Dopad na aplikaci | Kalendářní týdny | Náklady |
|---|---|---|---|---|---|
| F8 v2 → v3 (výměna senzoru) | 0 LOC | 1 400 LOC | 80 LOC (konfigurace) | 6 | 11 200 $ |
| L5 → T2 (výměna audio DAC) | 200 LOC | 2 100 LOC | 0 LOC | 4 | 9 600 $ |
| Q6 → Q8 (výměna monitoru baterie) | 0 LOC | 600 LOC | 0 LOC | 2 | $4,400 |
Prvním případem byla tendrová zakázka maloobchodního řetězce z oblasti Perského zálivu, která vyžadovala OID senzor s vyšším rozlišením. Vyměnili jsme senzor ve vrstvě BSP (1 400 řádků kódu pro pin-mux a konfiguraci sběrnice I²C), provedli menší změnu formátu dekodérové tabulky OID (80 řádků kódu v aplikační vrstvě) a dodali jsme za 6 týdnů.
Druhým případem byl evropský školní obvod, který požadoval hlasitější reproduktor (5 W místo 3 W) na platformě L5. Přešli jsme na nový audio DAC; změnit se muselo jen 200 řádků kódu v HAL, protože nový DAC sdílel periférii I²S. Aplikační kód o tom vůbec nevěděl.
Třetím případem byl zákazník B2B, který trval na konkrétním obvodu pro monitorování stavu baterie. Vyměnili jsme monitorovací obvod na desce plošných spojů Q6 tak, aby odpovídal hardwaru Q8. HAL zůstal identický (stejná rodina dodavatele), takže jedinou prací bylo BSP.
7. Kam smí sahat aplikační vrstva
Aplikační vrstva smí volat ovladačové adaptéry (driver shims) a API operačního systému (fronty FreeRTOS, work items Zephyr, pthread v Linuxu, ALSA). Je zakázáno volat HAL přímo. Toto pravidlo vynucujeme pravidlem CI lintu nad grafem inkluzí. Regrese, která importuje hal/spi_master.h z app/audio_player.c selže při buildu.
Existují tři výjimky:
- Spouštěcí
bsp/<sku>/pinmux.csmí volat funkce HAL přímo, protože pin mux je ze své podstaty svázán s HAL. - Partition TrustZone TEE na SKU s Linuxem smí volat HAL, protože se jedná o samostatný firmware image.
- Kód pro řízení spotřeby na SKU s RTOS smí volat HAL, protože spravuje takty jádra a režimy spánku.
Tyto výjimky jsou zdokumentovány ve firmwarovém README a při každém vydání se auditují.
8. Vynucování v CI a statická analýza
Naše CI spouští u každého pull requestu čtyři kontroly:
- Kontrola grafu inkluzí — vynucuje jednosměrné závislosti.
- Kontrola stability API HAL — selže při buildu, pokud se signatura HAL změní bez navýšení MAJOR.
- Kontrola portu BSP — ověřuje, že BSP pro cílové SKU zkompiluje samostatně.
- Kontrola LOC aplikační vrstvy — omezuje růst LOC aplikace na +10 % za vydání, aby se podniková logika neplížila do nesprávné vrstvy.
CI běží na našich self-hosted GitLab runnerech v Šen-čenu a Jen-tchaj. Úplná validace trvá 22 minut pro SKU s RTOS a 48 minut pro SKU s Linuxem.
9. Body přizpůsobení pro OEM
Pokud jste OEM zákazník, vrstvy, kterých se typicky dotýkáte, jsou:
- BSP — pin mux, přiřazení GPIO, vzor LED, debouncing tlačítek.
- Driver shim — pokud přinášíte vlastní audio DAC, OID senzor nebo monitorovací obvod baterie.
- Aplikační vrstva — jazykové balíčky, hlasové výzvy, OEM logo na úvodní obrazovce, vlastní OID knihovny.
HAL se mění zřídka, pokud neměníte dodavatele SoC. Od roku 2023 jsme provedli tři porty HAL (Allwinner → NXP i.MX, STM32F4 → GD32 a pilotní projekt s Rockchip). Každý trval 16–22 týdnů inženýrské práce.
Tip pro kupujícího: Pokud vaše tendrová zakázka vyžaduje konkrétního dodavatele SoC, zeptejte se OEM, zda je jejich vrstva HAL abstraktní, nebo hard-coded na jednoho dodavatele. Hard-coded HAL znamená 4–6 měsíců portování; abstraktní HAL znamená 6–10 týdnů.
10. Co vám architektura přináší
Dobře vrstvená architektura firmwaru přináší tři věci:
- Přenositelnost — na nový SoC, senzor nebo DAC můžete přejít v řádu týdnů, ne měsíců.
- Auditovatelnost — váš compliance tým může kontrolovat jednu vrstvu po druhé.
- Testovatelnost — driver shimy lze unit-testovat proti mockům bez potřeby reálného hardwaru.
Dnešní řada 11 SKU je toho důkazem. Od roku 2023 jsme migrovali 6 z 11 SKU minimálně jednou, bez přepisů aplikační vrstvy, a průměrné náklady na port jsou nyní 4–8 týdnů inženýrské práce za známou cenu.
Pokud máte dotaz ohledně portování, zašlete nám zdrojové i cílové SKU a my vám do 48 hodin odpovíme cenovou nabídkou s pevnou cenou.
11. Reálné příklady driver shimů
Aby byly abstraktní vrstvy konkrétní, uvádíme čtyři driver shimy, které dnes běží v našem produkčním firmwaru.
Shim OID senzoru. Každé SKU používá stejné API oid_sensor_read_page() bez ohledu na to, zda je senzor OID2000, CMOS kamera, nebo ToF modul. Shim překládá API na I²C transakce dodavatele. B2 používá burst 12 snímků při 30 fps; L5 používá jeden 720p snímek; T2 používá snímek s ToF hloubkovou anotací při 60 fps. Všechny tři volají stejný shim a shim provádí překlad.
Shim audio DAC. Shim audio DAC zajišťuje konverzi vzorkovací frekvence, rampy hlasitosti a ztlumení. Ve firmwaru B2 2.4.7 dodáváme MAX98357A; ve firmwaru L5 4.2.0 dodáváme TLV320AIC23. Funkce shimu audio_dac_set_volume() implementuje logaritmickou rampu po dobu 40 ms, aby se zabránilo efektu zipu (zipper noise). Aplikace nikdy nevidí zápis do registru.
Shim koexistence Wi-Fi/BT. U modelů F8, L5, T2 a Y6 arbitraci přístupu k anténě mezi Wi-Fi rádiem a BLE rádiem zajišťuje převodník Wi-Fi/BT. Převodník je postaven na rozhraní Packet Traffic Arbitration (PTA) podle standardu LTE. HAL implementuje 4vodičové piny PTA. Aplikace pracuje pouze s jedním voláním wireless_tx_request().
Převodník měřiče baterie. Modely Q6, Q8, K7, KF1, L5, T2 a Y6 se dodávají s palivoměrem TI BQ27426 nebo BQ40Z50. Převodník zpřístupňuje battery_get_soc_pct(), battery_get_temperature_c(), battery_get_voltage_mv() a battery_get_health(). Převodník ukládá naměřené hodnoty do mezipaměti na 1 sekundu, aby se zabránilo probouzení měřiče častěji než jednou za cyklus.
12. Mapy paměti a linkovací skripty pro každou vrstvu
Každá vrstva má omezenou mapu paměti. Rozpočet RAM a Flash přidělujeme po vrstvách a vynucujeme jej pomocí linkovacích skriptů. Rozpočet pro firmware B2 verze 2.4.7 vypadá takto:
| Sekce | Vrstva | Velikost | Účel |
|---|---|---|---|
.bss |
HAL | 8 KB | DMA buffery, kruhové buffery |
.bss |
Převodník ovladače | 4 KB | Mezipaměť audio streamu |
.bss |
Aplikace | 12 KB | Mezipaměť vyhledávací tabulky OID |
.text |
HAL | 14 KB | Implementace HAL |
.text |
Převodník ovladače | 6 KB | Implementace převodníku ovladače |
.text |
Aplikace | 22 KB | Dekodér OID + audio přehrávač |
.rodata |
Převodník ovladače | 22 KB | Metadata knihovny OID |
.rodata |
Aplikace | 38 KB | Hlasové pokyny + vyhledávací tabulky |
| Rezervováno | TrustZone-M | 4 KB | Zabezpečené úložiště klíčů |
| Rezervováno | Příprava OTA | 256 KB | OTA obraz |
Celková stopa Flash na firmwaru B2 verze 2.4.7 je 1,4 MB; celková stopa RAM je 64 KB. SKU pro Linux mají větší rozpočty — firmware L5 verze 4.2.0 rezervuje 140 MB pro aplikaci, 28 MB pro HAL a 12 MB pro převodníky ovladačů.
13. Jak auditovat firmware čtecího pera z hlediska přenositelnosti
Pokud jste compliance důstojník nebo OEM kupující hodnotící firmware třetí strany, zde je 12otázkový audit, který zvládnete za 2 hodiny:
- Může aplikační kód zkompilovat bez dostupných HAL hlaviček?
- Kompiluje BSP vrstva samostatně?
- Existuje zdokumentované jednosměrné pravidlo závislostí?
- Vynucuje CI pravidlo závislostí?
- Je HAL API verzované?
- Zůstává počet řádků aplikace v rámci 10% růstového rozpočtu na vydání?
- Jsou driver shimy unit-testovány s mocky?
- Je velikost BSP zdokumentována pro každé SKU?
- Existuje kalkulačka nákladů na HAL port?
- Kontroluje se v CI stabilita HAL?
- Jsou výjimky z pravidla závislostí zdokumentovány?
- Je linker skript per-vrstva?
Pokud je odpověď na všech 12 ano, firmware je přenositelný. Pokud je méně než 8 ano, považujte codebase za závazek na jedno SKU.