1. Popis a použití Xilinx EDK V softwarovém balíku firmy Xilinx pro vývoj aplikací pro jejich hradlová polé se nachazejí dvě, spolu úzce spojené aplikace. Jedná se o aplikace, které umožnují návrh uživatelsky definovaného SoC (System on Chip) s softwarovým procesorem Microblaze a vývoj aplikací pro vytvořený SoC. Jak již názve napovídá jedná se v privní řádě o nástroj s názvem Xilinx Platfor Studio, které slouží ke konfiguraci SoC a příslušného hardwaru a Xilinx Software Developer Kit, který slouží pro vývoj aplikací.
1.1. Xilinx Platform Studio 1.1.1.
Počátční nastavení
Po spuštění tohto nástroje je možné si vybrat prázdný projekt, nastavení pomocí vizárdu a otevření již vytvořeného projektu. Toto okno je vidět na Obrázek 1.
Obrázek 1 - Počáteční okno platform studia.
My budeme používat vizárdu, protože vede nejrychleji k základní konfiguraci a minimalizuje riziko chyb. Po vybrání možnosti konfigurace pomoci vizárku se objeví okno pro vybrání složky kde má být projekt uložen. Následně se objeví hlavní okno vizárdu. V prvním kroku je uživatel dotazování jaký typ interní sběrnice bude použit a to z toho důvodu, že fy. Xilinx plánuje přechod na sběrnici AXI jejíž implementace je ve stavu testování. V dalším kroku se vizárd dotazuje zda chceme vytvořit úplně nový projekt nebo založit projekt na základě projektu předcházejících. Ve většině případu je nejbezpečnější založit nový projekt. Po stisku tlačítka Next se vizárd dotazuje na výběr cílové platformy. Toto ono lze vidět na Obrázek 2.
Obrázek 2 - Okno vizárdu pro nastavení cílové platformy.
1
Zde jsou dvě možnosti. První možnost je že chcete vytvořit projekt s vývojovou deskou. V takovém případě si vyberete první možnost se zvolenou desku. V takovémto případě máme usnadněnou práci, protože vizárd automaticky vloží moduly pro všechny hlavní periferie na desce a nastaví vstupy výstupu na odpovídající vývody hradlového pole. V případě, že chceme vytvořit projekt pro vlastní zapojení, nebo desku, která není v seznamu, musíme vybrat druhou možnost a správně nastavit typ použitého hradlového pole (V obou případech jsou další kroky stejné). Po stisku tlačítka next si může uživatel vybrat jestli chce systém s jedním nebo dvěma procesory. Toto okno je vidět na Obrázek 3.
Obrázek 3 - Okno vizárdu pro výběr procesorů.
V dalším kroku je uživatel dotazován na typ procesoru a to z toho důvodu, že v některých hradlových polích Virtex jsou hardwarové procesory Power PC. Dále je třeba vyplnit políčko referenční hodiny, které udává frekvenci externího oscilátoru, požadovanou rychlost procesoru, velikost interní paměti, tato paměť je tvořena BRAM bloky v hradlovém poli a její maximální hodnota závisí na vybraném hradlovém poli. Dále je možné zapnou FPU jednotu. Toto okno je zobrazeno na Obrázek 4.
Obrázek 4 - Okno vizárdu pro výběr základních vlastností procesoru.
2
V následujícím kroku je uživatel dotazován na periferie, které chce do projektu přidat. V případě, že vytváříme projekt pro předdefinovanou desku je seznam vybraných periferii předvyplněn a uživatel si může vybrat z omezeného množství viz Obrázek 5, nebo v případě, že vytváříme projekt pro vlastní desku můžeme si vybrat s celé škály periferii a jejich přednastavených názvu. Po vložení periferie nebo kliknutí na vloženou periferii můžeme definovat i její vlastnosti např. jestli má byt výstup přerušení periferie připojen k řadiči přerušení nebo pro GPIO nastavení počtu IO linek a jejich směru I, O a IO.
Obrázek 5 - Okno vizárdu s nastavením periferii pro předpřipravenou desku.
V následujících korcích můžeme povolit paměti cache procesoru a nastavit jejich velikost (paměť chache je také tvořena BRAM bloky hradlového pole). Toto okno je zobrazeno Obrázek 6.
Obrázek 6 - Okono vizárdu pro nastavení cache pamětí.
V předposledním kroku si můžeme vybrat kde bude paměťový a programový region pro standartní testovací aplikace a stdio. Toto je vidět na Obrázek 7.
3
Obrázek 7 - Okno vizárdu pro nastavení aplikace.
V posledním kroku se zobrazí seznam periferii a jejich adresový prostor spolu s výčtem umístění základních aplikaci pro testování. Toto okno je zobrazeno na Obrázek 8.
Obrázek 8 - Okno vizárdu souhrnu nastavení.
1.1.2.
Xilinx Platform Studio GUI
Na obrázku 9 je vidět okno Platform Studia. V levé části se nachází okno, které se děli na tří záložky. 1. 2. 3.
Seznam IP jader Testovací aplikace Soubory projektu
4
Přidělení adresových prostoru IP jadrům Propojení IO mezi IP jádry a okolím IP jádra v projektu - připojení ke sběrnici
Seznam IP Jader
Propojení sběrnic
Výstup události
Obrázek 9 - Okno platform studia.
Uprostřed celého okna se nachází podokno s IP jádry, které je rozděleno na tři části. První, která slouží pro připojení vložených jader na sběrnici, kde po rozbalení IP jádra se zobrazí možnosti napojení na sběrnici, případně po poklepání pravým tlačítkem myši se zobrazí okno s nastavením daného IP jádra. Na levé straně tohoto okna se nachází grafické zobrazení připojených sběrnic a na pravé straně můžeme vybraná propojení filtrovat. Druhé podokno porty slouží pro nastavení připojení IO jak mezi jednotlivými IP jádry tak hlavně s vnějším okolím. Zde po rozbalení daného IP jádra se zobrazí seznam IO signálu. Zde je třeba provést napojení potřebných signálu na IO hradlového pole. V případě, že jsme systém konfigurovali pro podporovanou desku nemusíme dělat nic. V případě, že IP jádro nebylo přidáno pomoci vizárdu je zapotřebí napojit příslušené IO signály na příslušné vývody hradlového pole v ucf souboru. Seznam IO signálu je již v tomto souboru předpřipraven (ucf soubor se nachází pod záložkou Projekt). Pokud jsme však IP jádro přidali manuálně bez vizárdu musíme propojení udělat ručně. A to tak, že v pravém horním rohu okna pro propojení zmáčkneme tlačítko vytvořit externí propojení. Tím vytvoříme externí signál, který se vytvoří jak v našem projektu tak v ucf souboru. Následně takto vytvořeny signál musíme připojit na požadovaný IO signál IP jádra a v ucf souboru mu přiřadit odpovídající vývod hradlového pole. Nesmíme však zapomenou, že připojení vektorových hodnot je v opačném pořadí například pro GPIO modul s osmi výstupy sedmý bit odpovídá LSB a nultý MSB hodnotě. Po dokončení konfigurace můžeme stisknout tlačítko Hardware – Gnerate bit stream, a následně nahrát zapojení do hradlového pole pomoci Device configuration – Download Bitstream. 1.1.3.
Nastavení adresového prostoru IP jader
U každého IP jádra je zapotřebí nastavit jeho adresový prostor. Počáteční adresa modulu se nastaví automaticky a je třeba nastavit rozsah adres. Rozsah adres je většinou udáván v dokumentaci k modulu, kterou je možno získat kliknutím levým tlačítkem myši na vybrané IP jádro a objeví se rozbalovací menu kde je i položka View PDF datasheet. Tento rozsah však nemusí byt přesně podle dokumentace, ale musí však být větší. Pro většinu IP jader stačí nastavit velikost adresového prostoru na 64KB. Pokud jde o řadiče paměti, velikost jejich adresového prostoru se nastaví podle velikosti vybraného paměťového modulu.
5
V záložce nastavení adres a rozsahu adres lze pro kontrolu stisknou tlačítko generate address, které slouží pro vygenerování adresových prostoru IP jader. V případě, že funguje špatně je nutné nastavit rozsahy manuálně (u některých starších verzí se to stávalo). 1.1.4.
Export projektu do SDK
Export projektu do SDK se provádí pomocí tlačítka Project – Export hardware to SDK. Pomoci této volby následně můžeme projekt exportovat do SDK a spustit SDK nebo jen exportovat upravený hardware.
1.2. SDK Xilinx Microblaze SDK je postaveno na známém vývojovém prostředí Eclipse. Hlavní okno toho prostředí je na obrázku 10. Seznam závislosti a definic
Okno s otevřenými sobory Okno projekt exploreru
Okno výstupu
Obrázek 10 - Okno SDK.
Hlavní okno se, jak je vidět, dělí na čtyři hlavní oblasti. 1. 2. 3. 4.
Okno s otevřenými soubory, převážně zdrojovými. Okno projekt exploreru, kde mohou být programové projekty, BSP (Board Suppor Package) a HW platforma exportovaný s platform studia. Okno outline, kde se zobrazují závislosti z aktuálně zobrazeného souboru jako hlavičkové soubory, definice a podobně. Okno výstupu, které obsahuje jak výstup kompilátoru tak i výstupy z jiných míst. 1.1.5.
Vytvoření nového projektu
Vytvoření nového projektu můžeme provést po exportu hardwarového projektu do SDK, který se exportuje pod názve hw_platform_0. Dále můžeme postupovat výběrem File – Project – New – Bord support package viz Obrázek 11, nebo přímo výběrem nového projektu C nebo C++, který vytvoří automaticky i odpovídající Bord support package.
6
Obrázek 11 - Oko pro vytvoření board support package.
Přehlednější je vytvořit nejdříve board support packake, kde si můžeme vybrat hardwarovou platformu pokud jich v projektu máme více (mít v projektu více hardwarových platforem může však vést k chybám a omylům proto toto nedoporučuji), dále lze vybrat samostatnou aplikaci nebo s podporou staticky linkovaného operačního systému, který podporuje POSIXové funkce. Nedoporučuji měnit název projektu, protože v některých verzích to může způsobovat jisté potíže. Po dokončení se zobrazí okno s nastavením, kde můžeme ještě udělat úpravy jako změnit napojení stdio viz Obrázek 12. Stdio může být buď vypnuté, nebo používat komunikaci přes debug JTAG a nebo před hardwarový sériový port. Dále se mohou přidat některé speciální ovladače po kliknutí na Overview a podobně.
Obrázek 12 - Nastavení ovladačá a stdio.
Po dokončení můžeme vytvořit vlastní projekt buď v jazyce C nebo C++. Zde si můžeme vybrat z několika přednastavených ukázkových a testovacích aplikaci viz Obrázek 13. V případě, že zvolíme prázdnou aplikaci musíme do vytvořeného projektu přidat zdrojové kódy (hlavně zdrojový kód z funkci main). Proto je nejlepší zvolit aplikaci hello world, která obsahuje základní zdrojový kód a inicializaci a s ní vycházet. V posledním kroku si můžeme vybrat BSP pro, který chceme aplikaci vytvořit viz Obrázek 14.
7
Obrázek 13 - Nastavení aplikace.
Obrázek 14 - Nstavení BSP pro aplikaci.
BSP je knihovní modul obsahující veškeré podpůrné knihovny, ovladače periferii a inicializační rutiny celého systému. 1.1.6.
Práce s SDK
Do projektu lze přidávat soubory pravým kliknutím na požadovanou složkou a výběrem požadované položky (zdrojový, hlavičkový a jiný soubor). Sestavení projektu se obvykle provede po uložení modifikovaného zdrojového souboru nebo manuálně tlačítkem Project – Build All. Projekt můžeme do procesoru nahrát dvojím způsobem. Zaprvé tlačítkem ve tvaru znaku play , které jen do procesoru projekt nahraje a spustí. Druhý způsob je z možností ladění. Pokud chceme aplikaci ladit zmáčkneme ve vývojovém prostředí tlačítko tvaru brouka . Prostředí se potom přepne do debug modu, kde k základním oknům přibydou okna s informacemi o běžícím procesu, watch window a případně okno disasembleru. Řízení běhu programu je v nabídce Run. Do módu psáni zdrojových kódu se můžeme přepnut tlačítkem C/C++ wiew v pravém horním rohu okna. 8
Popis ovladačů periferii a procesorů se da najít v BSP. Po kliknutí na soubor system.mss se zobrazí seznam použitých IP jader a po kliknutí na položku Documentation se zobrazí dokumentace k ovladačům.
1.3. Popis ovladačů základních periferii Ovladače lze rozdělit na dva základní typy. Prvním typem ovladače jsou low level ovladače, které jsou tvořeny převážně definicí maker pro nastavení registrů a jejich řídících bitů a ovladače na vyšší úrovni, které by měly fungovat správě i v případě, že dojde k revizi daného IP jádra. Zde budou popsány ovladače vyšší vrstvy. 1.1.7.
Ovladače GPIO
Nejprve je třeba ovladač GPIO inicializovat pomocí funkce int XGpio_Initialize(XGpio*InstancePtr, u16 DeviceId) Prvním parametrem této funkce je ukazatel na strukturu XGpio, která musí být nejdříve alokování a je inicializováno touto funkcí. Touto hodnotou se dále odkazujeme na instanci daného GPIO. Druhým parametrem je ID instance. Definice tohoto ID lze najít v hlavičkovém souboru xparameters.h. Název tohoto ID je tvořen takto XPAR_název_DEVICE_ID, kde název odpovídá názvu periferie v platform studiu. Návratová hodnota funkce XST_DEVICE_NOT_FOUND.
je
v případě
úspěchu
XST_SUCCESS
a
v případě
neúspěchu
Nastavení IO linek jako vstupu/výstupu se provádí pomoci funkce void XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Chanel, u32 DirectionMask) v případě, že je celý GPIO kanál nastaven jako vstupní či výstupní již při návrhu hardwaru není nutno tuto funkci používat. Kde první parametr je ukazatel na strukturu XGpio viz inicializace, druhým parametrem je GPIO kanál, který může být 1 nebo 0 viz dokumentace k GPIO, třetí parametr určuje směr jednotlivých vývodu GPIO modulu a platí výstup – 0 vstup – 1. Nastavení směru GPIO linek lze pomocí funkce void XGpio_GetDataDirection(XGpio *InstancePtr, unsigned Channel) Kde první parametr je ukazatel na strukturu XGpio viz inicializace, druhým parametrem je GPIO kanál, který může být 1 nebo 0 viz dokumentace k GPIO. Pro změnu stavu jednotlivých výstupu GPIO modulu jsou k dispozici tři funkce: void XGpio_DiscreteClear(XGpio *InstancePtr, unisgned Channel, u32 Mask) tato funkce vynuluje příslušené vývody GPIO modulu v závislosti na hodně Mask (vynuluje ty hodnoty, které jsou v Mask nastaveny na hodnotu 1). void XGpio_DiscreteSet(XGpio *InstancePtr, unisgned Channel, u32 Mask) Tato funkce se chová podobně jako předcházející funkce s tím rozdílem, že nastavuje příslušné vývody. void XGpio_DiscreteWrite(XGpio *InstancePtr, unisgned Channel, u32Data) Tato funkce zapíše na výstupy GPIO modulu hodnotu parametru Data. Funkce void XGpio_DiscreteRead(XGpio *InstancePtr, unisigned Chanel) provede přečtení IO linek GPIO modulu. 9
Ovladač také obsahuje další funkce, pro řízení přerušení GPIO modulu, které jsou k dispozici pokud je v hardwaru GPIO modulu tento rys povolen. Popis těchto funkcí viz originální dokumentace. 1.1.8.
Ovladače časovače
Inicializace časovače probíhá podobně jako je tomu u GPIO modulu pomocí funkce: int XTmrCtr_Initialize ( XTmrCtr *InstancePtr, u16 DeviceId) Prvním parametrem této funkce je ukazatel na strukturu XTmrCtr, která musí být nejdříve alokování a je inicializována touto funkcí. Touto hodnotou se dále odkazujeme na instanci daného časovače. Druhým parametrem je ID instance. Definice tohoto ID lze najít v hlavičkovém souboru xparameters.h. Název tohoto ID je tvořen takto XPAR_název_DEVICE_ID, kde název odpovídá názvu periferie v platform studiu. Návratové hodnoty funkce jsou následující: XST_SUCCESS pokud inicializace proběhlá v pořádku. XST_DEVICE_IS_STARTED pokud už časovač je zapnutý a XST_DEVICE_NOT_FOUND pokud specifikované zařízení nebylo nalezeno. Funkcí void XTmrCtr_SetOptions ( XTmrCtr *InstancePtr, u8 TmrCtrNumber, u32 Options) se provádí nastavení časovače, kde první parametr je ukazatel na strukturu XTmrCtr, druhý parametr je číslo časovače. Toto číslo může nabývat hodnot podle hardwarové specifikace a posledním parametrem je nastavení a může nabývat těchto hodnot, které mohou být spojeny logickou operací OR. XTC_ENABLE_ALL_OPTION umožnuje nastavení všech čítačů na jednou se stejnými parametry. XTC_DOWN_COUNT_OPTION nastaví čítání čítače směrem dolů od počáteční hodnoty. Pokud není tento parametr použit čítač čítá směrem nahoru. XTC_CAPTURE_MODE_OPTION povolení módu zachytávání. XTC_INT_MODE_OPTION povolení přerušení od daného čítače. XTC_AUTO_RELOAD_OPTION povolení obnovení hodnoty čítače s compare registru v compare modu. V případě zachytávacího módu se hodnota compare registru přepíše při každém zachycení příslušné události. XTC_EXT_COMPARE_OPTION povolení externího výstupu compare. Další funkce slouží pro nastavení hodnoty, která je přednastavena do čítače při přeteční. void XTmrCtr_SetResetValue ( XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 ResetValue) první dva parametry této funkce jsou stejné jako v předchozím případě a poslední hodnota odpovídá požadované hodnotě pro přednastavení čítače. Čítač se spouští pomocí funkce void XTmrCtr_Start ( XTmrCtr * InstancePtr, u8 TmrCtrNumber) kde oba parametry této funkce odpovídají zase předcházejícím funkcím. Čítač se zastavuje funkcí void XTmrCtr_Stop ( XTmrCtr * InstancePtr, u8
TmrCtrNumber)
10
kde oba parametry této funkce odpovídají zase předcházejícím funkcím. Dále je možné specifikovaný čítač vynulovat na jeho resetovací hodnotu pomocí funkce void XTmrCtr_Reset ( XTmrCtr * InstancePtr, u8
TmrCtrNumber )
Ostatní funkce viz dokumentace k ovladači. 1.1.9.
Řadič přerušení
Inicializace řadiče přerušení probíhá podobně jako v předchozích případech. Pro inicializaci se používá funkce int XIntc_Initialize ( XIntc *InstancePtr, u16 DeviceId) Prvním parametrem této funkce je ukazatel na strukturu XIntc, která musí být nejdříve alokování a je inicializována touto funkcí. Touto hodnotou se dále odkazujeme na instanci řadič přerušení. Druhým parametrem je ID instance. Definice tohoto ID lze najít v hlavičkovém souboru xparameters.h. Název tohoto ID je tvořen takto XPAR_název_DEVICE_ID, kde název odpovídá názvu periferie v platform studiu. Návratové hodnoty této funkce mohou být XST_SUCCESS pokud inicializace proběhlá v pořádku. XST_DEVICE_IS_STARTED pokud už řadič je zapnutý a XST_DEVICE_NOT_FOUND pokud specifikované zařízení nebylo nalezeno. Připojení callback funkce pro požadované přerušení se provádí funkcí int XIntc_Connect ( XIntc *InstancePtr, u8 Id, XInterruptHandler Handler, void * CallBackRef) Kde první parametr je ukazatel na strukturu XIntc druhým parametrem je ID vstupu přerušení, který chceme připojit. Počet těchto hodnot odpovídat hardwarové konfiguraci řadiče přerušení a hodnota pozici na, kterou je přerušení připojeno v řadiči přerušení. Druhý parametr je ukazatel na callback funkci, která se volá pokud nastane dané přerušení a třetí parametr je parametr, který chceme této funkci přiřadit. Návratová hodnota této funkce, pokud proběhla v pořádku, je XST_SUCCESS. V opačném případě není hodnota definována. Připojení obslužné funkce z řadiče přerušení lze odebrat pomocí funkce void XIntc_Disconnect (XIntc *InstancePtr, u8 Id) Kde parametry této funkce odpovídají prvním dvěma parametrům funkce předcházející. Spuštění/povolení řadiče přerušení probíhá pomocí funkce int XIntc_Start (XIntc *InstancePtr, u8 Mode) kde první parametr funkce je ukazatel na strukturu XIntc a druhým parametrem se nastavuje mód řadiče přerušení, který pro normální použit musí mít hodnotu XIN_REAL_MODE, druhá možnost je pro simulační účely viz dokumentace k ovladači. Návratová hodnota této funkce může být XST_SUCCESS pokud spuštění proběhlo v pořádku v opačném případě není hodnota specifikována.
11
Zakázat přerušení lze pak funkcí void XIntc_Stop ( XIntc * InstancePtr ) kde první parametr je stejný jako v přechozích případech. Funkce void XIntc_Enable ( XIntc *InstancePtr, u8 Id) a void XIntc_Disable ( XIntc *InstancePtr, u8 povolují a zakazují specifikované přerušení v řadiči přerušení. Funkcí void XIntc_Acknowledge (XIntc * InstancePtr, u8
Id)
se potvrdí vstup do dané rutiny přerušení a vynuluje se příznak daného přerušení. Ostatní funkce viz dokumentace k ovladači.
12
Id)