Přeskočit na hlavní obsah

11 článků s tagem "C"

Embedded C

Zobrazit všechny tagy

Ladění HardFaultu na Cortex-M: od záhady k řádku kódu

· 10 minut čtení

Každý embedded vývojář zná ten okamžik: firmware běžel, a pak najednou neběží. Debugger ukazuje, že program sedí v nekonečné smyčce se jménem jako HardFault_Handler nebo Default_Handler, a call stack tvoří pár nic neříkajících rámců. Ta smyčka je výchozí handler ze startup kódu a o tom, co se stalo, neříká absolutně nic. Chyba má ale příčinu a procesor si ji už zapsal: v osmi registrech na zásobníku a ve čtyřech stavových registrech. Stačí je jen přečíst.

Tento článek ukazuje, jak z té smyčky získat řádek zdrojového kódu, na dvou skutečných příkladech, které jsem spustil v QEMU (model desky se STM32F4) a prozkoumal pomocí GDB: volání ukazatele na funkci s hodnotou NULL a zápis na adresu, kde nic není. Všechny výstupy jsou skutečné.

Spuštění skutečného firmwaru bez hardwaru: simulátor v CI

· 8 minut čtení

V článku o unit testování s Unity a CMock jsem řekl, že testy na PC nenajdou „rozdíly mezi PC a MCU". Tento článek je o těchto rozdílech a o nástroji, který je najde: simulátoru, který spouští skutečný binární soubor. Ne logiku přeloženou pro PC, ale přímo .elf, který vytvořil překladač ARM, se skutečným startup kódem a skutečným linker scriptem, na modelu procesoru a jeho periferií.

Ukážu dva experimenty, které jsem spustil: tentýž zdrojový kód testu, který na PC projde a na Cortex-M4 selže, a firmware, který zapisuje do registrů USART na skutečných adresách STM32F4 a jehož text se objeví v terminálu. Na konci je upřímný seznam toho, co vám simulátor neřekne.

Návrh API periferie: osm rozhodnutí za modulem Gpio

· 9 minut čtení

GPIO je nejjednodušší periferie mikrokontroléru: pin je high nebo low. Právě proto je dobrým tématem pro článek o návrhu rozhraní. Není tu žádná hardwarová složitost, za kterou by se dalo schovat, a každé rozhodnutí je volbou návrháře: jak se pin jmenuje, co funkce vrací, kde žije polarita LED. Modul Gpio z MCAL v Embedbits BSP je skutečný příklad se skutečnými odpověďmi a projdu je jednu po druhé, včetně alternativ a ceny.

Kód z modulu je citován z větve STM32H5 repozitáře Bsp-Mcal-Gpio. Příklady, které ho používají, byly přeloženy a spuštěny proti skutečným Gpio_Port.h a Gpio_Types.h, s malou náhradní implementací, aby bylo možné API vyzkoušet na PC.

Doxygen pro embedded C: dokumentace, na kterou nelze zapomenout

· 7 minut čtení

Každý projekt má dokumentaci a každý projekt má dokumentaci, která lže. Word soubor s popisem rozhraní byl správný v týdnu, kdy vznikl. Komentář nad funkcí je poctivější, protože je pár řádků od kódu, který popisuje, ale píší ho tytéž lidé, kteří zapomínají. Cesta ven nevede přes větší disciplínu, ale přes nástroj, který komentáře přečte, sestaví z nich dokumentaci a shodí build, když něco chybí. Tím nástrojem je Doxygen.

Tento článek ukazuje, jak vypadá zdokumentovaný modul v mých projektech, jak se generuje a jak z dokumentace udělat součást CI, kterou nelze přeskočit. Příklady vznikly s Doxygen 1.9.8 a Graphviz a výstupy jsou skutečné.

Přerušení a main(): jak bezpečně sdílet data

· 9 minut čtení

Obsluha přerušení a hlavní smyčka jsou dva programy, které běží ve stejné paměti a o sobě nevědí. Překladač C neví, že přerušení existuje, a CPU neví, že dvě proměnné patří k sobě. Ví to jen programátor a chyby, které z toho vznikají, jsou ty nejhorší: objeví se jednou za tisíc běhů, zmizí, když připojíte debugger, a při code review se nikdy neukážou, protože kód vypadá správně.

Tento článek prochází tři problémy sdílených dat, jeden po druhém, s kódem, který selhává, a potom ukazuje vzory, které fungují. Experimenty běží na Cortex-M4 (v QEMU, na modelu desky s STM32F4) nebo na PC a výstupy jsou skutečné.

Konečné automaty v praxi: tlačítko s debounce a dlouhým stiskem

· 9 minut čtení

V prvním článku o konečných automatech jsem vám dal šablonu a skončil jsem slovy „pokračování příště“. Tohle je to pokračování a nejlepší způsob, jak pokračovat po teorii, je problém. Vybral jsem takový, který má každý embedded projekt a který nikdo nenapíše správně na první pokus: tlačítko.

Tlačítko vypadá triviálně: pin, high nebo low. Jenže mechanický kontakt zakmitává, takže pin udělá 1 0 1 1 0 1, než se ustálí, a produkt obvykle chce od stejného tlačítka dvě různé věci: krátký a dlouhý stisk. Napsané pomocí příznaků a čítačů v hlavní smyčce to skončí jako pár ifů, které na sobě závisejí způsobem, který po měsíci nikdo nevysvětlí. Konečný automat to vyřeší tak, že to vysvětlíte tabulkou.

Co se děje před main(): reset, startup kód a linker script

· 10 minut čtení

Každý tutoriál jazyka C začíná int main(void). Nikdo ale nevysvětluje, kdo ji volá. A přitom když napíšete uint32_t counter = 5; jako globální proměnnou a první řádek main() přečte 5, už se odvedlo hodně práce. Když se ta práce neodvede, projeví se to proměnnou s náhodnou hodnotou, která „včera fungovala".

V tomto článku budeme sledovat mikrokontrolér od resetu až po první řádek main(): co udělá hardware sám, co říká linker script a co musí udělat startup kód. Jde o obsah dvou modulů Embedbits BSP (Linker a Startup), ale princip je stejný na každém Cortex-M. Veškerý kód v článku byl přeložen pomocí arm-none-eabi-gcc 13.2.1 a spuštěn v QEMU na modelu desky se STM32F405, takže adresy i výstupy jsou skutečné.

Unit testování embedded C na PC pomocí Unity a CMock

· 9 minut čtení

„Embedded software se nedá unit testovat, potřebujete hardware." Slýchám to často a platí to přesně pro jeden druh kódu: kód, který sahá na registry. Všechno ostatní, stavové automaty, parsery protokolů, řídicí logika, převody hodnot, je obyčejné C, které se přeloží na vašem PC. A na PC běží v milisekundách, bez debuggeru, bez kabelu a bez flashování.

Tento článek ukazuje, jak otestovat modul pomocí Unity (testovací framework) a CMock (generátor mocků), od návrhu, který to umožňuje, až po soubor CMake, který to sestaví. Všechno bylo sestaveno a spuštěno a výstupy níže jsou skutečné.

Organizace souborů v embedded C: jak se ze složky stane modul

· 9 minut čtení

Můj coding style říká, že názvy souborů začínají názvem modulu a že „kompletní organizace souborů je popsána jinde". Tohle je to „jinde".

C nemá private, jmenné prostory ani balíčky. Jakmile je kód rozdělen do souborů, jsou soubory a build systém jedinými nástroji, kterými můžete říct, co k sobě patří, co je veřejné a co se nikoho jiného netýká. Organizace souborů tedy není věcí vkusu, je součástí návrhu. Tento článek popisuje, jak organizuji embedded projekt na třech úrovních: projekt, modul a jednotlivý soubor.

Pravidla MISRA C v praxi: co jsou zač, proč existují a jak s nimi žít

· 17 minut čtení

Řekněte „MISRA“ v místnosti plné embedded vývojářů a polovina si povzdechne, zatímco druhá se zeptá, jaký nástroj používáte. Pověst těchto pravidel je rozporuplná: pro některé je to byrokracie, která před každým vydáním sežere týden, pro jiné důvod, proč se auto na dálnici nerestartuje. Obě skupiny mají zčásti pravdu.

V tomto článku projdu pravidla, se kterými se setkávám nejčastěji, jedno po druhém: co pravidlo požaduje, co za to získáte, jak vypadá špatný kód, jak vypadá dobrý kód a kdo za vás problém najde. Všechny příklady jsou skutečný C kód, který jsem přeložil a spustil.