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.
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.
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.
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.
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.
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 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.
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:
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
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 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.