\chapter{C API komunikační rozhraní}
\label{sec:cAPI_rozhrani}
Jako C API (Application Programming Interface) je označováno rozhraní, které je využíváno pro programování heterogenních aplikací. API obsahuje funkce, třídy anebo procedury nějaké knihovny, které mohou být programátorem použity. Application Programming Interface popisuje, jak se daná funkce volá a~jaký parametr po jejím zavolání funkce vrátí v~návratové hodnotě. Rozhraní založené na~stejném principu bylo implementováno pro vytvoření komunikace mezi RealTime procesorem a \zk{zkFPGA} na~platformě \zk{zkcRIO}.

\begin{figure}[!h]
	\begin{center}
	\includegraphics[width=1 \linewidth]{obrazky/C_API_overview2}
	\caption{C interface pro \zk{zkFPGA} \cite{Building_R_Series_FPGA_Interface_Host_Application_in_C}	}
	\label{obr:C_API_overview2}
	\end{center}
\end{figure}
Na obrázku \ref{obr:C_API_overview2} je znázorněno propojení RealTime procesoru a~\zk{zkFPGA}, které jsou osazeny uvnitř platformy \zk{zkcRIO}. Programová výbava musí být vytvořena individuálně pro každý procesor. Tvorba programu pro RealTime procesor může být realizována buď pomocí grafického programování nebo programováním v~jazyce C. Programování \zk{zkFPGA} je možné realizovat pouze pomocí grafického uživatelského prostředí \zk{zkLabVIEW}, které musí být následně přeloženo do~jazyka VHDL. Po překladu vytvořeného programu pro \zk{zkFPGA} musí být přeložený program do~\zk{zkFPGA} nahrán a~následně spuštěn.

\section{Popis rozhraní C API}
Fyzickou vrstvou komunikace mezi RealTime procesorem a~\zk{zkFPGA} tvoří systémová sběrnice AXI (Advanced Extensible Interface). Aby bylo možné po této sběrnici posílat data mezi procesorem a~\zk{zkFPGA}, musí být vytvořen komunikační kanál, kterým budou posílány data v~podobě zpráv mezi procesorem a~hradlovým polem.

Při řešení této práce musela být vyřešena situace, kdy byl vytvořen řídicí algoritmus pro práci s~instancí \zk{zkFMU}, který měl být schopen zpracovávat naměřená data z~reálného prostředí. V~systémech \zk{zkcRIO} je možné pro zvýšení spolehlivosti měření fyzikálních veličin použít \zk{zkFPGA}, ke kterému jsou připojeny vstupně výstupní karty. Vstupně výstupní karty slouží pro interakci mezi okolním prostředím a~\zk{zkFPGA} a~také pro převod fyzikálních veličin do~digitální podoby. Vstupně výstupní karty mohou být v~libovolné konfiguraci a~pořadí připojeny do~šasi platformy \zk{zkcRIO}. K~těmto kartám jsou připojeny jednotlivé senzory, které snímají sledované fyzikální veličiny. Tímto je zajištěno měření fyzikálních veličin na~reálném systému.

Naměřené hodnoty, jejichž spolehlivé snímání zajišťuje \zk{zkFPGA}, však bylo nutné zpracovat v~RealTime procesoru, ve kterém se nacházel vlastní algoritmus instance \zk{zkFMU}. K~předání naměřených hodnot z~\zk{zkFPGA} do~RealTime procesoru (nebo naopak) slouží spojení pomocí DMA rozhraní nebo Peer-to-Peer spojení. V~případě použití DMA rozhraní musí být v~projektové složce \zk{zkLabVIEW} vytvořena fronta typu FIFO, do~které je následně možné například z~VI pro \zk{zkFPGA} zapisovat naměřené hodnoty. Naměřené hodnoty je pak možné v~nadřazené RealTime aplikaci dále podle potřeby zpracovávat a~vyhodnocovat.

\begin{figure}[!h]
	\begin{center}
	\includegraphics{obrazky/NIcRIO9068inside}
	\caption{Propojení \zk{zkFMU} s~\zk{zkLabVIEW} \zk{zkFPGA}}
	\label{obr:NIcRIO9068inside}
	\end{center}
\end{figure}
Pro splnění posledního bodu zadání této práce bylo nutné realizovat propojení vytvořené instance \zk{zkFMU} (umístěna v~RealTime části \zk{zkcRIO}) s~\zk{zkLabVIEW} \zk{zkFPGA}. Za tímto účelem bylo použito \zk{zkFPGA} C API rozhraní, které podle \cite{Introduction to the FPGA Interface C API} poskytuje téměř totožnou funkcionalitu, jako grafický nástroj \zk{zkLabVIEW}. Výhodou \zk{zkFPGA} C API rozhraní je, že přináší možnost automatického generování graficky vytvořeného programu v~prostředí \zk{zkLabVIEW} přímo do~programu jazyka C. Vygenerovaný program jazyka C je možné následně vložit do~programu pro RealTime procesor a~zpracovávat v~něm naměřená data z~\zk{zkFPGA}. 


\section{Propojení \zk{zkFMU} s~\zk{zkLabVIEW} \zk{zkFPGA}}
Pro realizaci propojení \zk{zkFMU} s~\zk{zkLabVIEW} \zk{zkFPGA} byl nejprve vytvořen nový projekt v~prostředí \zk{zkLabVIEW}. V~projektu bylo vytvořeno nové VI s~názvem \textit{FPGA.vi}, které bylo ve stromu projektu umístěno pod zařízením \zk{zkFPGA}. Před samotným vytvořením programu pro \zk{zkFPGA} v~grafickém prostředí byla do~šasi stanice \zk{zkcRIO} vložena vstupně výstupní karta s~označením \textit{NI-9401}.

\begin{figure}[!h]
	\begin{center}
	\includegraphics{obrazky/NI9401vstupyvystupy}
	\caption{Vnitřní struktura digitální vstupně výstupní karty NI 9401 \cite{NI9401datasheet}	}
	\label{obr:NI9401vstupyvystupy}
	\end{center}
\end{figure}
Karta \textit{NI-9401} disponovala 8~DIO s~TTL logikou. Uvnitř karty je 8~DIO seskupeno do~dvou portů, které mohou být nakonfigurovány buď jako vstupy nebo jako výstupy. Aby mohla být jednoduše otestována funkčnost propojení \zk{zkFMU} s~\zk{zkLabVIEW} \zk{zkFPGA}, byl první port nakonfigurován jako vstupní a~druhý port jako výstupní. Na~jeden vstupní pin prvního portu bylo připojeno tlačítko a~ke dvěma výstupním pinům druhého portu byly připojeny LED diody s~předřadným rezistorem. Hodnota předřadného rezistoru byla stanovena pomocí Ohmova zákona na~základě maximálního dovoleného proudu, který měl diodou téct v~sepnutém stavu.

Poté byl v~prostředí \zk{zkLabVIEW} pomocí knihovních bloků vytvořen program (viz obrázek \ref{obr:FPGA_VI}), který realizuje rozsvícení jedné LED diody po stisknutí tlačítka. Tento program byl přeložen do~jazyka VHDL. Při spuštění překladu programu pomocí tlačítka \textit{Run}, došlo k~chybě, která vznikla kvůli nenainstalovanému překladač VHDL jazyka. Na~stránkách National Instruments byl jako kompatibilní překladač pro platformu NI~\zk{zkcRIO}~9068 nalezen \textit{LabVIEW 2017 FPGA Module Xilinx Compilation Tool for Vivado 2015.4}. Získaný překladač byl po zavření všech otevřených projektů nainstalován. Po opětovném spuštění vytvořeného projektu a~spuštěním kompilace vytvořeného programu proběhl překlad do~jazyka VHDL v~pořádku a~vzniklý binární soubor byl nahrán do~\zk{zkFPGA}. Po úspěšném otestování funkčnosti rozsvícení jedné LED diody pomocí tlačítka byl program modifikován tak, aby druhá LED dioda byla ovládaná pomocí binární proměnné na~front panelu VI pro \zk{zkFPGA}. Program byl opět přeložen do~jazyka VHDL a~nahrán do~\zk{zkFPGA}, jako v~předchozím případě.

\begin{figure}[!h]
	\begin{center}
	\includegraphics{obrazky/FPGA_VI}
	\caption{Vytvořený program v~FPGA.vi}
	\label{obr:FPGA_VI}
	\end{center}
\end{figure}
Z informací uvedených v~\cite{Introduction to the FPGA Interface C API} vyplynulo, že C API rozhraní používá k~vytvoření zdrojových souborů jazyka C generátor, který tvoří zdrojové soubory na~základě binárního souboru vytvořeného při překladu grafického programu do~jazyka VHDL. Na~základě informací uvedených v~\cite{Introduction to the FPGA Interface C API} byla spuštěna generace zdrojových souborů jazyka C. Po jejím spuštění nastala chyba, která byla způsobena absencí SW \textit{FPGA Interface C API 2.0} dostupného z~\cite{CAPIlinktowownload}.

Po doinstalování \textit{FPGA Interface C API 2.0} a~znovu spuštění procesu generování zdrojových souborů jazyka C, byl v~projektové složce vytvořen nový adresář s~názvem \textit{FPGA Bitfiles}. Tento adresář obsahoval soubory \textit{NiFpga.c}, \textit{NiFpga.h}, \textit{NiFpga\_FPGA.h} a~\textit{NiFpga\_FPGA.lvbitx}.

Je nutné zdůraznit, že C API generátor nepodporuje všechny datové typy, které grafické programovací prostředí \zk{zkLabVIEW} nabízí. Mezi C API generátorem podporované datové typy patří:

\begin{itemize}
\item Boolean
\item Integer
\item Floating Point
\item \zk{zkLabVIEW} \zk{zkFPGA} controls/indicators
\item DMA FIFOs
\item a~přerušení
\end{itemize}
\smallskip
Ostatní datové typy jako například Fixed point, což je nativní datový typ pro \zk{zkFPGA}, a~clustery, které používá prostředí \zk{zkLabVIEW}, nejsou podle \cite{Programming with the FPGA Interface C API} podporovány.

\section{Práce s~rozhraním C API}
C API generátorem vytvořené soubory byly vloženy do~Eclipse projektu, ve kterém byla vytvořena instance \zk{zkFMU}. Bylo nutné přidat složku s~umístěním těchto souborů do~cesty linkeru v~\textit{Project properties}. K~tomu, aby mohly být využity funkce C API rozhraní, musel být vložen soubor \textit{NiFpga\_FPGA.h} do~programu \textit{main.c} pomocí klíčového slova \textit{\#include "NiFpga\_FPGA.h"}. Kromě toho musela být do~Eclipse projektu přidána také knihovna standardních symbolických konstant a~typů pomocí příkazu \textit{\#include <unistd.h>}.

V souboru \textit{NiFpga\_FPGA.h} se nachází funkce rozhraní C API, které je možné použít při vytváření vlastní aplikace. Kromě samotných funkcí je v~tomto souboru definována proměnná \textit{NiFpga\_FPGA\_Bitfile}, která říká jak je pojmenován bitový soubor \textit{*.lvbitx}. Je zde také uvedena proměnná \textit{NiFpga\_FPGA\_Signature} jejíž hodnota definuje digitální podpis binárního souboru.

Na základe tutoriálu nalezeného v~\cite{Programming with the FPGA Interface C API} byl do~programu \textit{main.c}, který řešil simulaci instance \zk{zkFMU}, vytvořen program, který zprovoznil komunikaci mezi RealTime procesorem a~\zk{zkFPGA}.
\begin{small}
\begin{lstlisting}[breaklines=true, caption={Vytvoření relace spojení RealTime procesoru a~FPGA},captionpos=b,label={lst:CAPI_creation_relace}]
NiFpga_Session session;

/* Load FPGA interface library */
NiFpga_Status status = NiFpga_Initialize();

/* Open a~session with FPGA, download and run the bitstream on the FPGA and store any error info in "status" */
NiFpga_MergeStatus(&status, NiFpga_Open("/home/admin/ProjectsMalik/NiFpga_FPGA.lvbitx",
				NiFpga_FPGA_Signature,
				"RIO0",
				0,
				&session));
}
\end{lstlisting}
\end{small}
\par
Po vložení vygenerovaných souborů do~Eclipse projektu byl do~hlavního programu vložen hlavičkový soubor \textit{NiFpga\_NazevVlastnihoFPGAprojektu}. V~tomto souboru byly definovány všechny C API rozhraním podporované proměnné, které byly vytvořeny v~rámci VI umístěného v~\zk{zkFPGA}.

Před tím, než mohla být zahájena výměna dat mezi RealTime a~\zk{zkFPGA} uvnitř \zk{zkcRIO}, musela být nejprve vytvořena relace spojení odkazující na~příslušný bitový soubor, viz výpis \ref{lst:CAPI_creation_relace}.

K vytvoření relace bylo nutné zadat unikátní podpis bitového souboru a~také název zdroje. Dalším krokem před zahájením komunikace byla inicializace proměnných, které ovládaly chování VI aplikace v~\zk{zkFPGA}, viz výpis \ref{lst:CAPI_initialize}.

\begin{small}
\begin{lstlisting}[breaklines=true, caption={Inicializace řídicích proměnných C API},captionpos=b,label={lst:CAPI_initialize}]
/* Initialize variables that control the application behavior */
	NiFpga_Bool button_pressed = 0;		/* button is not pushed */
	NiFpga_Bool LED = 0;				/* LED is OFF */
}
\end{lstlisting}
\end{small}
\par
Po periodicky se opakující komunikaci mezi RealTime procesorem a~\zk{zkFPGA} byla vytvořena \textit{while} smyčka s~časováním 100~ms. Uvnitř této smyčky byl vytvořen program, který zpracoval událost stisknutí tlačítka z~reálného prostředí a~na základě této události reagoval pomocí připojené LED diody, která signalizovala stisknutí tlačítka.

\begin{small}
\begin{lstlisting}[breaklines=true, caption={Komunikace mezi RealTime procesorem a~FPGA v~platformě cRIO},captionpos=b,label={lst:CAPI_komunikace}]
while(NiFpga_IsNotError(status)){
		NiFpga_MergeStatus(&status, NiFpga_ReadBool(session,
				NiFpga_FPGA_IndicatorBool_Buttonoutput,
				&button_pressed));
		if (button_pressed){
			LED = 1;
		}
		else {
			LED = 0;
		}
		NiFpga_MergeStatus(&status, NiFpga_WriteBool(	session,
					NiFpga_FPGA_ControlBool_Boolean,
					LED));
		usleep(100000); /* 100ms delay */
	}
}
\end{lstlisting}
\end{small}
\par
Vytvořený program, který je uveden ve výpisu \ref{lst:CAPI_komunikace}, běží tak dlouho, dokud není některou z~C API funkcí vrácen status \textit{Error}. Hodnota tohoto statusu je kontrolována vždy na~začátku iterace while smyčky. Další částí vytvořeného programu bylo zjištění, zda reálné tlačítko, které bylo k~platformě \zk{zkcRIO} připojeno pomocí digitální karty NI~9401, není stisknuté. Kontrola stisknutí tlačítka byla provedena pomocí C API funkce \textit{NiFpga\_MergeStatus}, jejíž druhý parametr nařizoval použít inline funkci čtení stavu příslušného tlačítka.

Na základě výsledku inline funkce \textit{NiFpga\_ReadBool} byla změněna hodnota bitové proměnné \textit{LED}, která byla vzápětí použita pro zápis hodnoty do~proměnné, která v~\zk{zkFPGA} ovládala LED diodu, připojenou k~výstupnímu portu digitální karty. Aby mohla být definována proměnná typu bool v~jazyce ANSI C byla ve vlastním programu použita knihovna \textit{stdbool.h}, který tento datový typ definuje.

Vytvořený program ovládání LED diody pomocí tlačítka byl zkompilován a~nahrán pomocí vzdálené správy zařízení do~platformy \zk{zkcRIO}. Ještě před spuštěním programu musel být umístěn bitový soubor vygenerovaný rozhraním C API na~cílovou platformu.

Po prvním spuštění vytvořeného programu v režimu ladění byla odhalena chyba. Při volání funkce \textit{NiFpga\_Initialize()}, která je uvedena na 4. řádku výpisu \ref{lst:CAPI_creation_relace}, byla inicializační funkcí vrácena hodnota -- 63194. Tato hodnota podle \cite{CAPIhelperror} říká, že verze SW na platformě NI~\zk{zkcRIO}~9068 není kompatibilní s použitou verzí rozhraní C~API~17. K odstranění této chyby musí být použity stejné verze SW pro platformu \zk{zkcRIO}, \zk{zkLabVIEW} a C~API rozhraní (generátor).

Odstraněním chyby \textit{NiFpga\_Status\_VersionMismatch} byl úkol propojení RealTime části platformy \zk{zkcRIO} s~\zk{zkFPGA} splněn, nicméně by bylo vhodné pro velké objemy přenášených dat použít DMA FIFO než jednotlivé proměnné. Před zahájením komunikace pomocí DMA kanálu je zapotřebí provést jeho inicializaci, která trvá déle, než v~případě použití jednotlivých proměnných. Výhodou DMA kanálu je však rychlejší předávání dat mezi instancí \zk{zkFMU} a~\zk{zkFPGA}.
