Teoretické minimum: klíčové otázky pro programování mikrokontrolérů
Programátoři mikrokontrolérů musí perfektně ovládat specifika jazyka C v podmínkách omezených zdrojů. Níže najdete výběr praktických otázek s důrazem na kompilaci, paměť a optimalizaci. Tyto témata se pravidelně objevují na pohovorech v embedded firmách.
Klíčová slova a jejich použití
Static omezuje viditelnost proměnné na aktuální soubor nebo funkci, u lokálních static zachovává hodnotu mezi voláními. Volatile brání optimalizaci kompilátorem pro proměnné měněné zvenčí (registry, paměť, přerušení).
Příklad problematického kódu:
int square(volatile int *ptr) {
return *ptr * *ptr;
}
Zde se volatile aplikuje jen na první dereferenci, druhá může být optimalizována. Správně: (ptr) (*ptr).
Const volatile je vhodné pro data neměnná zvenčí, jako statusové registry. Register navrhuje kompilátoru uložit proměnnou v registru (zastaralé v C11). Restrict signalizuje absenci aliasingu pointerů pro vektorizaci.
Práce s pamětí a strukturami
Globální const proměnná se umístí do Flash. Pro konstantní pole 32 KB s hodnotou 0xFF použijte linker script sekci s fill(0xFF).
Bitové operace: kontrola bitu — n & (1 << k), vymazání — n & ~(1 << k). Srovnání float: fabs(a - b) < EPSILON.
Velikost struktur závisí na zarovnání. Pro
struct Foo {
int iiii;
char c;
};
je velikost 8 bajtů (4 bajty padding). Balení v GCC: __attribute__((packed)).
Příklad výstupu řetězců:
char str5[]={'s','t','r','i','n','g'}; // size:7 len:6
char *str1="string"; // size:4 len:6 (pointer)
char str3[]="string"; // size:7 len:6
char str4[10]="string"; // size:10 len:6
Systémy sestavení a toolchain
Systém sestavení automatizuje kompilaci, linkování a závislosti. Make zpracovává změny souborů, Ninja je rychlejší díky paralelizmu a jednoduchosti.
VPATH v GNU Make hledá zdrojáky v uvedených adresářích.
Cesta kódu: .c → .i (předzpracování) → .s (assembler) → .o → .elf → .bin/.hex.
Vypnout varování GCC: #pragma GCC diagnostic ignored "-Wrestrict".
Zkomprimovat firmware: -ffunction-sections -fdata-sections, ld --gc-sections, optimalizace -Os.
Artefakty sestavení
.o— objektové soubory.elf— spustitelný soubor se symboly.hex/.bin— pro firmware (hex s adresami)
Binutils: objdump (dizassembler), objcopy (konvertor), readelf (ELF analýza).
Zkontrolovat sestavení souboru: make V=1 nebo -n (dry-run).
Datové struktury a algoritmy
Cyklický buffer — kruhové pole s indexy head/tail, liší se od FIFO absencí posunů.
Odstranění ze spojeného seznamu: změnit prev->next = node->next (potřeba prev) nebo node->next->prev = node->prev (dvojitě spojený).
Polymorfismus v C: pointery na funkce ve strukturách (podobně jako vtable).
Úloha bez if/switch:
void print_num(int n) {
const char *nums[] = {"","Jeden","Dva"};
printf("%s", nums[n]);
}
do-while(0) pro makra — jediná iterace s více příkazy.
Přerušení a RTOS
Přerušení — hardwarový mechanismus skoku do ISR při události. Vektorová tabulka obsahuje adresy ISR. Cortex-M4: 12–16 taktů na vstup (uložení kontextu).
Algoritmus: hardware ukládá PC/LR, načte vektor, skok do ISR, návrat přes POP.
Reentrant funkce — bezpečná pro paralelní volání (žádné static/lokální bez synchronizace).
V RTOS:
- Vlákno — jednotka provádění se stackem
- Mutex — vzájemné vyloučení
- Semaphore — počítadlo událostí
- Spinlock — busy-wait blokování
Problém v kódu: deadlock kvůli pořadí locků (TaskA: ma→mb, TaskB: mb→mc→ma).
Inverze priorit: vysoká priorita čeká na nízkou. Řešení: dědičnost priorit.
Atomové operace
Příklad: __atomic_exchange_n(&x, &y, __ATOMIC_SEQ_CST).
Bit-banding — přímý přístup k bitům bez masek (Cortex-M3/4).
Toolchain a ladění
ABI — rozhraní binární kompatibility (calling convention).
Segmenty: .text (Flash kód), .data (RAM inicializované), .bss (RAM nuly), .rodata (Flash konstanty).
Rozložit předzpracování: gcc -E file.c > expanded.i.
Dokumentace: datasheet, referenční manuál, programovací manuál, schéma.
Co je důležité
- Volatile jsou nutné pro registry periferií
- Packed struktury šetří RAM, ale zpomalují přístup
- RTOS vyžaduje thread-safe kód a ochranu kritických sekcí
- Optimalizace sestavení: sekce + gc-sections
- Přerušení pracují ve stacku aktuálního vlákna
Pro padding 0xFF ve strukturách: linker script s fill nebo __attribute__((packed)) + ruční vyplnění.
— Editorial Team
Zatím žádné komentáře.