Čeština / English
Login

Návody / Tvorba vlastní aplikace

Autor: Zdeněk Vašíček ()

Abstrakt: Cílem tohoto dokumentu je seznámit čtenáře, jak postupovat v případě, že si přeje vytvořit vlastní aplikaci pro FITkit. Úkolem bude vytvořit čítač, který je možné ovládat z mikrokontroleru a jehož stav bude zobrazován na LCD displeji.

Update: 25.9.2009

1. Příprava - tvorba projektu

Nejprve je nutné vytvořit složku, do které poté umístíme zdrojové kódy. Veškeré zdrojové kódy aplikací jsou z důvodu přehlednosti uloženy v podadresářich adresáře apps v SVN. Doporučujeme si alespoň zběžne strukturu SVN projít.

Zvolme si např. adresář demo, kde vytvoříme podadresář counter. Aby bylo možné přeložit aplikaci, je nutné v tomto adresáři vytvořit soubor project.xml, který popisuje jednak projekt samotný a jednak jeho závislosti.

Pro náš cíl (tvorba čítače v FPGA a jeho řízení z MCU), rozvrhněme projekt následovně:

  • main.c - soubor obsahující firmware, tedy kód pro mikrokontroler

  • counter.h - soubor obsahující kód pro komunikaci s čítačem

  • counter.vhd - soubor obsahující VHDL kód čítače

  • top_level.vhd - top level kód pro FPGA, tzn. propojení čítače s komunikačním systémem

Soubory mohou být uloženy přímo v adresáři counter nebo lépe v podadresářích fpga respektive mcu. Obsah souboru popisujícího projekt to neovlivní, neboť FCMake podporuje několik řežimů relativního adresování.

Soubor project.xml může vypadat následovně:

<?xml version="1.0" encoding="utf-8"?>
<project outputprefix="counter">
 
  <!--  Project description -->
  <name>Tutoriál - čítač</name>
  <description>
      FPGA obsahuje čítač, který je možné ovládat pomocí terminálu.
      Stav čítače se zobrazuje na LCD displeji.
  </description>
 
  <!--  MCU part -->
  <mcu>
      <include>mcu/libs/lcd/package.xml</include>
      <file>main.c</file>
  </mcu>
 
  <!-- FPGA part -->
  <fpga>
      <include>fpga/ctrls/lcd/package.xml</include>
      <file>counter.vhd</file>
      <file>top_level.vhd</file>
  </fpga>
 
</project>

Syntaxi a význam jednotlivých značek naleznete v dokumentu Překladový systém. Soubor obsahuje popisnou část a dále dvě sekce, jednu věnovanou zdrojovým kódům pro MCU a druhou zdrojovým kódům pro FPGA. Protože budeme využívat LCD displej, přidáváme do obou sekcí balíčky obsahující potřebné zdrojové soubory.

2. Kód pro FPGA

2.1. Čítač

Začněme nejprve s kódem samotného čítače. Soubor counter.vhd bude obsahovat entitu (tj. rozhraní neboli seznam signálů obvodu) i architekturu (tj. vlastní implementaci neboli VHDL kód).

Přepokládejme, že chceme popsat universální čítač nahoru s libovolným počtem bitů, který bude možné specifikovat pomocí generického parametru. Poté bude mít rozhraní následující tvar:

entity counter is
   generic (
      DATA_WIDTH : integer := 3
   );
   port(
      CLK      : in std_logic;
      RST      : in std_logic;
      EN       : in std_logic;
      DATA_OUT  : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0)
   );
end counter;

Význam jednotlivých signálů je následující:

  • CLK - hodinový synchronizační signál

  • RST - asynchronní reset (uvedení do výchozího stavu)

  • EN - povolení čítání, pokud EN=1 pak čítač s každým hodinovým taktem zvýší hodnotu na výstupu DATA_OUT

  • DATA_OUT - k-bitový výstup čítače, počet bitů je specifikován parametrem DATA_WIDTH jehož výchozí hodnota je 3

VHDL kód popisující čítač může vypadat následovně (viz dokument Popis HW pomocí VHDL):

architecture arch_counter of counter is
   signal cnt : std_logic_vector(DATA_WIDTH-1 downto 0);
begin
   DATA_OUT <= cnt;
 
   -- Counter
   process(CLK, RST)
   begin
    if (RST = '1') then
       cnt <= (others => '0');
    elsif (CLK'event) and (CLK='1') then
       if (EN = '1') then
          cnt <= cnt + 1;
       end if;
    end if;
   end process;
 
end arch_counter;

2.2. Top-level architektura

Popis čítače je hotov, nyní je nutné vyrobit kód, který se po překladu nahraje do FPGA.

V prvním kroku je však zapotřebí zvolit pro jakou top-level entitu budeme architekturu vytvářet. V SVN existují tři top-level entity, které a) integrují nezbytné komponenty (generátor hodinového signálu, řadič rozhraní SPI) b) poskytují různý interface dle použití. Volba top-level entity se děje pomocí atributu architecture v souboru project.xml v sekci FPGA.

toplevelfpga.png

Obrázek 2.1: Architektura top-level FPGA, umístění entity tlv_gp

Předdefinované entity:

  • bare - základní entita, vhodná pro aplikace nevyužívající port X ani periferie na FITkitu,

  • gp - entita vhodná pro aplikace, které využívají pouze X port

  • pc - entita určená pro aplikace využívající periferie FITkitu (VGA port, PS/2, atd). Dodejme že tato entita reflektuje situaci, kdy propojka J6 je aktivní, periferie kitu jsou povoleny a tudíž část portu X je sdílena s těmito periferime. Rozdíl oproti předchozím entitám spočívá v tom, že rozhraní obsahuje signály portu X pojmenované dle dané periferie.

tlventity.png

Obrázek 2.2: Entity bare a pc

V našem případě nám postačí entita bare. V top-level architektuře musíme pouze a) instancovat řadič displeje a připojit jej k komunikačnímu rozhraní SPI a dále b) instancovat čítač a připojit taktéž ke komunikačnímu rozhraní. Propojení usnadňuje navržený propojovací systém, který je popsán v dokumentu Komunikační systém. Úkolem bude instancovat pro každý prvek komunikující s MCU tzv. adresový dekodér SPI_adc , na jehož výstupu máme k dispozici jednoduché paralelní rozhraní a tento prvek nastavit tak, aby měl každý vlastní disjunktní adresový prostor.

Na následující ukázce je zobrazen pouze kód týkající se připojení čítače na komunikační rozhraní SPI. Kompletní kód lze nalézt v SVN.

-- SPI dekoder pro citac
spidecc: SPI_adc
   generic map (
      ADDR_WIDTH => 8,     -- sirka adresy 8 bitu
      DATA_WIDTH => 8,     -- sirka dat 8 bitu
      ADDR_OUT_WIDTH => 1, -- sirka adresy na vystupu (neni vyuzito)
      BASE_ADDR  => 16#80# -- adresovy prostor od 0x80-0x081
   )
   port map (
      CLK      => CLK,
      CS       => SPI_CS,
 
      DO       => SPI_DO,
      DO_VLD   => SPI_DO_VLD,
      DI       => SPI_DI,
      DI_REQ   => SPI_DI_REQ,
 
      ADDR     => open,
      DATA_OUT => open,
      DATA_IN  => cnt_data_in,
      WRITE_EN => cnt_write_en,
      READ_EN  => open
   );
 
-- citac
cntr: counter
   generic map (
      DATA_WIDTH => 3
   )
   port map (
      CLK       => CLK,
      RST       => RESET,
      EN        => cnt_write_en,
      DATA_OUT  => cnt_data_in(2 downto 0)
   );
 
cnt_data_in(7 downto 3) <= (others => '0');

V první části instancujeme adresový dekodér, který bude mít následující parametry:

  • data budou přenášena po 8 bitech,

  • k adresování všech zařízení připojených na propojovací systém budeme používat 8 bitů,

  • pro naše zařízení nám vystačí jeden adresový bit; pomocí SPI budeme vyčítat pouze obsah čítače, takže rozlišení dalších komponent vůbec nepotřebujeme, avšak nelze zadat hodnotu 0

  • naše zařízení bude namapováno na adresu 0x80 a protože používáme jeden adresní bit, tak bude okupovat i adresu 0x81

Ze signálů adresového dekodéru budeme využívat pouze tyto (význam jednotlivých signálů lze nalézt zde:

  • WRITE_EN - zápis na adresu 0x80 nebo 0x81 způsobí inkrementaci čítače,

  • DATA_IN - při požadavku na čtení z adresy 0x80 nebo 0x81 se načte stav tříbitového čítače

3. Kód pro MCU

Pro usnadnění tvorby kódu pro mikrokontroler byla vytvořena knihovna funkcí libfitkit, která zajišťuje inicializaci periferií, programování FPGA, komunikaci s terminálem apod. Minimální kód pro mikrokontroler musí obsahovat následující funkce:

  • print_user_help - funkce volaná při zadání příkazu help do terminálu,

  • decode_user_cmd - funkce volaná pri zadání příkazu, který není znám knihovnou libfitkit; používá se pro obsluhu vlastních příkazů,

  • fpga_initialized - tato funkce se volá jakmile je naprogramován FPGA obvod, kód se používá k inicializaci periferií

  • main - vstupní bod programu, musí obsahovat inicializaci MCU a nekonečnou smyčku v jejímž těle se volá obsluha terminálu, případně vlastní akce.

Detailní popis jednotlivých funkcí lze nalézt v dokumentu Knihovna libfitkit.

Pro naše účely definujeme vytvoříme příkazy START, STOP a NEXT, které budou znamenat povolit čítání, zastavit čítání, zvýšit hodnotu čítače. Navíc se při každém zvýšení hodnoty čítače vypíše jeho obsah na LCD displej.

Na následující ukázce je uveden kód důležitějších funkcí, kompletní kód lze nalézt v SVN.

void fpga_initialized()
{
  LCD_init();
  LCD_write_string("Counter ...");
}
 
 
int main(void)
{
  unsigned int cnt = 0;
  autocount = 1;
 
  initialize_hardware();
 
  while (1) {
    delay_ms(10);
    cnt++;
    if (cnt > 50)
    {
      cnt = 0;
      if (autocount)
      {
        LCD_append_char(read_count()+'0');
        next_count();
      }
    }
 
    terminal_idle();  // obsluha terminalu
  }
 
}

Funkce fpga_initialized zajistí inicializaci LCD displeje a vypsání řetězce na displej. V hlavní smyčče je každých 10 ms inkrementováno počítadlo milisekund a obsloužen terminál. Uplyne-li 500ms a je zapnuto automatické čítání, je nejprve načten stav čítače read_count() a získaná hodnota je zobrazena na displeji jako znak '0'-'7'; poté dojde ke zvýšení hodnoty čítače next_count().

Obsluha čítače je definována v souboru counter.h s využitím funkcí knihovny libkitclient. Detailní informace o použitých funkcích nalézt v dokumentu Komunikace s FPGA (SPI v libfitkit).

#define BASE_ADDR_COUNTER 0x80
 
#define next_count() FPGA_SPI_RW_A8_D8(SPI_FPGA_ENABLE_WRITE, BASE_ADDR_COUNTER, 0)
 
#define read_count() (FPGA_SPI_RW_A8_D8(SPI_FPGA_ENABLE_READ, BASE_ADDR_COUNTER, 0)

Ke komunikaci přes 8bitovou adresu s datovou šířkou 8 bitů lze použít makro FPGA_SPI_RW_A8_D8, jehož parametry mají následující význam. První udává, zda-li se jedná o čtení nebo zápis, či zápis kombinovaný se čtením. Druhý parametr obsahuje adresu, v našem případe 0x80. Třetí parametr obsahuje hodnotu zapisovaného bytu. Makro vrací načtený byte.

4. Překlad aplikace

Máme-li vytvořen kód pro MCU i FPGA, je možné projekt přeložit a to buď z příkazové řádky nebo pomocí aplikace QDevkit. Překlad projektu popisuje dokument Překlad aplikace. Pro úspěšný překlad je zapotřebí překladač MSPGCC a nástroj Xilinx ISE.

Po spuštění aplikace QDevkit se v případě validního projektu objeví v seznamu dostupných aplikací projekt s názvem "Tutoriál - čítač". Pomocí kontextového menu lze projekt přeložit.

5. Programování FITkitu

Po úspěšném překladu lze FITkit naprogramovat, opět je možné pracovat v příkazové řádce nebo s využitím aplikace QDevkit. Programování FITkitu popisuje dokument Programování FITkitu.

Dvojklikem na projekt s názvem "Tutoriál - čítač" se naprogramuje FITkit.

6. Otestování aplikace

Funkčnost aplikace lze ověřit např. pomocí QDevKitu. Možnostmi komunikace s FITkitem se zabývá dokument Komunikace s FITkitem.

Dvojklikem na ikonu FITkitu se zahájí komunikace a zobrazí se terminálové okno. Po úspěšné inicializaci FITkitu lze zadávat do příkazového řádku příkazy. Zadáním příkazu START se spustí čítání a na displeji se každých 500ms zobrazí nová hodnota.

Zobrazeno: 6011x Naposledy: 20.9.2017 15:41:37