RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
5)De IPC@CHIP software op het RIOT bord. Het Operating system in een notedop. Zoals op elk computersysteem moet ook op een IPC@CHIP een operating system (OS) voorhanden zijn, voor het besturen van de verschillende hardwarecomponenten. Wanneer een computer wordt aangeschakeld begint het OS de hardwarecomponenten te initialiseren of in te stellen voor een correcte (samen)werking in het systeem. Om de gebruiker toe te laten dingen te wijzigen in de normale instellingen van het systeem zal het OS hiervoor informatie lezen uit verschillende files, waar de gebruiker dan zijn specifieke instellingen kan aangeven. Bij de IPC@CHIP zijn dit de chip.ini en de autoexec.bat files. In deze laatste file kan de gebruiker bijvoorbeeld aangeven welk user-programma moet opgestart worden nadat de systeem-initialisering afgelopen is.
De autoexec.bat en chip.ini files. Deze autoexec.bat en chip.ini files zijn ascii files, en kunnen met een eenvoudige texteditor zoals Windows-Notepad aangemaakt worden. De autoexec.bat file, moet zich net als de chip.ini file in de rootdirectory van het virtuele diskettestation a:\ bevinden, en wordt gelezen na de chip.ini file. Het doel van de chip.ini file is het vrijgeven en de instelling van de verschillende componenten van het OS, zoals vb. de FTP-, HTTP-, Telnet-, en PPP-server. Het belangrijkste doel van de autoexec.bat file is het automatisch opstarten van programma’s. De commando’s die in deze file worden opgenomen zijn identiek aan diegene die met de hand op de console ingegeven kunnen worden. Wanneer men een programma, na het booten van de IPC@CHIP, automatisch wil laten opstarten, schrijft men met een texteditor de naam van het uit te voeren programma’s (vb. test.exe) naar een file autoexec.bat, dit wordt aangegeven in figuur 5.1. Daarna moet deze file op de IPC@CHIP geladen worden, langs de seriële poort of via FTP. Bij het opstarten zal dan de volgende keer het programma test.exe automatisch worden uitgevoerd.
Figuur 5.1:De autoexec.bat file. De autoexec.bat file is een batch file, wat door de extentie .bat aangegeven wordt. De naam duidt erop dat in de file de commando’s sequentieel achter elkaar worden geschreven om dan door het OS in die volgorde te worden uitgevoerd. Om te testen of alles werkt kunnen deze commando’s met de hand in de command interpreter worden ingegeven. Daarna kunnen ze in dezelfde volgorde in de batch-file worden geschreven, en worden opgeladen. Men moet er dan wel rekening mee houden het systeem eerst terug op te starten vooraleer deze door de command interpreter worden uitgevoerd.
Versie 1.0
55
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
De command interpreter COMMAND. Dit is de interface van de IPC@CHIP naar de gebruiker toe om vb. een programma op te starten. De commando interpreter kan bevelen die van de terminal of de autoexec.bat-file komen interpreteren en deze omzetten in een aantal OS-routine oproepen. De beschikbare commando’s worden beschreven in een doc-file die hoort bij elke beschikbare versie van het OS. Deze doc-file is na het “un-zippen” van deze BIOSversie (OS)-ZIP file beschikbaar, en kan met een Webbrowser doorlopen worden. De BIOS versie die actueel in de RIOT systemen wordt gebruikt is SC12V0101, die samen met de documentatie in de bijhorende .ZIP file is gecomprimeerd. Volgende commando’s (Tabel 5.1) staan ter beschikking: Tabel 5.1: Commando's van de command-interpreter Commando Beschrijving Commando’s aangeven help Wissen van file’s del Directory opvragen dir Uitschrijven van tekstfile type File’s copiëren copy Rename file’s ren Make directory md Change directory cd Console definition con
Voorbeeld help del *.jpg dir *.exe type autoexec.bat copy chip.ini chip.tst ren chip.new chip.ini md temp cd temp con com con ext con com telnet
ale pcs iw ow ib ob
Enable/disable ALE pin Enable chip select Input word Output word Input byte Output byte
ale 0 pcs 5 iw 500 ow 500 1f4e ib 500 ob 500 fa
ip ipeth ping netmask gateway dhcp ftp tftp tcpipmem ipcfg
IP address define Restart ethernet Ping to address Set netmask Set gateway address Enable/disable dhcp Enable/disable ftp server Enable/disable tftp server Show reserved TCP/IP stack Show IP configuration
ip 192.168.0.1 ipeth ping 192.168.0.45 netmask 255.255.255.0 gateway 192.168.0.0 dhcp 0 ftp 1 tftp 0 tcpipmem ipcfg
reboot memopt
Restart system Enable/disable memory optimalisation Setup batchmode
reboot memopt 1
batchmode
Versie 1.0
56
batchmode 1
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
wait format a: ver xtrans
Tabel 5.1: Commando's van de command-interpreter (vervolg). Command interpreter sleep wait 1 Format flashdisk A: format a: Show bios version ver File transfer with XMODEM xtrans ext s test.exe protocol xtrans com r main.htm
mem
Show memorymap
mem
cgistat webstat closetelnet
Show installed CGI handlers Show startpage of webserver Close telnet session
cgistat webstat closetelnet
Versie 1.0
57
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
De API’s van het OS. De software-ontwerpers van het OS en de BIOS software moeten een grondige kennis bezitten van de werking van de hardware van de computer om deze te kunnen instellen. Wanneer dit niet het het geval zou zijn functioneert een deel van de hardware niet of toch niet naar behoren. Zo moeten ze bijvoorbeeld weten welke locatie van de seriële poort ( UART) moet gelezen worden om na te gaan of een toets is ingedrukt op het keyboard van de aangesloten terminal, of naar welke locatie ze moeten schrijven om op het scherm iets weer te geven. Men wil voorkomen dat elke programmeur al deze systeemkennis nodig heeft om een userprogramma te kunnen schrijven. Daarom stelt het OS en de BIOS een aantal softwareroutines ter beschikking, die door de ontwerpers met verstand van zaken zijn geschreven, om deze specifieke hardware gebonden taken van de programmeur van user-programma’s over te nemen. De programmeur van user-software moet nu alleen de documentatie van deze OS of BIOS-routines doornemen om deze te kunnen hergebruiken in zijn software. Hij weet hiermee wat er gebeurt als hij een bepaalde OS of BIOS-routine oproept, hoe en waarom dit gebeurt is voor hem dan van ondergeschikt belang. Deze OS-routines die als ‘software interface’ het leven van de ontwerper van user-software vergemakkelijken noemt men API’s (Application Programmers Interfaces). Zo zijn er op de IPC@CHIP verschillende categoriën te onderscheiden: HARDWARE API Langs de routines van deze interface worden de hardware-pinnen van de IPC@CHIP bestuurd . Zo kunnen er langs deze API de bus-mode en de chipselects worden ingesteld, timers worden gestart, gestopt en gelezen, I/O pinnen worden gelezen en aangestuurd. BIOS API BIOS staat voor Basic Input Output Systemprogram. Hier bevinden zich de routines die zorgen voor standaard input en output . Zoals :‘Get a character from std in, wait if none available’, ‘Check if a character is available from standard input’, ‘Get the IP address as a string.’, enz… FOSSIL API De routines van deze API houden zich alleen bezig met het besturen van de beide seriële poorten van de IPC@CHIP . Deze kunnen hier worden aan of uitgeschakeld, wat hun pinnen vrijgeeft voor andere toepassingen, de BAUD-rate en buffer instellingen kunnen hiermee gebeuren. Voorbeelden zijn: ‘Read a byte from the receiver buffer. Wait for a byte to arrive if none is available.’, ‘Configure the flow control for a port’, ‘Enable the RS485 mode’,… IIC API De besturing voor deze tweedraads bus gebeurt met routines uit deze API. Zo zijn er oa. volgende routines: ‘Initialize the I2C Bus’, ‘Send or receive a single character’, ‘Report addresses of slave devices, one at a time’, … EXTERNE DISK API Deze API is enkel van nut indien op de IPC@CHIP een externe harddisk is aangesloten. De benodigde interface-hardware moet echter eerst geïmplementeerd worden, daar de chip hiervoor zelf geen voorzieningen heeft. Dit is echter onmogelijk op het RIOT bord, zodat deze API voor ons van geen belang is. Versie 1.0
58
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
DOS-API Deze Disk Organisation System-routines zijn de op de BIOS volgende software-layer. De ‘disk’ wordt op een IPC@CHIP computer in een Flash-ROM als een virtueel diskettestation A:\ geëmuleerd. Hierbij stelt DOS dezelfde functionaliteit ter beschikking als bij een echte disk, maar dan in FlashROM. Mogelijke services zijn: ‘Create a new subdirectory’, ‘Open an existing file’, ‘Create New File Handle’, ‘Allocate memory for the process’,… RTOS API RTOS staat voor Real Time OS, en geeft de mogelijkheid meerdere systeem- en user-programma’s gelijktijdig te laten lopen. In deze API vinden we routines die dienen voor de sheduling van de lopende programma’s (Tasks). Hierin vinden we oa. volgende services: ‘Create and start a task’, ‘Stop and kill specified task’, ‘Suspend a task’, ‘Create a semaphore’, ‘Get tick count of system clock’, … TCP/IP API De netwerkmogelijkheden van een IPC@CHIP computer zijn gebaseerd op de geïmplementeerde TCP/IP stack. Services die in deze API ter beschikking staan van de gebruiker zijn oa.: ‘open a socket’, ‘close a socket’, ‘Bind a unnamed socket with an address and port number’, ‘get options on socket’,… ETHERNET API Met deze API komen routines ter beschikking die het transport van data pakketjes over het ethernet controleren. Zoals: ‘Send bytes in provided packet buffer over Ethernet’, ‘Install Access Handler’, ‘Get the SC12 Ethernet Address’, … WEB SERVER CGI API Met de routines van deze API kunnen drivers geïnstalleerd worden voor het dynamisch aanmaken van Hypertextpagina’s, en kan de rootdirectory en de startpagina van de http:// en ftp:// netwerkservers ingesteld worden. Te gebruiken routines zijn o.a. : ‘Install a CGI function’, ‘Remove a CGI function’, ‘Set a new main page’, ‘Install a Turbo Pascal CGI procedure’, ‘Get Web server's root directory’, … Voor de beschrijving van de werking en het gebruik van de beschikbare API’s verwijzen we naar de “SC12V010x.ZIP” bestanden die ter beschikking staan op de website van BECK. De “x” staat hier voor het versienummer van de firmware. Hierin zit een .doc file verpakt die de beschrijving bevat van de verschillende API’s.
Versie 1.0
59
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Het toepassen van deze systeem API's vanuit 'C'. Het toepassen van deze API's is gebaseerd op het gebruik van software-interrupts (of ook wel eens system calls genoemd) op het IPC@CHIP systeem. Wat is een software interrupt? Een software interrupt is een mechanisme waarmee men een routine (functie) van het OS of de BIOS software kan uitvoeren zonder dat men moet weten waar deze routines zich bevinden in het geheugen. Men roept deze OS routines immers op via een tussenstap. Namelijk a.d.h.v. een Interrupt Service Routine (ISR) geïnitieerd door een INT instructie op de 80186 processor ( zie instructieset van de 80186 microprocessor) van de IPC@CHIP. Afhankelijk van de meegegeven parameter (getal tussen 0 en 255) bij de INT instructie zal de processor het adres berekenen van de bijhorende vector in een (door het OS ingevulde) vectortabel. Deze vector is niets anders dan het startadres van de ISR routine die men wil uitvoeren. Op deze manier kan de processor uiteindelijk de ISR routine terugvinden die de gebruiker wil uitvoeren. De opgestarte ISR zal dan afhankelijk van de inhoud van de processorregisters een bepaalde taak uitvoeren voor de gebruiker. De gebruiker kan deze taak selecteren door de nodige parameters te schrijven in de registers van de processor voordat de INT instructie wordt uitgevoerd. Samengevat komt het op het volgende neer: de taak die wordt uitgevoerd voor de gebruiker wordt bepaald door het nummer dat meegegeven wordt met de INT instructie én door de waarde van de processorregisters op dat ogenblik. Het voordeel van deze omslachtige manier van werken is, dat de gebruiker om een bepaalde routine uit te voeren, steeds dezelfde sequentie van instructies kan gebruiken in zijn toepassingsprogramma. De ontwerper van het OS of de BIOS software moet er alleen maar voor zorgen dat de vectortabel met de adressen van de ISR's bij elke nieuwe release van het OS of de BIOS software wordt aangepast aan de nieuwe situatie. De toepassingssoftware kan zo telkens de gewenste OS routines blijven aanspreken zonder de nieuwe adressen van de OS routines te moeten kennen. Op deze manier kan toepassingssoftware toch blijven werken met nieuwe releases van het OS dat zo onafhankelijk kan worden aangepast aan nieuwe noden en nieuwe hardware.
Versie 1.0
60
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Hoe voeren we een software interrupt uit vanuit 'C' ? Syntaxmatig kunnen we dit in onze programma's noteren zoals in het volgende code fragment. #include <dos.h> #define PFE_INT union REGS union REGS struct SREGS
0xa2 // Pin Function Enabler inregs; outregs; segregs;
/******************************************************************************/ // enable the databus on the IPC@CHIP (ALE signal, PCS1 activates 100H-1FFH addresses) /******************************************************************************/ void enable_databus (void) { // enable 8 bit databus inregs.x.ax = 0x8001; //enable ALE, databus inregs.x.dx = 0x00ff; //all 8 bits are enabled int86x (PFE_INT,&inregs,&outregs,&segregs); //enable chip select 1 (PIO4) inregs.h.ah = 0x83; inregs.x.dx = 0x02; //PCS1# (100h-1ffh) int86x (PFE_INT,&inregs,&outregs,&segregs); }
//software interrupt (OS call)
In de dos.h file worden structs,unions macro's en functies gedefiniëerd voor het gebruik met MSDOS. In deze file worden oa. de union REGS en de struct SREGS gedefiniëerd. De union REGS en struct SREGS worden gebruikt om info door te geven naar en van de int86x functie. Ook worden in dos.h de structs BYTEREGS en WORDREGS gedefiniëerd voor het opslaan van byte en woord registers. Om dit beter te begrijpen geven we in figuur 5.1 de registerstructuur weer van de 80186 processor.
Figuur 5.2: Register structuur van de 80186 processor.
Versie 1.0
61
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Zoals uit figuur 5.2 duidelijk wordt heeft de 80186 een aantal registers die op woordbasis en bytebasis kunnen aangesproken worden, nl: AX (AH,AL) , DX (DH,DL), CX (CH,CL) en BX (BH,BL). Om deze op een eenvoudige manier vanuit C te kunnen aanspreken worden zoals eerder gezegd in dos.h een aantal decaraties gedaan, nl: struct BYTEREGS { unsigned char al; //unsigned char heeft lengte 8 bits unsigned char ah; unsigned char bl; unsigned char bh; unsigned char cl; unsigned char ch; unsigned char dl; unsigned char dh; }; struct WORDREGS { unsigned short ax; //unsigned short heeft lengte 16 bits unsigned short bx; unsigned short cx; unsigned short dx; unsigned short si; unsigned short di; unsigned short cflag; unsigned short flags; }; struct SREGS { unsigned short es; unsigned short cs; unsigned short ss; unsigned short ds; }; union REGS { //overlay van de byte (var. h) en word (var. x) registerstructs struct WORDREGS x; //hierdoor kan éénzelfde register variabele aangesproken struct BYTEREGS h; //worden als twee indviduele bytes of als een word }; Met de declaratie van union REGS inregs in ons programma wordt een variabele inregs gecreëerd die bestaat uit een overlay van een variabele x van het type WORDREGS (met daarin de members ax tot flags) en een variabele h van het type BYTEREGS (met daarin de velden al tot dh). Een member van deze variabele inregs kan daarna op woord of bytebasis worden aangesproken. inregs.h.ah inregs.x.dx
=0x83; // hier spreken we de variabele inregs aan op bytebasis (type BYTEREGS). =0x02; // hier spreken we de variabele inregs aan op wordbasis (typeWORDREGS).
Hiermee bepalen we welke functie we willen uitgevoerd zien door het OS. Het is juist deze informatie die is beschreven in de documentatie die hoort bij de API's.
Versie 1.0
62
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Aan de functie int86x worden de adressen doorgegeven van de inregs, outregs en segregs variabelen. int86x (PFE_INT,&inregs,&outregs,&segregs);
Met int86x wordt een software interrupt uitgevoerd gespecifiëerd door het argument PFE_INT (in dit geval de waarde A2h zoals aangegeven in de define). Vóór het opstarten van de software interrupt worden de processorregisters door de functie int86x geladen met de waarden uit inregs. De waardes segregs->ds en segregs->es worden ook in de overeenkomstige processorregisters geladen. Ná het beëindigen van de software interrupt wordt door de functie int86x ook de inhoud van processorregisters geladen in outregs . Op de volgende manier worden de verschillende functies uit de API's beschreven in de betreffende documentatie, hier werd als voorbeeld de functie Initialize the I2C Bus genomen uit de IIC API. Interrupt 0xAA service 0x80: Initialize the I2C Bus This function sets the I2C bus clock speed to that specified by the caller. It also configures two of the programmable I/O (PIO) pins for usage as I2C bus data and clock signals. Parameters AH 0x80 AL no longer used CX 0 Comments The user can specify which two PIO are used for I2C clock and data. After calling this initialization function, these two pins will no longer be available as PIO pins unless the PFE Enable function is called for these pins following this function call. Related Topics Select I2C Clock Pin Select I2C Data Pin PFE: Enable Programmable I/O Pins #include <dos.h> #define IIC_INT union REGS union REGS struct SREGS
0xaa // IIC bus functions inregs; outregs; segregs;
inregs.h.ah = 0x80; inregs.x.cx = 0x00; int86x (IIC_INT,&inregs,&outregs,&segregs);
Op deze manier kunnen we de functie Initialize the I2C Bus uitvoeren, zonder voorkennis over de hiervoor gebruikte hardware, dit is de bedoeling van de API's .
Versie 1.0
63
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Verwerken van hardware interrupts vanuit 'C'. Bij een software interrupt is het de bedoeling een routine uit het OS uit te voeren die een bepaalde service verleent aan de gebruiker. Bij een hardware interrupt is het meestal de bedoeling een zelf geschreven functie (ISR) uit te voeren wanneer een hardware-onderdeel er aan de hand van een interruptsignaal om vraagt. De ISR wordt dus opgeroepen door een signaal dat asynchroon binnenkomt ten opzichte van de normale programma-uitvoering. De ISR wordt verder opgestart aan de hand van hetzelfde mechanisme als bij een software interrupt. Afhankelijk van het type interrupt zal een vector uit de vectortabel worden opgehaald die aangeeft waar de ISR zich ergens bevindt in het geheugen, en de processor zal deze ISR dan uitvoeren. De programmeur moet er echter op letten dat hij zelf via software deze vector in de vectortabel invult. Dit in tegenstelling met een software interrupt waar het OS er voor zorgt dat de betreffende vector correct in de vectortabel wordt ingevuld. Zoals we uit het schema van de interface van de DPRAM met de IPC@CHIP kunnen afleiden is het mogelijk dat de IPC@CHIP processor vanuit de DPRAM een interruptsignaal binnenkrijgt (/INT0). Dit kan als gevolg van: • Het indrukken van een toets op de keyboardinterface van IOsys. • Na het verstrijken van de cyclustijd van de IOsys. • Na het verwerken van een opdracht van de IPC@CHIP door IOsys. Voor bijkomende informatie verwijzen we naar Hfdstk. 6 en meerbepaald naar het deel 'cyclustijd en interrupt controleregisters van IOsys' van de intelligente I/O controller IOsys. Een voorbeeld voor het verwerken van interrupts op de IPC@CHIP wordt in het volgende C programma gegeven. /***************************************************************************/ // Example of using interrupts on the RIOT board v1.0 // // Created by [dp] 23.04.2002 // This program reads the contents of memory bank 0,1,2,3 of the // dual port ram on the RIOT board, and writes it to stdio // every time an external interrupt0 occurs. // Interrupt0 is activated by the dual port ram as a result // of a write access to location 83ffh from the IOsys side. // /***************************************************************************/ /***************************************************************************/ // Includes /***************************************************************************/ #pragma option -1 // create 80186 code #include <stdio.h> #include <dos.h>
Versie 1.0
64
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 ***************************************************************************/ // Defines /***************************************************************************/ #define PFE_INT 0xA2 #define HAL_INT 0xA1 #define TCP_INT 0xAC #define INTR0 0x0C // External interrupt0 vector number /***************************************************************************/ // Variables /***************************************************************************/ union REGS inregs; union REGS outregs; struct SREGS segregs; int ok_flag=1; unsigned char getal0,getal1,getal2,getal3; unsigned int address=0x1fe; /***************************************************************************/ // Init RIOT v1.0. /***************************************************************************/ void enable_databus (void) { // Enable 8 bits databus inregs.x.ax = 0x8001; // enable ALE, databus inregs.x.dx = 0x00FF; // all 8 bits are enabled int86(PFE_INT, &inregs, &outregs); // Enable programmable chip select1 (poi4) inregs.h.ah = 0x83; inregs.x.dx = 0x02; // PCS1# (100h-1FFh) int86(PFE_INT, &inregs, &outregs); } void select_bank0 (void) { // Reset pio2, pio3 lines inregs.h.ah = 0x82; inregs.h.al = 0x05; // pio2,pio3 both 0 inregs.x.dx = 0x000B; // enable pio2,pio3 int86(PFE_INT, &inregs, &outregs); }
void select_bank1 (void)
Versie 1.0
65
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
{ // Reset pio3 line inregs.h.ah = 0x82; inregs.h.al = 0x05; // pio3 state 0 inregs.x.dx = 0x0008; // enable pio3 int86(PFE_INT, &inregs, &outregs); // Set pio2 line inregs.h.ah = 0x82; inregs.h.al = 0x04; // pio2 state 1 inregs.x.dx = 0x0004; // enable pio2 int86(PFE_INT, &inregs, &outregs); } void select_bank2 (void) { // Set pio3 line inregs.h.ah = 0x82; inregs.h.al = 0x04; // pio3 state 1 inregs.x.dx = 0x0008; // enable pio3 int86(PFE_INT, &inregs, &outregs); // Reet pio2 line inregs.h.ah = 0x82; inregs.h.al = 0x05; // pio2 state 0 inregs.x.dx = 0x0004; // enable pio2 int86(PFE_INT, &inregs, &outregs); } void select_bank3 (void) { // Set pio2, pio3 lines inregs.h.ah = 0x82; inregs.h.al = 0x04; // pio2,pio3 both 1 inregs.x.dx = 0x000B; // enable pio2,pio3 int86(PFE_INT, &inregs, &outregs); } /***************************************************************************/ // Read databus on specified address /***************************************************************************/ unsigned char read_databus (unsigned int ram_address) { unsigned char value; // read data bus inregs.h.ah = 0x80; inregs.x.di = ram_address; // address = user parameter inregs.x.bx = 0xFFFF; // wAND=0xFFFF inregs.x.cx = 0x0000; // wXOR=0x0000 int86x(HAL_INT, &inregs, &outregs, &segregs); value = outregs.h.al; return value; }
Versie 1.0
66
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 /***************************************************************************/ // Write databus to specified address /***************************************************************************/ void write_databus (unsigned char value,unsigned int ram_address) { // write data bus inregs.h.ah = 0x81; inregs.x.di = ram_address; // address = user parameter inregs.h.dh = 0; inregs.h.dl = value; inregs.x.bx = 0xFF; // wAND=8 bits databus inregs.x.cx = 0x0000; // wXOR=0x0000 int86x(HAL_INT, &inregs, &outregs, &segregs); } //************************************************************************** // Following routines are the interrupt enable and mode setting routines //************************************************************************** void enable_int0 (void) { inregs.h.ah = 0x84; inregs.x.dx = 0x0001; int86 (PFE_INT,&inregs,&outregs); }
// Enable interrupt0
void pos_edgeint0 (void) { inregs.h.ah = 0x86; inregs.x.dx = 0x0001; int86 (PFE_INT,&inregs,&outregs); }
// Rising edge sensitive interrupt0
//************************************************************************** // This is the interrupt service routine (ISR), it sets the ok_flag for the main function. //************************************************************************** void interrupt int0handler () // Declare this function as an ISR! { ok_flag=1; select_bank3(); getal3=read_databus (0x1fe); // read location 1fe and reset int condition // Give specific int0 EOI to the PIC (SC12 i/o base address ff00h) see 80186 USERS MAN. outport (0xff22,INTR0); }
Versie 1.0
67
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
//************************************************************************** // Main loop /*************************************************************************** void main (void) { enable_databus (); ok_flag=1; setvect (INTR0,int0handler); enable_int0 (); pos_edgeint0 ();
// Put INT0 interrupt entry (address of int0handler) // in the vector table. // enable this type of interrupt // set the sensivity to rising edge
while(1) { while (ok_flag==1) // This flag gets set only when INT0 is encountered { ok_flag=0; printf("\r\n BANK0 BANK1 BANK2 BANK3"); for (address=0x1fe; address<=0x1ff; address++) { // Read RIOT dual port ram on address 100h-1ffh at different banks select_bank0(); getal0=read_databus (address); select_bank1(); getal1=read_databus (address); select_bank2(); getal2=read_databus (address); select_bank3(); getal3=read_databus (address); // By reading this bank on location // 1feh, the interrupt condition is // removed in the dp ram printf("\r\nADDRESS:%02Xh %02Xh %02Xh %02Xh %02Xh", address,getal0,getal1,getal2,getal3); } } } } In de hardware API vinden we functies terug om welbepaalde interrupts aan te schakelen, en hun mode in te stellen (niveau- of flankgevoelig). De functie enable_int0 () zal hier de INT0 pin activeren, en de functie pos_edgeint0 () zal een stijgende flank gevoeligheid instellen. Deze functies worden uitgevoerd in het initialisatiedeel van de main() functie.
Versie 1.0
68
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 Vooraleer we ook interrupts daadwerkelijk kunnen verwerken moeten we in de vectortabel van de processor op de plaats die hoort bij de INT0 interrupt ook het adres plaatsen van de interruptserviceroutine (ISR) die hierbij hoort. Dit wordt gedaan met de setvect (INTR0,int0handler) functie in de main () functie. Met #define INTR0 0x0C // External interrupt0 vector number definiëren we het interrupttype aan dat we willen gebruiken. Zie tabel 5.2 voor de verschillende types. De functie int0handler () wordt dan als interruptserviceroutine (ISR) aangegeven door void interrupt int0handler (). In deze interrupthandler moet men er dan voor zorgen dat het End Of Interrupt (EOI) register van de interruptcontroller die in de 80186 CPU van de IPC@CHIP aanwezig is wordt geschreven met een code die aangeeft dat de interrupthandler is beëindigd. Dit kan door de functie outport (0xff22,INTR0). Hierdoor wordt de betreffende bit in het In Service (IS) register voor deze interruptbron uitgeschakeld, waardoor er een volgende interrupt van dit type kan worden gedetecteerd. Doet men dit niet dan zal alleen de eerste interrupt van dit type worden afgehandeld, en wordt daarna dit interrupttype geblokeerd omdat de CPU denkt dat de vorige ISR van dit type nog niet is afgewerkt. Het adres 0xff22 dat gebruikt wordt is dit van het EOI register. Zoals uit de 'Memory en I/O map' van de IPC@CHIP blijkt zitten de interne CPU registers gemapt vanaf het adres 0xff00. De users manual van de 80186 CPU geeft aan dat het EOI register met een offset van 0x22 bytes t.o.v. dit adres is verschoven, zodoende komt men aan 0xff22. De nodige informatie hierrond kan men terugvinden in de 80186 users manual bij de Interrupt Control Unit. Tabel 5.2: 80186 CPU interrupt types.
Versie 1.0
69
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
CGI verwerking op de IPC@CHIP. De HTTP netwerkserver van de SC12 IPC@CHIP heeft de mogelijkheid om Common Gateway Interface (CGI) programma's te verwerken. Het gaat hier om een interface tussen een Webserver en een programma dat wordt gestart. Dit programma noemt men een CGI proramma of CGI script. Figuur 5.3 geeft een situering van deze CGI . CGI programma's kunnen interactieve, dynamische websites genereren, en kunnen ook als verbinding (Gateway) tussen de Webserver en een extern toepassingsprogramma fungeren. De CGI functies bij de IPC@CHIP verschillen een weinig met de normale CGI functies op een PC of andere computer. De CGI functies zijn normaal uitvoerbare programma's die worden opgestart. Bij de IPC@CHIP zijn het CGI functies in een EXE-programma. Meestal verzendt een HTTP server statische (vaste onveranderlijke) HTML pagina's. Deze zijn bij de server normaal geordend volgens een WEB-ROOT-hierarchie. De HTML pagina's kunnen zo van buitenaf door een tweede computer, de client, waarop een browser draait, opgevraagd worden. Vraagt de client van de server een HTML pagina op zonder daarbij te vermelden welke pagina, dan zal de server zijn START pagina versturen. De naam van deze startpagina in de WEB-ROOThierarchie is typisch INDEX.HTM of MAIN.HTM. Van hieruit kunnen via LINKS dan andere pagina's ( met eigen naam.htm ) opgevraagd worden. Wanneer de server een CGI interface bezit dan kan hij dynamisch, zelf samengestelde, HTML pagina's verzenden. Dit opent interessante perspectieven wanneer de server over actuele gegevens kan beschikken die bij het normale opvragen van een HTML pagina nog niet voorhanden zijn. Een eenvoudig voorbeeld hiervan is de bezoekerteller (Counter) die vele Homepages verzenden. Bij een CGI interface wordt deze pagina door een programma aangemaakt wanneer de client erom vraagt, en dit programma voegt de actuele waarde van de teller ( of vb. actuele meetgegevens) in, in de HTML pagina. Ook in de omgekeerde richting functioneert CGI. Het is mogelijk dat de Web-server met CGI programma's een toepassing bestuurt aan de hand van parameters (datastrings) die van een browser afkomstig zijn. CLIENT (PC)
IPC@CHIP
RTOS CGI-API
Webbrowser
Intranet Internet
Webserver + CGI handling
CGI Application function program
I/0
Application
Figuur 5.3: Situering van CGI.
Versie 1.0
70
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Vanuit de fabrikant Beck wordt voor de programmering van CGI functies een CGI-API ter beschikking gesteld. Aan de hand van deze CGI-API kunnen CGI functies in DOS toepassingsprogramma's aangegeven worden, die uitgevoerd worden wanneer de Webserver een aanvraag voor een HTML pagina met de geldige parameters binnenkrijgt. Om een CGI-API functie uit te voeren moet bij de software interrupt de waarde 0xAB meegegeven worden. De waarde in AH geeft aan welke functie de software interrupt moet uitvoeren. De beschikbare API functie worden aangegeven in tabel 5.3. Tabel 5.3: Beschikbare CGI-API functies (@CHIP-RTOS V1.04). Interrupt number/ Function (AH value) CGI-API function 0xAB Function 0x01 CGI INSTALL, install a cgi function. 0xAB Function 0x02 CGI REMOVE, remove a cgi function. 0xAB Function 0x03 CGI SETMAIN, set a new mainpage. 0xAB Function 0x04 CGI SETROOTDIR, set Webserver's root directory. 0xAB Function 0x05 CGI GETROOTDIR, get Webserver's root directory. 0xAB Function 0x06 CGI GETMAIN, get mainpage name. 0xAB Function 0x07 CGI GETFORMITEM, split a formular into name and value. 0xAB Function 0x08 CGI FINDNEXTITEM, return the address off the next formular tag. 0xAB Function 0x09 CGI INSTALL PAS, install Turbo Pascal CGI procedure. Als voorbeeld gebruiken we de CGI INSTALL functie. De op de IPC@CHIP geïmplementeerde Webserver heeft toegang tot een interne CGI tabel. Elke tabelentry omvat de URL van de dynamisch aan te maken HTML pagina, de verwachtte HTTP methode ( GET, HEAD of POST ) en een pointer naar de uit te voeren cgi functie van het usersprogramma. De volgende structuur CGI_Entry uit de Beck headerfile cgi.h geeft de betreffende datatypes aan: Typedef struct tag_cgi_table { char * PathPtr; // naam van de pagina, URL int method; // HTTP methode: get,head of post void *CgiFuncPtr; // pointer naar de CGI functie die de dynamische pagina // aanmaakt in het toepassingsprogramma }CGI_Entry;
Versie 1.0
71
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
De volgende stappen moeten in een programma worden ondernomen om CGI verwerking op te starten (zie Figuur 5.4): • Declaratie van een variabele van het type CGI_entry. Een variabele vb. 'example' met deze structuur kunnen we op volgende manier in een programma declareren. #include "cgi.h" CGI_Entry example; • Installatie van de CGI functie. De members van deze variabele kunnen dan als volgt worden gedefinieerd. example.PathPtr = HtmlPageName; // HtmlPageName bevat hier vb. "riot" example.method = 1; // CGI Http GET (zie cgi.h) example.CgiFuncPtr = CGI_example_func; // uit te voeren functie bij browserrequest met //"riot" als paginanaam Een CGI INSTALL functie oproepen kan op volgende manier. inregs.h.ah =0x01; inregs.x.dx =FP_SEG(&example); inregs.x.si =FP_OFF(&example); int86 (0xAB,&inregs,&outregs); Het systeem krijgt zo een copie van de variabele example in zijn CGI tabel. Hierin zit de HtmlPageName (vb."riot"), dit is de paginanaam die de CGI verwerking opstart als ze door een browser wordt aangevraagd met de "GET" methode (zie Http protocol GET). Verder zit hierin ook een pointer naar de CGI functie die moet worden opgestart (CGI_example_func). •
CGI functie aangeven in het userprogramma.
De CGI functie kan op volgende manier worden aangegeven: void huge_pascal CGI_example_func (rpCgiPtr CgiRequest) De functienaam CGI_example_func kan men net zoals de variabelenaam CgiRequest zelf kiezen. Indien de Webserver een aanvraag binnenkrijgt met de geschikte parameters (zie hierboven) zal deze de functie CGI_example_func opstarten aan de hand van de gegevens in zijn entry 'example' in de CGI tabel. Hierbij wordt een pointer doorgegeven aan de functie CGI_example_func. Het is een pointer naar een structure CgiRequest, van het type rpCgiPtr, (voor info over deze struct zie cgi.h). Hierin zit alle info van de browser request en responce. De functie CGI_example_func zal dan dynamisch een tekststring in de variabele DynamicHtmlPage aanmaken. Dit gebeurt vb. op volgende wijze: strcpy (DynamicHtmlPage,Pagehead); //vaste header invullen sprintf (tmpbuffer,"blablabla %ld",variable);//tijdelijke buffer opvullen met dynamische info strcat (DynamicHtmlPage,tmpbuffer); //buffer in pagina plakken strcat (DynamicHtmlPage,Page_end); //vast einde invullen
Versie 1.0
72
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Wanneer de dynamische Webpagina op deze manier is aangemaakt in een char buffer (in dit geval DynamicHtmlPage) moet deze aan de webserver worden doorgegeven. Dit kan worden gedaan door een aantal members van de structure CgiRequest met de gewenste informatie te initialiseren. Dit kan op volgende manier: CgiRequest -> fHttpResponse= CgiHttpok; // Http 200 ok, request has succeeded CgiRequest ->fResponseBufferPtr=DynamicHtmlPage; // pointer naar char buffer doorgeven CgiRequest ->fResponseBufferLength=strlen(DynamicHtmlPage); //lengte van pagina De Webserver zal nu deze pagina doorgeven aan de browser die erom vroeg.
WEB Http://192.168.200.8/riot
WEBSERVER met CGI
Geheugen
Userprogramma
Cgirequest
Void huge_pascal CGI_example_func (rpCgiPtr Cgirequest)
{ aanmaken DynamicHtmlPage();
fResponseBufferPtr
Cgirequest->fHttpresponse=CGIHttpOk Cgirequest->fResponseBufferPtr=DynamicHtmlPage Cgirequest->fResponseBufferlength=strlen(DynamicHtmlPage)
DynamicHtmlPage
}
Tabel met CGI TAGS
example.PathPtr= “riot” example.method= GET example.CgiFuncPtr=CGI_example_func
‘example’
Figuur 5.4: Opstarten van een CGI functie.
Versie 1.0
73
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
Het volgende voorbeeld zal in dit verband veel duidelijk maken. /**************************************************************************** * Example of using the CGI on the RIOT board v1.0 * * Created by [dp] 23.04.2002 * Based on an example of BECK IPC GmbH * * BECK IPC GmbH * Garbenheimerstr. 38 * D-35578 Wetzlar * * Phone : (49)-6441-905-240 * Fax : (49)-6441-905-245 * * --------------------------------------------------------------------------Function : This program demonstrates the usage of the implemented CGI-Interface of IPC@CHIP in a dos program. The programmer could use this program as an example for building own cgi functions. Compiler : Borland C 3.0 Memorymodel : Large Note: Before testing this example, the directory "web" and the file "main.htm" should exist at the IPC@CHIP. This could be done with FTP or via the serial port. Description: At the start of the program, we set the current root directory of the webserver to the directory "web" and set a new mainpage name "main.htm". This is only to demonstrate this features, it's not important for the working of the program. After doing that, the webserver searches for all requested files at this directory. A browserrequest with the '/ ' e.g. http://192.168.205.4/ is (from now on) answered from the server with the new mainpagefile "main.htm" at the root directory "web". Furthermore we install a cgi function, which produces a dynamic htmlpage in the memory. This page has the name "DynamicHtmlPage". The name of the installed cgi function is "CGI_example_func". The expected http method is "GET". If a browserrequest e.g. http://192.168.205.4/riot comes in, the web server calls this function. At the mainloop of our program, we read the temperature that is measured by the IOsys chip. An analog temp. Sensor LM35 (10mV/Kelvin) is connected to the analog input 0 of IOsys. This analog value is converted to a 10 bit digital value by IOsys, and can be read by the IPC@CHIP. The called function builds a string, which contains a small html page with the actual value of our temperature. During runtime of the program, the page "riot" can be loaded from a browser. After two minutes the program ends. A browserrequest after the end of the program returns "Object not found, ......" Important: At the end of the program we must remove the installed cgi function from webservers CGI table. *****************************************************************************/
Versie 1.0
74
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
/****************************************************************************/ /* includes /****************************************************************************/ #include
#include <STDIO.H> #include <STRING.H> /****************************************************************************/ /* API includes: This can be as simple as: #include "CGI.H" /* but for illustration purpose the file is included in integral form here /****************************************************************************/ #ifndef _CGI_H__ #define _CGI_H__ /*****************************************************************************/ //CGI defines /*****************************************************************************/ //Cgi HTTP requests #define CgiHttpGet 1 #define CgiHttpHead 2 #define CgiHttpPost 3
/* Cgi request is HTTP GET */ /* Cgi request is HTTP HEAD */ /* Cgi request is HTTP POST */
//Cgi HTTP responses #define CgiHttpOk 0 /* Cgi returns HTTP 200 Ok */ #define CgiHttpOkStatic 1 /* Cgi returns HTTP 200 Ok - Static Object */ #define CgiHttpRedirect 2 /* Cgi returns HTTP 302 Moved Temp */ #define CgiHttpNotModified 3 /* Cgi returns HTTP 304 Not Modified */ #define CgiHttpUnauthorized 4 /* Cgi returns HTTP 401 Unauthorized */ #define CgiHttpNotFound 5 /* Cgi returns HTTP 404 Not Found */ #define CgiHttpOKNoDoc 6 /* Cgi returns HTTP 204 No document follows*/ //CGI constants for content types ,fDatatype #define #define #define #define #define #define #define #define #define #define #define #define #define
CGIDataTypeHtml 0 /* CGI returns text/html */ CGIDataTypeImageGif 1 /* image/gif */ CGIDataTypeApplet 2 /* application/octet-stream */ CGIDataTypeText 3 /* text/plain */ CGIDataTypeImageJpeg 4 /* image/jpeg */ CGIDataTypeImagePict 5 /* image/pict */ CGIDataTypeImageTiff 6 /* image/tiff */ CGIDataTypeImagePng 7 /* image/png */ CGIDataTypeForm 8 /* application/x-www-form-urlencoded */ CGIDataTypeIpp 9 /* application/ipp */ CGIDataTypeCss 10 /* text/css */ CGIDataTypeXml 11 /* text/xml */ CGIDataTypeWav 12 /* audio/wav */
Versie 1.0
75
[dp] D. Pauwels
RIOT #define #define #define #define #define #define #define #define
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 CGIDataTypePdf 13 /* application/pdf */ CGIDataTypeJavaArchive 14 /* application/java-archive */ CGIDataTypeOctet 15 /* application/octet-stream */ CGIDataTypeVndWapWml 16 /* text/vnd.wap.wml */ CGIDataTypeVndWapWbmp 17 /* image/vnd.wap.wbmp */ CGIDataTypeVndWapWmlc 18 /* application/vnd.wap.wmlc */ CGIDataTypeVndWapWmlscript 19 /* text/vnd.wap.wmlscript */ CGIDataTypeVndWapWmlscriptc 20 /* text/vnd.wap.wmlscriptc */
/*****************************************************************************/ //Cgi API calls /*****************************************************************************/ #define CGI_INSTALL 1 /* Install a cgi function */ #define CGI_REMOVE 2 /* Delete a cgi function */ #define CGI_SETMAIN 3 /* Set new main page name */ #define CGI_SETROOTDIR 4 /* Set webservers root directory */ #define CGI_GETROOTDIR 5 /* Get webservers root directory */ #define CGI_GETMAIN 6 /* Get name of main page*/ #define CGI_GETFORMITEM 7 /* Split argumentbuf into formular name and value*/ #define CGI_FINDNEXTITEM 8 /* Find next formitem, if one */ #define CGI_INSTALL_PAS 9 /* Install a Turbo Pascal cgi procedure */ /*****************************************************************************/ //CGI API general Errorcodes /*****************************************************************************/ #define CGI_NOT_SUPPORTED -2 #define CGI_ERROR -1 #define CGI_ENOERROR 0 /*****************************************************************************/ //CGI API special Errorcodes, returned at the ax-register /*****************************************************************************/ #define CGI_INVALID_METHOD -1 #define CGI_INVALID_NAME -2 #define CGI_INVALID_DIR -3 #define CGI_NO_FREE_ENTRY -4 #define CGI_NOT_FOUND -5 #define PFE_INT 0xA2 #define HAL_INT 0xA1
Versie 1.0
// Pin Function Enable sw INT // Hardware Abstraction Layer sw INT
76
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
/*****************************************************************************/ //types /*****************************************************************************/ typedef struct tag_cgi_table{ char *PathPtr; //name of the page int method; //httpmethod: get or post void *CgiFuncPtr; //ptr to callback function of this page }CGI_Entry; /* the called cgi function gets as a parmeter a pointer of the following structure, which contains the needed http-request data and response data */ typedef struct { //Request fields, read only!!!! unsigned char fConnectionId; // internal use only int fHttpRequest; // internal use only char * fPathPtr; // URL char * fHostPtr; // Host: char * fRefererPtr; // (at time not supported) char * fAgentPtr; // (at time not supported) char * fLanguagePtr; // (at time not supported) unsigned long fBrowserDate; // Date: (internal) char * fArgumentBufferPtr; // Pointer at argument buffer long fArgumentBufferLength; // length of argument buffer, -1 buffer empty char * fUserNamePtr; // Username from Authorization char * fPasswordPtr; // Password from Authorization long *
fRemoteIPPtr; // Pointer to RemoteIP in wrong byte order // , do not modify
//Response fields, int fResponseState; // internal, do not modify int fHttpResponse; // response msg mostly CgiHttpOK int fDataType; // content type mostly text/html char * fResponseBufferPtr; // pointer to created dynamic html page long fResponseBufferLength; // length of the created page unsigned long fObjectDate; // internal, do not modify unsigned int fHostIndex; // internal, do not modify } rpCgi, *rpCgiPtr; /*****************************************************************************/
Versie 1.0
77
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
/*************************************************************************/ //defines /*************************************************************************/ //needed interrupt vectors #define TCP_INT 0xAC #define CGIVECT 0xAB #define MAIN_LOOPS
120L /* our program run MAIN_LOOPS seconds*/
/****************************************************************************/ //needed registerstructs for CGI interrupt calls /****************************************************************************/ static union REGS inregs; static union REGS outregs; static struct SREGS segregs; // Make sure that the lower priority tasks like the webserver get some time to // execute their code, .... otherwise no concurrent webserver! void api_sleep (int ms) { inregs.x.ax=0x0900; inregs.x.bx=ms; int86x(TCP_INT,&inregs,&outregs,&segregs); } static float volt1,volt=0,voltcgi=0; /****************************************************************************/ // we set the name "main.htm" as main page name // this means: if a browserrequest e.g. http://192.168.205.4/ // occurs, the webserver returns the file "main.htm" /****************************************************************************/ char * MainpageName = "main.htm"; /****************************************************************************/ // we set the default directory as root directory /****************************************************************************/ char * WebRootDirectory = "web"; /*************************************************************************** the name of the (dynamic) page for the browserrequest e.g. http://192.168.200.5/riot ****************************************************************************/ char * HtmlPageName = "riot"; /*************************************************************************** //our cgi entry webserver ***************************************************************************/ CGI_Entry example; // example is a struct of te CGI_Entry type
Versie 1.0
78
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
/***************************************************************************/ // Init RIOT v1.0. /***************************************************************************/ void enable_databus (void) { // Enable 8 bits databus inregs.x.ax = 0x8001; // enable ALE, databus inregs.x.dx = 0x00FF; // all 8 bits are enabled int86(PFE_INT, &inregs, &outregs); // Enable programmable chip select1 (poi4) inregs.h.ah = 0x83; inregs.x.dx = 0x02; // PCS1# (100h-1FFh) int86(PFE_INT, &inregs, &outregs); } void select_bank0 (void) { // Reset pio2, pio3 lines inregs.h.ah = 0x82; inregs.h.al = 0x05; // pio2,pio3 both 0 inregs.x.dx = 0x000C; // enable pio2,pio3 int86(PFE_INT, &inregs, &outregs); } void select_bank1 (void) { // Reset pio3 line inregs.h.ah = 0x82; inregs.h.al = 0x05; // pio3 state 0 inregs.x.dx = 0x0008; // enable pio3 int86(PFE_INT, &inregs, &outregs); // Set pio2 line inregs.h.ah = 0x82; inregs.h.al = 0x04; // pio2 state 1 inregs.x.dx = 0x0004; // enable pio2 int86(PFE_INT, &inregs, &outregs); } void select_bank2 (void) { // Set pio3 line inregs.h.ah = 0x82; inregs.h.al = 0x04; // pio3 state 1 inregs.x.dx = 0x0008; // enable pio3 int86(PFE_INT, &inregs, &outregs);
Versie 1.0
79
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
// Reset pio2 line inregs.h.ah = 0x82; inregs.h.al = 0x05; // pio2 state 0 inregs.x.dx = 0x0004; // enable pio2 int86(PFE_INT, &inregs, &outregs); } void select_bank3 (void) { // Set pio2, pio3 lines inregs.h.ah = 0x82; inregs.h.al = 0x04; // pio2,pio3 both 1 inregs.x.dx = 0x000C; // enable pio2,pio3 int86(PFE_INT, &inregs, &outregs); } /***************************************************************************/ // Read databus on specified address ( inportb (address);) /***************************************************************************/ unsigned char read_databus (unsigned int ram_address) { unsigned char value; // read data bus inregs.h.ah = 0x80; inregs.x.di = ram_address; // address = user parameter inregs.x.bx = 0xFFFF; // wAND=0xFFFF inregs.x.cx = 0x0000; // wXOR=0x0000 int86x(HAL_INT, &inregs, &outregs, &segregs); value = outregs.h.al; return value; } /***************************************************************************/ // Write databus to specified address ( outportb (portaddress,value);) /***************************************************************************/ void write_databus (unsigned char value,unsigned int ram_address) { // write data bus inregs.h.ah = 0x81; inregs.x.di = ram_address; // address = user parameter inregs.h.dh = 0; inregs.h.dl = value; inregs.x.bx = 0xFF; // wAND=8 bits databus inregs.x.cx = 0x0000; // wXOR=0x0000 int86x(HAL_INT, &inregs, &outregs, &segregs);
Versie 1.0
80
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
} /*************************************************************************** Predefine head and tail of our page ***************************************************************************/ char * PageHead = "<TITLE>CGI on the riot MGM/[dp] board" "<META http-equiv=\"REFRESH\" content=\"1\">"; char * PageMiddle =// "" this line is included dynamicaly! // with the color changing as a function of temp, see the CGI_example_func "
" "" " Dynamic Web page on the MGM/[dp] RIOT board
" " Temperature in our office
" "
" ""; char * PageEnd = "" "
" "<SMALL><EM> © MGM[dp], 2002 " "" ""; /*************************************************************************** The cgi function stores the dynamic HTML page in this buffer ***************************************************************************/ char DynamicHtmlPage[512];
Versie 1.0
81
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 /**************************************************************************** CGI function, the webserver executes this function, if a browser request e.g. http://192.168.200.8/riot comes in. Whit this function we build a new html page in memory, including the current temperature value of the main loop. At the end of this function we tell the webserver the address of our buffer and its length. The webserver sends this buffer back to the browser ****************************************************************************/ void huge pascal CGI_example_func(rpCgiPtr CgiRequest) { char tmpbuffer[80],tmpbuffer1[20]; char *red="a0",*green="a0",*blue="a0"; /**********************************/ //building the page /**********************************/ //insert the head of the page strcpy(DynamicHtmlPage,PageHead); // change the color as a function of the measured temperature if (voltcgi<14.0) {red="00";green="2E";blue="E2";} if ((voltcgi<15.0) && (voltcgi>=14.0)){red="00";green="2E";blue="E2";} if ((voltcgi<16.0) && (voltcgi>=15.0)){red="06";green="00";blue="E2";} if ((voltcgi<17.0) && (voltcgi>=16.0)){red="33";green="00";blue="E2";} if ((voltcgi<18.0) && (voltcgi>=17.0)){red="6B";green="00";blue="E2";} if ((voltcgi<19.0) && (voltcgi>=18.0)){red="9B";green="01";blue="D7";} if ((voltcgi<20.0) && (voltcgi>=19.0)){red="AB";green="02";blue="CA";} if ((voltcgi<21.0) && (voltcgi>=20.0)){red="BD";green="03";blue="BD";} if ((voltcgi<22.0) && (voltcgi>=21.0)){red="BD";green="03";blue="8F";} if ((voltcgi<23.0) && (voltcgi>=22.0)){red="CA";green="02";blue="7F";} if ((voltcgi<24.0) && (voltcgi>=23.0)){red="CA";green="02";blue="64";} if ((voltcgi<25.0) && (voltcgi>=24.0)){red="CA";green="02";blue="58";} if ((voltcgi<26.0) && (voltcgi>=25.0)){red="DC";green="02";blue="3C";} if ((voltcgi<27.0) && (voltcgi>=26.0)){red="FA";green="00";blue="2D";} if (voltcgi>=27.0) {red="FF";green="00";blue="00";} sprintf (tmpbuffer1,"
",red,green,blue); strcat(DynamicHtmlPage,tmpbuffer1); // Add color info dynamicaly strcat(DynamicHtmlPage,PageMiddle); //get main loop temperature sprintf(tmpbuffer,"
is currently: %2.1f gr.Celcius
",voltcgi); strcat(DynamicHtmlPage,tmpbuffer); //append the predefined tail strcat(DynamicHtmlPage,PageEnd);
Versie 1.0
82
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 /**********************************/ //give it to the webserver /**********************************/ CgiRequest->fHttpResponse = CgiHttpOk; CgiRequest->fResponseBufferPtr = DynamicHtmlPage; CgiRequest->fResponseBufferLength = strlen(DynamicHtmlPage); } /****************************************************************************/ int main(void) { printf("\r\nStarting CGI example program\r\n\r\n"); /********************************/ //Set mainpage name /********************************/ inregs.h.ah = CGI_SETMAIN; inregs.x.dx = FP_SEG(MainpageName); // "main.htm" inregs.x.si = FP_OFF(MainpageName); int86(CGIVECT,&inregs,&outregs); if(outregs.x.dx == (unsigned int)CGI_ERROR) { printf("\r\nSetting mainpage %s failed\r\n",MainpageName); } /********************************/ //Set webservers rootdirectory /********************************/ inregs.h.ah = CGI_SETROOTDIR; inregs.x.dx = FP_SEG(WebRootDirectory); // "Web" inregs.x.si = FP_OFF(WebRootDirectory); int86(CGIVECT,&inregs,&outregs); if(outregs.x.dx == (unsigned int)CGI_ERROR) { printf("\r\nSetting root directory %s failed\r\n",WebRootDirectory); } /********************************/ //Get mainpage name /********************************/ inregs.h.ah = CGI_GETMAIN; int86x(CGIVECT,&inregs,&outregs,&segregs); printf("\r\nMainpage : %s",(char *)MK_FP(segregs.es,outregs.x.di));
Versie 1.0
83
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
/********************************/ //Get root directory /********************************/ inregs.h.ah = CGI_GETROOTDIR; int86x(CGIVECT,&inregs,&outregs,&segregs); printf("\r\nRoot directory: %s\r\n",(char *)MK_FP(segregs.es,outregs.x.di));
/********************************/ //install example cgi function /********************************/ //init CGI_entry example; example.PathPtr = HtmlPageName; //name of the page "riot" example.method = CgiHttpGet; //method example.CgiFuncPtr = CGI_example_func; //function
cgiptr = &example; // We need this helpptr because the Microsoft compiler // will not accept the following: // inregs.x.dx = FP_SEG(&example); // inregs.x.si = FP_OFF(&example); inregs.h.ah = CGI_INSTALL; inregs.x.dx = FP_SEG(cgiptr); inregs.x.si = FP_OFF(cgiptr); int86(CGIVECT,&inregs,&outregs); if(outregs.x.dx == (unsigned int)CGI_ERROR) { printf("\r\nInstalling CGI function %s failed --> exit program\r\n",example.PathPtr); return 0; }
Versie 1.0
84
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal .
Gebruikers handleiding v1.0 /*******************************************************************/ //Main loop // /*******************************************************************/ unsigned char index; unsigned int teller=0; char temp_buf[10]="0000000000"; char buffer[50]="Test for the RIOT Temperatuur \null"; // LCD text buffer enable_databus (); // Enable 8 bit databus select_bank3(); write_databus (0x05,0x100); // Cycle time IOsys controller 5msec. write_databus (0x01,0x102); // Port B is digital i/o write_databus (0x00,0x103); // All bits are output write_databus (0x02,0x106); // Port D is digital i/o write_databus (0xFF,0x107); // All bits are input write_databus (0xFF,0x109); // Pull-ups on all inputs write_databus (0x02,0x10C); // Port E is the LCD port write_databus (0x03,0x113); // Type of LCD = 2x 20 chars write_databus (0x02,0x114); // Write buffer to LCD with clear. write_databus (0x01,0x111); // Init port F bit0 as analog input to measure temperature // as an analog voltage.of a LM35 temp sensor write_databus (0x01,0x110); // port F in mode 1 for (index=0; index<=40 ;index++) { write_databus (buffer[index],index+0x115); // init lcd buffer } write_databus (0xFF,0x1ff); // Generate interrupt to the IOsys chip // trough the dual port ram to start cycling unsigned long int Loopcounter=0; while (Loopcounter<32000) { unsigned char byte; api_sleep(100); Loopcounter+=1; byte =read_databus (0x10b); write_databus (byte,0x105); teller++; volt1= inport (0x0166);
// Give the lower prio tasks a break...
// read the dual port ram // write back // Average the analog value // Read analog word on location 0x166 // and 0x167 =portF bit0 volt1= ((volt1*500)/1024)-273; // Calculate the temperature measured // by the lm35 10mv/gr Kelvin // with a ref value of 5V. volt+=volt1; // Accumulate analog value to moving average it out
Versie 1.0
85
[dp] D. Pauwels
RIOT
Remote Internet Operated Terminal . Gebruikers handleiding v1.0
if (teller==10) // Calc. average after 10 cycles { volt=volt/10; voltcgi=volt; //temperature value for dynamic Web page and LCD teller=0; sprintf (temp_buf," %2.1fgrC",volt); for (index=0; index<=9 ;index++) { write_databus (temp_buf[index],index+0x115+32); // init lcd buffer } write_databus (0x01,0x114); // Write buffer to LCD without clear. } }// end loop while Loopcounter<32000 /***************************************/ //Important: remove example cgi function /***************************************/ inregs.h.ah = CGI_REMOVE; inregs.x.dx = FP_SEG(example.PathPtr); inregs.x.si = FP_OFF(example.PathPtr); int86(CGIVECT,&inregs,&outregs); if(outregs.x.dx == (unsigned int)CGI_ERROR) { printf("\r\nRemoving %s failed\r\n",example.PathPtr); return 0; } printf("\r\nExit program\r\n"); return 0; } /*************************************************************************/ //end example /***************************************************************************************/
Versie 1.0
86
[dp] D. Pauwels