česky english Vítejte, dnes je pátek 19. duben 2024

Vývoj bez kompromisů s procesory ARM – 2. část

DPS 1/2012 | Články
Autor: Ing. Jan Weinbrenner

V předcházející části článku jsme si představili vývojový kit (i.MX53 QSB) s procesorem ARM I.MX53 od firmy Freescale. Popsali jsme si hardwarové vybavení tohoto kitu a stručně představili procesor. Uvedli jsme si, že výkon tohoto procesoru je dostatečný na to, aby v něm běžel operační systém s interakcí s uživatelem přes monitor, popř. dotykovou obrazovku, počítačovou myší a běžnou klávesnicí. Také jsme si řekli, že máme na výběr mezi operačním systémem Windows Embedded Compact 7 a distribucí Linuxu. Z informací na webové stránce výrobce kitu firmy Freescale se nám jeví Linux jako preferovaná záležitost. Další důležitou informací je skutečnost, že z velkého množství distribucí Linuxu zvolil výrobce kitu distribuci Linux Ubuntu.

V tomto díle se nejprve vrátíme trochu zpět na začátek. Řekneme si, co nás přimělo věnovat se takovému komplexnímu zařízení a vybereme operační systém. Vše se bude vztahovat ke skutečnému zařízení, tedy k vývojovému kitu. Dále si ukážeme možnosti, jak napsat jednoduchou aplikaci typu „Ahoj svete“, jak ji přeložit a spustit. Rozblikáme LED diodu na kitu, která je připojena na vstupně-výstupní port procesoru. U tohoto zdánlivě jednoduchého úkolu mi nedá, abych se nezastavil. Většinou napíši několik řádků v programovacím jazyce C, přeložím aplikaci a naprogramuji procesor. Pokud to nefunguje, tak je obvykle v zapojení nějaká hardwarová chyba, např. špatně nastavená konfigurace bootování atd. Protože v tomto případě již pracuji s hotovým zařízením, tak jsem to považoval za velmi snadný úkol, jehož vyřešení ale nakonec zabralo několik nocí.

Co mě přimělo uvažovat o změně v konstrukci mých zařízení?

Vývoji aplikací se věnuji již mnoho let a tak vidím, že vývoj je stále složitější a složitější a množství věcí, které musí člověk nastudovat, roste snad geometrickou řadou. Poslední dobou jsou požadavky uživatelů na funkčnost zařízení stále náročnější, kdy i u velmi jednoduchých konstrukcí je vyžadován přístup na internet, aktualizace software po internetu, ukládání velkého množství dat atd. Tyto požadavky jsou nyní na zařízeních bez operačního systému, jenom s vlastním softwarem naprogramovaným od vývojáře, již prakticky nesplnitelné.

Po velmi pečlivém zvažování jsem se nakonec rozhodl, že mé další konstrukce poběží na Linuxu.

Proč jsem zvolil Linux?

Linux je systém, který sice běží na velkém počtu zařízení, ale do detailního kontaktu s ním přijde jenom velmi malá část lidí. Co jsem si já pamatoval z posledního setkání s ním bylo to, že člověk musel psát velmi dlouhé skripty do příkazového řádku, aby mohl něco udělat či nastavit. Přitom se pochopitelně mohlo stát, že někde na začátku psaní se zaměnilo malé písmeno za velké a mohlo se začít psát znovu. Naštěstí od mého posledního setkání s Linuxem již doba pokročila, ale i když je spousta věcí již zautomatizována, bez příkazové řádky se ani dnes neobejdeme. Zatímco je u Linuxu ve srovnání s Windows pořád ještě potřeba znát systém do větších podrobností, umožní nám tento systém spoustu věcí lépe nastavit. Protože se jedná o otevřený systém, tak nezanedbatelnou výhodou je přístup ke zdrojovým kódům. Pokud tedy budeme do systému přidávat nějakou funkčnost, máme se kde inspirovat.

Existuje způsob, jak se s Linuxem snadno seznámit?

Výrobci tohoto kitu je zřejmě známa nedůvěra uživatelů k operačnímu systému Linux, protože se rozhodl nám seznámení s ním co nejvíce usnadnit. Součástí DVD dodávaného k vývojovému kitu je obraz nainstalované distribuce Linux Ubuntu pro virtuální počítač (zde pro WM player) ve Windows. Instalace je shodná s instalací na SD kartě pro vývojový kit. Pro ty uživatele, kteří nevědí o co se jedná, to trochu uvedu. Z internetu se zdarma stáhne program WM Player, který simuluje další virtuální počítač v rámci současných Windows, přičemž vše běží v okně. Na tento další, tedy virtuální počítač, je tak možno nainstalovat jiný operační systém. Tento virtuální počítač je potom v podobě jednoho souboru na disku a cokoliv v něm provádíme, nemá vliv na původní instalaci Windows. Pokud tedy nějakým způsobem instalaci virtuálního počítače poškodíme, tak WM playeru znovu dáme původní soubor z DVD a můžeme začít znovu. Není tedy potřeba druhý počítač pro instalaci Linuxu. Tato instalace nám také umožní si zkusit naprogramovat a odladit aplikace nezávislé na hardwarovém zařízení v Linuxu.

Jak naprogramujeme a spustíme co nejjednodušší aplikaci?

Zde jsem, jako člověk, který je zvyklý na pohodlí Visual studia a Windows, zapátral nejdříve na internetu. Brzy jsem zjistil, že možností je jenom několik. Nástrojů, které by uměly generovat kód pro Linux a procesory ARM a poskytovaly kompletní vizuální prostředí, je jen několik. Zvolil jsem 30denní trial verze nástroje Sourcery CodeBench IDE od firmy Mentor Graphics. Přeložil jsem jednoduchou aplikaci, která vypisovala text do textového okna, nahrál na klíč a spustil na vývojovém kitu. Výsledkem byla funkční aplikace. Následně jsem zdrojový kód aplikace nechal přeložit interním C++ překladačem, který je součástí vývojového kitu. A opět jsem dostal funkční aplikaci. Interní překladač ale funguje pouze z příkazové řádky. Povzbuzen tímto úspěchem jsem se rozhodl dále pokračovat v pokusech. Protože se zabývám vývojem zařízení, další pokusy měly směřovat k interakci zařízení s okolím. Pohledem na vývojový kit a následně do katalogového listu jsem objevil, že uživateli jsou k dispozici 1 LED dioda a 2 tlačítka připojená k vstupně-výstupním pinům procesoru. Proto další snadný pokus měl být rozblikání LED diody.

Jak rozblikat LED diodu u procesoru v Linuxu?

Předpokládal jsem velmi snadný úkol a rozhodl jsem se zdrojový kód překládat interním překladačem vývojového kitu. Pohledem do schématu zapojení jsem zjistil, ke kterému pinu procesoru je LED připojena. Z katalogového listu jsem zjistil adresu paměti pro ovládání výstupní brány procesoru a napsal program, který na danou adresu zapíše hodnotu pro rozsvícení LED diody. Program jsem přeložil a spustil, ale program ihned zahlásil chybu segmentace a ukončil činnost. Po chvíli jsem si uvědomil svou chybu – program běžel ve virtuální paměti a do hlavní paměti neměl přímý přístup. Tím začala má noční můra, při které jsem pátral po ovladači vstupních a výstupních bran a hlavičkovém souboru knihovny. Když jsem ale zjistil, že distribuce Linuxu obsahuje statisíce souborů, došel jsem k závěru, že pro neznalého člověka to je hledání jehly v kupce sena. Po dvou dnech marných pokusů jsem zapátral ve fóru konkurenčního kitu, kterým je open source kit BeagleBoard. Ten sice nemá zdaleka takové možnosti, ale je na trhu déle a návštěvnost fóra je mnohem četnější. Nakonec vše vyřešilo několik řádků programu. Otevřeme vlastně zařízení paměť, získáme jeho adresu a tu si „namapujeme“ jako sdílenou paměť – viz následující řádky kódu: Není to nyní zrovna čisté řešení, obcházíme přístup přes ovladač, ale nějak začít musíme.

Nyní mám tedy namapovanou paměť a zapisuji správnou hodnotu do příslušného portu v programu. Program přeložím a spustím, ale musím ho spustit s pomocí příkazu SUDO, tedy pod uživatelem s neomezenými právy. Program proběhne bez chyby, ale nic se neděje. Pohledem do katalogového listu si uvědomuji svoji chybu – procesor má obrovské množství periferií. Příkladem je 8 UART portů, 300 vstupně-výstupních bran, možnosti připojení kamery, 4 SD karet atd. Pro obsloužení všech těchto periferií by musel mít procesor několik tisíc pinů. Proto je to zde provedeno jinak, kdy každý pin procesoru má vlastní registr a multiplexer s 8 vstupy. Tento registr s pomocí multiplexeru vybírá, ke které periférii je pin připojen. Protože je tak možné propojit ohromné množství periferií s piny procesoru, lze zdarma od výrobce stáhnout program (IO MUX), který úlohu usnadní tím, že vybíráme pin a periferii a program hlídá kolize.

Nyní tedy mohu nastavit správně multiplexer daného pinu a zapsat hodnotu. Po 30 hodinách usilovné práce LED dioda konečně bliká.

Jaké je řešení, pokud chceme více než blikající LED?

Řešení se nám nabízí pohledem na vývojový kit, kde je vidět volný 120pinový poměrně drobný konektor. Pohledem do katalogového listu kitu zjistíme, že konektor je určen pro připojení LCD displeje a popřípadě CMOS kamery. My ale přeci žádný další displej připojit nechceme, máme k VGA výstupu připojený velký LCD monitor. Dokonce ani kameru nemáme. My chceme připojit další LED diody, aby toho blikalo více, a také třeba nějaký analogový převodník. Řešení je naštěstí snadné. Pohledem do katalogového listu procesoru a programu IO MUX zjistíme, že na místo LCD displeje a kamery lze namapovat periferie jako třeba UART port, SPI port, vstupy a výstupy. Vzniká proto deska plošného spoje, která má zespodu připájen protikus konektoru z vývojového kitu a kde jsou rozvedeny všechny piny konektoru do okolí na plošky pro možnost připájení vodičů. Na destičce je také připájeno několik LED diod a je tu také místo pro připájení oddělovače sběrnice, případně LCD displeje. Součástí destičky je i propojovací pole. Vše je provedeno tak, aby vzájemné propojení bylo možné zapájením vodičů.

Nyní tedy připájím LED diody, ochranný odpor a jednu LED diodu připojím ke konektoru

V programu přemapuji vývody LCD výstupu na vstupně-výstupní piny, zapisuji správné hodnoty a led dioda bliká. Tentokrát vše funguje v podstatně kratší době.

A co na závěr?

Výsledek těchto pokusů se nyní jeví poněkud rozporuplný. Na jedné straně máme hotovou hlavní část elektroniky za velmi nízkou cenu a vše nám funguje. Nemusíme si lámat hlavu s velikostí bufferu pro sériovou linku a podobnými věcmi. Používáme také mnohokrát prověřené části kódu. Pro spoustu běžných aplikací, kdy se něco přijme po sériové lince, zobrazí na displeji, přefiltruje, pošle dále třeba po počítačové síti a současně zapíše na připojený SATA disk, je toto řešení k nezaplacení. Navíc si většinou vystačíme se znalostmi, které máme z programování z Windows. Na druhé straně, pokud budeme potřebovat reagovat na změnu hodnoty na některém pinu procesoru a následně něco poslat třeba po SPI portu, tak to už tak snadné nebude. Zde budeme muset nastudovat něco o psaní ovladačů pro LINUX a také vnitřní funkci LINUXu. Bez toho se ale neobejdeme, pokud budeme brát v úvahu nároky uživatelů na zařízení, zejména na možnost připojení k internetu.

int fd = open(„/dev/mem“, O_RDWR | O_SYNC);
if (fd < 0) {
printf(„Nelze otevrit pamet \n“);
return 0;
}
volatile ulong *pinconf;
pinconf = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x48000000);