INGENIØRHØJSKOLEN I ÅRHUS Elektro- og IKT-afdelingen Side 1 af 7 Eksamenstermin: DECEMBER 2003 / JANUAR 2004 Varighed: 4 timer - fra kl. 9.00 til kl. 13.00 Ingeniørhøjskolen udleverer: 3 omslag samt papir til kladde og renskrift Særlige bemærkninger: Besvarelsen afleveres således, at I3PRG3 opgave nr. 1, I3DTM3 opgave nr. 2 og I3ISY1 opgave nr. 3 afleveres i hvert sit omslag
Side 2 af 7 OPGAVE 1. I forbindelse med håndtering af hœndelser anvendes i et system blandt andet klasserne: class Event enum PriorityLevel LOW = 0, NORMAL = 1, HIGH = 2 virtual ~Event()} virtual PriorityLevel priority() = 0; virtual void info() = 0; virtual void action() = 0; class EventQueue // Det er Event pointere der er i EventQueue virtual ~EventQueue()} virtual void put(event *eventptr) = 0; virtual Event *get() = 0; // skal returnere 0 hvis køen er tom class EventHandler EventHandler(EventQueue *eventqueueptr); ~EventHandler(); void handleevent(); // Henter nœste hœndelse (Event) i køen og // udfører action(). Hvis priority() er LOW // eller NORMAL kaldes info() der laver // passende udskrifter. // Afslutningsvis fjernes (deallokeres) // hœndelsen. // Hvis køen er tom returneres umiddelbart. private: EventQueue *m_eventqueueptr; endvidere skal klassen SpecialBuffer der implementerer en speciel effektiv buffer anvendes. Opgave 1 fortsættes næste side
Side 3 af 7 OPGAVE 1, fortsat. SpecialBuffer er erklœret således: template <class T> class SpecialBuffer SpecialBuffer(); ~SpecialBuffer(); void insert(t t); // indsœtter en vœrdi i bufferen T extract(); // henter en vœrdi fra bufferen bool isempty(); private:... og såvel.hpp som.cpp fil er til rådighed. a) Lav på grundlag af klassen EventQueue klassen SBEventQueue (.hpp og.cpp filer) med anvendelse af SpecialBuffer, altså class SBEventQueue : public EventQueue, hvor SpecialBuffer anvendes til implementeringen af SBEventQueue. b) Lav klassen EventHandler (.cpp filen). Besvarelsen af opgaven skal indeholde passende forklaring på hvad der laves.
Side 4 af 7 Følgende er givet: En SBC686 med et IO686-kort monteret. OPGAVE 2. Et DOS exe-program, der initierer PPI'en på IO686 til: Mode 0 med porta, portb og portc = indgange. I programmets datasegment er følgende buffer til 6 WORD defineret:.data buffer DW 6 DUP(0) Programmet udfører den nødvendige initiering til at muliggøre HW-interrupt fra IRQ5. HW-interrupt IRQ5 aktiveres af et ekstern signal. a) Skriv i MASM en interruptservicerutine hentdata til håndtering af interrupt fra IRQ5. Servicerutinen skal i hvert gennemløb foretage indlæsning af 6 WORD fra PPI'en til buffer. Servicerutinens funktion kan beskrives på følgende måde: Aflæsningen af de 6 WORD er styret af et ekstern signal, der sender pulser til portc's bit 0, således at aflæsning af hvert enkelt WORD skal ske umiddelbart efter bit 0 på portc skifter fra høj(1) til lav(0). Hvert WORD aflæses på PPI'ens porta (LSByte) og portb (MSByte) og skrives fortløbende i buffer, og det først aflæste WORD skrives på plads (index) 0. Det kan antages, at portc's bit 0 er lav i starten af servicerutinen og imellem aflæsningerne så detektering af begge flanker er muligt og nødvendigt! inden aflaesning af porta og portb. Ovenstående kan også beskrives med følgende tidsdiagram: Desuden er der følgende krav til servicerutinen: Der skal enables for HW-interrupt med højere prioritet (end IRQ5) inden aflæsningen begynder. Der skal sendes EOI-kommando når aflæsningen er slut. Opgave 2 fortsættes næste side.
Side 5 af 7 OPGAVE 2, fortsat. PPI'ens portadresser er: porta = 304h, portb = 305h og portc = 306h. Interruptcontrolleren's OCW2-adresse er: 20h. b) Skriv i MASM en procedure findmin, der har følgende funktionalitet: Proceduren skal finde det mindste tal i buffer og returnere det fundne tal i register AX. Tallene i buffer er signede WORD i 2-komplement kode. Procedurens C-prototype er: short findmin();
Side 6 af 7 OPGAVE 3. Et RTKernel system består blandt andet af processerne (trådene) Dataopsamling, Beregning, Alarm og main. I forbindelse med opbevaring af data anvendes en RTKernel bufferpool (se bilag 1) med en blokstørrelse på BLOK_LEN og BLOK_ANTAL antal blokke. Data samples med anvendelse af funktionen sample(void *bufptr, int n) der er defineret andetsteds, og hvor bufptr en en pointer til en buffer (en blok) hentet fra poolen og n er antal bytes der samples. Processerne Dataopsamling og Beregning kommunikerer via en postkasse mbdata med MB_DATA_LEN pladser (slots) der hver kan indeholde en pointer til en buffer (en blok). Processerne Beregning og Alarm kommunikerer via en semafor alarmsem. Proces Dataopsamling skal hver gang der er gået 50 msek allokere en buffer fra bufferpoolen, sample BLOK_LEN bytes og anbringe bufferen i postkassen mbdata (hvis poolen er tom laves der ikke noget i den aktuelle runde). Proces Beregning skal hver gang der hentes en buffer fra postkassen beregne middelvœrdien af data (bytes) i bufferen og hvis middelvœrdien ligger uden for intervallet [MIN_LIMIT - MAX_LIMIT] skal der signaleres til alarmsem. Beregning skal også deallokere den aktuelle buffer (levere den tilbage til bufferpoolen). Proces Alarm venter ved alarmsem og når der signaleres skal funktionen alarmaction() (defineret andetsteds) kaldes. Proces main skal initiere systemet, oprette alle relevante objekter (bufferpool, postkasse, semafor og procesobjekter) og starte alle processer. Følgende definitioner er altså lavet andetsteds og kan uden videre anvendes: BLOK_LEN BLOK_ANTAL MB_DATA_LEN MIN_LIMIT MAX_LIMIT void sample(void *bufptr, int n); void alarmaction(); ligesom den i ISY-1 tidligere anvendte class Thread kan anvendes. a) Lav klasserne Dataopsamling og Beregning (begge arver fra class Thread). Klassen Alarm skal altså ikke laves. b) Lav main processen (proces Alarm medtages ikke). Besvarelsen af opgaven skal indeholde passende forklaring på hvad der laves. Bilag 1 til opgave 3 følger næste side
Side 7 af 7 BILAG 1 TIL OPGAVE 3. Function RTKAllocMemPool Function RTKAllocMemPool creates and initializes a Memory Pool: void RTKAllocMemPool(RTKMemPool * Pool, unsigned BlockSize, unsigned Blocks); Parameters Pool: Pointer to the pool handle of the pool to initialize. BlockSize: Block size to use for the memory pool. Blocks: The pool is allocated with Blocks data buffers of size BlockSize. The buffers are allocated using RTKAlloc, which in turn uses RTKernel-32's memory driver. Therefore, RTKAllocMemPool will generally not fulfil real-time requirements. Its time behavior is non-deterministic and it must not be called in interrupt handlers. Function RTKGetBuffer Function RTKGetBuffer retrieves a buffer from a Memory Pool: void * RTKGetBuffer(RTKMemPool * Pool); Parameters Pool: Pointer to the pool handle of the pool from which to retrieve the buffer. return value: A pointer to the buffer is returned. If this was the last available buffer in the pool, *Pool is assigned the value RTK_EMPTY_POOL. If Pool is empty, the return value is NULL. Function RTKFreeBuffer Function RTKFreeBuffer passes a buffer to a Memory Pool: void RTKFreeBuffer(RTKMemPool * Pool, void * Buffer); Parameters Pool: Pointer to the pool handle of the pool to which to pass the buffer. Buffer: Pointer to the buffer to pass. In general, the buffer will have been retrieved previously from the pool; however, it can also have been allocated by a different method (e.g., malloc, RTKAlloc, or allocated as a static variable). It must be ensured that the same buffer is not passed to a pool twice by RTKFreeBuffer, because this would destroy the Memory Pool. This condition is not recognized by RTKFreeBuffer and the program will crash in most cases.