VI. fejezet - Célspecifikus alkalmazások

Tartalom
VI.1. SOC (System On a Chip)
VI.1.1. A SOC definíciója
VI.1.2. A SOC részei
VI.2. Beágyazott eszközök, PC-s fejlesztő rendszerek
VI.2.1. Atmel: WinAVR és AVR studio
VI.2.2. Microchip: MPLAB IDE és MPLAB-X
VI.3. Elosztott rendszerek programozása
VI.3.1. CORBA
VI.3.2. A CORBA nyílt forráskódú implementációi
VI.3.3. ICE – internet communication engine

VI.1. SOC (System On a Chip)

VI.1.1. A SOC definíciója

A „SOC” rövidítés jelentése „System on a Chip”, vagyis rendszer egy integrált áramköri tokban. Kifejlesztési szempontjainál lényeges szerepet játszott a teljes berendezés alacsony összköltsége, a berendezés kis mérete, fogyasztása. Nem tudunk éles határvonalat húzni a SOC és a mikrovezérlő közt, szokásosan a 128 kb RAM memória feletti eszközöket nevezzük SOC-nak, az ez alattiakat pedig mikrovezérlőnek. Természetesen ez a határvonal sem éles, ugyanis létezik mikrovezérlőként gyártott eszköz 512k memóriával is. Más szempontból is húzhatunk határvonalat (bár ez sem lesz éles): a SOC-on általában interaktív felületű operációs rendszert futtatunk (legtöbbször valami Unix-klónt, pl. Linuxot), míg a mikrovezérlőn egy feladatspecifikus program működik. Ez a szempont is a memóriamérettel operál: általában a Unix-klónoknak nem elég a 128 kbyte körüli memória.

VI.1.2. A SOC részei

A SOC (és a mikrovezérlő is) különböző hardverelemekből állhat, azonban mindig tartalmaz egy vagy több CPU (esetleg DSP) magot, amely egy műveletvégző egység. Szokásos gyártási eljárás, hogy a SOC gyártója a CPU magot másik gyártótól veszi, majd körberakja a saját hardverelemeivel, és betokozza. Ez a rész felel meg kb. a PC-k processzorának. A tápellátó és buszvezérlő áramkörök is mindig megtalálhatók. Ezen elemek (pl a CPU mag) lábai közvetlenül nem jelennek meg a SOC lábai közt. A busz is jellemzően belső busz szokott lenni, ha külső memória/periféria csatlakoztatási lehetőség is van, azt buszillesztőn keresztül vezetik ki.

Opcionális, szokásos hardverelemek:

  • RAM: operatív memória. A mikrovezérlőnél a kisméretű memória a tokban kapott helyet, míg a SOC-nál általában memóriabusz van kivezetve, amelyen keresztül külső, általában dinamikus RAM IC-ket lehet a SOC-hoz kötni. Ennél a megoldásnál a rendszertervező a szükséges méretű memóriával láthatja el a rendszert. A mikrovezérlőket többféle memóriamérettel gyártják, hogy az adott alkalmazáshoz leggazdaságosabban alkalmazhatót lehessen beszerezni.

  • ROM: csak olvasható memória. Mikrovezérlőnél a teljes programot tárolja, és a tokban van elhelyezve, míg a SOC-nál külső ROM busz lett kialakítva, amely vagy a teljes operációs rendszert tárolja, vagy csak egy betöltő programot, a tényleges operációs rendszer valahonnan betöltődik (háttértár, hálózat). A manapság használatos SOC-okat és mikrovezérlőket flash típusú EEPROM-mal látják el, hogy a szoftver (firmware) felhasználók által is lecserélhető legyen. Programfejlesztés közben ez a megoldás kényelmes: az UV fénnyel törölhető EPROM-ok korszakában egy programhiba javítása a törlés miatt legalább 10 percet vett igénybe, ma ezredmásodperces a nagyságrend. A SOC/mikrovezérlő tartalmazhat olyan kódot, amely a saját ROM memóriáját képes programozni (self-write, bootloader). A mikrovezérlő gyártók kész program és nagy mennyiség rendelése esetén maszkprogramozott ROM-mal is gyártanak, amikor már gyártás közben belekerül a módosíthatatlan program a mikrovezérlőbe, így lesz a fajlagos költség a legkisebb.

  • Oszcillátor: a kisebb mikrovezérlők tartalmaznak belső RC oszcillátort, amely az órajelgenerátor szerepét képes betölteni. Az előállított frekvencia nem elég pontos az USB-hez és az ethernethez, de elég az RS-232-höz.

  • Watchdog: egy CPU-tól független számláló, amelyet programból periodikusan le kell nulláznunk. Amennyiben „elszáll” a program (vagy elfelejtettük nullázni), a túlcsordulásakor egy hardver reset jelet küld a CPU-nak, vagyis hardveres újraindítás történik.

  • Interrupt és DMA vezérlők: a megszakítások és a direkt memóriába történő adatmozgatás vezérlését végzik. Az összes periféria (időzítők, A/D átalakító, GPIO) képesek bizonyos feltételek esetén megszakítást kérni, amely után a megszakításkezelő programok futnak le.

  • GPIO szabadon felhasználható digitális ki/bemenet, általában párhuzamos portillesztéssel, vagyis a processzor szóhosszúságának megfelelő számú vezeték, amelyeket egyetlen utasítással lehet aktualizálni vagy beolvasni. A GPIO minden SOC-nál megtalálható, hogy a rendszer tervezője képes legyen perifériákkal (pl. egy LED-del) jelezni a készülék üzemállapotát. A GPIO általában programozható kimenetre és bemenetre is: egy programrészlet mondja meg, hogy a láb a kimeneti regiszterben található értéket vegye fel (ekkor beolvasva természetesen a kimeneti regiszter értékét kapjuk), vagy nagyimpedanciás állapotban (TRI-State) a külvilág állíthatja be a bit tartalmát, amelyet beolvashatunk (például egy nyomógomb).

  • A/D átalakító: az adott lábra analóg feszültség kapcsolható, amelyet programból beolvashatunk. A beépített átalakítók 10-12 bitesek, és néhány megaHertz az átalakítási órajelük. Több láb is lehet analóg bemenet egy átalakítóhoz, ekkor először egy multiplexerrel kell kiválasztani, melyik csatornát szeretnénk használni. Az A/D átalakító referenciafeszültsége lehet a vezérlő tápfeszültsége, valamelyik analóg inputot fogadni képes lába, vagy belső, programozható feszültségreferencia.

  • Komparátor: az analóg bemenetre használt lábakat egy összehasonlító áramkörre is vezethetjük, amelynek a másik bemenetén ugyanazon lehetőségek közül választhatunk, mint az A/D átalakítónál. A komparátor kimenete a két jel összehasonlításának eredménye (kisebb, egyenlő, nagyobb).

  • Időzítő/számláló (Timer/Counter): Ezek az eszközök növekvő számlálót tartalmaznak. Az időzítő adott érték elérésekor kimeneti jelet ad vagy megszakítást kér. A számláló bemenete lehet egy digitális bemenet láb, vagy a rendszer órajele, valamilyen leosztás (prescaler) után. A számláló túlcsorduláskor kér megszakítást. A számláló értéke ki is olvasható. 8- és 16-bites számláló használata szokásos, a többi bitet a megszakításkezelőben szoftverből kell megvalósítani.

  • PWM kimenet: impulzusszélesség-modulált kimenet. Egy adott frekvenciájú (timer kimenete) négyszögjel, amelynek kitöltési tényezője programozható (0%-nál csak L szintű, 100%-nál csak H szintű). DC motorok és lámpák kis veszteségű teljesítményszabályozására használható. Rendszerint legalább 2 van belőle, hogy a teljes H hidat meg lehessen valósítani (két másik digitális kimenettel a forgásirány szabályozáshoz). Teljesítményfokozat nincs beépítve, mindig külső FET-eket kell illeszteni.

  • Soros ki/bemenet: kétvezetékes aszinkron kommunikáció, egyszerűen megvalósítható akár gépi kódban is. A régebbi PC-k soros portjához (COM) tudtunk kapcsolódni, a port mára eltűnt a PC-kről, de az iparban még mindig használják egyszerűsége és robosztussága miatt. A SOC (és mikrovezérlő) tápfeszültségei nem teszik lehetővé az RS-232 szabvány szerinti jelszinteket, így mindig külső szintillesztőt kell alkalmazni. Hasonlóan RS-422-re is illeszthető a rendszer, ha nagyobb távolságú átvitelre van szükség. Az adatátviteli sebesség 75 bit/sec-től (baud) 115200 bit/sec-ig terjedhet. Szokásos sebességek a 9600 és a 19200 bit/sec. A modern pc-hez soros bővítőkártyával vagy USB-serial konverterrel csatlakozhatunk, amely a PC-n egy virtuális soros portot hoz létre. Gyakran a SOC-nál (amelyben operációs rendszer is fut) a soros portra irányítják a konzol üzeneteket, kezdve a kernel indításától. A soros port csatlakozó header-ét (tüskesor) a SOC-ot tartalmazó nyomtatott áramköri lapon szintillesztés nélkül kivezetik. Szintillesztővel és egy, a PC-n futó terminálprogrammal közvetlenül az operációs rendszernek adhatunk parancsokat.

  • USB: ma szinte minden számítógép tartalmaz USB portot, és rengeteg USB-s eszköz kapható. Az USB előnyei, hogy tápfeszültséget is találunk benne (5V/500mA), az adatátviteli sebesség magasabb, mint a soros portnál: 1.5 Mbit/sec (1.0 low speed) , 12 Mbit/sec (1.0 full speed), 480 Mbit/sec (2.0 high speed), 5 Gbit/sec (3.0 superspeed), valamint menet közben is rácsatlakoztatható a gépre, amely vezérlő programját automatikusan elindítja. Többfajta megvalósítása lehet az USB-s kommunikációnak: lehet a PC a master, a SOC pedig az USB-s periféria, vagy lehet a SOC a master (USB Host), és egy pendrive vagy külső HDD, webkamera a periféria. A SOC által megvalósított periféria is többféle lehet: általában az USB stack valamelyik szintjét használják, például a CDC-t, amely soros portként látszik a PC-n, és emiatt a soros portot kezelni tudó programokkal külön meghajtó program nélkül is tud kommunikálni. Készülhet még HID protokollal és a nyílt forráskódú libusb-vel a kommunikáció, ekkor a PC-re is telepíteni kell a szükséges programokat.

  • Ethernet: a helyi hálózat, 10/100/1000 Mbit/sec sebességgel. Általában nem épül be a SOC-ba, mert külső transzformátort és transceivert igényel, de a SOC-ot fel kell készíteni a kezelésére, a szükséges bitszélességű MII porttal. Az ethernettel felszerelt SOC-ot általában nem natív ethernet protokollal kezeljük, hanem TCP/IP-vel. Így a SOC internetre köthető, emiatt távolságproblémák nem lépnek fel a kommunikációban. A TCP/IP szintje felett szabványos kimenetű alkalmazások állhatnak: például webszerver, ekkor a PC-n (vagy akár mobiletelefonon) web böngészővel kommunikálhatunk a SOC-cal. Tipikus alkalmazása a SOC-oknak a szélessávú router, amely egy ethernet portot tartalmaz az Internethez való csatlakozáshoz (ezen a porton DHCP vagy PPPoE kliens fut a szolgáltatóhoz bejelentkezve) és egy 4-portos ethernet kapcsolót (switch), ezeken a portokon DHCP és egyéb szerverek biztosítják a gépek csatlakoztatását. A konfigurálás webes felületen történik, a beépített webszerverrel. Az operációs rendszer általában Linux, az EEPROM és a RAM külső. Soros port a nyomtatott áramköri lapon kiépítve, ide kerülnek a kernel üzenetei. Némelyik eszközben USB port is helyet kapott, az ide kötött perifériákat (nyomtató, külső HDD) a hálózat eszközei is láthatják.

  • I2C: a Philips által kifejlesztett kétvezetékes (SDA, SCL) soros kommunikáció, ahol egy mester (master) eszközhöz több szolga (slave) eszköz is csatlakoztatható, a nyitott kollektoros kimeneteknek és a felhúzó ellenállásoknak köszönhetően. A SOC képes a master és a slave szerepében is működni, de legtöbbször masterként alkalmazzuk. I2C -n különféle perifériákat kapcsolhatunk a SOC-hoz: például EEPROMot, hőmérőt, gyorsulásmérőt, hangerőszabályzót, tv-tunert. Az I2C órajelének sebessége max. 100 kHz, az újabb eszközöknél 400 kHz. Minden eszköznek 7-bites címe van, így 127 eszköz használható egy buszon. Az Intel néhány alaplapján alkalmazza a protokollt, smbus néven. A kommunikációt mindig a master kezdeményezi, a végén „ACK” jelzést küld a megcímzett eszköz, így jelenléte detektálható.

  • SPI: soros periféria busz. Az adatvonalakból kettőt alkalmaz: egyet a mastertől a slave-ig, egyet pedig visszafele, így a kommunikáció full-duplex is lehet. Órajelből csak egy van: mastertől a slave-ig. Célszerűen pont-pont összeköttetésre tervezték, de több slave is felfűzhető a buszra, a „Slave Select” jel segítségével, amelyek közül csak egyet kell aktivizálni. A szabványban nem szerepel maximális sebesség, az adott gyártó adatlapján kell tájékozódni. Azonban ez a sebesség Mbit/s nagyságrendbe szokott esni, ami az I2C -nél nagyobb.

  • RTCC: valós idejű óra, különálló táplálással. A rendszeridő aktualizálódik a SOC kikapcsolása után is.

  • CAN busz interfész: főleg a járműiparban használt hardver és protokoll a központi számítógép (ECU) (esetleg SOC) valamint a szenzorok és aktuátorok közti kommunikációra. Néhány ipari és egészségügyi berendezés is alkalmazza.

  • Képmegjelenítő egység: a médialejátszókba épített SOC-ok tartalmaznak mpeg-2 és h.264 videó dekódert, manapság HDMI kimenettel.

Álljon itt két tipikus blokk-diagram: egy mindentudó mikrovezérlőé (forrás: Microchip, típus: PIC32MX család), és egy médialejátszóba szánt SOC-é (forrás: Realtek, tipus: RTD1073) A Realtek kevésbé dokumentált, ott csak a külső csatlakozásokat tüntették fel.

A PIC32MX blokkdiagramja
VI.1. ábra - A PIC32MX blokkdiagramja


RealTek SOC csatlakoztatási lehetőségei
VI.2. ábra - RealTek SOC csatlakoztatási lehetőségei


VI.2. Beágyazott eszközök, PC-s fejlesztő rendszerek

Mint ahogy láttuk, a SOC-ok egy PC-hez képest kisebb memóriával és háttértárral rendelkeznek, megjelenítő eszközzel általában nem. A mikrovezérlők még kisebb memóriát tartalmaznak. Ezekre az eszközökre készülő fejlesztő rendszerek nem az adott eszközön futnak (nem is futhatnának), hanem egy általános célú számítógépen, ami általában PC. A SOC-ok magja valamilyen RISC processzor szokott lenni, ehhez a GCC képes kódot generálni, cross-compiler üzemmódban. Kezelői felület nincs a fejlesztő eszközhöz: szövegszerkesztővel írjuk a C forrásprogramokat, majd lefordítjuk a cross-compiler GCC-vel. Összerakjuk a Linux kernelt, és a rendszerfájlokat, valamint a felhasználói állományokat és a rendszerbetöltőt egy ROM fájlba, és ezt a fájlt töltjük be a SOC EEPROM-jába. Az első alkalommal, amíg még a rendszerbetöltő nincs bent, a SOC JTAG csatlakozóján keresztül tudjuk az EEPROM-ot írni, egy JTAG égető segítségével. A SOC-okhoz általában nem készül SDK (szoftver fejlesztő készlet), mert azok egyedi gyártással születnek, így a kereskedelemben az IC-k nem is kaphatók, csak valamilyen eszközbe építve. A kész berendezéshez (pl. szélessávú router) amennyiben Linux-ot használ, kötelező forrást adni a gyártó honlapján. Ennek módosításával tudunk beavatkozni az eszköz működésébe, vagy egy másik Linux-ot fordítani hozzá. Ilyen például az OpenWRT projekt, amelyben Linux alatt, egy cross-gcc-vel saját disztribúciót készítettek, amely egyes, a dokumentációban megjelölt routerekre feltölthető. Az OpenWRT viszonylag jól dokumentált projekt, a dokumentáció reverse-engineering módszerrel keletkezett, valamelyik gyártmány GPL forrásából.

A mikrokovezérlők esetén más a helyzet. Általános célú, program nélküli eszközök, amelyeket nagy mennyiségben gyártanak, lehetővé téve a felhasználó számára a feladatnak megfelelő program beleírását. Az alkalmazott nyelv leggyakrabban a K&R C (a C++ kód futtatása túl nagy memóriát igényelne). A kisebb, 8-bites mikrokovezérlőket lehet gépi kódban is programozni. A gépi kód előnye, hogy kisméretű, hatékony és gyors program keletkezik, hátránya, hogy a kód (és az utasításkészlet ismerete) nem hordozható. A mikrovezérlő gyártók minden esetben biztosítanak fejlesztő eszközöket az ingyenes, oktatási célú felhasználásra szánt (de már működő és a gyártó oldaláról letölthető) fordítótól, a professzionális, cégeknek szánt komplett fejlesztő környezetig. Más mikrovezérlőket a GCC is támogat, ott a gyártó csak fejállományokat és kezelői felületet biztosít. Miután a fordítóprogramok C nyelvű fájlokat fordítanak futtatható ROM fájlokká parancssoros fordítóprogrammal, ezért akár a Visual Studio is használható kezelői felületként, megfelelő beállítások után. Az elkészült kódot itt is JTAG-gal, vagy az adott mikrovezérlő programozójával lehet a mikrovezérlőbe betölteni. Általában a költséges JTAG helyett 50$ körüli áron kaphatók ezek a programozók, és az internet tele van kapcsolási rajzokkal, amelyek 1-2$-ból kihoznak valami használható megoldást. A továbbiakban a két legnagyobb mikrovezérlő gyártó, az Atmel és a Microchip fejlesztő eszközeit ismertetjük. A két gyártó nagyjából ugyanazt gyártja, izlés dolga, hogy melyiket alkalmazzuk. Az Atmel inkább a professzionális felhasználókat célozza meg, ez az árakban is érvényesül. A Microchip az amatőr felhasználóknak is gyárt: DIP foglalatos mikrovezérlő otthoni körülmények közti forrasztáshoz, kis mennyiségben (1 darab) is általában beszerezhető a magyarországi hivatalos disztribútornál. Mindkét gyártó készít úgynevezett kezdő készleteket (starter kit), amelyek egy kész próbapanelt mikrovezérlővel, ki- és bemeneti perifériákat (az olcsó változatban LED és nyomógomb, a drágában DC motor és érintőképernyő), programozót, és készen lefordítható és futtatható demo-programokat tartalmaznak.

VI.2.1. Atmel: WinAVR és AVR studio

A legtöbb Atmel mikrovezérlőt a GCC fordító is támogatja, így nyílt forráskódú IDE is készült hozzá: a WinAVR a Sourceforge weblapon található. Ingyenes, regisztrációmentes letöltés és telepítés után a GCC fordító és a szükséges binutils, valmint a gdb debugger is használható. Az ingyenes programokra jellemzően nincsenek kényelmi funkciók, vagy programkönyvtárak a speciális hardverekhez; ezeket külön kell telepítenünk. A VI.3. ábra ábra egy interneten található led-villogtató mintaprogram fordítását mutatja a WinAVR-rel. A Makefile-t és a led.c fájlt kellett ehhez a projekthez megírni a szövegszerkesztővel, majd a Tools menü „Make All” menüpontját kiválasztani.

A mintaprogram
VI.3. ábra - A mintaprogram


Az első két értékadó utasítás lefordítva:

void main(void)
 
{ unsigned char i;
 // set PORTD for output 
DDRB = 0xFF; 
  34:    8f ef           ldi    r24, 0xFF    ; 255
  36:    87 bb           out    0x17, r24    ; 23
PORTB = 0b00000001; 
  38:    81 e0           ldi    r24, 0x01    ; 1
  3a:    88 bb           out    0x18, r24    ; 24

Elkészült az EEPROM tartalom (led.eep), amit az avrdude programozó szoftverrel, stk600-as hardverrel (200$) vagy AVRISP-vel (40$) be lehetne égetni az ATTiny2313-ba.

Az Atmel is elkészítette a saját IDE-jét, amelyhez több programkönyvtárat is adnak, ennek neve AVR Studio. Tartalmaz beépített C fordítót, de az internetes világ a GCC fordítót használja, így az AVR Studio beállítható úgy, hogy a WinAVR-ben található GCC fordítóval működjön együtt.

VI.2.2. Microchip: MPLAB IDE és MPLAB-X

A Microchip-nél gcc támogatás nincs (picgcc projekt ugyan létezik, de letölthető változat nincs), így a cég weboldaláról ingyenesen letölthetjük az MPLAB IDE-t, amely assembler fordítót (MPASM) tartalmaz az összes termékükhöz (16xx,18xx,24xx,dsPIC), kivéve a PIC32 családot (MIPS core:asm32), és a C fordítóból az oktatási licenszű verziót a 18-as (c18), 24-es (c24) és 32-es (c32) sorozathoz. Az IDE a szerkesztésen kívül az összes beszerezhető programozót és debuggert is támogatja. Amennyiben kényelmesen szeretnénk használni, ne kérjünk teljes telepítést (full installation), csak a meglévő (tervezett) eszközeinket és fordítóprogramokat telepítsük fel. Hasznos eszköz lehet az MPLAB SIM, amellyel konkrét hardver nélkül futtathatjuk, debuggolhatjuk programjainkat, egy virtuális CPU-n. A virtuális CPU nagy előnye, hogy fordított polaritású tápcsatlakoztatással nem tehető tönkre, a valódi változattal szemben. A következő ábrán (VI.4. ábra) a IV.2.23. szakasz szakaszban található programmal (SerialPort) kommunikáló programrészlet fejlesztése látható.

A VI.4. ábra programrészletete egy PicKit2-vel (eredeti: 40$, klón: 25$) beégethetjük egy PIC18f4550-be, és USB-n keresztül már kommunikálhatunk is a hardverrel.

Az MPLAB IDE fejlesztése során alkalmazott problémákat (Windows-függőség) próbálja meg feloldani az új MPLAB-X. A NetBeans alapú környezet fut Linuxon és MacOS-X-en is. Ez már tartalmazza a Visual Studio-ban alkalmazott automatikus kódkiegészítő funkciót és a függvény-definíció keresőt.

Az MPLAB IDE
VI.4. ábra - Az MPLAB IDE


VI.3. Elosztott rendszerek programozása

Az internet és alapprotokolljának elterjedésével nemcsak az emberek közti kommunikáció gyorsult fel. Ma már a szuperszámítógépek nem egy nagy órajelű processzort és nagymennyiségű operatív és háttértárat tartalmaznak. Az órajelben elértük a technológiai határt, teljesítménynöveléshez csak a párhuzamosan egyszerre működő elemi számoló egységek számának növelésével juthatunk el. Ezt a célt szolgálja az egyetlen integrált áramkörbe tokozott több processzor mag (Dual, Quad stb core). Kézenfekvő volt, hogy valahogy szétoszthatók legyenek a feladatok interneten keresztül is. Az internetes kapcsolat két gép közt szekvenciális fájlként jelentkezik, a socket programcsomagot használva. Az első, socketre épülő, de annál magasabb szintű elérést lehetővé tevő módszer a távoli függvényhívás (RPC), amelyet pl. a SUN NFS Unix alapú fileszerver valósít meg. A programozó viszont nem protokollt, hibakezelést és fájlelérést szeretne fejleszteni, rendelkezésre állnak a socketre épülő objektumorientált technológiák is. Ezeknél a technológiáknál a kiszolgálón levő objektum tulajdonságai az ügyfélen elérhetők, metódusai a kiszolgálón futtathatók, az ügyfélen egyszerű függvényhívásként. Hasonlóan, a szerveren fellépő esemény is a kliensen lévő triggerelt metódussal kezelhető. Arra is van lehetőség, hogy az IP címen csak egy proxy szerepeljen, és továbbítsa a felhasználó kérését egy éppen szabad kiszolgáló gép számára. A mai nagy számításigényű rendszerek a kereskedelemben és a kutatásban is hasonló elven működnek. Példaként az amazon.com-ot, a google rendszerét vagy a JUQUEEN és JUROPA gépeket (IBM) említhetjük.

VI.3.1. CORBA

A CORBA egy, az OMG (Object Management Group) által definiált szabványos objektum környezet, 1990-ben jelent meg az első verziója, amellyel különféle nyelveken írt, és/vagy különálló gépeken futó alkalmazások együtt képesek dolgozni. Az alkalmazás a metódusokat ugyanúgy használhatja a távoli gépen is, mint a helyi gépen. A szabvány fontos eleme az interfész definíciós nyelv (IDL), amely a konkrétan használt fordítóprogramtól (amely fordíthat C-ről, C++-ról, Java-ról, Cobol-ról és még néhány egyéb nyelvről) független. A CORBA fordító elkészíti az adott nyelvhez az IDL-ben megírt objektumokhoz a függvények fejléceit (skeleton - csontváz), amelyet nekünk kell az adott nyelven implementálni, ezt a folyamatot „mapping”-nek, az így készített objektumokat pedig „adapter”-nek nevezzük. A mapping a Java nyelvben egyszerű, a nyelv erősen objektum-orientált tulajdonságai miatt. C++-ban kissé többet kell dolgozni: összetett adatszerkezetek felhasználására van szükség, amelyek néha összekeverednek a szabványos sablonkönyvtár (STL) típusaival. A CORBA implementáció tartalmaz egy IDL fordítót, amely már a felhasznált nyelvre (pl C++) fordít, és a szabályos fordítóval és szerkesztővel készíthetünk futtatható programot, természetesen az IDL-ből fordított függvények definiálásával (a csontváz „felöltöztetésével”) az adott programnyelven. Emellett tartalmaz natív kommunikációs komponenseket, amelyek az internetes, socket szintű kommunikációt bonyolítják, a felhasználó számára transzparens módon. Az alábbi (VI.5. ábra) ábrán egy kiszolgálón működő objektum ügyfélből történő elérését szemléltetjük:

CORBA beépítés
VI.5. ábra - CORBA beépítés


VI.3.2. A CORBA nyílt forráskódú implementációi

A CORBA egy szabvány, emiatt nem egy gyártótól szerezhető be: többen is implementálták a struktúrát. Licenszelhető (vásárolható) és nyílt forráskódú változatok egyaránt léteznek. A licenszelhető implementációk főleg a pénzügyi szektorban terjedtek el, az oktatásban az ingyenesen hozzáférhető nyílt forráskódú változatok valamelyikét használjuk.

MICO: www.mico.org a Frankfurti egyetem fejlesztéséből született, C++ nyelven íródott, egyedül Unix API hívásokat alkalmaz. A forrásfileokat a SourceForge-n tárolják, onnan letölthetők.

JacORB: www.jacorb.org Java nyelvű ORB, LGPL licensszel. JDK 1.6 kell a működéséhez.

TAO: www.ociweb.com A Washingtoni egyetem fejlesztése, létezik ingyenes és kereskedelmi változatban is. Unix-on és Windows-on is használhatjuk, létezik valós idejű (real-time) operációs rendszeren futó verzió is.

ORBiT: orbit-resource.sourceforge.net Alap C-ben és Perl-ben is használható, nyílt forráskódú CORBA 2.4 implementáció. Mivel a GNOME rendszerhez fejlesztették ki, a legtöbb Linux disztribúció tartalmazza. Win32 alatt futó változat is készült belőle.

Az alábbi példában egy "távoli" számítást fogunk elvégezni, az ügyfél megadja a műveletet, a kiszolgáló elvégzi, az ügyfél pedig kijelzi az eredményt. A példában mindkét program (a kliens és a szerver) is ugyanazon a számítógépen fut. Az IDL fájl a lehető legegyszerűbb, egy interfészt két függvénnyel tartalmaz:

// Calculator interface: calculator.idl
//
interface Calculator
{
      double add(in double number1, in double number2);
      double sub(in double number1, in double number2);
};

Fordítsuk le az idl compilerrel: /usr/pkg/bin/orbit-idl-2 calculator.idl !

orbit-idl-2 2.14.17 compiling mode, hide preprocessor errors, passes: stubs skels common headers
Processing file calculator.idl

Ekkor elkészül a „csontváz” (calculator-skel.c), a kliensen futtatható stub (calculator-stubs.c), és a fejállomány (calculator.h). A header fájlban megtaláljuk a CORBA kompatibilis osztályt (alap C, struct függvényekkel):

typedef struct {
  void *_private;
CORBA_double (*add)(PortableServer_Servant _servant, const CORBA_double number1, const CORBA_double number2, CORBA_Environment *ev);
CORBA_double (*sub)(PortableServer_Servant _servant, const CORBA_double number1, const CORBA_double number2, CORBA_Environment *ev);
} POA_Calculator__epv;

Ezeket kell implentálnunk (skelimpl.c):

static CORBA_double
impl_Calculator_add(impl_POA_Calculator * servant,
            const CORBA_double number1,
            const CORBA_double number2, CORBA_Environment * ev)
{
   CORBA_double retval;
 
   /* ------   insert method code here   ------ */
   g_print ("%f + %f\n", number1, number2);
   retval = number1 + number2;
   /* ------ ---------- end ------------ ------ */
 
   return retval;
}
 
static CORBA_double
impl_Calculator_sub(impl_POA_Calculator * servant,
            const CORBA_double number1,
            const CORBA_double number2, CORBA_Environment * ev)
{
   CORBA_double retval;
 
   /* ------   insert method code here   ------ */
   g_print ("%f - %f\n", number1, number2);
   retval = number1 - number2;
   /* ------ ---------- end ------------ ------ */
 
   return retval;
}
Ezután következhet a kiszolgáló oldali főprogram:
static CORBA_Object
server_activate_service (CORBA_ORB           orb,
             PortableServer_POA  poa,
             CORBA_Environment  *ev)
{
    Calculator  ref = CORBA_OBJECT_NIL; 
 
    ref = impl_Calculator__create (poa, ev);
    if (etk_raised_exception(ev)) 
        return CORBA_OBJECT_NIL;
    
    return ref;
}

A kiszolgáló main() függvényben elindítjuk a szolgáltatást:

servant = server_activate_service (global_orb, root_poa, ev);
server_run (global_orb, ev);

Az ügyfélen a stubon nem kell változtatnunk, csak a main() függvény megírása hiányzik:

static
void
client_run (Calculator service,
    CORBA_Environment *ev)
{
    CORBA_double result=0.0;
    result = Calculator_add(service, 1.0, 2.0, ev);
    g_print("Result: 1.0 + 2.0 = %2.0f\n", result);
}

Ezt az ügyfél main() függvényéből meghívjuk, és a kiszolgáló elvégzi a számolást:

calculator-server & elindítjuk a kiszolgálót a háttérben, ami vár a kliens csatlakozására

calculator-client elindítjuk az ügyfelet

1.000000 + 2.000000

Result: 1.0 + 2.0 = 3

VI.3.3. ICE – internet communication engine

A CORBA rendszert megvizsgálva azt láthatjuk, hogy sok feladatra alkalmazható, azonban a szükséges programozási munka nagy része a feleslegesen túlbonyolított objektumokra és osztályokra megy el. Néhány CORBA fejlesztő ezért egy kis fejlesztő csapatot alakított, hogy a CORBA elveit újragondolva, készítsenek egy bizonyos szempontból leegyszerűsített, bizonyos szempontból bővített távoli objektumelérést támogató rendszert. Erre a feladatra egy céget is alapítottak, ZeroC néven (www.zeroc.com). A rendszert ICE-nak nevezték el, és kétfajta licenszeléssel hozzáférhető: GPL és kereskedelmi licensz is létezik belőle. A kereskedelmi (fizetős) licenszhez terméktámogatás jár. Külön előny, hogy az ICE-hez lélezik a manapság divatos érintőképernyős platformokon futó változat, pl. az IceTouch, amely az OS-X fordítójához (Xcode) készült, és iOS szimulátort is tartalmaz. Az ICE disztribúció tartalmaz mindent, amire a környezetnek szüksége van: eszközöket, API-kat, könyvtárakat az objektumorientált kiszolgáló-ügyfél alkalmazások készítéséhez. Támogatja az architektúrák és nyelvek közti átjárhatóságot: az ügyfél és a kiszolgáló is futhat más platformon, más programozási nyelven megírva. A leíró nyelvet, amelyben definiáljuk az ICE objektumot, Slice-nek nevezzük (Specification Language for Ice). Ez tartalmazza az interfészeket, a műveleteket és az adattípusokat, amelyek a kiszolgálón és az ügyfélen közösen definiáltak. Ezeket a Slice fájlokat egy fordító API hívásokra fordítja, forrásnyelvű programrészletekre, amelyek az aktuális rendszerben és programozási nyelven lefordíthatók, természetesen csak a skeleton kitöltése (a függvények {} közti részének megírása) után. Az egyes nyelvekre való fordítást "language mapping"-nak nevezzük. Az ICE rendszerben a használt nyelv lehet C++, Java, C#, Python, Objective-C. Az ügyféloldalon PHP is alkalmazható. Az ICE-t használó programok szerkezete az alábbi (VI.6. ábra) ábrán látható:

Az ICE programok szerkezete
VI.6. ábra - Az ICE programok szerkezete


Az ICE saját protokollt használ az IP fölött, ez lehet TCP vagy UDP is. Amennyiben érzékeny adatokat tartalmaznak az objektumaink, SSL-t is használhatunk a kiszolgáló és az ügyfél között. A hagyományos távoli objektumhoz képest plusz szolgáltatásokat is kínál, mint pl. az IceGrid, amelyben több kiszolgáló is tartalmazhatja az objektumot, teherelosztás (load-balancing) céljából, vagy az IceStorm, amely események szétosztását végzi a közzétevők és az esemény iránt érdeklődő előfizetők között.

Az alábbi, egyszerűsített példában egy ipari robot ICE kiszolgáló oldalát készítjük el, a robothoz kapcsolódó ügyfelek képesek a robot mozgatására és az aktuális koordináták lekérdezésére. A slice definiciós állomány a következő (Kuka.ice – a Visual Studioval csak mint szövegfájl nyitható ki):

module CyberLab
{
 
  struct e6pos 
  {
    float x; // x,y,z milliméterek
    float y;
    float z;
    float a; // a,b,c szögek, fokban
    float b;
    float c;
  };
 
 
  interface Robot6Dof
  {
    void GotoHome(); // alap pozíció a robot programban
    e6pos GetPosition(); // hol vagy ?
    void GotoPosition(e6pos p); // menj egy pozícióba
  };
};

Ezt a fájlt a slice2cpp.exe-vel lefordítjuk, keletkezik 2 állomány: Kuka.cpp, és Kuka.h. Ez az úgynevezett „csontváz”, amelyben a definiált metódusok, mint absztrakt virtuális tagfüggvények szerepelnek:

virtual void GotoPosition(const ::CyberLab::e6pos&, const ::Ice::Current& = ::Ice::Current()) = 0;

Ráismerhetünk az interfész utolsó függvényére. Ahhoz, hogy az osztályt példányosítsuk, ezt a függvényt definiálnuk kell. A Robot6Dof osztályból örököltetünk egy új osztályt (az implementációs osztályt: Robot6DofI), amelyben ezen tagfüggvények kifejtése szerepel:

class Robot6DofI : public Robot6Dof {
public: 
    virtual void GotoHome(const Current& c);
    virtual e6pos GetPosition(const Current& c);
virtual void GotoPosition(const e6pos& e6, const Current& c);
};

Majd ezeket a függvényeket ki is fejtjük:

void Robot6DofI::GotoHome(const Current& c)
{
    Send_command_to_robot(CMD_ROBOT_HOME);
}
 
e6pos Robot6DofI::GetPosition(const Current& c)
{
    e6pos poz;
    Send_command_to_robot(CMD_ROBOT_GET_POSITION,poz);
    return poz;
}
 
void Robot6DofI::GotoPosition(const e6pos& e6, const Current& c)
 {
     Send_command_to_robot(CMD_ROBOT_GOTO_POSITION,e6);
 }

A kifejtésben felhasználtuk a már meglévő kommunikációs függvényeket, amelyek a robotnak RS-232-n keresztül parancsokat küldtek. Már csak a főprogramot kell megírni, létrehozni a kommunikációs adaptert (az ICE demo program alapján):

int _tmain(int argc, _TCHAR* argv[])
{
    int status = 0;
    std::string s1="KukaAdapter";
    std::string s2="default -p 10000";
    Ice::CommunicatorPtr ic;
    Ice::InitializationData id;
    argc=0;
    try 
    {
    ic = Ice::initialize(id);
    Ice::ObjectAdapterPtr adapter=ic->createObjectAdapterWithEndpoints
(s1,s2);
    Ice::ObjectPtr object = new Robot6DofI;
    adapter->add(object,ic->stringToIdentity("Kuka"));
    adapter->activate();
    ic->waitForShutdown();
    } 
    catch (const Ice::Exception& e) 
    {
        cerr << e << endl;
        status = 1;
    } 
    catch (const char* msg) 
    {
        cerr << msg << endl;
        status = 1;
    }
    if (ic) 
    {
        try 
        {
            ic->destroy();
        } 
        catch (const Ice::Exception& e) 
        {
            cerr << e << endl;
            status = 1;
        }
    }
    return status;
}

Ne felejtsük el a projektünk tulajdonságaiban beállítani az ICE include és library könyvtárait, mert azok nélkül nem képes lefordítani és összeszerkeszteni a programot!

A hibátlan fordítás után már csak az ICE-hez tartozó DLL-eket kell a program futása közben elérhetővé tenni, és indulhat a szerver. A Kuka.ice file-t átküldve a külföldi partnernek, ő elkészíti az ügyfelet (valamilyen programozási nyelven, pl C++-ban, vagy C#-ban), és távolról képes irányítani a robotot.

Az ICE könyvtárak
VI.7. ábra - Az ICE könyvtárak