Table of Contents

10. Semestrální úloha - display a klávesnice na PCIe

Zadání úlohy

Pomocí PCIe karty EVB/Altera DB4CGX15 a přípravku s LCD a klávesnicí realizujte systém pro zaslání jednoduché číselné zprávy/kódu (pager, předchůdce SMS). Předpokládejte, že každá jednotka bude mít přiřazené unikátní číslo ID pod kterým se přihlašuje k centrálnímu serveru služby. Číslo ID a IP adresa centrálního serveru budou programu předané na příkazovém řádku při spuštění. Po spuštění bude jednotka v základním režimu. Při stisku libovolné číselné klávesy přejde jednotka do režimu zadání zprávy. Na klávesnici pak bude dokončené zadání ID čísla cílové jednotky a poté maximálně šest číslic kódu, který má být doručený na cílovou jednotku. Na každý stisk klávesy jednotka reaguje krátkou akustickou odezvou. Pokud uživatel po 30 sekund nestiskne klávesu, dojde automaticky k přechodu jednotky do základního režimu. V základním režimu se jednotka centrálního serveru každých pět sekund dotáže, jestli se na něm nenachází zpráva určená pro danou jednotku. Pokud ano, tak jednotka provede akustickou signalizaci a zobrazí zprávu na displeji tak dlouho, dokud nebude potvrzená k tomu určeným tlačítkem. Poté oznámí serveru přečtení zprávy. Nedílnou součástí řešení bude uživatelský manuál a technická zpráva (včetně zdrojových kódů). Protokol pro dotazování serveru bude realizován s využitím TCP/IP. Jednoduchý server a popis jeho protokolu bude k dispozici. Po dohodě se cvičícím je možné navrhnout protokol i server vlastní, požadavkem je podpora alespoň 10 účastníků sítě a fronty alespoň 10 čekajících zpráv pro každého účastníka. Rozšířené řešení také může obsahovat podporu zpětnou informaci o doručení zprávy případně informaci o aktuálně aktivních uživatelích nebo rozšíření o editaci textových zpráv na mobilní klávesnici.

Při odevzdání se kontroluje funkčnost řešení, porozumění problematice a dokumentace. Dokumentace je vždy povinná, boduje se ale pouze v případě finálního a funkčního řešení.

Hodnocení plným počtem bodů je možné při odevzdání nejpozději na cvičení v zápočtovém týdnu. Každý další týden se hodnocení snižuje o 5 bodů.

Doporučený postup řešení a hodnocení

Server pro uchování a předání zpráv

K dispozici je následující minimalistická implementace serveru pro ukládání a výběr zpráv

apo-pagercentral-2015-1.tar.gz

Zdrojové kódy se zkompilují příkazem make. Program je možné spustit s parametrem -v, kdy vypisuje diagnostické hlášky na chybový výstup.

./pagercentral -v

Server se základním nastavením pak naslouchá na portu 55556. Server lze otestovat programem telnet nebo nc

telnet localhost 55556

Dotaz na přítomnost zprávy ve frontě zpráv určených pro danou jednotku

 <pager_id>
querrymessage 42

Odpověď obsahuje klíčový token querrymessage_r, pager_id , a dále pokud je fronta prázdná, tak text none. Pokud není fronta prázdná tak bude následovat číselný identifikátor zprávy v systému, poté číslo ID jednotky odesílatele a nakonec vlastní text/kód zprávy. Server se snaží vysvětlit v odpovědi i případné chyby v poslaných datech. Při spuštění s přepínačem -v je i značné množství diagnostických hlášek vypisované přímo na konzoli serverem. Příjem a přečtení zprávy se potvrdí příkazem

 <pager_id> <message_id>
confirmmessage 42 123456

Server odešle odpověď confirmmessage_r a zopakuje číslo pageru a zprávy.

Nová zpráva je centrálnímu systému vyslaná příkazem

 <pager_id> <recipient_id> <message_text> 
sendmessage 42 53 1337

Odpověď bude místo textu zprávy obsahovat přiřazené unikátní číslo v rámci systému

 <pager_id> <recipient_id> <message_id> 
sendmessage_r 42 53 123456

Pro popis jednotlivých volání použijte příkaz man nebo prostudujte Beej's Guide to Network Programming.

Popis hardware

Hardware se skládá z vstupně výstupní karty realizující vstupně výstupní brány a registry mapované do paměťového adresního prostoru PCI sběrnice a externího kytu obsahujícího jednoduchou maticovou klávesnici, řadič znakového displeje 2×16 znaků a 8 LED diod.

Karta s obvodem FPGA, umožňuje nastavovat řídit signály na 8-bit paralelním portu, který slouží pro generování řídicích signálů na softwarově řízené 8-bit paralelní sběrnici. Dále obsahuje 8-bit registr, který slouží pro přípravu dat vybavených na datové vodiče (D0 až D7) a 8-bit bránu pro čtení dat z datových vodičů, když je periferie naadresovaná v režimu čtení.

Registry mapované na softwarově řízenou 8-bit sběrnici

Adresa na 8-bit sběrnici Směr Označení Popis
0 WR LCD_INST Zápis instrukce do řadiče LCD
1 RD LCD_STAT Stavový registr LCD řadiče
2 WR LCD_WDATA Zápis dat do zobrazovací paměti
nebo generátoru znaků
3 RD LCD_RDATA Čtení dat z paměti LCD řadiče
1 WR LED_WR Zápis LED
3 WR KBD_WR Zápis do scanovacího registru klávesnice a sirénky
0 RD KBD_RD Čtení vrácených hodnot při testování klávesové matice

Registry naprogramované na kartě EVB/Altera DB4CGX15. V případě naprogramování karty za běhu počítače je nutné vyvolat novou enumeraci karty.

sudo -i
echo 1 > /sys/bus/pci/rescan
lspci -nn -v -d 1172:1f32
echo 1 >/sys/bus/pci/devices/0000\:bb\:dd.f/enable

V případě přítomnosti karty během startu systému není tato inicializace potřeba. V prosředí laboratoře KN:E-328 je však nutné pro přihlášeného studenta povolit přístup paměti pro čtení a zápis. Pro tyto účely je k dispozici nástroj

devmemrw

který je potřeba před začástkem experimentování spustit.

Adresa na PCIe sběrnici Směr Označení Popis
BAR0+0x0000 RD/WR RAM Lokální paměť 32kB RAM v obvodu FPGA
BAR0+0x8000 RD/WR timer_0 Časovač na kartě s možností generování IRQ
BAR0+0x8020 WR emul_bus_data_out Datové signály - výstupní hodnoty
BAR0+0x8040 RD emul_bus_data_in Datové signály - čtení aktuální hodnoty
BAR0+0x8060 WR emul_bus_addr Hodnota na adresové vodiče emulované sběrnice
BAR0+0x8080 WR emul_bus_ctrl Řídicí signály emulované sběrnice
BAR0+0x80A0 WR Led_Pio Zápis na LED přímo na kartě

8-bitový výstupní registr s řídícími signály emulované sběrnice (emul_bus_ctrl)

Bit Označení
signálu
Pin IO
Modulu
Pin FPGA Popis
0 RD IO13 L9 Řízení čtení (aktivní v L)
1 WR IO14 K9 Řízení zápisu (aktivní v L)
2
3
4
5
6 CS0 IO15 N10 Potvrzení výběru periferie (aktivní v L)
7 PWR IO18 L11 Povolení napájení periferie

8-bitový výstupní registr pro nastavení adresy na emulované sběrnici (emul_bus_addr)

Bit Označení
signálu
Pin IO
Modulu
Pin FPGA Popis
0 A0 IO11 K8 Adresový bit 0 (LSB)
1 A1 IO12 N9 Adresový bit 1
2
3
4
5
6
7

8-bitový výstupní registr (emul_bus_data_out) definuje data, která jsou přivedena na simulovanou datovou sběrnici v době zápisu. Stejné je i mapování bitů ve vstupním registru (emul_bus_data_in), který slouží ke čtení aktuálních hodnot datových vodičů především pro cyklus čtení.

Bit Označení
signálu
Pin IO
Modulu
Pin FPGA Popis
0 D0 IO1 L4 Bit 0 datové sběrnice (LSB)
1 D1 IO2 M4 Bit 1 datové sběrnice
2 D2 IO3 N4 Bit 2 datové sběrnice
3 D3 IO4 N5 Bit 3 datové sběrnice
4 D4 IO5 L5 Bit 4 datové sběrnice
5 D5 IO6 N6 Bit 5 datové sběrnice
6 D6 IO7 M6 Bit 6 datové sběrnice
7 D7 IO8 L7 Bit 7 datové sběrnice (MSB)

Další řídicí signály (z pohledu programátora nejsou důležité)

     IO10 (M9) = not WR and RD
          = not IO14 and IO13
     IO9 (N9) = (WR   and RD   and CS0)  or not (WR   or RD) 
         = (IO14 and IO13 and IO15) or not (IO14 or IO13)

Přepínání směru emulované sběrnice je řízené signály RD, WR a CS0. Směr je přepnutý na výstup z FPGA při (not WR and RD to je not IO14 and IO13)

Další signály jsou pro toto cvičení konstantní

     IO19 (N12) = 0
     IO20 (K10) = 1

Maticová klávesnice

Popis vyhodnocení stisku kláves na maticové klávesnici

Řadič LCD displeje

Přípravek používá standardní HD44780 řadič.

Pro inicializaci

Zápis znaku

Posun na danou pozici pro zápis dalšího znaku

(Upraveno 4.5. na základě upozornění na nedostatky panem Tomášem Krupkou)

Nápověda k řešení

Otestování připojení a funkčnosti přípravku

mmaped_8bit_bus_kbd-test-2014.tar.gz

Vlastní programování

V následujícím archivu jsou uložené hlavičkové soubory s adresami registů displeje a klávesnice na emulované sběrnici.

mmaped_8bit_bus_kbd-headers-2014.tar.gz

Procházení adresářů ''/proc/bus/pci''

opendir

readdir

closedir

Načtení PCI hlavičky

Jednotlivé soubory /proc/bus/pci/bb/dd.f obsahují data PCI hlaviček (kopii PCI configuration space) v systému nalezených zařízení

fopen

fread

fclose

Formát hlavičky PCI zařízení je popsaný například na Wikipedii

Podrobnější popis architektury sběrnice PCI a PCIe byl probíraný i v rámci přednášek 5. I/O podsystém 1 a 6. I/O podsystém 2. Hierarchii PCI/PCIe popisuje především prezentace PCI a PCI Express sběrnice a PCIe.

V prvních čtyřech byte je zakódovaná identifikace výrobce a zařízení - pro použitý FPGA design/kartu je kód výrobce 0x1172 a kód zařízení 0x1f32.

Fyzická adresa paměťového okna karty je uložena registru BAR0. Spodní bity registru je potřeba odmaskovat - viz tabulka PCI BAR Bits.

Zařízení by mělo být před prvním přístupem povoleno zápisem hodnoty “1” do souboru /sys/bus/pci/devices/0000:bb:dd.f/enable
Misto hodnot bb, dd a f pouzijte konkretni hodnoty bus, device a function zjistene pomoci prikazu lspci.

Otevření a mapování ''/dev/mem''

open

použít O_FSYNC , aby byl přístup přímý bez průchodu vyrovnávací pamětí.

Fyzická adresa reprezentovaná /dev/mem se namapuje do adresního prostory procesu funkcí

mmap

Aby nedošlo při zápisu do stránek k spuštění mechanizmu Copy on Write (COW), je třeba použít volbu MAP_SHARED

Přístup k registrům na kartě

K vlastním registrům pak přistupovat přes ukazatele typu (volatile uint32_t *)

Nejdříve si vyzkoušet zápis a čtení paměti mapované na FPGA, pak pokročit k zapnutí přípravku a simulaci sběrnicových cyklů.

Prográmek pro přímé čtení, zápis a vyplňování oblastí a registrů mapovaných nejen do fyzické paměti (/dev/mem)

rdwrmem.tar.gz

Po skompilování příkazem make si lze vypsat nápovědu zadáním parametru -h

./rdwrmem -h

Počáteční adresa zápisu se specifikuje parametrem -s. Pro začátek práce s předloženým HW je pro první test nejsnažší specifikovat adresu řídicího registru emul_bus_ctrl . Ten se nalézá na adrese BAR0 + 0x8080. Při zápisu hodnoty s nastaveným bitem č. 7 (-F 0xFF) dojde k zapnutí napájení přípravku.

Píklad přístupu k registru KBD_WR a vypnutí piezoměniče. Poznamka: Zustante prihlihlaseni pod spravcem (prikaz: sudo -i).

# zapnutí napájení
./rdwrmem -s <BAR0+0x8080> -F 0xFF

# příprava adresy pro zápis (budeme posilat 03)
./rdwrmem -s <BAR0+0x8060> -F 0x03

# příprava dat pro zápis (budeme posilat 00)
./rdwrmem -s <BAR0+0x8020> -F 0x00

# aktivace signálu WR
./rdwrmem -s <BAR0+0x8080> -F 0xFD

# signály WR a CS0 aktivní
./rdwrmem -s <BAR0+0x8080> -F 0xBD

# prodleva - alespoň 10 mikrosekund
sleep 1

# deaktivace CS0
./rdwrmem -s <BAR0+0x8080> -F 0xFD

# deaktivace WR
./rdwrmem -s <BAR0+0x8080> -F 0xFF

Dotaz serveru na povolení přístupu

  int res, gate_id, user_id;
  char *s;
  res = fscanf(client_file, "checkaccess %d %d %as", &gate_id, &user_id, &s);

  fseek(client_file, SEEK_CUR, 0)

Výchozí C program pro semestrální práci

Pokud někdo pořád ještě neví jak začít, může využít následující výchozí program v jazyce C, který dovede zapnout a vypnout přípravek. Kód obsahuje řadu TODO odkazů s náměty pro pokračování. Archiv obsahuje i Makefile, takže může vše přeložit zadáním make , případně pro build, tj. nové sestavení všeho, zadejte napřed make clean a poté příkaz make.

zaklad.tar.gz

#define DEV_ENABLE "/sys/bus/pci/devices/0000:03:00.0/enable"
#define DEV_ADDRESS 0xfe8f0000

#define CTRL 0x8020

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>

/* Rutina pro aktivaci PCI zarizeni, pokud nebylo konfigurovane pri startu pocitace (BIOS) */
/* Pro zapis je nutne opravneni superuzivatele */
int pciEnable(int isEnable)
{
   char cen = isEnable!=0 ? '1' : '0';
   int enable = open(DEV_ENABLE,O_WRONLY); //TODO: cestu DEV_ENABLE nutno nacist prohledanim PCI seznamu
   if(enable==-1) return 0; // TODO: Doplnit poradne chybove hlaseni
   write(enable,&cen,1); close(enable);
   return 1; 
}
int main()
{       	
   int soubor= open("/dev/mem",O_RDWR | O_SYNC);
   if(soubor==-1) return 1; // TODO: Doplnit poradne chybove hlaseni

   // TODO: konstantu DEV_ADDRESS a delku 0x10000 musite najit prohledanim seznamu PCI zarizeni
   unsigned char * base = mmap(NULL,0x10000,PROT_WRITE | PROT_READ, MAP_SHARED,
                               soubor, DEV_ADDRESS);
   if(base==MAP_FAILED) return 2; // TODO: Doplnit poradne chybove hlaseni       

   /* Aktivace dekoderu PCI karty - bezne se o ni pastara BIOS
    * pritom vyzaduje opravneni superuzivatele - spravce 
    * if(!pciEnable(1))
    *   exit(1);
    * /

  *(base+CTRL)=0xF0;  // zapni napajeni
  sleep(1);  // cekej 1 vterinu - kratsi doba cekani-hledejte: usleep, nanosleep
  // TODO: Vase semestralni prace
  *(base+CTRL)=0x00;  // vypni napajeni      

  /* pciEnable(0); */
  return 0;
}

//TODO: Podprogram pro zapis/cteni bytu na emulovane PCI sbernici
//+TODO: cteni klavesnice, 
//+TODO zapis na LCD
//+TODO: program automatu na jizdenky

Nejvhodnějším mechanizmem pro vložení prodlevy je volání

/*
   Protože clock_nanosleep timespec je definované
   až v novějším standardu IEEE Std. 1003.1j-2000
   je potřeba buď kompilovat s CFLAGS+=-std=gnu99
   nebo nastavit
*/
#define _GNU_SOURCE
/* případně podle standardu */
#if !defined(_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L)
  #undef _POSIX_C_SOURCE
  #define _POSIX_C_SOURCE 200112L
#endif

#include <time.h>

void v_tele_funkce(void)
{
  struct timespec wait_time  = {
               .tv_sec = 0,        /* seconds */
               .tv_nsec = 12000       /* nanoseconds [0 .. 999999999] */
           };

  clock_nanosleep(CLOCK_MONOTONIC, 0, &wait_time, NULL);

}

Při linkování je pak vyžadovaná knihovna rt. Lze přidat přepínačem -lrt nebo v Makefile

LDFLAGS+=-lrt

Technická dokumentace k použitému hardware

Dokumentace k přípravku/desce maticové klávasnice MO_KBD3

mo_kbd3-minimal-sch.pdf - Zjednodušené schéma kytu klávesnice MO_KBD3

mo_kbd3-sch.pdf - Úplné schéma MO_KBD3 včetně možnosti osazení MCU pro přístup přes sběrnici CAN

mo_kbd3-top.pdf - Osazovací výkres - horní strana

mo_kbd3-bot.pdf - Osazovací výkres - spodní strana

Dokumentace k desce napěťového přispůzobení a nosiče konektorů CON-DB4CGX15

con-db4cgx15-sch.pdf - Schéma propojovací desky CON-DB4CGX15

con-db4cgx15-top.pdf - Osazovací výkres - horní strana

con-db4cgx15-bot.pdf - Osazovací výkres - spodní strana

Dokumentace k FPGA návrhu pro softwarovou simulaci 8-bit sběrnice (mmaped_8bit_bus)

mmaped_8bit_bus-toplevel.pdf - Nejvyšší úroveň návrhu propojení PCIe subsytému, registrů a pinů FPGA

mmaped_8bit_bus-sopc-avalon.pdf - Propojení registrů a PCIe na sběrnici Avalon v SW Altera SOPC Builder

Konfigurace generátoru PCIe bloku v SW Altera SOPC Builder PCI Compiler

Virtuální hardware klávesnice (APOHW) pro emulátor QEMU

Na úloze je možné pracovat i bez přístupu k vlastnímu HW. Virtuální hardware pro předmět APO byl implementovaný Rostislavem Lisovým na základě jeho předchozí diplomové práce Prostředí pro výuku vývoje PCI ovladačů do operačního systému GNU/Linux.

Podrobné informace k projektu APOHW se nacházejí na stránce

Virtuální hardware APOHW v QEMU

Aktuální verze implementuje zápis na LED diody, výpis na display a zjednodušené zpracování klávesnice. Klávesa stlačená a odeslaná programem TELNET nastaví propojení křížení sloupce a řádku pro odpovídající klávesu '0' až '9', '*' a '.'. Veškeré propoje v matici jsou pak smazané po přijetí znaku/klávesy mezera (' '). Stav klávesnice a displeje je uživateli zprostředkovaný přes jednoduchý telnet server, který naslouchá na portu 55555. Připojit se lze příkazem

telnet localhost 55555

Upozornění: Projekt musí být při odevzdání funkční i na fyzickém hardware. Virtuální HW slouží především k testování základního návrhu a SW s tím, že požadavky na časování i některé funkce neimplementuje zcela přesně.

Kompletní virtuální systém s implementovaným hardwarem APOHW.

qemu-run-apohw-32.tar.gz (32-bit GNU/Linux verze)

qemu-run-apohw-64.tar.gz (64-bit GNU/Linux verze)

Základem je QEMU s rozšířením o HW, jádro systému Linux, BusyBox a další výbava pro spuštění. Spustitelný soubor QEMU je zkompilovaný pro 32-bitovou verzi systému Linux.

K běhu programu sestavení emulátoru “qemu-system-i386-apohw” jsou potřeba ROM obrazy základního a grafického BIOSu pro počítačový systém PC. V distribuci Debian a Ubuntu se instalují s balíčekem “qemu-system” jako jeho závislosti.

Pro zjednodušení instalace byly obrazy ROM přibaleny i do archivu. Cesta k lokální kopii je ve skriptu “qemu-run-apohw” specifikovaná parametrem přepínače “-L”.

Po spuštění příkazu “qemu-run-apohw” dojde k vytvoření virtuálního stroje s architekturou PC.

Přepínač “-device apohw” specifikuje, že má být doplněný o jednu instanci emulace PCIe karty odpovídající APO hardware.

Přepínač “-kernel vmlinuz-3.2.0-2-686-pae” zajistí přímé natažení jádra systému Linux (k tomu je využit option ROM “linuxboot.bin”).

Přepínač “-initrd ramdisk.cpio” specifikuje, že po startu systému je do dočasného/RAM filesystému tmpfs rozbalený obsah GZIP komprimovaného CPIO archivu “ramdisk.cpio”. Tento archiv je ze souborů v adresáři “rootfs” a popisu zařízení vytvořen příkazem “mkramdisk-apohw”. Potřebné nástroje k úpravám jsou součástí archivu.

Po rozbalení archivu jádrem Linux do paměti je předáno řízení programu “linuxrc”, případně “/bin/init”. Tento program interpretuje shellový skript “/etc/init.d/rcS”. Součástí skriptu je vytvoření spojení jádra OS Linux s hypervisorem QEMU na úrovni protokolu 9P. Přes tento protokol je pak do virtuálního systému do adresáře “/mnt/shareddir” připojen vnější adresář “shareddir” z hostitelského systému. V něm jsou předpřipravené nástroje “rdwrmem” a “apohw/mmaped_8bit_bus_kbd”.

Alternativou je připojit do QEMU CDROM některé z distribucí GNU/Linuxu a na připojený obraz disku nainstalovat celý systém.

./qemu-system-i386-apohw -L pc-bios -boot c -hda file-to-emulate-hd -cdrom install.iso

Emulátor je nainstalovaný i na virtuální stanici/serveru postel. Zde je sdílený adresář mapovaný do domovského adresáře uživatele na ~/apo/shareddir . Emulátor je možné pustit vzdáleně v grafickém režimu po protunelování X protokolu přes ssh

ssh -X
qemu-run-apohw

Alternativou je spuštění emulátoru v textovém režimu, kdy textový režim grafické karty překládá na ncurses příkazy textové konsole

qemu-run-apohw -curses

Další možnost je grafický výstup zcela vypnout a přesměrovat výstup Linuxového jádra a shellu na virtuální sériový port

qemu-run-apohw -nographic -append "console=ttyS0"

Emulátor se pak ovládá příkazy pře CTRL+A. Seznam příkazů CTRL+A h. Vypnutí CTRL+A x.

Při spuštění více instancí emulátoru na serveru postel nastane kolize v telnet portu pro přístup k displeji. Lze to řešit nastavením vlastního portu v parametrech emulátoru.

Další informace o možnostech práce s QEMU lze nalézt na mnoha místech. Z našich předmětů a projektů například v A4M35OSP, Stránky IT podpory K13135, atd.