Novinka:Začínáme s STM32F4 Discovery 12
(Kategorie: Mikroprocesory)
Napsal mard
01.01.1970 01:00

Autorem tohoto dílu kolega yaqwsx, který je "zodpovědný" též za 9. díl. Děkuji za server za zaslání kódu a návodu pro ostatní. Předmětem článku je připojení STM32F4 Discovery kitu k zařízení Anroid, kdy F4 vytváří USB host připojení a Android je USB Device (stačí verze Android > 2.2). Doufám že i pro Vás to bude tak zajímavé čtení, jako pro mne.




Připojení STM32F4 Discovery kitu k zařízení s Androidem

Jak jsem zde již psal před Vánocemi, pořídil jsem si levný čínský tablet, který bych rád využil jako pohodlné uživatelské rozhraní k aplikaci běžící na STM32F4 kitu. Vedla mě k tomu nejen cena takového řešení, ale i relativní jednoduchost vývoje takového rozhraní a také to, že připojení tabletu mi otevře další možnosti – snadno připojím různá vstupní zařízení (USB disk, WiFi, připojení k internetu atd.) a také můžu využít jeho výpočetní výkon a na STM32F4 nechat pouze obsluhu IO (GPIO, SPI, atd.) a úkoly, které vyžadují přesné časování.
Po prvních pokusech, které se nepovedly, se mi konečně podařilo propojit tablet s STM32F4 kitem. Rád bych se v tomto článku podělil o některé mé poznatky a zkušenosti. Pro tuto ukázku jsem nechal v Discovery kitu nahraný program z článku „Začínáme s STM32F4 Discovery 8“ (nebo 8B či 9 – záleží, jak byly články číslovány), kde se kit hlásí jako vendor-defined zařízení s 1 vstupním a 1 výstupním bulk endpointem. Aby bylo vidět, že komunikace funguje, tak kit podle 1. přijatého bytu z paketu rozsvítí/zhasne příslušnou LED (0-3) a při stisku uživatelského tlačítka na kitu odešle textový řetězec s celkovým počtem stisků tlačítka.
Toto byla má první zkušenost s vývojem aplikace pro Android a po dlouhé době nějaká aplikace napsaná v Javě. Omlouvám se, pokud jsou v kódu nějaké prvky či konstrukce, které se v Javě nenosí. Java není můj šálek kávy a raději se jí obloukem vyhýbám.
Pokud s vývojem pro Android začínáte tak jako já, můžu vás odkázat na výborný seriál článků o vývoji pro Android: www.zdrojak.cz/clanky/vyvijime-pro-android-zaciname/. Myslím, že je skvělým učebním materiálem do začátků.


Realizace androidí aplikace

Pro přístup k zařízení využívám USB Host API, díky kterému odpadá nutnost psát kernel modul. Umožňuje nám tedy přímo zapisovat na endpointy z user space – stejně jako např. WinUSB nebo libUSB.
Původně jsem zamýšlel si napsat obecnou třídu pro obsluhu zařízení, kterou bych mohl do budoucna používat ve svých projektech. Tato třída by měla v podstatě 2 metody – Inicializovat, Odeslat data + by se jí předal callback objekt pro zpracování přijatých dat. Poté, co jsem se ponořil do studia USB Host API, mě tato myšlenka přešla. Nevím proč je toto API tak úzce vázáno na androidí Activity. Dokonce i ukázkové kódy od Googlu se nesnaží o nějaké oddělení samotné komunikace od GUI aplikace. Tento fakt mě zarazil – nedovedu si zatím představit, jak to vše bude vypadat v rozsáhlé aplikaci.
Když jsem se oprostil od snahy elegantně oddělit komunikaci a GUI, ukázalo se, že práce s USB zařízením je hračka. Vše potřebné je poměrně pěkně popsáno v dokumentaci, ze které jsem hodně čerpal z developer.android.com/guide/topics/connectivity/usb/host.html. Myslím si, že práci se zařízením není problém pochopit z dokumentace a kód mé demonstrační aplikace je celkem jasný. Přesto jej však stručně okomentuji.
Demonstrační aplikace obsahuje 2 textView – v jednom se zobrazuje současný stav zařízení (připojeno/nepřipojeno), v druhém se zobrazuje řetězec přijatý z kitu. Pod nimi se nachází tlačítko, kterým lze rozsvítit/zhasnou LED.
Během inicializace Activity je třeba si vyžádat UsbManager, který je bránou pro práci s USB zařízeními. Dále je třeba zaregistrovat Intent filtr pro obsluhu některých událostí – zejména událost ACTION_USB_PERMISSION, kdy je aplikaci uděleno povolení komunikovat s USB zařízením. Tato událost se projeví jako dialogové okno, které se uživatele ptá, jestli povolit naší aplikaci komunikaci s daným zařízením. Bohužel se mi nepovedlo zjistit, jak toto povolení udělit permanentně. Pokud se někdo vyznáte ve vývoji pro Android, byl bych velice rád za radu – zdali je to vůbec možné.
V mé aplikaci jsem ještě zaregistroval filtr pro odpojení zařízení a pokusil se aplikovat i filtr pro připojení zařízení. Ten mi bohužel nefunguje – tato notifikace k mé aplikaci nikdy nedorazí (viz mUsbReceiver v kódu). Tento filtr jsem ponechal (třeba někdo mou chybu najde), ale detekci zařízení má na starosti samostatné vlákno, které se každých 400 ms pokouší enumerovat zařízení.
Enumeraci zařízení má na starosti funkce TryToEnumerate, která si vyžádá z UsbManageru seznam všech připojených zařízení. Poté pro každé zařízení zkontroluje VID a PID, aby našlo náš kit. Jakmile jej najde, vyžádá si povolení s ním začít komunikovat.
Potvrzení o povolení obdrží objekt mUsbReceiver, který zavolá metodu Connect. Tato metoda se postará o vše ostatní. Otevře rozhraní, uloží si endpointy a spustí vlákno, které obsluhuje příjem dat.
Naopak metoda Disconnect uzavře komunikaci se zařízením. Zde si všimněte, že veškerá práce s UI je prováděna skrze funkci runOnUiThread. Metody Connect a Disconnect totiž mohou být (a jsou) volány z jiného vlákna, což by mohlo způsobovat problémy.
Samotné posílání/přijímání dat jev API řešeno funkcí UsbConnection::bulkTransfer, která přebírá endpoint, buffer, jeho délku a timeout. Tato funkce slouží k synchronnímu čtení/zápisu. Měla by vždy být volána v pracovním vlákně, nikdy ne ve vlákně UI, aby nezpůsobila krátkodobé „zamrznutí“ aplikace. Existuje i třída UsbRequest, která má za úkol provádět čtení/zápis asynchronně. Tu jsem však v této demonstrační ukázce nepoužil.


Problémy a triky

Během snahy rozchodit USB komunikace mezi tablet a kitem jsem narazil na celou řadu problémů, které se mi však povedly vyřešit. Zde je uvádím:


ADB ovladač pro no-name zařízení

Zařízení s Androidem mohou fungovat jako hardwarový debugger. Pro tento účel však potřebují ADB ovladače, které má dle Googlu dodávat výrobce zařízení. Což je u no-name zařízení problém. Naštěstí existuje univerzální ovladač. Aby šel použít, je potřeba upravit inf soubory – doplnit do nich správná PID a VID. Ovladač naleznete v přiloženém archívu.


Debuggování aplikací využívající USB host

Na mém tabletu je realizováno USB OTG – tedy přes jeden konektor může fungovat tablet jako host nebo device. Tím pádem nelze mít tablet jako debugger připojený k počítači kabelem a zároveň mít k tabletu připojený kit. Naštěstí na to existuje elegantní řešení – ADB komunikaci pro debuggování lze „přesměrovat“ na WiFi. Stačí připojit tablet k počítači pomocí USB a poté postupovat podle tohoto návodu: developer.android.com/guide/topics/connectivity/usb/index.html. Toto řešení funguje spolehlivě, až na jedno drobné úskalí – pokud uložím počítač do režimu spánky či hibernace, tak se už kabel nechce ani pomocí WiFi, ani pomocí kabelu k počítači připojit. Jediným řešením je restartovat tablet.


Nefungující USB Host API

Když jsem poprvé zkusil připojit kit k tabletu, nepovedlo se mi to. Ačkoliv tablet fungoval s jakýmkoliv zařízením (od myší, přes klávesnice až po disky), tak mi USB Host API neenumerovalo jediné zařízení. Dlouho jsem tento problém nemohl vyřešit, až po tipu uživatele XDA Developers jsem našel řešení. Problém byl v chybějících permissions souborech v systému. Pro povolení stačí postupovat podle tohoto návodu: stackoverflow.com/questions/11183792/android-usb-host-and-hidden-devices.


Spouštění aplikace při připojení zařízení

Přidáním několika málo řádků do manifestu aplikace lze definovat aplikaci jako výchozí pro dané zařízení – tedy to, že se Android při připojení daného zařízení uživatele zeptá, zdali chce spustit naši aplikaci.
Stačí do sekce dopsat následující kód:
<intent-filter>      <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /></intent-filter><meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />

a vytvořit XML soubor device_filter s obsahem:
<?xml version="1.0" encoding="utf-8"?><resources>    <usb-device vendor-id="1155" product-id="22288" /></resources>

Pozor – VID i PID jsou v decimálním, nikoliv hexadeciálním tvaru, jak je zvykem.

Závěr

Zkombinováním tabletu a mikroprocesoru se dle mě otevírají obrovské možnosti pro hobby sféru. Doufám, že vám tento mini-návod přinesl něco nového.
Pokud máte nějaké připomínky/dotazy rozhodně mě kontaktujte. A pokud máte nějaký projekt postavený na tomto řešení, určitě se pochlubte!


Odkazy

Zdrojový kód C pro STM32F4 Discovery je zde.
Zdrojový kód Java pro tablet s Androidem je zde.


Začínáme s STM32F4 kitem 1. odkaz (vývojové prostředí, atd.)
Začínáme s STM32F4 kitem 2. odkaz (USB Úvod)
Začínáme s STM32F4 kitem 3. odkaz (USB Enumerace)
Začínáme s STM32F4 kitem 4. odkaz (USB Virtual COM port)
Modifikace USB HID pro STM32F103 odkaz
Začínáme s STM32F4 kitem 5. odkaz (označení portů, alternativní funkce)
Začínáme s STM32F4 kitem 6. odkaz (VGA monitor)
Začínáme s STM32F4 kitem 7. odkaz (USB HID)
Začínáme s STM32F4 kitem 7b. odkaz (Doplněk k HID - senzory)
Začínáme s STM32F4 kitem 8. odkaz (PC aplikace k USB HID)
Začínáme s STM32F4 kitem 9. odkaz (USB Bulk transport)
Začínáme s STM32F4 kitem 10. odkaz (Micro-Xplorer)
Začínáme s STM32F4 kitem 11. odkaz (časovač/timer)



Tato novinka je z -MCU-mikroelektronika
( http://mcu.cz/news.php?extend.3292 )