Preskočiť na hlavný obsah

11 príspevkov so štítkom „C“

Embedded C

Zobraziť všetky štítky

Ladenie HardFaultu na Cortex-M: od záhady k riadku kódu

· 10 minút čítania

Každý vývojár embedded systémov pozná ten okamih: firmvér bežal a zrazu už nebeží. Debugger ukazuje, že program sedí v nekonečnej slučke s názvom ako HardFault_Handler alebo Default_Handler, a zásobník volaní tvorí niekoľko nezmyselných rámcov. Tá slučka je predvolený handler zo startup kódu a o tom, čo sa stalo, nehovorí vôbec nič. Porucha má príčinu a procesor si ju už zapísal: do ôsmich registrov na zásobníku a do štyroch stavových registrov. Stačí ich len prečítať.

Tento článok ukazuje, ako z tej slučky získať riadok zdrojového kódu, na dvoch reálnych príkladoch, ktoré som spustil v QEMU (model dosky s STM32F4) a preskúmal pomocou GDB: volanie NULL ukazovateľa na funkciu a zápis na adresu, kde nie je nič. Všetky výstupy sú skutočné.

Spustenie skutočného firmvéru bez hardvéru: simulátor v CI

· 8 minút čítania

V článku o unit testovaní s Unity a CMock som napísal, že testy na PC nenájdu „rozdiely medzi PC a MCU". Tento článok je o týchto rozdieloch a o nástroji, ktorý ich nájde: o simulátore, ktorý spúšťa skutočný binárny súbor. Nie logiku skompilovanú pre PC, ale ten istý .elf, ktorý vyrobil kompilátor ARM, so skutočným startup kódom a skutočným linker scriptom, na modeli procesora a jeho periférií.

Ukážem dva experimenty, ktoré som spustil: ten istý zdrojový kód testu, ktorý prejde na PC a zlyhá na Cortex-M4, a firmvér, ktorý zapisuje do registrov USART na skutočných adresách STM32F4 a ktorého text sa objaví v termináli. Na konci je úprimný zoznam toho, čo vám simulátor nepovie.

Návrh API periférie: osem rozhodnutí za modulom Gpio

· 9 minút čítania

GPIO je najjednoduchšia periféria mikrokontroléra: pin je high alebo low. Presne preto je dobrým námetom na článok o návrhu rozhrania. Nie je tu žiadna hardvérová zložitosť, za ktorou by sa dalo schovať, a každé rozhodnutie je voľbou návrhára: ako sa pomenuje pin, čo funkcia vracia, kde žije polarita LED. MCAL modul Gpio z Embedbits BSP je skutočný príklad so skutočnými odpoveďami a prejdem ich jednu po druhej, aj s alternatívami a cenou.

Kód z modulu je citovaný z vetvy STM32H5 repozitára Bsp-Mcal-Gpio. Príklady, ktoré ho používajú, som skompiloval a spustil proti skutočným Gpio_Port.h a Gpio_Types.h, s malým fake implementácie, aby sa API dalo vyskúšať na PC.

Doxygen pre embedded C: dokumentácia, na ktorú sa nedá zabudnúť

· 7 minút čítania

Každý projekt má dokumentáciu a každý projekt má dokumentáciu, ktorá klame. Súbor Wordu s popisom rozhrania bol správny v týždni, keď vznikol. Komentár nad funkciou je čestnejší, pretože je len pár riadkov od kódu, ktorý opisuje, ale píšu ho tí istí ľudia, ktorí zabúdajú. Cesta von nie je viac disciplíny, ale nástroj, ktorý číta komentáre, zostaví z nich dokumentáciu a pri chýbajúcom popise zlyhá build. Tým nástrojom je Doxygen.

Tento článok ukazuje, ako vyzerá zdokumentovaný modul v mojich projektoch, ako sa generuje a ako z dokumentácie urobiť súčasť CI, ktorú nemožno preskočiť. Príklady boli zostavené s Doxygen 1.9.8 a Graphviz a výstupy sú skutočné.

Prerušenia a main(): ako bezpečne zdieľať dáta

· 9 minút čítania

Obsluha prerušenia a hlavná slučka sú dva programy, ktoré bežia v tej istej pamäti a o sebe nevedia. Kompilátor C nevie, že prerušenie existuje, a CPU nevie, že dve premenné patria k sebe. Vie to jedine programátor a chyby, ktoré z toho vznikajú, sú najhoršieho druhu: objavia sa raz za tisíc behov, zmiznú, keď pripojíte debugger, a nikdy sa neobjavia pri code review, pretože kód vyzerá správne.

Tento článok prejde tri problémy zdieľaných dát jeden po druhom s kódom, ktorý zlyháva, a potom ukáže vzory, ktoré fungujú. Experimenty bežia na Cortex-M4 (v QEMU, na modeli dosky STM32F4) alebo na PC a výstupy sú skutočné.

Konečné automaty v praxi: tlačidlo s debounce a dlhým stlačením

· 9 minút čítania

V prvom článku o konečných automatoch som vám dal šablónu a skončil som slovami „pokračovanie nabudúce“. Toto je to pokračovanie a najlepší spôsob, ako pokračovať v teórii, je problém. Vybral som taký, ktorý má každý embedded projekt a ktorý nikto nespraví správne na prvý pokus: tlačidlo.

Tlačidlo vyzerá triviálne: pin, high alebo low. Lenže mechanický kontakt poskakuje, takže pin robí 1 0 1 1 0 1, kým sa ustáli, a produkt od jedného tlačidla zvyčajne chce dve rôzne veci: krátke a dlhé stlačenie. Napísané s príznakmi a počítadlami v hlavnej slučke to skončí ako zopár ifov, ktoré od seba závisia spôsobom, ktorý po mesiaci nikto nevie vysvetliť. Konečný automat to rieši spôsobom, ktorý viete vysvetliť tabuľkou.

Čo sa stane pred main(): reset, startup kód a linker script

· 10 minút čítania

Každý tutoriál jazyka C začína int main(void). Nikto však nevysvetlí, kto túto funkciu volá. A pritom, keď napíšete uint32_t counter = 5; ako globálnu premennú a prvý riadok main() prečíta hodnotu 5, už sa vykonalo veľa práce. Ak sa táto práca nevykoná, prejaví sa to premennou s náhodnou hodnotou, ktorá „včera fungovala".

V tomto článku budeme sledovať mikrokontrolér od resetu až po prvý riadok main(): čo robí hardvér sám od seba, čo hovorí linker script a čo musí urobiť startup kód. Je to obsah dvoch modulov Embedbits BSP (Linker a Startup), ale princíp je rovnaký na každom Cortex-M. Všetok kód v článku bol zostavený pomocou arm-none-eabi-gcc 13.2.1 a spustený v QEMU, na modeli dosky s STM32F405, takže adresy a výstupy sú skutočné.

Unit testovanie embedded C na vašom PC s Unity a CMock

· 9 minút čítania

„Embedded softvér sa nedá unit testovať, potrebujete hardvér." Počúvam to často a platí to presne pre jeden druh kódu: pre kód, ktorý sa dotýka registrov. Všetko ostatné, stavové automaty, parsery protokolov, riadiaca logika, prevod hodnôt, je obyčajné C, ktoré sa skompiluje na vašom PC. A na vašom PC beží v milisekundách, bez debuggera, bez kábla a bez flashovania.

Tento článok ukazuje, ako otestovať modul pomocou Unity (testovací framework) a CMock (generátor mockov), od návrhu, ktorý to umožňuje, až po súbor CMake, ktorý to zostaví. Všetko bolo zostavené a spustené a výstup nižšie je skutočný.

Organizácia súborov v embedded C: ako sa z priečinka stane modul

· 9 minút čítania

Môj coding style hovorí, že názvy súborov začínajú názvom modulu a že „kompletná organizácia súborov je popísaná inde". Toto je to „inde".

Jazyk C nemá private, menné priestory ani balíky. Keď sa kód rozdelí do súborov, súbory a build systém sú jediné nástroje, ktorými môžete povedať, čo patrí k sebe, čo je verejné a čo nikoho iného nezaujíma. Organizácia súborov preto nie je vec vkusu, ale súčasť návrhu. Tento článok popisuje, ako organizujem embedded projekt na troch úrovniach: projekt, modul a jednotlivý súbor.

Pravidlá MISRA C v praxi: čo sú zač, prečo existujú a ako s nimi žiť

· 17 minút čítania

Povedzte „MISRA“ v miestnosti plnej embedded vývojárov a polovica z nich si vzdychne, zatiaľ čo druhá polovica sa opýta, aký nástroj používate. Povesť týchto pravidiel je rozporuplná: pre niekoho je to byrokracia, ktorá zje týždeň pred každým vydaním, pre iných dôvod, prečo sa auto na diaľnici nerestartuje. Obe skupiny majú sčasti pravdu.

V tomto článku prejdem pravidlá, s ktorými sa stretávam najčastejšie, jedno po druhom: čo pravidlo žiada, čo vám prinesie, ako vyzerá zlý kód, ako vyzerá dobrý kód a kto za vás problém nájde. Všetky príklady sú skutočný C kód, ktorý som skompiloval a spustil.