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ů.
lspci -nn -v -d 1172:1f32
(přes /proc/bus/pci
) [2b]
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.
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
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)
V následujícím archivu jsou uložené hlavičkové soubory s adresami registů displeje a klávesnice na emulované sběrnici.
Jednotlivé soubory /proc/bus/pci/
bb/
dd.
f obsahují data PCI hlaviček
(kopii PCI configuration space) v systému nalezených zařízení
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.
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í
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
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
)
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
int client_socket = socket(AF_INET,SOCK_STREAM,0);
… více o volání
struct sockaddr_in address;
voláním inet_aton nebo inet_addr
fdopen
lze přímo na vytvořený stream použít fprintf.
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)
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
.
#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
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
con-db4cgx15-sch.pdf - Schéma propojovací desky CON-DB4CGX15
mmaped_8bit_bus-toplevel.pdf - Nejvyšší úroveň návrhu propojení PCIe subsytému, registrů a pinů FPGA
Konfigurace generátoru PCIe bloku v SW Altera SOPC Builder PCI Compiler
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.