A Microchip TCP/IP Stack implementációjának alkalmazása a gyakorlatban Ivanov Péter 2004. május 18.
i
Tartalomjegyzék 1. Bevezeto˝ 1.1. Köszönetnyilvánítás . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 2
2. Soros vonal
3
3. A TCP/IP Stack felépítése 3.1. A Stack rétegei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 5
4. User Datagram Protocol (UDP)
7
5. A TCP/IP Stack konfigurálása
9
6. A TCP/IP Stack moduljai 6.1. Address Resolution Protocol modul . . . . . . . . . 6.1.1. ARP funkciók . . . . . . . . . . . . . . . . . . 6.1.2. ARPTask funkciók . . . . . . . . . . . . . . . 6.2. User Datagram Protocol (UDP) modul . . . . . . . . 6.3. Stack Manager modul . . . . . . . . . . . . . . . . . 6.4. A soros-UDP átalakító modul . . . . . . . . . . . . . 6.5. HTTP szerver modul . . . . . . . . . . . . . . . . . . 6.5.1. Dinamikus honlap generálás . . . . . . . . . 6.5.2. HTTP CGI . . . . . . . . . . . . . . . . . . . . 6.6. Microchip fájlrendszer (MPFS) . . . . . . . . . . . . 6.6.1. MPFS kép készítése . . . . . . . . . . . . . . . 6.6.2. MPFS könyvtár . . . . . . . . . . . . . . . . . 6.7. FTP szerver modul . . . . . . . . . . . . . . . . . . . 6.7.1. MPFS kép feltöltése FTP kliens segítségével . 7. Hardver 7.1. Alkatrészek . . . . . . . . . . . . . . . . 7.1.1. PIC18F452 mikrovezérl˝o . . . . . 7.1.2. RTL8019AS ethernet vezérl˝o . . 7.1.3. 24LC256 típusú soros EEPROM . 7.1.4. MAX232A soros vonali illeszt˝o .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .
13 14 14 16 17 27 27 34 35 36 39 40 41 41 42
. . . . .
44 44 44 48 48 49
ii 8. Az eszköz használata és tesztelése 8.1. Az eszköz használata . . . . . . . . . 8.2. Konfigurálás böngész˝oprogrammal . 8.2.1. Hálózat beállítása . . . . . . . 8.2.2. Soros vonal beállítása . . . . 8.2.3. Statisztika . . . . . . . . . . . 8.3. Az eszköz tesztelése . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
50 50 51 51 53 53 54
iii
Ábrák jegyzéke 1.1. A rendszer blokkvázlata . . . . . . . . . . . . . . . . . . . . . . . . . .
1
2.1. Egy bájt átvitele soros vonalon . . . . . . . . . . . . . . . . . . . . . .
3
3.1. A TCP/IP referencia modell rétegei . . . . . . . . . . . . . . . . . . . . 3.2. A referencia modell és a Microchip TCP/IP Stack rétegei . . . . . . . .
4 5
4.1. UDP csomag felépítése . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2. Az el˝o-fejléc felépítése . . . . . . . . . . . . . . . . . . . . . . . . . . .
7 8
6.1. 6.2. 6.3. 6.4. 6.5. 6.6. 6.7. 6.8.
A Stack Manager algoritmusának folyamatábrája . . . . . . A Serial2UDP_GetSerialData függvény folyamatábrája . . A Serial2UDP_ProcessUDPData függvény folyamatábrája ˝ Urlapok kezelése . . . . . . . . . . . . . . . . . . . . . . . . MPFS képfájl felépítése . . . . . . . . . . . . . . . . . . . . . MPFS FAT bejegyzés felépítése . . . . . . . . . . . . . . . . MPFS adatblokk felépítése . . . . . . . . . . . . . . . . . . . MPFS képfájl feltöltése FTP kliens segítségével . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
28 31 32 38 39 40 40 43
7.1. 7.2. 7.3. 7.4.
Soros vonali illeszt˝o és tápfeszültség stabilizátor kapcsolási rajza A PIC18F452 típusú mikrovezérl˝o lábkiosztása . . . . . . . . . . . A 24LC256 típusú soros EEPROM lábkiosztása . . . . . . . . . . . A MAX232 típusú soros vonali illeszt˝o lábkiosztása . . . . . . . .
. . . .
. . . .
45 46 49 49
8.1. 8.2. 8.3. 8.4. 8.5. 8.6. 8.7. 8.8.
A doboz oldal- és elölnézete . . . . . . . . . . . Az eszköz használata . . . . . . . . . . . . . . . Konfigurálás böngész˝oprogrammal: index . . . Hálózat beállítása böngész˝oprogrammal . . . . Soros vonal beállítása böngész˝oprogrammal . Statisztika megtekintése böngész˝oprogrammal Az eszköz tesztelése . . . . . . . . . . . . . . . Az UDP test program . . . . . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
50 51 52 52 53 54 54 55
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
iv
Táblázatok jegyzéke 5.1
Konfigurációs definíciók ill. változók . . . . . . . . . . . . . . . . . . .
12
6.1 6.2. 6.3. 6.4.
TCP/IP Stack moduljai . . . . . . . . . . . . . . . . . . A soros-UDP átalakító modul konfigurációs változói A soros-UDP átalakító modul bels˝o változói . . . . . A soros-UDP modul átalakító állapotai . . . . . . . . .
14 29 29 33
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
1
1. fejezet Bevezeto˝ Manapság az ethernet hálózat elterjedését láthatjuk a hétköznapi használatban és az iparban egyaránt. A csavart érpáros kábelek nagy távolságra vezethet˝ok, olcsók, könnyen szerelhet˝ok és az árnyékolatlan kábelek (UTP) is relatíve érzéketlenek az elektromos zavarokra, de ipari alkalmazásban általában árnyékolt kábeleket (STP) használnak. A most bemutatásra kerül˝o rendszerrel egyszeruen ˝ és gyorsan képessé tehetjük PIC mikrokontrolleres alkalmazásunkat, hogy kommunikáljon az intraneten vagy interneten. E szakdolgozatban egy a valóságban is felhasználható alkalmazást mutatok be, hogyan illeszthetjük a soros vonalon kommunikáló régebbi fejlesztésu˝ eszközünket ethernet hálózathoz. A rendszer leegyszerusített ˝ blokkvázlata az 1.1. ábrán látható.
1.1. ábra. A rendszer blokkvázlata A Microchip kifejlesztette a PIC18-as mikrokontroller családhoz a TCP/IP Stack-et és egy komplett web szervert. Fejlesztéseit szabadon hozzáférhet˝ové tette és letölthet˝o az internetr˝ol. Ezeket a forráskódokat használtam fel. A programcsomaggal egy HTTP szervert építhetünk, aminek honlapját FTP-n frissíthetjük. Szükség van egy PIC 18-as mikrovezérl˝ore, egy NIC-re (például Realtek 8019AS). Kell még egy C fordító, a program lefordításához. Én a PIC C18 demó verzióját használtam. Érdemes letölteni az MPLAB legfrissebb verzióját. Ez egy integrált
2 fejleszt˝oi környezet (IDE) amiben szerkeszthetjük a forrásfájlokat, lefordíthatjuk a programot és fel is tölthetjük a mikrovezérl˝obe. Kell még egy PIC programozó is. Én az ICD2 nevezetu˝ programozó és nyomkövet˝o eszközt használtam. A szögletes zárójelben lev˝o számokkal mindig az irodalomjegyzékben szerepl˝o dokumentumokra hivatkozok.
1.1.
Köszönetnyilvánítás
Ezúton szeretném megköszönni Dr. Kónya László tanár úrnak és Kolinger Attilának a segítséget és a fejlesztéshez nélkülözhetetlen eszközöket.
3
2. fejezet Soros vonal Els˝osorban az RS-232C szabványról lesz szó ebben a fejezetben. Ez az adatátviteli forma széles körben elterjedt és még most is nagyon sok eszköz használja az iparban és a számítástechnikában ezt a módszert. Az RS232 hátrányai közé tartozik, hogy „aszimetrikus”, tehát közös a föld, ezért zaj érzékeny és csak kis távolságra vezethet˝o. Nagyobb távolságok áthidalására az RS-422 ill. RS-485 szabványú adatátvitel használható. Az átvitel aszinkron, full duplex és a bájtok átvitele mindig egy start bit elküldésével kezd˝odik, ezt követi 5–9 darab adatbit végül egy, másfél vagy kett˝o stop bit. A kilencedik bit lehet paritás bit is vagy a cél eszköz megcímzésére használhatjuk. A kilencedik bitet alapesetben RS-232C kapcsolatnál címzésre használni nem lehet (de lehet például az RS-422-nél és RS-485-nél). A legelterjedtebb a „8n1” típusú átvitel, ahol 8 adatbit egy stop bit küldése ill. fogadása lehetséges, paritás nélkül. Az általam elkészített program is ebben a formátumban kezeli az adatokat. Az adatátviteli sebesség 75, 150, . . . , 2400, 4800, 9600, 19200, 38400, 57600, . . . baud lehet. A baud az átvitt jel értékében történ˝o változások száma egy másodperc alatt. Tehát a sebesség megadásánál a baud mértékegység nem egyezik meg a bit/másodperccel, mert az utóbbiba nem értend˝o bele a start-, stop- és paritás bitek átvitele. Egy bájt (0xC8) átvitele látható a 2.1. ábrán (TTL szintuek ˝ a jelek).
2.1. ábra. Egy bájt átvitele soros vonalon
4
3. fejezet A TCP/IP Stack felépítése Számos TCP/IP implementáció követi a „TCP/IP referencia modell” nevu˝ szoftver architektúrát. Azok a programok, amik erre a modellre alapulnak több rétegre vannak osztva, ezek a rétegek egymásra épülnek1 és minden réteg egy vagy több alatta lév˝o réteggel kommunikál. A TCP/IP referencia modell a 3.1. ábrán látható.
3.1. ábra. A TCP/IP referencia modell rétegei A TCP/IP rétegek „aktívak”, vagyis nem csak akkor muködnek, ˝ ha kérés érkezik egy szolgáltatáshoz, hanem akkor is, id˝otúllépés történt vagy egy új csomag érkezett. Egy olyan rendszer, ahol sok adat- és programmemória áll rendelkezésre könnyen teljesíti a kéréseket. Egy multitaszkos operációs rendszer extra képességei lehet˝ové teszik, hogy az implementáció moduláris legyen. A program viszont bonyolult lesz, ha csak egy 8 bites mikrovezérl˝o áll rendelkezésre néhány száz bájt RAM-mal és korlátozott programmemóriával. Továbbá, egy multitaszkos operációs rendszer nélkül sok id˝ot kell arra fordítani a programozás során, hogy a Stack független maradjon a f˝o alkalmazástól. Relatíve könnyu˝ elkészíteni és helytakarékos az a TCP/IP Stack, amely bele van integrálva a f˝o alkalmazásba. De sok probléma léphet fel, amikor újabb funkciókat szeretnénk a programhoz hozzáadni. 1
Az egymásra épülést angolul a „stacked” szóval fejezik ki, ezért hívják TCP/IP Stack-nek.
5 Ez a TCP/IP Stack moduláris, C programozási nyelven íródott és a Microchip C18 és a HiTech PICC 18 fordítókkal is lefordítható. A forrásfájl automatikusan eldönti, hogy milyen fordítóval szeretnénk fordítani. A két fordító közötti különbségekb˝ol ered˝o problémákat a compiler.h fájlban lev˝o definíciókkal küszöböljük ki. Ez a TCP/IP Stack csak PIC 18-as mikrovezérl˝okön fut.
3.1.
A Stack rétegei
A 3.2 ábrán is látható, hogy a Microchip TCP/IP Stack is különböz˝o rétegekre van osztva. A kód úgy lett megírva, hogy minden réteg külön forrásfájlban van, míg az API2 külön fejlécfájlban van.
3.2. ábra. A TCP/IP referencia modell és a Microchip TCP/IP Stack rétegeinek összehasonlítása Ellentétben a referencia modellel, a Microchip TCP/IP Stack-ben egyes rétegek nem csak a közvetlenül alatta lev˝o réteget érik el. A legnagyobb különbség a hagyományos TCP/IP Stack implementációtól két új modul: StackTask és az ARPTask. A StackTask vezérli a Stack összes moduljának muködését ˝ az ARPTask pedig az ARP réteg szolgáltatásait valósítja meg. Ez a Stack az általánosan ismert kooperatív multitaszk technikát alkalmazza, hogy független legyen a f˝o alkalmazástól. Egy kooperatív multitaszkos rendszerben több taszk muködik, ˝ minden taszk végrehajt egy feladatrészt, majd a vezérlést visszaadja és a következ˝o taszk fut. Ebben az értelmezésben a StackTask és az ARPTask egy-egy kooperatív taszk. A f˝oprogramba vagy az operációs rendszerbe is lehet implementálni a kooperatív – vagy más típusú – multitaszkot megvalósító kódot. A Stack úgy lett megtervezve, hogy független legyen bármilyen operációs rendszert˝ol, vagyis saját kooperatív multitaszk rendszere van. Ennek eredményeként használható bármilyen rendszerben függetlenül attól, hogy használ-e multitaszkos operációs rendszert vagy sem. Azonban, ha a saját alkalmazásunk használja ezt a 2
Application Programming Interfaces, vagyis a felhasználói program interfész.
6 TCP/IP Stack-et, alkalmaznunk kell a kooperatív multitaszk technikát a saját taszkjaink megírásakor. Ez elérhet˝o úgy is, hogy a feladatot több taszkra osztjuk vagy a feladatot egy FSM-nek (Finite State Machine, Véges Állapotú Automata) továbbítjuk ami a feladatot sok kis részfeladatra bontja és egymás után futtatja le o˝ ket. A HTTP szerver az utóbbi megoldást használja. Jegyezzük meg, hogy ebben a TCP/IP Stack-ben nincs implementálva az összes olyan modul, ami egy átlagos TCP/IP Stack-ben implementálva van, de ha szükség van egy olyan funkcióra, ami nincs implementálva, bármikor megírható külön taszkként vagy modulként.
7
4. fejezet User Datagram Protocol (UDP) Az RFC 768-as [2] dokumentumban található az UDP protokoll leírása. Ez a protokoll az Internet Protocol-ra (IP) épül. El˝onye, hogy a programok nagyon egyszeruen ˝ küldhetnek és fogadhatnak üzeneteket, de nincs garantálva, hogy az üzenet nem veszik el ill. nem duplázódik. Azok az alkalmazások amelyeknél adatfolyamok megbízható továbbítására van szükség, a Transmission Control Protocol-t (TCP) használják.
4.1. ábra. UDP csomag felépítése Az UDP csomagok felépítése a 4.1. ábrán látható. A forrás port opcionális mez˝o, akkor érdemes használni, ha a csomagot küld˝o folyamat választ vár. Ha nincs használva, nullát kell a helyére írni. A cél port a cél címen belül egy folyamatot vagy programrészt jelent, de lehet más jelentése is. A hossz a csomag oktetjeinek számát mutatja meg, beleértve a fejlécet és az adatokat is. Tehát a legkisebb érték, amit felvehet: nyolc. Az ellen˝orz˝o összeg az IP fejlécb˝ol készült „el˝o-fejléc”, az UDP fejléc és az adat egyes komplemense 16 bitre kiegészítve. Azért hívják el˝o-fejlécnek, mert az IP fejlécb˝ol másolódnak az adatok. Az el˝o-fejléc (4.2. ábra) az UDP fejléc el˝ott van és tartalmazza a forrás- és célcímet, protokoll típusát és az UDP csomag hosszát. Ez az információ véd az eltévedt csomagok ellen. Az ellen˝orz˝o összeg számítása hasonlít a TCP-ben használt ellen˝orz˝o összeg számításhoz. Ha a kiszámított ellen˝orz˝o összeg nulla, akkor az összeg egyes komplemense lesz elküldve (FFFFh). Ha az ellen˝orz˝o összegként nullát küld a forrás, az azt jelenti, hogy
8
4.2. ábra. Az el˝o-fejléc felépítése a küld˝o nem számolt összeget. Nyomkövetéskor alkalmazható vagy, ha a fels˝obb szintu˝ protokollok nem használják ezt az összeget. Ebben a TCP/IP Stack-ben az ellen˝orz˝o összeg számítás nincs implementálva. Az UDP modulnak ismernie kell a forrás és cél internet címét és a protokoll típusát. Ezt a protokollt használják az internetes név szerverek (DNS) és Trivial File Transfer Protocol (TFTP). Ha az Internet Protocol-on belül használjuk az UDP-t, akkor az a 17-es (oktálisan 21) számú protokoll.
9
5. fejezet A TCP/IP Stack konfigurálása Ez a kooperatív multitaszk rendszer lehet˝ové teszi, hogy a felhasználói alkalmazás saját taszkokat futtasson. Eközben a TCP/IP Stack-kel nem is kell foglalkoznia. Ehhez természetesen az kell, hogy a felhasználó úgy írja meg programját, hogy a kooperatív multitaszkos rendszerben muködjön. ˝ Az egyszeru˝ konfigurálás érdekében a program C definíciókat használ. A legtöbb paraméter engedélyezése, tiltása vagy beállítása a StackTsk.h fejléc fájlban lehetséges. Azok a paraméterek, amelyek más fájlban találhatóak, azoknak zárójelben megadom a fájl nevét. Ha valamelyik paramétert változtattuk, a projektet – vagy egyes részeit – újra kell fordítani1 . Azonosító CLOCK_FREQ (compiler.h)
Értékek Órajel frekv. (Hz)
Használ Tick.c
TICKS_PER_SECONDS
10-255
Tick.c
TICK_PRESCALE_VALUE
Tick.c
MPFS_USE_PGRM
2, 4, 8, 16, 32, 64, 128, 256 -
MPFS_USE_EEPROM
-
MPFS.c
MPFS_RESERVE_BLOCK
0-255
MPFS.c
EEPROM_CONTROL
Küls˝o mem. kódja
MPFS.c
MPFS.c
Megjegyzés Definiálja a rendszer órajel frekvenciáját, hogy ki lehessen számolni az id˝ozít˝o számláló értékét. Egy másodperc hány taktusból áll. Id˝ozítéshez milyen el˝oosztó legyen beállítva. Ha a programmemóriát akarjuk használni adattárolásra. Ha küls˝o soros EEPROM-ot akarunk adattárolásra használni. Az MPFS fájlrendszer el˝ott fenntartott bájtok száma. Hogy meg tudjuk címezni a küls˝o EEPROMot.
1 Az MPLAB fejleszt˝oi környezet érzékeli a változtatásokat és kezeli a függ˝oségeket, csak azt fordítja le, ami szükséges.
10 Azonosító STACK_USE_ICMP
Értékek -
STACK_USE_SLIP
-
STACK_USE_IP_GLEANING
-
STACK_USE_DHCP
-
STACK_USE_FTP_SERVER
-
STACK_USE_TCP
-
STACK_USE_UDP
-
STACK_CLIENT_MODE
-
TCP_NO_WAIT_FOR_ACK
-
MY_DEFAULT_IP_ADDR_BYTE? 0-255 MY_DEFAULT_MASK_BYTE? 0-255 MY_DEFAULT_GATE_BYTE? MY_DEFAULT_MAC_BYTE?
0-255 0-255
MY_IP_BYTE?
0-255
MY_MASK_BYTE? MY_GATE_BYTE? MY_MAC_BYTE?
0-255 0-255 0-255
Használ Megjegyzés StackTsk.c Ha nincs szükség ICMP-re, ne definiáljuk. SLIP.c Ha nincs szükség SLIPre ne definiáljuk. StackTsk.c Ha nincs szükség IP Gleaning-re ne definiáljuk. DHCP.c, Ha nincs szükség DHCPStackTsk.c re ne definiáljuk. FTP.c Ha nincs szükség FTP szerverre ne definiáljuk. TCP.c, Ha nincs szükség TCPStackTsk.c re ne definiáljuk. Automatikusan engedélyezi, ha valamelyik modulnak szüksége van TCP-re. UDP.c, Ha nincs szükség UDPStackTsk.c re ne definiáljuk. Automatikusan engedélyezi, ha valamelyik modulnak szüksége van UDP-re. ARP.c, Ha definiáljuk a kliens TCP.c módú függvények engedélyez˝odnek. TCP.c A TCP várjon vagy ne az ACK-re a következ˝o csomag küldése el˝ott. felh. alk. Alap IP: 10.10.5.15 felh. alk. Alap netmaszk: 255.255.255.0 felh. alk. Alap átjáró: 10.10.5.15 felh. alk. Alap MAC: 00:04:163:00:00:00 felh. alk. Aktuális IP. Ha DHCP engedélyezett akkor a szerver által adott konfiguráció. felh. alk. Aktuális netmaszk. felh. alk. Aktuális átjáró. felh. alk. Aktuális MAC.
11 Azonosító MAX_SOCKETS
Értékek 1-253
Használ TCP.c
MAX_UDP_SOCKETS
1-254
UDP.c
MAC_TX_BUFFER_SIZE
201-1500
MAX_TX_BUFFER_COUNT
1-255
TCP.c, MAC.c MAC.c
MAX_HTTP_CONNECTIONS
1-255
HTTP.c
MPFS_WRITE_PAGE_SIZE (MPFS.h)
1-255
MPFS.c
FTP_USER_NAME_LEN (FTP.h)
1-31
FTP.c
MAX_HTTP_ARGS (HTTP.c)
1-31
HTTP.c
MAX_HTML_CMD_LEN (HTTP.c)
1-128
HTTP.c
STACK_USE_SER2UDP
-
ser2udp.c
TARGET_DEFAULT_ IP_ADDR_BYTE? (ser2udp.h DEFAULT_TARGET_PORT (ser2udp.h
0-255
ser2udp.c
Megjegyzés Definiálja, hogy hány TCP socket használható (a RAM mennyiségét˝ol függ). Fordítás közben ellen˝orzi, hogy elegend˝o-e a TCP moduloknak a megadott érték. Definiálja, hogy hány UDP socket használható (a RAM mennyiségét˝ol függ). Fordítás közben ellen˝orzi, hogy elegend˝o-e a UDP moduloknak a megadott érték. Definiálja a küld˝o puffer méretét. Definiálja a küld˝o pufferek számát. Definiálja az egyszerre fenntartható HTTP kapcsolatok számát. Definiálja a lapméretet az MPFS fájlrendszerhez. Definiálja az FTP felhasználónév maximális hosszát. Definiálja az urlapok ˝ mez˝oinek maximális számát, beleértve a mez˝o nevét is. Definiálja az urlappal ˝ átadható sztring maximális hosszát. Ha nincs szükség a soros-UDP átalakító modulra ne definiáljuk. Alap cél IP cím: 10.10.5.5.
1-65535
ser2udp.c
Alap cél port: 2222.
12 Azonosító DEFAULT_LOCAL_PORT (ser2udp.h INITWAIT_SEC (ser2udp.h
Értékek 1-65535
Használ ser2udp.c
042949672
ser2udp.c
Megjegyzés Alap forrás port: 2221.
ARP kérés el˝otti várakozás ideje másodpercben. Alap: 4. TIMEOUT_SEC (ser2udp.h 0ser2udp.c ARP kérés után hány 42949672 másodpercig vár a válaszra. Alap: 4. SER2UDP_USE_INTERRUPT ser2udp.c A soros adatok vételé(ser2udp.h hez használjon-e megszakítást a modul. 5.1. táblázat: Konfigurációs definíciók ill. változók
A fejlesztés során egy projektet érdemes használni. Projekt fájlból is van el˝ore elkészített a programcsomagban. Én az MPNICEE.pjt fájlt használtam. Ezt a fájlt akkor érdemes használni, ha a Microchip C18 fordítót Realtek NIC-et és küls˝o soros EEPROM-ot használunk, továbbá szükségünk van HTTP, FTP szerverre és ICMP-re. Ugyanis ezeket tudja alapból az a program, amit ezzel a projekt fájllal fordítunk. Fontos megjegyezni, hogy a projekt fájlokban is lehet definíciókat megadni.
13
6. fejezet A TCP/IP Stack moduljai A moduláris felépítés miatt könnyen beállíthajuk, hogy milyen szolgáltatásokra van szükségünk. Egy modul letiltása csak annyiból áll, hogy a megfelel˝o definíció elé egy megjegyzés jelet teszünk és a forrásfájlokat eltávolítjuk a projektb˝ol. A TCP/IP Stack moduljainak rövid áttekintése: Modul MAC SLIP ARP
Fájl szükséges MAC.c, Delay.c SLIP.c
ARP.c, ARPTsk.c, MAC.c vagy SLIP.c, Helpers.c IP IP.c, MAC.c vagy SLIP.c, Helpers.c ICMP ICMP.c, StackTsk.c, IP.c, MAC.c vagy SLIP.c, Helpers.c TCP StackTsk.c, TCP.c IP.c, MAC.c vagy SLIP.c, Helpers.c, Tick.c UDP StackTsk.c, UDP.c, IP.c, MAC.c vagy SLIP.c, Helpers.c Stack Manager StackTsk.c, TCP.c, IP.c, ICMP.c, ARPTsk.c, ARP.c, MAC.c vagy SLIP.c, Tick.c, Helpers.c HTTP Server HTTP.c, TCP.c, IP.c, MAC.c vagy SLIP.c, Helpers.c, Tick.c, MPFS.c, XEEPROM.c DHCP Client DHCP.c, UDP.c, IP.c, MAC.c, Helpers.c, Tick.c
Leírás Közeghozzáférési réteg Közeghozzáférési réteg SLIPhez Address Resolution Protocol Internet Protocol Internet Control Message Protocol Transmission Control Protocol User Datagram Protocol Stack Manager (StackTask), ami vezérli a TCP/IP Stack moduljait. HyperText Transfer Protocol szerver Dynamic Host Configuration Protocol
14 Modul IP Gleaning FTP Server Serial2UDP
Fájl szükséges Leírás StackTsk.c, ARP.c, IP cím konfiguráláshoz ARPTsk.c, ICMP.c, MAC.c vagy SLIP.c FTP.c, TCP.c, IP.c, File Transfer Protocol szerver MAC.c vagy SLIP.c ARP.c, UDP.c, MAC.c vagy Soros-UDP átalakító SLIP.c 6.1. táblázat: TCP/IP Stack moduljai
Most a soros-UDP átalakító modul által használt modulok részletes leírása következik. Az itt nem tárgyalt modulok (MAC, SLIP, IP, ICMP, TCP, DHCP) angol nyelvu˝ leírása az AN833-as [1] dokumentumban található.
6.1.
Address Resolution Protocol modul
Az ARP modul gondoskodik arról, hogy az IP címekb˝ol megtudjuk, hogy milyen hardveres cím (MAC cím) tartozik hozzá és hogy más eszközök az IP címünket tudva, megkapják a MAC címünket. Az Microchip TCP/IP Stack-jének ARP rétege két modulból áll: ARP.c és ARPTask.c. Az ARP modulban (ARP.c) az ARP alapvet˝o függvényeit definiálja. Az ARPTask – ami az ARPTsk.c fájlban található – ezeket a függvényeket felhasználva valósítja meg az ARP szolgáltatást. Az ARPTask válaszol az ARP kérésekre és egy egyszintu˝ tárban tárolja a más hosztok ARP válaszát. Az ARPTask modulban nincs megvalósítva az id˝otúllépés kezelése, ezt a fels˝obb szintu˝ modulokban kell megoldani. Az ARPTask kétféle módban muködhet: ˝ szerver illetve szerver/kliens. A szerver/kliens módban lehetséges ARP kérések generálása. Szerver módban ez a kódrész nincs befordítva. Általában az alkalmazások szerver módban futnak és érdemes is szerver módba fordítani, a kód méretének csökkentése érdekében. Továbbá szerver módban nem kerül lefoglalásra az egyszintu˝ tár és ezzel RAM területet takaríthatunk meg. Ha a STACK_CLIENT_MODE definiálva van szerver/kliens módban fog muködni ˝ az ARPTask modul. A soros-UDP konverter szerver/kliens módban használja az ARP modult.
6.1.1. ARP funkciók ARPIsTxReady Ez egy makró ami megállapítja, hogy adatok küldése lehetséges-e. Szintaxis: ARPIsTXReady() Paraméter: Nincs Visszatérési érték: IGAZ: Ha legalább egy küld˝o puffer üres. HAMIS: Nincs üres küld˝o puffer. Elofeltétel: ˝ Nincs
15 Mellékhatás: Nincs Megjegyzés: Ez csak egy makródefiníció a MACIsTxReady függvényre. Példa: // Ha a küldő puffer üres, elküldünk egy ARP csomagot if ( ARPIsTxReady() ) { // ARP csomag küldése ARPPut(&RemoteNode, ARP_REPLY); } ARPGet Ez a funkció beolvas egy ARP csomagot és visszatéréskor megadja a szükséges információkat a csomagról. Szintaxis: BOOL ARPGet(NODE_INFO *remote, BYTE *opCode) Paraméter: remote [kimen˝o] A távoli eszközhöz tartozó információk, a MAC és az IP cím. opCode [kimen˝o] ARP kód. A paraméter lehetséges értékei a következ˝ok: ARP_REPLY Egy ARP válasz csomag érkezett ARP_REQUEST Egy ARP kérés csomag érkezett ARP_UNKNOWN Egy ismeretlen ARP csomag érkezett Visszatérési érték: IGAZ: Ha egy érvényes ARP csomag érkezett és az a mi eszközünknek van címezve. HAMIS: Ha ismeretlen ARP kódja van a csomagnak vagy nem nekünk van címezve a csomag. Elofeltétel: ˝ MACGetHeader már meg volt hívva és a kapott MAC csomag típusa MAC_ARP Mellékhatás: Nincs Megjegyzés: Ez a funkció azt feltételezi, hogy az aktív pufferben van egy ARP csomag és a hozzáférési mutató az ARP csomag elejére mutat. Általában a magasabb szintu˝ rétegek ellen˝orzik a MAC puffert és csak akkor hívják ezt a függvényt, ha ARP csomagot érzékeltek. Ez a funkció beolvassa az egész ARP csomagot és felszabadítja az aktív puffert. Példa: // Ha MAC csomag érkezett... if ( MACGetHeader(\&RemoteNode, \&PacketType) ) \{ // Ha ez egy ARP csomag, beolvassuk if ( PacketType == MAC\_ARP ) \{ // Ez egy ARP csomag ARPGet(\&RemoteNode, \&ARPCode); ...
16 ARPPut Ez a funkció feltölti a MAC puffert egy érvényes ARP csomaggal. Szintaxis: void ARPPut(NODE_INFO *remote, BYTE opCode) Paraméter: remote [bemen˝o] A távoli eszköz adatai, mint a MAC és az IP cím opCode [bemen˝o] ARP kód. Lehetséges értékei a következ˝ok: ARP_REPLY ARP válaszként küldi el a csomagot ARP_REQUEST ARP kérésként küldi el a csomagot Visszatérési érték: Nincs Elofeltétel: ˝ ARPIsTxReady == TRUE Mellékhatás: Nincs Megjegyzés: Felépíti az ARP csomagot és elküldi. Példa: // Megnézzük, hogy küldő puffer elérhető-e if ( ARPIsTxReady() ) { // Igen, elküldjük ARPPut(&RemoteNode, ARP_REQUEST); ... }
6.1.2. ARPTask funkciók ARPInit Ez a funkció inicializálja az ARPTask modult és el˝okészíti az ARP kérések küldésére és megválaszolására. Szintaxis: void ARPInit() Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Szerver/kliens módban ez a funkció inicializálja az egyszintu˝ tárolót. Példa: // Initialize ARPTask ARPInit(); ... ARPResolve Ez a funkció egy ARP kérést küld egy távoli eszköznek. Szintaxis: void ARPResolve(IP_ADDR *IPAddr) Paraméter: IPAddr [bemen˝o] A távoli eszköz IP címe, aminek a MAC címét szeretnénk tudni. Visszatérési érték: Nincs Elofeltétel: ˝ ARPIsTxReady == TRUE
17 Mellékhatás: Nincs Megjegyzés: Ez a funkció csak szerver/kliens módban elérhet˝o. Példa: // Ellenőrizzük, hogy a küldő puffer elérhető-e if ( ARPIsTxReady() ) { // ARP kérés küldése ARPResolve(\&RemoteNodeIP); ... } ARPIsResolved Ez a funkció ellen˝orzi a bels˝o tárolót és visszatérési értékként megadja a cél hoszt MAC címét. Szintaxis: BOOL ARPIsResolved(IP_ADDR *IPAddr, MAC_ADDR *MACAddr) Paraméter: IPAddr [bemen˝o] A távoli eszköz IP címe, aminek a MAC címét szeretnénk tudni. MACAddr [kimen˝o] A puffer ami a távoli hoszt MAC címét fogja tárolni. Visszatérési érték: IGAZ: Ha egyez˝o IP cím van a bels˝o tárolóban és az átmásolódott a MACAddr változóba. HAMIS: Ha nincs egyez˝o IP cím a bels˝o tárolóban. Ilyenkor a MACAddr értéke nem változik. Elofeltétel: ˝ Nincs Mellékhatás: A bels˝o tárolóból az átmásolt adatok eltávolításra kerülnek. Megjegyzés: Az ARPTask csak egyszintu˝ tárolóval dolgozik, ezért a fels˝obb rétegnek kell arról gondoskodnia, hogy másik ARP kérést ne küldjön, míg az el˝oz˝ore nem érkezett válasz. Ez a funkció csak szerver/kliens módban elérhet˝o. Példa: // Ellenőrizzük, hogy érkezett-e válasz if ( ARPIsResolved(&RemoteIPAddr, &RemoteMACAddr) ) { // MAC cím megvan. Más feladat következhet... ... } else { // Még nincs meg a MAC. Várunk... ... }
6.2.
User Datagram Protocol (UDP) modul
Az UDP réteg az UDP.c fájlban van implementálva. A fejléc fájlban (UDP.h) vannak definiálva a réteg szolgáltatásai. Ebben a Stack architektúrában az UDP egy aktív
18 réteg. Veszi az UDP csomagot és a megfelel˝o UDP socket-et értesíti az adat érkezésér˝ol. Az UDP modul kooperatív taszkként van implementálva és automatikusan muködik ˝ a f˝o alkalmazástól függetlenül. A réteg legfeljebb 254 UDP socket-et használhat. Ez az érték csak az elérhet˝o memóriától és a fordítótól függ. Több socket használatával több szimultán UDP kapcsolat használható. Fontos megjegyezni, hogy minden socket körülbelül 19 byte memóriát használ (érdemes ellen˝orizni az UDP.h fájlt) és minden socket növeli az UDP csomagok feldolgozásának idejét. Ellentétben a többi socket implementációtól, a Microchip TCP/IP Stack-ben minden socket egy küld˝o puffert használ. Ez csökkenti a RAM szükségletet, de problémát okozhat, ha néhány socket nem szabadítja fel a küld˝o puffert. Ebben az esetben a távoli hosztok és/vagy helyi alkalmazások nem tudnak kapcsolatba lépni az eszközzel. Ennek elkerülése érdekében a felhasználónak gondoskodnia kell arról, hogy az összes socket számára elegend˝oen nagy puffer álljon rendelkezésre. A vételi oldalon is csak egy puffer van, ezért ha adatot olvasunk, az összes adatot be kell olvasni egy taszkban és üríteni a puffert, hogy a többi socket is tudja olvasni az adatát. Nem lehet azt tenni, hogy a taszk csak a puffer egy részét olvassa be és majd egy következ˝o hívás esetén dolgozza fel a maradékot. A Microchip TCP/IP Stack-ben nincs implementálva az UDP ellen˝orz˝o összeg képzés. Az ellen˝orz˝o összeg helyére mindig nulla érték kerül. Ezért minden UDP-t használó modulnak magának kell gondoskodnia az adatok integritásáról. UDPInit Ez a funkció inicializálja az UDP modult és el˝okészíti a többszálú UDP kapcsolatokra. Szintaxis: void UDPInit() Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Ezt a függvényt csak egyszer kell meghívni. Példa: // Initialize UDP UDPInit(); ... UDPOpen Ez a funkció el˝okészíti egy UDP socket-et, hogy a megadott porton adatokat tudjon továbbítani. Szintaxis: UDP_SOCKET UDPOpen(UDP_PORT localPort, NODE_INFO *remoteNode, TCP_PORT remotePort) Paraméter: localPort [bemen˝o] A helyi UDP port, ahonnan az adat jön. remoteNode [bemen˝o] A távoli hoszt, ahova az adatokat küldjük. remotePort [bemen˝o] A távoli hoszt egy UDP portja, ahova az adatokat küldjük.
19 Visszatérési érték: Egy érvényes socket azonosító, ha volt szabad socket vagy INVALID_UDP_SOCKET, ha nem volt szabad socket. Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Ez a funkció egyszerre használható helyi ill. távoli kezdeményezésu˝ adattovábbításra. Nincs konkrét kapcsolódási séma az UDP-ben. Ha egy UDP socketet megnyitottak, akkor az kész az adatok küldésére és fogadására is, egészen addig, amíg be nem zárják a socket-et. Példa: switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else // Egy DHCP üzenet elküldése break; ... UDPClose Bezártja a megadott UDP socket-et és szabadnak jelöli. Szintaxis: void UDPClose(UDP_SOCKET socket) Paraméter: socket [bemen˝o] A bezárandó socket azonosítója. Visszatérési érték: Nincs Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Ezt a függvényt csak egyszer kell meghívni. Példa: switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else
20 { // Egy DHCP üzenet elküldése ... // Socket bezárása UDPClose (DHCPSocket); } break; ... UDPIsPutReady Ez a makró állapítja meg, hogy a megadott socket kész-e az adatok küldésére. A socket akkor kész adatküldésre, ha legalább egy MAC küld˝o puffer üres. Amikor ezt a makrót meghívjuk, automatikusan aktív socket-té válik. Szintaxis: BOOL UDPIsPutReady(UDP_SOCKET socket) Paraméter: socket [bemen˝o] Az ellen˝orizend˝o socket azonosítója. Visszatérési érték: IGAZ: Ha a megadott socket kész az adatok küldésére. HAMIS: Ha nincs szabad küld˝o puffer. Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Egy socket mindig kész az adatküldésre, amíg van üres MAC küld˝o puffer. Amikor ellen˝orizzük a socket-et, az aktívvá válik és a többi UDP funkció is muköd˝ ˝ oképes lesz: UDPGet, UDPFlush és UDPDiscard. Példa: ... switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else { // Egy DHCP üzenet elküldése smState = SM_BROADCAST; break; } case SM_BROADCAST: if ( UDPIsPutReady(DHCPSocket) ) { // A socket kész az adatküldésre... ...
21 } break; ... UDPPut Az aktív socket küld˝o pufferébe egy bájt adatot helyez. Szintaxis: BOOL UDPPut(BYTE byte) Paraméter: byte [bemen˝o] Az adat, amit a küld˝o pufferbe akarunk tenni. Visszatérési érték: IGAZ: Ha a megadott adatot sikerült a pufferbe tölteni és még van hely több adatnak. HAMIS: Ha az adatot sikerült a pufferbe tölteni, de nincs hely több adatnak. Elofeltétel: ˝ UDPIsPutReady == TRUE Mellékhatás: Nincs Megjegyzés: Ha egy socket küldésre kész, akkor összes adatot be kell töltenünk vagy addig tölthetjük fel amíg teljesen tele nem lesz a socket puffere. A felhasználó nem töltheti az adat egyik felét egy socket-be a másik felét egy másik socket-be. Fontos megjegyezni, hogy amikor betöltjük az adatokat, akkor az adatok küldése nem történik meg. Kivéve akkor, ha a puffer megtelik, ekkor a funkció automatikusan elkezdi az adatok küldését és HAMIS értékkel tér vissza. A felhasználói program kés˝obb próbálhat adatot betölteni. Ha az elküldend˝o adat kevesebb, mint a küld˝o puffer, a felhasználói programnak kell kezdeményezni a puffer ürítését az UDPFlush funkció hívásával. Általában, érdemes a puffert üríteni, ha egy egységnyi adatot betöltöttünk a pufferbe, attól függetlenül, hogy a puffer még nincs tele. Példa: ... switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else { // Egy DHCP üzenet elküldése smState = SM_BROADCAST; break; } case SM_BROADCAST: if ( UDPIsPutReady(DHCPSocket) ) { // A socket kész az adatküldésre...
22 // Az UDPPut közvetlenül nem kapja meg az DHCPSocket paramétert // Az UDPPut az aktív socket-et használja, // amit az UDPIsPutReady() állít be, ez a DHCPSocket. UDPPut(0x55); ... } break; ... UDPFlush Az aktív socket küld˝o puffert küldésre késznek állítja be. Szintaxis: void UDPFlush() Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Az UDPPut() függvény már meg volt hívva és a socket aktív, vagyis már futtattuk a UDPIsPutReady() függvényt. Mellékhatás: Nincs Megjegyzés: Ez a funkció küldésre késznek állítja a küld˝o puffert, de a küldés nem indul el egyb˝ol. A felhasználónak nem kell ellen˝oriznie a küldési folyamat állapotát. A NIC 15-ször próbálja meg a elküldeni az adatot (legalábbis a RTL8019AS, más NIC esetén a NIC adatlapjában található ez az információ). Ha a socket puffer egyszer már ürítve volt és üres, a további UDPFlush hívásokat a program figyelmen kívül hagyja. Példa: ... switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else { // Egy DHCP üzenet elküldése smState = SM_BROADCAST; break; } case SM_BROADCAST: if ( UDPIsPutReady(DHCPSocket) ) { // A socket kész az adatküldésre...
23 // Az UDPPut közvetlenül nem kapja meg az DHCPSocket // paramétert. Az UDPPut az aktív socket-et használja, // amit az UDPIsPutReady() állít be, ez a DHCPSocket. UDPPut(0x55); ... // Most elküldjük UDPFlush(); } break; ... UDPIsGetReady Ez a funkció megállapítja, hogy a megadott socket tartalmaz-e vett adatokat és a socket-et aktívnak jelöli ki. Szintaxis: BOOL UDPIsGetReady(UDP_SOCKET socket) Paraméter: socket [bemen˝o] A socket azonosítója Visszatérési érték: IGAZ: Ha a megadott socket tartalmaz vett adatokat. HAMIS: Ha a megadott socket nem tartalmaz vett adatokat. Elofeltétel: ˝ Az UDPOpen() függvény már meg volt hívva. Mellékhatás: Nincs Megjegyzés: Nincs Példa: ... switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else // A DHCP szervertől választ várunk smState = SM_WAIT_FOR_DATA; break; case SM_WAIT_FOR_DATA: if ( UDPIsGetReady(DHCPSocket) ) { // Adatokat olvashatók a socket-ből. Kiolvassuk és // feldolgozzuk... ... } break;
24 ... UDPGet Az aktív socket vételi pufferéb˝ol egy bájt adatot olvas ki. Szintaxis: BOOL UDPGet(BYTE *byte) Paraméter: byte [kimen˝o] A beolvasott adatbájt. Visszatérési érték: IGAZ: Ha sikerült egy bájtot beolvasni. HAMIS: Ha nem sikerült az adat beolvasása. Elofeltétel: ˝ UDPIsGetReady == TRUE Mellékhatás: Nincs Megjegyzés: Ha a socket-ben adatok vannak, a felhasználói programnak be kell olvasnia egy vagy több bájtot egy taszk ideje alatt és a socket puffert felszabadítani. Más socket-b˝ol adatot kiolvasni addig nem szabad, amíg az el˝oz˝o puffer nem lett felszabadítva. Példa: ... switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else // A DHCP szervertől választ várunk smState = SM_WAIT_FOR_DATA; break; case SM_WAIT_FOR_DATA: if ( UDPIsGetReady(DHCPSocket) ) { // Adatokat olvashatók a socket-ből. Kiolvassuk és // feldolgozzuk... // A buffer egy BYTE mutató while( UDPGet(buffer) ) buffer++; // Feldolgozzuk... ... // Socket puffer ürítése ... } break; ...
25 UDPDiscard Az aktív socket vételi pufferét felszabadítja. Szintaxis: BOOL UDPDiscard() Paraméter: Nincs Visszatérési érték: IGAZ: Ha a vételi puffert sikerült felszabadítani. HAMIS: Ha a vételi puffer egyszer már fel lett szabadítva. Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Nincs Példa: ... switch(smState) { case SM_OPEN: // Megpróbálunk egy DHCP szerverhez kapcsolódni DHCPSocket = UDPOpen(68, &DHCPServerNode, 67); if ( DHCPSocket == INVALID_UDP_SOCKET ) { // Nincs szabad socket // Hiba kiírása } else // A DHCP szervertől választ várunk smState = SM_WAIT_FOR_DATA; break; case SM_WAIT_FOR_DATA: if ( UDPIsGetReady(DHCPSocket) ) { // Adatokat olvashatók a socket-ből. Kiolvassuk és // feldolgozzuk... // A buffer egy BYTE mutató while( UDPGet(buffer) ) buffer++; // Feldolgozzuk... ... // Socket puffer ürítése UDPDiscard(); } break; ... UDPProcess Ez a funkció egy taszkként muködik. ˝ Egy beérkezett UDP csomagról megállapítja, hogy melyik UDP socket-hez tartozik. Ezt a funkciót csak akkor kell meghívni,
26 ha egy UDP csomag érkezett. Szintaxis: BOOL UDPProcess(NODE_INFO *remote, WORD len) Paraméter: remote [bemen˝o] A távoli eszköz adatai, ahonnan az UDP csomag érkezett len [bemen˝o] Az UDP csomag teljes hossza a fejlécet is beleszámítva Visszatérési érték: IGAZ: Ha a taszknak sikerült teljesen feldolgoznia a megadott csomagot. HAMIS: Ha a taszknak csak részben sikerült feldolgoznia a megadott csomagot. Elofeltétel: ˝ IPGetHeader == TRUE és IPProtocol = IP_PRO_UDP Mellékhatás: Nincs Megjegyzés: Ahogy fentebb is megjegyeztük, ez a funkció valósítja meg az UDP taszk funkciót. Akkor kell meghívni, ha egy UDP csomag érkezett ez a funkció beolvassa és feldolgozza azt. A funkció visszatérési értéke mutatja meg a hívónak, hogy a StackTask állapotjelz˝ojét meg kell-e változtatni. Ebben a implementációban mindig IGAZ értékkel tér vissza a funkció. További információért a Stack Manager forráskódját érdemes megnézni, ami a StackTsk.c fájlban található. Fontos észben tartani, hogy ezzel a funkcióval nem kell tör˝odni, ha a StackTask funkciót használjuk. Példa: ... switch(smState) { case SM_STACK_IDLE: if ( MACGetHeader(&RemoveMAC, &MACFrameType) ) { if ( MACFrameType == MAC_IP ) smState = SM_STACK_IP; ... return; case SM_STACK_IP: if ( IPGetHeader(&RemoteNode, &IPFrameType, &IPDataCount) ) { if ( IPFrameType == IP_PROT_UDP ) smState = SM_STACK_UDP; ... return; case SM_STACK_UDP: if ( UDPProcess(&RemoteNode, IPDataCount) ) smState = SM_STACK_IDLE; return; ...
27
6.3.
Stack Manager modul
Ahogy már korábban is említettem, ez a Stack különböz˝o modulok gyujteménye. ˝ Néhány modult (mint az IP, TCP, UDP és ICMP), akkor kell meghívni, ha olyan csomag érkezett. Annak az alkalmazásnak, ami a Microchip TCP/IP Stack-et használja, gondoskodnia kell arról, hogy ezek a modulok megfelel˝o id˝oközönként fussanak. A Stack Manager modul csak a TCP/IP Stack moduljait vezérli. A f˝o alkalmazásban nem kell foglalkoznunk a különböz˝o modulok meghívásával, csak a StackTask nevu˝ taszkot kell meghívnunk. Ez a modul egy külön réteg – a StackTask réteg – aminek a forrása a StackTask.c fájlban található. Amikor ez a taszk fut, megkérdezi a hálózatelérési réteget, hogy érkezett-e valamilyen csomag. Ha érkezett, akkor megnézi a fejlécét és a megfelel˝o modulnak átadja további feldolgozás céljából. Miel˝ott a Stack Manager-t munkára fognánk, meg kell hívni a StackInit() funkciót, ami inicializálja a modult. Ha ez megtörtént a StackTask() függvényt kell periodikusan meghívni, hogy a beérkez˝o csomagokat id˝oben elirányítsuk és eközben az id˝o túllépést és hibákat is kezelni tudjuk. A StackTask pontos muködésének ˝ algoritmusa a 6.1. ábrán látható.
6.4.
A soros-UDP átalakító modul
Mivel ezt a modult írtam én, ezért részletesen leírom a bels˝o muködését. ˝ A modul használatához két darab UDP socket-re van szükség. A soros vonalon érkez˝o adatokat megszakítással és polling eljárással is vételezhetjük. Természetesen érdemes a megszakítás használatát engedélyezni a ser2udp.h fájlban. A soros vonalról érkez˝o adatok egy alapból 50 bájtos pufferbe kerülnek. Ha megtelik vagy enter (0xA, 0xD) karakter érkezik, akkor azonnal felépítjük és elküldjük az UDP csomagot. A soros adatok küldésekor sajnos nem lehet megszakítást használni, mert ha az UDP csomagot megkaptuk azt fel kell dolgozni és fel kell szabadítani a puffert ugyanabban a taszkban, ahol érzékeltük, hogy UDP csomag érkezett. Ha lenne elegend˝o memóriánk, akkor az adatokat átmásolva megoldható lenne a megszakításos adatküldés. Az AppConfig struktúrájába került új változók listája a 6.2. táblázatban látható. A 6.2. táblázatban látható változók a websrvr.c fájlban az InitAppConfig függvényben kapnak egy kezdeti értéket, ill. ha létezik elmentett beállítás a küls˝o soros EEPROM-ban, akkor az értékük onnan tölt˝odik be. Jelenleg sem soros adatfolyamszabályozás sem paritás ellen˝orzés nincs implementálva. A 6.3. táblázatban lev˝o bels˝o változókat a modul függvényei használják. Serial2UDP_Init A modul inicializálását ez a függvény végzi el. Szintaxis: Serial2UDP_Init Paraméter: Nincs Visszatérési érték: Nincs
28
6.1. ábra. A Stack Manager algoritmusának folyamatábrája
29 NODE_INFO target WORD target_port WORD local_port BYTE refresh BYTE baud BYTE FlowCtrl
BYTE Parity
A céleszköz adatai: IP cím és MAC cím. A cél port száma. A helyi port száma. A statisztikák megtekintésekor a frissítések közötti id˝o másodpercben. Az baud-dal arányos kiszámított érték, ami az SPBRG változóba kerül. Értéke lehet 0: nincs szabályozás, 1: szoftveres szabályozás, 2: hardveres adatfolyam szabályozás. (Jelenleg nincs használva, kés˝obbi fejlesztéshez fenntartva.) Értéke lehet 0: nincs paritás ellen˝orzés, 1: páratlan paritás, 2: páros paritás ellen˝orzés. (Jelenleg nincs használva, kés˝obbi fejlesztéshez fenntartva.)
6.2. táblázat. A soros-UDP átalakító modul konfigurációs változói static UDP_SOCKET UDPSocket BYTE status DWORD rxbytes, txbytes static WORD count static BYTE buf[BUF_SIZE] static BYTE buf_end static BYTE_VAL misc
Az adatok továbbításához használt socket. A modul állapotát tároló változó. További információk a 6.4. táblázatban. A fogadott és elküldött oktetek száma. A bemeneti soros pufferben elküldésre várakozó bájtok száma. A bemeneti soros puffer. Alapesetben 64 bájt méretu. ˝ Az adatok száma a soros pufferben. Egyes bitjei más-más jelentéssel bírnak. A 0. bit: A SendSerialData függvény legközelebbi futásakor megpróbáljuk-e elküldeni az adatokat.
6.3. táblázat. A soros-UDP átalakító modul bels˝o változói Elofeltétel: ˝ Nincs Mellékhatás: A modul inicializálása legalább 4 másodpercig (INITWAIT_SEC) tart. Megjegyzés: El˝oször vár 4 másodpercet. Ennyi id˝o elég, hogy feléledjen a NIC és érzékelje, hogy a kapcsolat él. (A kés˝obbiekben érdemes lenne kódot átírni úgy, hogy a NIC interfészén keresztül kérdezze le, hogy él-e a kapcsolat.) Utána elküld egy ARP kérés csomagot, hogy megtudja a cél IP címhez tartozó MAC címet. Még négy másodpercig vár (TIMEOUT_SEC) utána „Hiba: MAC cím lekérdezése közben id˝otúllépés történt” hibaállapotba lép. Ha sikerült a MAC lekérdezése megpróbál egy UDP socket-et megnyitni. Ennek sikertelensége esetén „Hiba: Nincs szabad UDP socket”, ellenkez˝o esetben „Rendben” állapotba kerül. A függvényt csak egyszer kell meghívni. Példa: ... Serial2UDP_Init ();
30 ... Serial2UDP_GetSerialData Beolvassa a soros vonalról jöv˝o adatot és elhelyezi a buf pufferben, ha lehetséges. Ha a puffer megtelt vagy soremelés (0xD), kocsi vissza (0xA) karakter érkezett, akkor a flush vátozót igaz értékre állítja. Ha a soros vonali adatok vételénél keret hiba történt a modul „Hiba: RS-232 keret hiba” állapotba kerül. Ha az adatok vételekor a vételi puffer felülírása következett be, akkor a „Hiba: Az RS-232 puffer felülírás” állapot áll be. A függvény folyamatábrája a 6.2. ábrán látható. Az ábrán a szaggatott vonal akkor érvényes, ha ezt a függvényt a Serial2UDP függvény hívja meg és nem megszakítással muködik. ˝ Szintaxis: void Serial2UDP_GetSerialData () Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Megszakításos módban és a pollingolásnál is ez a függvény muködik. ˝ Pollingnál a Serial2UDP függvény hívja meg ezt a függvényt. Példa: Nincs Serial2UDP_SendSerialData Ha a buf puffer tele van (a flush bit 1 értéku), ˝ akkor elkészít egy UDP csomagot és elküldi a beállított IP címnek. Szintaxis: void Serial2UDP_SendSerialData () Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: A Serial2UDP függvény hívja meg ezt a függvényt. Példa: Nincs Serial2UDP_ProcessUDPData A fogadott UDP csomagot azonnal elküldi a soros vonalon keresztül. Folyamatábrája a 6.3. ábrán látható. Szintaxis: void Serial2UDP_ProcessUDPData () Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: A Serial2UDP függvény hívja meg ezt a függvényt. Példa: Nincs
31
6.2. ábra. A Serial2UDP_GetSerialData függvény folyamatábrája Serial2UDP Ez egy kooperatív taszk, amit a f˝o ciklusban kell meghívni. Szintaxis: void Serial2UDP () Paraméter: Nincs Visszatérési érték: Nincs Elofeltétel: ˝ Inicializálás megtörtént. Mellékhatás: Nincs Megjegyzés: A soros vonalon beérkez˝o adatokat a buf pufferben tárolja a Serial2UDP_GetSerialData () függvény segítségével (csak polling módszernél).
32
6.3. ábra. A Serial2UDP_ProcessUDPData függvény folyamatábrája A SendSerialData () eljárással küldi el a buf pufferben tárolt adatokat a soros vonalon és a ProcessUDPData () függvénnyel a megadott portra érkez˝o UDP csomagokat egyb˝ol kiírja a soros vonalra. Példa: ... StackTask(); HTTPServer(); Serial2UDP(); ... Serial2UDP_ReInit A konfiguráció megváltozásakor kell meghívni. Szintaxis: void Serial2UDP_ReInit () Paraméter: Nincs Visszatérési érték: Nincs
33 Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Szinte teljesen megegyezik az Serial2UDP_Init funkcióval, de az ARP kérés kiküldése el˝ott nincs 4 másodperces várakozás. Példa: Serial2UDP_GetStatusString A modul állapotára vonatkozó stringre mutató mutatót ad vissza. Szintaxis: char *Serial2UDP_GetStatusString (void) Paraméter: Nincs Visszatérési érték: Egy sztring mutató, ami megegyezik a Serial2UDP_StatusString változóban lev˝o értékkel. Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: A sztring HTML kódokat tartalmaz, 0 kódú karakterrel van lezárva és a programmemóriában van. A lehetséges állapotok szövegei a 6.4. táblázatban láthatók. Sorszám 0 1 2 3 4 5 6
Angolul Unknown Ok Error: UDP socket not available Error: Can’t resolve MAC address, time out Error: Buffer is full Error: RS-232 Framing error Error: RS-232 Overrun error
Magyarul Ismeretlen Rendben Hiba: Nincs szabad UDP socket Hiba: MAC cím lekérdezése közben id˝otúllépés történt Hiba: A puffer tele van Hiba: RS-232 keret hiba Hiba: RS-232 puffer felülírás
6.4. táblázat. A soros-UDP modul átalakító állapotai Példa: ... WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val) { switch(var) { case VAR_DEVSTATUS: if (ref == HTTP_START_OF_VAR) { Serial2UDP_GetStatusString (); ref = (BYTE)0; } *val = Serial2UDP_StatusString[(BYTE)ref]; if (Serial2UDP_StatusString[(BYTE)ref + 1] == ’\0’) return HTTP_END_OF_VAR;
34 (BYTE)ref++; return ref; ...
6.5.
HTTP szerver modul
Ez a HTTP szerver kooperatív taszkként fut, amit a f˝o alkalmazásból kell meghívni. A szerver a HTTP.c forrásfájlban van implementálva és a felhasználói programban két segédrutint (angolul callback function) használhatunk. Az bemutató alkalmazás forrásfájlját – a websrvr.c fájlt – használtam fel a saját programom írásához. Ez a HTTP szerver egy csökkentett tudású program, direkt beágyazott rendszerekhez íródott. A szerver tulajdonságai: • Többszálú HTTP kapcsolatok • Egy egyszeru˝ fájlrendszert támogat (MPFS) • A honlapokat a bels˝o programmemóriában és küls˝o EEPROM-ban is tárolhatjuk • Tartalmaz egy PC-s programot MPFS képfájl létrehozásához • A HTTP GET metódust támogatja (más metódusok könnyen hozzáadhatók) • Egy módosított Common Gateway Interface-t (CGI) támogat • Dinamikusan generálható a honlapok tartalma. A HTTP szerver használatbavételéhez a következ˝o lépéseket kell végrehajtani: 1. A StackTsk.h fájlban vagy a projekt beállításnál definiálni kell a STACK_USE_HTTP_SERVER definíciót. 2. A StackTsk.h fájlban be kell állítani a MAX_HTTP_CONNECTIONS értékét. 3. A http.c és mpfs.c fájlokat hozzá kell adni a projekthez. 4. Attól függ˝oen, hogy hol szeretnénk a weblapokat tárolni, definiálni kell az MPFS_USE_PGRM vagy az MPFS_USE_EEPROM kulcsszavakat. Ha küls˝o EEPROMot használunk tárolóelemnek az xeeprom.c fájlt is hozzá kell adni a projekthez. 5. A main() függvényt módosítani kell, hogy a HTTP szerver muködjön. ˝ Az összes weblapot egy MPFS (Microchip File System) fájlrendszerbe kell konvertálni. Ha az MPFS képfájlt küls˝o EEPROM-ban tároljuk, akkor a felhasználói programba implementálni kell az adatok rögzítéséhez szükséges függvényt. A HTTP szerver alap honlapként az index.htm fájlt használja. Ha például egy böngész˝o a HTTP szerverhez fordul úgy hogy csak az IP címet adták meg a böngész˝onek az index.htm fájlt kapja meg a böngész˝o. Tehát minden MPFS képfájlban lennie kell egy index.htm fájlnak. Ha szükséges az alap fájlnév megváltoztatható, ha a http.c forrásban a HTTP_DEFAULT_FILE_STRING definíciót átírjuk. Fontos, hogy a weblap fájlok nevei ne tartalmazzák a következ˝o karaktereket:
35 • aposztróf és idéz˝ojel (’ és ") • kisebb-nagyobb jelek (< és >) • kett˝os kereszt jel (#) • százalék jel (%) • szögletes és kapcsos zárójelek ([, }, [, {) • szur˝ ˝ o jel (|) • vissza perjel (\) • kalap jel Ha egy fájl neve tartalmaz ezek közül egy karaktert, akkor az a honlap nem lesz elérhet˝o. A HTTP szerveren van egy lista a támogatott fájl típusokkal. Ezt az információt a böngész˝o használja fel; ebb˝ol állapítja meg, hogy hogyan értelmezze a kapott adatokat. A fájlok azonosítása a hárombetus ˝ kiterjesztés alapján történik. Alapból a HTTP szerver a következ˝o fájltípusokat támogatja: .txt, .htm, .gif, .cgi, .jpg, .cla, .wav. Ha egy alkalmazásban olyan fájltípust akarunk használni, ami nincs a listában, akkor a http.c fájlban httpFiles táblázatot kell módosítani utána a httpContents felsorolást. Az ismert fájltípusok listáját a stíluslapok típussal b˝ovítettem (.css).
6.5.1. Dinamikus honlap generálás A HTTP szerver dinamikusan meg tudja változtatni a honlapok tartalmát. A CGI (.cgi kiterjesztésu˝ legyen) fájlokban a %xx kulcsszó helyére tetsz˝oleges adat helyettesíthet˝o. A % jel egy vezérl˝o karakter. Az xx egy kétjegyu˝ azonosító, hexadecimális formában. Ügyeljünk arra, hogy az A-F karakterek nagy betuvel ˝ legyenek írva! Így 256 féle változót használhatunk. Ha % jelet szeretnénk kiírni, írjunk egymás után két százalék jelet: %%. Az eredeti Microchip megoldásban nem teljes értéku˝ hexadecimális számok voltak megadhatók. A % jel után két darab decimális számot kellett írni, amit a programban hexadecimális számként kellet feldolgozni. Így 00-99 változó megadása lehetséges. Én írtam egy egyszeru˝ konvertert, ami a hexadecimális stringet átalakítja egy bájttá. Így 00-tól FF-ig adhatók meg az azonosítók. HTTPGetVar Ez a funkció egy segédfüggvény (callback function) a HTTP-hez. Ha HTTP szerver egy %xx szöveget talál egy CGI lapon, akkor meghívja ezt a funkciót. Ezt a funkciót a felhasználói programban kell megírni és különböz˝o változó adatokat tudunk vele továbbítani. Szintaxis: WORD HTTPGetVar(BYTE var, WORD ref, BYTE *val) Paraméter: var [bemen˝o] A változó azonosítója, aminek az állapotát akarjuk lekérdezni.
36 ref [bemen˝o] Ez az érték jelzi, hogy ha ez az els˝o függvényhívás. Ekkor a változó értéke HTTP_START_OF_VAR. Ez els˝o hívás után már ez a változó a felhasználói alkalmazásé. Egyszerre csak egy bájt átvitele lehetséges. Ez a változó teszi lehet˝ové, hogy több bájt átvitele esetén a HTTP szerver nyomon kövesse az adatok átvitelét úgy, hogy ebben a változóban az átvitt adat indexét kell tenni és visszatéréskor is ezt a változót kell átadni. Az utolsó bájt átvitelekor HTTP_END_OF_VAR értéket kell visszatérési értéknek megadni. A HTTP szerver egészen addig meghívja ezt a funkciót, amíg nem kap egy HTTP_END_OF_VAR értéket. val [kimen˝o] Egy bájt adat, amit küldeni szeretnénk. Visszatérési érték: A ref változó új értéke, amit a felhasználói alkalmazás állapít meg. Ha HTTP_END_OF_VAR értéket ad vissza, legközelebb csak akkor hívódik meg, ha megint szükség van a változó értékére. Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Ez a függvény egy változót kér a felhasználói alkalmazástól, de annak nem feltétlenül kell értékeket adni. Az hogy milyen információt ad át a függvény, az a hozzárendelt weblaptól függ. Példa: A soros-UDP átalakítóhoz készítettem a stats.cgi fájlt, ebben a következ˝o olvasható:
Device status | %01 |
Amikor a HTTP szerver a fájl feldolgozása során a %01 szöveghez ér, meghívja a következ˝o funkciót: HTTPGetVar(1, HTTP_START_OF_VAR, &value). A felhasználói alkalmazásban lev˝o websrvr.c fájlban van ez a funkció és ehhez hasonlóan néz ki: WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val) { switch(var) { ... case VAR_RXBYTES: if (ref == HTTP_START_OF_VAR) { ltoa (rxbytes, TmpString); ref = (BYTE)0; } *val = TmpString[(BYTE)ref]; if (TmpString[(BYTE)ref + 1] == ’\0’) return HTTP_END_OF_VAR; (BYTE)ref++; return ref; ...
6.5.2. HTTP CGI A CGI-nek egy módosított verziója használható ebben az implementációban. Ezzel az interfésszel a HTTP kliens egy funkciót tud meghívni a felhasználói alkal-
37 mazásban a HTML GET módszerével. További információk az RFC1866-os dokumentumban [5] találhatók. A HTTP szerver nem dekódolja az átadott URL-t. Ez azt jelenti, hogy ha az átadott urlapok ˝ mez˝oje speciális karaktereket tartalmaz (<, >, %, ékezetes karakterek, stb.), akkor a funkciónak átadott paraméter %xx formátumú sztringeket fog tartalmazni, ahol a xx az ASCII karakter hexadecimális kódja. Az urlapokat ˝ tartalmazó oldalakat .cgi kiterjesztéssel kell ellátni. Fontos észben tartani, hogy amikor jelszavakat továbbítunk CGI segítségével, a jelszavakat kódolatlanul továbbítjuk, tehát azok „lehallgathatók”. HTTPExecCmd Ez egy segédfüggvény (callback function). Ha a HTTP szerver a GET módszerrel történ˝o lekérdezésnél több mint egy paramétert kap, akkor hívja meg ezt a funkciót. Ezt a funkciót a felhasználói alkalmazásnak kell tartalmaznia. Szintaxis: void HTTPExecCmd(BYTE **argv, BYTE argc) Paraméter: argv [bemen˝o] Ez egy sztring tömb. Az els˝o sztring (argv[0]) az urlap ˝ action mez˝ojének tartalma, a többi (argv[1..n]) a paraméterek. argc [bemen˝o] A paraméterek száma, beleszámítva az action mez˝ot is. Visszatérési érték: A felhasználói alkalmazásnak be kell állítania az argv[0] változót egy érvényes honlapnévre, ami a visszatérési eredményt tartalmazza. Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: Ezt a függvényt a HTTP szerver hívja meg. A felhasználói alkalmazásnak ki kell tudnia szolgálnia az egymás utáni hívásokat. Alapesetben az argumentumok száma maximum 5 és az argumantumsztringek hossza legfeljebb 80 lehet. Ha egy alkalmazásnak ennél több argumentum vagy hosszabb sztring kell, a MAX_HTTP_ARGS vagy a MAX_HTML_CMD_LEN definíciót kell megváltoztatni. Ezek a http.c fájlban találhatók. Példa: A setup.cgi fájlt is a soros-UDP átalakítóhoz készítettem. Ebben olvasható a következ˝o:
Ennek a táblázatnak a második oszlopaiban adhatunk meg különféle szöveg formátumú adatokat. A képerny˝on látható kép a 6.4. ábrán van. Az utolsó sorban egy gomb látható „Save” felirattal. Ha rákattintunk erre a gombra, akkor az urlapot ˝ a „GET” módszerrel elküldi a böngész˝o.
˝ 6.4. ábra. Urlapok kezelése A HTTP kérés ez lesz: setup.cgi?0=10.10.5.15&1=2221&2=255.255.255.0& 3=10.10.5.15&4=10.10.5.5&5=2222&6=5&7=Save Ennek hatására HTTP szerver pedig a következ˝o paraméterekkel meghívja a HTTPExecCmd függvényt: argc = 17 argv[0] = "setup.cgi" argv[1] = "0" argv[2] = "10.10.5.15" argv[3] = "1" argv[4] = "2221" argv[5] = "2" argv[6] = "255.255.255.0" argv[7] = "3" argv[8] = "10.10.5.15" argv[9] = "4" argv[10] = "10.10.5.5" argv[11] = "5" argv[12] = "2222" argv[13] = "6" argv[14] = "5" argv[15] = "7" argv[16] = "Save" Ehhez természetesen MAX_HTTP_ARGS és a MAX_HTML_CMD_LEN értékét is meg kell növelni. Az adatokat feldolgozó függvény pedig így néz ki: void HTTPExecCmd(BYTE** argv, BYTE argc) { BYTE i; BYTE var; for (i = 1; i < argc; i += 2) { switch(argv[i][0] - ’0’) { case CGI_CMD_LOCALIP: StringToIPAddress (argv[i + 1], &AppConfig.MyIPAddr);
39 break; case CGI_CMD_LOCALPORT: AppConfig.local_port = atoi (argv[i + 1]); break; ... case CGI_CMD_BUTTON: // Ez a parameter adodik at utolsonak... Serial2UDP_ReInit (); SaveAppConfig (); break; } ... } Az egy karakterb˝ol álló azonosítók használata leegyszerusíti ˝ a program kódját, ezért érdemes alkalmazni.
6.6.
Microchip fájlrendszer (MPFS)
A HTTP szerver egy egyszeru˝ fájlrendszert használ a honlapok tárolására. A fájlrendszer képe a mikrovezérl˝o memóriájában és egy küls˝o soros EEPROM-ban is tárolható. A fájlrendszer formátuma a 6.5. ábrán látható.
6.5. ábra. MPFS képfájl felépítése A fenntartott terület mérete az MPFS_RESERVE_BLOCK definícióban van megadva. A fenntartott területet a felhasználói alkalmazás használhatja a konfigurációs értékek tárolására. Egy MPFS tároló egy vagy több MPFS FAT (Fájl Elhelyezkedési Tábla, File Allocation Table) bejegyzést tartalmaz, amit egy vagy több adatblokk követ. A FAT bejegyzés határozza meg a fájl nevét, pozícióját a memóriában és a fájl állapotát. A FAT bejegyzés formátuma a 6.6. ábrán van.
40 Az állapotjelz˝o mutatja meg, hogy a bejegyzés használatban van, törölve van ill. a FAT végét is jelezheti. Minden FAT bejegyzés tartalmaz egy 16 vagy 24 bites címet. A cím hossza a felhasznált memória típusától függ. Ha a bels˝o programmemóriát használjuk „kis” (small) memóriamodellel, akkor 16 bites címeket fog használni. Ha a bels˝o programmemóriát használjuk viszont „nagy” (large) memóriamodellel, akkor 24 bites címeket fog használni. A küls˝o EEPROM eszközöknél mindig 16 bites címzési módszert használunk, függetlenül a memóriamodellt˝ol. Ebben a fájlrendszerben a fájlnevek 8+3 bájt hosszúak. A fájl neve 8 bájtos és a kiterjesztés további 3 bájt hosszúságú. A 16 bites cím megadja az els˝o adatblokkot. Minden fájlnév nagybetukkel ˝ szerepel a könnyebb névkezelés érdekében. Az adatblokk formátuma a 6.7. ábrán szerepel. A blokk végét egy speciális karakter jelzi; az EOF (End Of File), amit 0xFFFF (16 bites címzésnél) vagy 0xFFFFFF (24 bites címzésnél) követ. Ha a fájl tartalmazza az EOF karaktert, akkor egy DLE (Data Link Escape) karakterrel jelezzük, hogy ez a fájl része. Ha a DLE karakter szerepel az adatblokkban, akkor két DLE karakter jelzi, hogy az a fájl része.
6.6.1. MPFS kép készítése A csomag része egy PC-s program (MPFS.exe), amivel MPFS képfájlokat hozhatunk létre. A program képes bináris és C nyelvu˝ adatok létrehozására is. Az MPFS.exe használata: mpfs [/?] [/c] [/b] [/r
] [bemenet] [kimenet], ahol • /? hatására segítséget ír ki, • /c paraméter segítségével C kódot kérhetünk, • /b paraméterrel bináris kódot készít (ez az alapbeállítás), • /r paraméterrel megadhatjuk hány bájtot szeretnénk fenntartani saját használatra, (ez csak bináris módban muködik, ˝ alap: 32 bájt), • bemenet a bemen˝o adatokat tartalmazó könyvtár,
6.6. ábra. MPFS FAT bejegyzés felépítése
6.7. ábra. MPFS adatblokk felépítése
41 • kimenet az MPFS képet tartalmazó fájl. Például: mpfs /c Honlap honlap.c Így egy C fájlt kapunk benne a Honlap könyvtárban lév˝o fájlok adatai. Bináris fájlt kapunk az mpfs Honlap honlap.bin parancs hatására. A bináris fájl elején 32 bájt fenntartott. Ha megváltoztatjuk a fenntartott terület méretét ne felejtsük el a StackTsk.h fájlban a MPFS_RESERVE_BLOCK definíciót megváltoztatni. Miel˝ott a képfájlt létrehozzuk az összes honlapot egy könyvtárba kell másolni. Ha egy fájl kiterjesztése .htm, akkor a program az összes kocsi vissza, új sor karaktert törli, hogy csökkentse a képfájl méretét. Ha az MPFS képfájlt C adatként használjuk, akkor a projektünkhöz hozzá kell adni a C fájlt. Ha a képfájlt küls˝o soros EEPROMban tároljuk, a bináris fájlt fel kell tölteni a memóriába. További információ a 41. oldalon az „FTP szerver modul” résznél. Az MPFS képkészít˝o program nem ellen˝orzi az elkészült fájl méretét. Bináris adat készítése esetén ellen˝orizni kell az adat méretét.
6.6.2. MPFS könyvtár Az MPFS fájlrendszer eléréséhez szükséges könyvtár az MPFS.c fájlban van implementálva. Az MPFS könyvtárat a HTTP és az FTP szerver használja a felhasználói alkalmazástól függetlenül. Az MPFS könyvtár jelenlegi verziójával nem lehet egy létez˝o fájlrendszerhez új fájlokat adni ill. törölni. Bármilyen változás esetén egy újabb képfájlt kell létrehozni. Ha a bels˝o programmemóriát használjuk a tárolásra, az MPFS_USE_PGRM szót definiálni kell. Ha viszont küls˝o EEPROM-ot használunk, a MPFS_USE_EEPROM kulcsszót kell definiálni. Egyszerre csak egyik definíció szerepelhet a StackTsk.h fájlban; ennek ellen˝orzésére a futásid˝o alatt egy ellen˝orz˝okód fut le. A memória típusától függ˝oen különböz˝o lappuffer méretet kell beállítani. Az alap méret (amit az MPFS_WRITE_PAGE_SIZE határoz meg) 64 bájt. Ha más pufferméretre van szükség az MPFS_WRITE_PAGE_SIZE definíciót kell megváltoztatni. Az MPFS könyvtárnak ez a verziója az xeeprom.c fájlt használja a küls˝o EEPROM eléréséhez. Miközben egy fájlt olvas vagy ír kizárólagosan az MPFS irányítja az I2 C buszt és nem engedélyezi más I2 C eszközöknek – legyen az szolga vagy mester – a hozzáférést. Ha több I2 C eszközt használunk, akkor a felhasználói alkalmazás írásakor ezt figyelembe kell venni.
6.7.
FTP szerver modul
Ez a modul is egy kooperatív taszkként funkcionál és az FTP.c fájlban van a szerver forráskódja. Ez az FTP szerver nem tudja az összes szolgáltatást, ami az RFC 959ben [6] le van leírva, mivel direkt beágyazott rendszerekhez lett tervezve, minimális a mérete és a tudása. A modul jellemz˝oi: • Egy szálú FTP kapcsolat. A felhasználó azonosítása az alkalmazás feladata, • Automatikusan kezeli az MPFS fájlrendszert,
42 • A „PUT” paranccsal egy új MPFS kép tölthet˝o fel, • A fájlok egyenkénti feltöltése nem lehetséges. A modul két részb˝ol áll: maga az FTP szerver és a felhasználó azonosító függvény, ami a felhasználói alkalmazásnak kell tartalmaznia. Egy FTPVerify függvényt kell írnia a felhasználónak, ami ellen˝orzi az FTP felhasználót és a jelszót. Itt is megjegyzem, hogy a jelszót kódolatlanul küldi el a számítógép, tehát azok a megfelel˝o eszközökkel „lehallgathatók”. Az FTP szerver használatához a következ˝oket kell megtettünk: 1. A STACK_USE_FTP_SERVER-t definiálni kell. A komment jelet el kell távolítani a StackTsk.h fájlban a definíció el˝ol. 2. A definiált socket-ek számát növelni kell kett˝ovel ugyancsak a StackTsk.h fájlban. 3. Az FTP.c és az mpfs.c fájlokat hozzá kell adni a projektünkhöz. 4. Vagy az MPFS_USE_PGRM MPFS_USE_EEPROM definíciót be kell állítani, attól függ˝oen, hogy milyen tárolóelemet használunk. Ha küls˝o EEPROM-ot, az xeeprom.c fájlt is adjuk hozzá a projektünkhöz. 5. Módosítsuk a main() függvényt, hogy az FTP szerver inicializáló függvénye és taszkja fusson. Az FTP szerver 180 másodperc után jelez id˝otúllépést feltöltésnél és letöltésnél egyaránt. Ha egy kapcsolat 180 másodpercnél tovább van „IDLE” (tétlen) állapotban, akkor automatikusan megszakítja a szerver a kapcsolatot. Így a bennragadt kliensek nem gátolhatják meg a további FTP muveleteket. ˝
6.7.1. MPFS kép feltöltése FTP kliens segítségével Az FTP szerver f˝o feladata ebben a Stack-ben, hogy távolról lehessen frissíteni az MPFS képfájlt. A jelenlegi verzió csak akkor muködik, ˝ ha küls˝o EEPROM-ot használunk adattárolásra. Egy képfájl feltöltése látható a 6.8. ábrán. A vastagon szedett betuk ˝ a felhasználó által beírt adatokat jelzi. A jelszó természetesen nem látszódik a képerny˝on. FTPVerify Ez egy segédfüggvény (callback function), amit az FTP szerver akkor hív meg, ha kérést vesz a kapcsolat felépítésére. Ezt a funkciót a felhasználói alkalmazásnak kell tartalmaznia. Szintaxis: BOOL FTPVerify(char *login, char *password) Paraméter: login [bemen˝o] Egy sztring, ami tartalmazza a felhasználó nevét. password [bemen˝o] Sztring, ami a jelszót tartalmazza. Visszatérési érték: IGAZ: Ha a felhasználói név és a jelszó érvényes. HAMIS: Ha vagy a felhasználó neve, vagy a jelszó érvénytelen.
43 c:\> ftp 10.10.5.15 220 ready User (10.10.5.15: (none)): ftp 331 Password required Password: microchip 230 Logged in ftp> put mpfsimg.bin 200 ok 150 Transferring data... 226 Transfer Complete 16212 bytes transferred in 0.01Seconds 16212000.00Kbytes/sec. ftp> quit 221 Bye 6.8. ábra. MPFS képfájl feltöltése FTP kliens segítségével Elofeltétel: ˝ Nincs Mellékhatás: Nincs Megjegyzés: A felhasználónév hossza nullától kilencig változhat. Ha hosszabb felhasználónévre van szükség az FTP_USER_NAME_LEN definíciót kell megváltoztatni az ftp.h fájlban. A jelszó és az FTP utasítások hossza legfeljebb 31 karakter hosszú lehet. Ha hosszabb jelszó és/vagy parancs szükséges, akkor a MAX_FTP_CMD_STRING_LEN definíciót kell megváltoztatni az FTP.c fájlban. Példa: ROM char FTP_USER_NAME[] #define FTP_USER_NAME_LEN
= "ftp"; (sizeof(FTP_USER_NAME)-1)
ROM char FTP_USER_PASS[] #define FTP_USER_PASS_LEN
= "microchip"; (sizeof(FTP_USER_PASS)-1)
BOOL FTPVerify(char *login, char *password) { if ( !memcmppgm2ram(login, (ROM void*)FTP_USER_NAME, FTP_USER_NAME_LEN) ) { if ( !memcmppgm2ram(password, (ROM void*)FTP_USER_PASS, FTP_USER_PASS_LEN) ) return TRUE; } return FALSE; }
44
7. fejezet Hardver A „PIConNET” kártya kapcsolási rajzát és a nyomtatott áramkört a ChipCad Kft. készítette. A kapcsolási rajz az 1. számú mellékleten látható. A rajzon látható 93LC46B típusú soros EEPROM nem lett beforrasztva. A kártyához készítettem egy soros vonali illeszt˝ot és egy egyszeru˝ tápfeszültségstabilizátort, ami a 7.1. ábrán látható. A soros vonal illesztését egy MAX232A típusú integrált áramkör valósítja meg. A rajzon MAX232 IC szerepel, a két IC között annyi a különbség, hogy a MAX232 mellé 1 µF-os kondenzátorokat kell tenni, míg a MAX232A megelégszik 100 nF-os kondenzátorokkal. A tápfeszültség stabilizálását pedig egy 78L05 IC végzi el.
7.1.
Alkatrészek
7.1.1. PIC18F452 mikrovezérlo˝ Ez egy FLASH programmemóriával rendelkez˝o RISC mikrokontroller10 MIPS teljesítményre képes és maximum 40 MHz-en muködhet. ˝ 32 kilobájt FLASH építettek be a programmemóriának, 1536 bájt RAM és 256 bájt EEPROM van benne. Utasításkészlete 75 utasításból áll és úgy optimalizálták, hogy a C programnyelven történ˝o fejlesztést megkönnyítse. 31 szintu˝ verem van beépítve, ami ha szükséges szoftveresen b˝ovíthet˝o. A nyomtatott áramköri lapon felhasznált TQFP tok rajza a 7.2. ábrán látható. Az IC részletes leírása az angol nyelvu˝ adatlapon [7] van. Perifériák jellemz˝oi: • A lábak áramleadása vagy -felvétele 25 mA lehet. • Három küls˝o megszakítást generáló láb áll rendelkezésre. • Timer0 modul: 8 bit ill. 16 bites id˝ozít˝o/számláló 8 bites programozható el˝oosztóval. • Timer1 modul: 16 bites id˝ozít˝o/számláló. • Timer2 modul: 8 bites id˝ozít˝o/számláló 8 bites periódus regiszterrel (id˝oalap a PWM-hez).
45
7.1. ábra. Soros vonali illeszt˝o és tápfeszültség stabilizátor kapcsolási rajza
46
7.2. ábra. A PIC18F452 típusú mikrovezérl˝o lábkiosztása • Timer3 modul: 16 bites id˝ozít˝o/számláló. • Opcionális másodlagos oszcillátor Timer1-es és Timer3-as modulokhoz. • Két Capture/Compare/PWM modul. A modul háromféleképpen konfigurálható: – Capture (mintavételez˝o) bemenetként (16 bites, maximum felbontás 6, 25ns = TCY /16), – Compare (összehasonlító) bemenetként (16 bites, maximum felbontás 100ns = TCY ), – PWM kimenetként (felbontás 1 bitt˝ol 10 bitig változtatható, 8 bites felbontásnál fmax = 156kHz, 10 bites felbontásnál fmax = 39kHz). • Szinkron soros port (Master Synchronous Serial Port, MSSP) modul. Három módban muködhet: ˝ – 3 vezetékes SPI módban (mind a négyfajta SPI módban muködik), ˝ – I2 C mester módban, – I2 C szolga módban.
47 – Címezhet˝o USART modul. RS-232 és RS-485 módot is támogatja. – Párhuzamos szolga port (PSP). Analóg paraméterek: • 10 bites AD konverter jellemz˝oi: – Gyors mintavételez˝o képesség, – Muködik ˝ szundi (SLEEP) módban, – Linearitás ≤ 1 Lsb. • Programozható feszültségesés jelzés (Programmable Low Voltage Detection, PLVD): megszakítás kérhet˝o, ha leesik a feszültség. • Tápfeszültség-kiesés esetén beállítható reset folyamat (Brown-out Reset, BOR). Speciális jellemz˝ok: • Tipikusan százezerszer törölhet˝o/írható a FLASH programmemória. • Tipikusan egy milliószor törölhet˝o/írható az adat EEPROM. • A FLASH és az adat EEPROM legalább 40 évig megtartja tartalmát. • A szoftverb˝ol lehet írni/olvasni a programmemóriát. • Fejlett beépített reset áramkör: Power-on Reset (POR), Power-up Timer (PWRT), Oscillator Start-up Timer (OST). • Watchdog id˝ozít˝o (WDT) saját RC oszcillátorral. • Programozható kódvédelem. • Tápegységkímél˝o szundi (SLEEP) mód. • Változtatható oszcillátorbeállítások: – az els˝odleges oszcillátor négyszerezése (PLL használatával), – másodlagos órajel engedélyezése/tiltása. • Soros programozás két lábon keresztül (In-Circuit Serial Programming, ICSP). • Nyomkövetés két lábon keresztül (In-Circuit Debugging, ICD). CMOS technológia el˝onyei: • Alacsony teljesítményu, ˝ nagy sebességu˝ FLASH/EEPROM technológia • Széles tápfeszültség-tartomány (2.0–5.5V) • Ipari- és kiterjesztett h˝omérsékleti tartományok • Alacsony teljesítményigény: – kisebb, mint 1,6 mA, ha 5V a tápfeszültség és 4 MHz a frekvencia – 25 µA, ha 3V a tápfeszültség és 32 kHz a frekvencia – kisebb, mint 0,2 µA szundi üzemmódban
48
7.1.2. RTL8019AS ethernet vezérlo˝ Ez az IC valósítja meg a fizikai kapcsolatot az ethernet hálózattal. A régebbi verziójú RTL8019-et továbbfejlesztették és 16 kilobájt SRAM-ot építettek be egy tokba. Full-duplex-es és 10 Mbit/s sebesség érhet˝o el. Csavart érpáros (10baseT) és koaxiális kábellel (10base5, 10base2) is használható, továbbá a már igen elavult AUI csatlakozást is használhatunk. A PIConNET kártyán egy RJ45-ös csatlakozó lett kialakítva a csavart érpáros kapcsolathoz, továbbá van négy LED, amely a kapcsolat létrejöttét ill. a hálózati forgalmat jelzi. További információ az IC adatlapján [8] található. Ez az integrált áramkör a beépített SRAM-ot pufferként felhasználva ethernet kereteket küld ill. fogad manchester kódolással és kezeli az ütközéseket. Az OSI/ISO modellben gyakorlatilag a fizikai- és adatkapcsolati réteget valósítja meg.
7.1.3. 24LC256 típusú soros EEPROM Ebben a memóriában 32 kilobájt méretu˝ EEPROM található és I2 C buszon keresztül kommunikál a mikrokontrollerrel. Egy speciális formátumba csomagolva FTP-n keresztül tölthetjük fel honlapunkat a memóriába, továbbá ebben az EEPROM-ban tároljuk az alkalmazás beállításait. További információ az angol nyelvu˝ adatlapon [11] van. A 7.3. ábrán látható a tok lábkiosztása. A tok jellemz˝oi a következ˝ok: • Kis fogyasztású CMOS technológiával készül: – Az íráskor felvett áram 3 mA 5.5V-os tápfeszültségnél. – Az olvasáskor felvett áram maximum 400 µA 5.5V-os tápfeszültségnél. – Nyugalmi áram átlagosan 100 nA 5.5V-os tápfeszültségnél. • Két vezetékes I2 C kompatibilis soros busz. • Kaszkádba köthet˝o maximum 8 eszköz. • Bels˝o id˝ozítésu˝ írási- és olvasási ciklusok. • 64 bájt méretu˝ lapok írása támogatott. • Maximális írási id˝o 5 ms. • Hardveres írás védelem. • Schmitt Trigger-es bemenetek. • Egymillió törlés/írás ciklus. • Minimum 4 kV-os elektrosztatikus kisülés ellen védett. • Adatmegtartási id˝o legalább 200 év. • 8 érintkez˝os PDIP, SOIC, TSSOP, MSOP, DFN és 14 érintkez˝os TSSOP tokkal is gyártják.
49
7.3. ábra. A 24LC256 típusú soros EEPROM lábkiosztása
7.1.4. MAX232A soros vonali illeszto˝ A soros vonal illesztését végzi ez az integrált áramkör (lábkiosztása a a 7.4. ábrán látható). Az 5V-os TTL szintu˝ jeleket ±12V-os szintre alakítja, ehhez négy darab 100 nF-os kondenzátorra van szükség. Két darab bemenetet és két darab kimenetet kezel, ebb˝ol csak egyet-egyet használtam fel. Az IC részletes leírása az adatlapján [10] olvasható.
7.4. ábra. A MAX232 típusú soros vonali illeszt˝o lábkiosztása
50
8. fejezet Az eszköz használata és tesztelése 8.1.
Az eszköz használata
A kész eszközön három csatlakozó és öt LED található(8.1. ábra).
8.1. ábra. A doboz oldal- és elölnézete Jelmagyarázat: 1. Soros vonal: egy DSUB9-es csatlakozó található a dobozon. Ezen keresztül történik az RS-232 szabvány szerinti kommunikáció. 2. Ethernet: egy RJ45-ös foglalat van a csavart érpáros kábelnek. 3. Tápfeszültség: a protokollkonverternek 5-15V egyenfeszültségre van szüksége. 4. Link LED (sárga): Ha világít, a kapcsolat létrejött a két ethernet-es készülék között. 5. RX LED (zöld): Ha villog, adatok érkeznek az ethernet hálózaton az eszköz felé. 6. TX LED (zöld): Ha villog, az eszköz adatokat küld az ethernet hálózaton. 7. OK LED (zöld): Ha világít, akkor az eszköz megfelel˝oen muködik. ˝ 8. ERROR LED (piros): Ha világít, akkor az eszköz muködése ˝ során hiba lépett fel.
51 Az eszköz használata a 8.2. ábrán látható. Az ethernet hálózat kialakítására számtalan lehet˝oség van: lehet csak csavart érpáros technológiát használni vagy csavart érpáros kábeleket és optikai vagy mikrohullámú átvitelt is. Az áthidalható távolság akár több kilométer is lehet.
8.2. ábra. Az eszköz használata
8.2.
Konfigurálás böngészoprogrammal ˝
Az eszköz konfigurálását bármilyen böngész˝oprogrammal elvégezhetjük. Alapesetben az eszköz IP címe 10.10.5.15 hálózati maszkja 255.255.0.0. A http://10.10.5.15 címet beírva a böngész˝obe a 8.3. ábrán látható képet kell látnunk. A „Help” linkre kattintva ennek a fejezetnek a kivonatos verzióját olvashatjuk el. Az egyes linkekre kattintva beállíthatjuk a soros vonalat, a hálózatot ill. megtekinthetjük a statisztikákat.
8.2.1. Hálózat beállítása A „Network setup” linkre kattintva a 8.4. ábrán látható oldalon a következ˝oket állíthatjuk be: • Local IP: az eszköz IP címe (alap: 10.10.5.15). • Local Port: az eszköz ezen a porton várja az adatokat (alap: 2221). • Netmask: hálózati maszk (alap: 255.255.0.0). • Gateway: ha a cél IP címe másik tartományba esik meg kell adni az átjárót (alap: 10.10.5.15). Ha ugyanabban a hálózatban van, akkor az átjáró megegyezik az eszköz IP címével. • Target IP: a soros vonalról érkez˝o adatokat ennek az IP címnek fogja továbbítani (alap: 10.10.5.5). • Target Port: a soros vonalról érkez˝o adatokat a megadott portra küldi (alap: 2222).
52
8.3. ábra. Konfigurálás böngész˝oprogrammal: index
8.4. ábra. Hálózat beállítása böngész˝oprogrammal
53 • Refresh rate: A statisztika megtekintésekor ennyi másodpercenként fog frissülni a lap (alap: 10). A „Save” gombra kattintva az adatokat eltárolja a I2 C buszos EEPROM-ba és az eszköz lekérdezi a megadott cél IP cím MAC címét.
8.2.2. Soros vonal beállítása A „Serial port setup” oldalon (8.5. ábra) a soros vonal sebességét lehet beállítani. A sebesség 2400-tól 57600 baud-ig állítható. A „Save” gombra kattintva a beállítás azonnal érvényes lesz és az értéket elmenti az EEPROM-ba.
8.5. ábra. Soros vonal beállítása böngész˝oprogrammal
8.2.3. Statisztika A statisztikákat tartalmazó oldalon (a 8.6. ábra) láthatjuk az eszköz állapotát (rendben van ill. valamilyen hiba történt), a beállított paramétereket és az eddig átvitt adatok számát bájtban. Ez a HTML oldal automatikusan frissül alapesetben 10 másodpercenként. Ez frissítési érték (Refresh rate) a hálózati beállításokat tartalmazó lapon átállítható tetsz˝oleges értékre.
54
8.6. ábra. Statisztika megtekintése böngész˝oprogrammal
8.3.
Az eszköz tesztelése
Mivel csak egy eszközt készült el, ezért a teszteléshez számítógépen egy programmal (UDP test) szimuláltam a másik eszközt és egy egyszeru˝ terminálprogrammal küldtem és fogadtam a soros vonali adatokat. A 8.7. ábrán látható az eszköz és a számítógép összekötése.
8.7. ábra. Az eszköz tesztelése Az UDP test (8.8. ábra) nevu˝ programot C++ nyelven írtam direkt azért, hogy a készüléket tesztelni tudjam. A program egy f˝o ablakból áll, ami két részre van osztva.
55
8.8. ábra. Az UDP test program A bal oldalon található egy UDP kliens: a megadott IP címre és annak megadott portjára elküldi a szövegdobozban található szöveget. A jobb oldalon az UDP szerver vezérelhetjük, ami a program futtatásakor automatikusan elindul. A szerver megadott portjára érkez˝o adatokat a program egy szövegdobozban jeleníti meg. A program muködését ˝ egyszeruen ˝ ki lehet próbálni: a szerver címének a loopback eszköz címét kell megadni (például 127.0.0.1). Majd a kliensnek is ezt a címet és a szerver portját adjuk meg. Ha az elküld gombra kattintunk az üzenetnek meg kell jelennie a jobb oldali szövegdobozban.
56
Irodalomjegyzék [1] Nilesh Rajbharti. The Microchip TCP/IP Stack, 2002. Fájl: tcpipstack/an833.pdf [2] J. Postel. User Datagram Protocol, RFC 768, 1980. Fájl: rfc/rfc768.txt.pdf [3] T. Bradley, C. Brown, A. Malis. Inverse Address Resolution Protocol, RFC 2390, 1998. Fájl: rfc/rfc2390.txt.pdf [4] David C. Plummer. An Ethernet Address Resolution Protocol – or – Converting Network Protocol Addresses to 48.bit Ethernet Address for Transmission on Ethernet Hardware, RFC 826, 1982. Fájl: rfc/rfc826.txt.pdf [5] T. Berners-Lee. Hypertext Markup Language - 2.0, RFC 1866, 1995. Fájl: rfc/rfc1866.txt.pdf [6] J. Postel, J. Reynolds. File Transfer Protocol, RFC 959, 1985. Fájl: rfc/rfc959.txt.pdf [7] Microchip. PIC18FXX2 Data Sheet, DS39564B, 2002. Fájl: adatlapok/pic18fxx2/pic18fxx2.pdf [8] Realtek. RTL8019AS, Realtek Full-Duplex Ethernet Controller with Plug and Play Function, Ver 2.0, 1996. Fájl: adatlapok/realtek/rtl8019asds.pdf [9] Realtek. RTL8019 Realtek Full-Duplex Ethernet Controller with Plug and Play Function, LS003.6, 1995. Fájl: adatlapok/realtek/rtl8019.pdf [10] Maxim. MAXIM +5V-Powered, Multichannel RS-232 Drivers/Receivers, 19-4323; Rev 11; 2003. Fájl: adatlapok/MAX220-MAX249.pdf [11] Microchip. 24LC256, DS21203K, 2003. Fájl: adatlapok/24lc256.pdf