Zadatak 1. Upravljački progam za AD karticu

Naš zadatak je bio ugraditi AD karticu u računalo, instalirati driver, testirati rad kartice te napisati program fserver.c koji odgovara na zahtijeve fclient.c programa.

Kod ugradnje AD kartice nije bilo probleme možda i zato što je već bila ugrađena. Baznu adresu tj. početna adresa na kojoj se kartica vidi namjestili smo na 0x330 jer se na toj adresi na dotičnom računalu (linlab8) ne sukobljava sa drugim uređajima.

Kod kompajliranja drivera došlo je do ozbiljnih problema. Mučili smo se dva dana s time i morali smo priznati neuspjeh. Problem je bio sa verzijom kernela i nekih deklaracija headera (nešto.h). Tu nam je pomogao vanjski suradnik Vedran Višnjić, zaposlenik radnog kluba Ericsson Tesla koji je odvojio od svoga sna sat vremena kako bi nama pomogao. Svaka čast. U to rano jutro uspijelo mu (nam) je instalirati driver te su proradili i testni programi.

To su jednostavni programi kojima se samo dokazuje da kartica i driver rade kako treba. Prvi je volt.c kojim preko potenciometra reguliramo napon, taj napon se očitava i prikazuje na led diodama. Nešto kao jednostavan VU metar. Drugi program je bio dtest.c koji po nekom redosljedu pali i gasi diode na vanjskoj pločici te na kraju binarno broji. Treći i zadnji testni program je bio dio.c koji je čitao stanje digitalnih ulaza te ih ispisivao na izlaz tj. njihova stanja je prikazivao na led diodama.

Driver svaki A/D kanal vidi kao device datoteku: /dev/das08jr_adc00 .. analogni ulaz (kanal 0) ,...., /dev/das08jr_adc07 .. kanal 7
Digitalni ulaz i izlaz vidi kao device datoteku /dev/das08jr_dio.
Driver i FIFO server komuniciraju pisanjem i čitanjem u device datoteke. FIFO server i FIFO klijent razmjenjuju podatke pisanjem i citanjem u FIFO cjevovod (datoteku).

Naš glavni posao je bio doraditi program fserver.c koji je u nerazdvojivoj vezi sa programom fclient.c. Uloga programa fserver je da čeka signal koji će mu zadati fclient te da nakon toga pročita odgovarajući niz podataka i pošalje ih na fifo strukturu tj. imenovani cjevovod. Budući da mi je najjednostavnije opisati rad programa pomoću njegovog koda sada slijedi program fserver.c.


Fserver.c

/* Ovaj program osluskuje signale i na temelju njih */
/* cita odredjene podatke s A/D kartice i salje ih */
/* na FIFO "cjevovod" FIFO_ADC. */
/* Prilikom pokretanja, program na FIFO pipe */
/* salje svoj pid kako bi drugi program npr. deamon */
/* koji posluzuje mail zahtjeve, moga ovom programu */
/* slati odgovarajuce signale. */
/* Konkretno program osluskuje signale USR1, USR2, */

/* INT i HUP te salje na FIFO_ADC uzorke */
/* ovisno o primljenom signalu */


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <linux/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <asm/user.h>
#include "a2dc.h"
#include "bsd_signal.h"


#define FIFO_FILE "FIFO_ADC"
#define FIFO_PID "FIFO_PID"


static void sig_usr(int); /* deklaracija funkcije za obradu signala */


static void sig_usr(int signo){ /* ova funkcija izvodi obradu signala */
int fo1,fo4,fod,fdes;
WORD buff[1000];
int n;
static unsigned char i;
puts("\nFIFOSERVER: Usao u signal handling funkciju.\n");fflush(stdout);

if ((fdes=open(FIFO_FILE,O_WRONLY|O_NONBLOCK)) < 0){ /*otvaranje cjevovoda */
puts("FIFOSERVER: Pogreska u otvaranju FIFO_ADC.");
exit(-1);
}
switch(signo){

case SIGUSR1: /* ovaj signal čita 100 vrijednosti sa analognog ulaza 4 */

/* koji je spojen na signal generator */

if ((fo4=open("/dev/das08jr_adc04",O_RDONLY)) < 0){
puts("FIFOSERVER: Ne mogu otvoriti adc04 kanal????");
puts("FIFOSERVER: Da li je instaliran driver?\n");
exit(-1);
}
n=read(fo4,&buff,100);
printf("\nFIFOSERVER: Procitao n= %d podataka s adc04.\n",n);
fflush(stdout);

for(n=0;n<100;n++){ /* ispis pročitanih vrijednosti */
printf("\nFIFOSERVER: signalgenerator -> buffer_%u = %u",n,buff[n]);
fflush(stdout);
}
write(fdes,buff,100*sizeof(WORD));
close(fo4); /* zatvara kanal 4 i cjevovod */
close(fdes);
break;

case SIGUSR2: /* ovaj signal čita 1000 vrijednosti sa analognog ulaza 4 */

/* koji je spojen na signal generator */

if ((fo4=open("/dev/das08jr_adc04",O_RDONLY)) < 0){
puts("FIFOSERVER: Ne mogu otvoriti adc04 kanal????");
puts("FIFOSERVER: Da li je instaliran driver?\n");
exit(-1);
}
n=read(fo4,&buff,1000);
printf("\nFIFOSERVER: Procitao n= %d podataka s adc04.\n",n);
fflush(stdout);

for(n=0;n<1000;n++){ /* ispis pročitanih vrijednosti */
printf("\nFIFOSERVER: signalgenerator -> buffer_%u = %u",n,buff[n]);
fflush(stdout);
}
wr
ite(fdes,buff,1000*sizeof(WORD));
close(fo4); /* zatvara kanal 4 i cjevovod */
close(fdes);
break;

case SIGINT: /* ovaj signal čita 10 vrijednosti sa analognog ulaza 1 */

/* koji je spojen na potenciometar */

if ((fo1=open("/dev/das08jr_adc01",O_RDONLY)) < 0){
puts("FIFOSERVER: Ne mogu otvoriti adc01 kanal????");
puts("FIFOSERVER: Da li je instaliran driver?\n");
exit(-1);
}
n=read(fo,&buff,10);
printf("\nFIFOSERVER: Procitao n= %d podataka s adc01.\n",n);
fflush(stdout);

for(n=0;n<10;n++){ /* ispis pročitanih vrijednosti */
printf("\nFIFOSERVER: potenciometar -> buffer_%u = %u",n,buff[n]);
fflush(stdout);
}
write(fdes,buff,10*sizeof(WORD));
close(fo1); /* zatvara kanal 1 i cjevovod */
close(fdes);
break;

case SIGHUP: /* ovaj signal čita digitalne ulaze i prikazuje ih na led diode */

if ((fod=open("/dev/das08jr_dio",O_RDWR)) < 0){
puts("FIFOSERVER: Ne mogu otvoriti dio????");
puts("FIFOSERVER: Da li je instaliran driver?\n");
exit(-1);
}
read(fod,&i,1);
write(fod,&i,1);
write(fdes,&i,1);
close(fod); /* zatvara dio i cjevovod */
close(fdes);

break;
default:
/* ovaj dio koda se u biti nikada nece izvrsiti, */
/* osim ako je u main funkciji definiran signal */
/* handler funkcija za signal, a on nije obuhvacen */
/* ovim case-om iznad */
puts("FIFOSERVER: Ne znam sto bih s ovim signalom?\n");
break;
}
return;

}
 
void main(void){

int proces_id,fd;
char sp_id[7];

/* ovaj program za IPC koristi fifo strukture */

umask(0); /* potrebno kako korisnicki file permission */
/* atributi ne bi sprijecili kreiranje FIFO */

mknod(FIFO_FILE,S_IFIFO|0666,0); /* stvaranje imenovanoh cjevovoda */
mknod(FIFO_PID,S_IFIFO|0666,0);

if((fd=open(FIFO_PID,O_WRONLY)) < 0){
puts("\nFIFOSERVER: Ne mogu otvoriti FIFO_PID\n");
fflush(stdout);
exit(-1);
}
proces_id=getpid();

printf("\nFIFOSERVER:\t PID= %d\n",proces_id);fflush(stdout);
sprintf(sp_id,"%06d",proces_id);
write(fd,sp_id,7); /* upisuje pid procesa u fifo da bi fclient znao pid fservera */
if (signal(SIGUSR1,sig_usr) == SIG_ERR){ puts("\nNe mogu USR1");exit;}

if (signal(SIGINT,sig_usr) == SIG_ERR){ puts("\nNe mogu INT");exit;}
if (signal(SIGUSR2,sig_usr) == SIG_ERR){ puts("\nNe mogu USR2");exit;}
if (signal(SIGHUP,sig_usr) == SIG_ERR){ puts("\nNe mogu HUP");exit;}

while(1);
}
 


Zaključak :

Program fserver stvara dva cjevovoda, jedan za pid procesa, a drugi za podatke. Program je sposoban obraditi samo četiri signala i to SIGUSR1, SIGUSR2, SIGINT, i SIGHUP.

Kada primi signal SIGUSR1 tada pročita 100 podataka sa signalnog generatora i te podatke pošalje na podatkovni cjevovod.

Slično je i sa SIGUSR2 samo se radi o 1000 podataka.

Kada primi signal SIGINT tada pročita 10 podataka sa potenciometra i te podatke pošalje na podatkovni cjevovod.

Signal SIGHUP čita samo digitalne ulaze i taj jedan podatak (Byte) pošalje u cjevovod i na digitalni izlaz tako da se odmah stanje može vidjeti i na led diodama.

U gore navedenom kodu svaki signal uzrokuje i ispis na ekran tako da se mogu pratiti zahtjevi i pročitane vrijednosti. Iste mogućnosti ima i program fclient.c koji smo također napisali da bi utvrdili dali program fserver radi kako treba. Sada slijedi kod programa fclient.c koji može pomoći sljedećoj grupi.


Fclient.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "a2dc.h"


#define FIFO_FILE "FIFO_ADC"
#define FIFO_PID "FIFO_PID"


int main(void){
FILE *fdes;
int fd,i,j;
WORD c[1000];
char s_pid[7];
int proces_id;

if ( (fd=open(FIFO_PID,O_RDONLY)) < 0 ){
puts("CLIENT: Ne mogu otvoriti FIFO_PID!");
exit(1);
}

read(fd,s_pid,7); /* sada se čita pid fservera jer je potreban kod slanja signala */

proces_id=atoi(s_pid);

printf("\n\tCLIENT: PID= %d",proces_id);
fflush(stdout);

i
f ( (fdes=fopen(FIFO_FILE,"r+")) == NULL ){

puts("CLIENT: Ne mogu otvoriti FIFO_FILE !");
exit(1);

}

for(j=0;j<2;j++){ /* salje sva cetiri signala redom i to dva puta */
puts("\n\tCLIENT: Saljem serveru signal SIGHUP !!!");
fflush(stdout);
kill(proces_id,SIGHUP); /* posalje signal SIGHUP procesu proces_id */
sleep(1);
i=fread(&c,sizeof(char),1,fdes); /* cita 1 podatak i pise u c */
fflush(fdes);
printf("\nUcitao sam ukupno %hd podataka\n",i);
usleep(500000);
printf("\n %d",c[0]);
sleep(5);
puts("\n\tCLIENT: Saljem serveru signal SIGUSR1 !!!");
fflush(stdout);
kill(proces_id,SIGUSR1); /* posalje signal SIGUSR1 procesu proces_id */
sleep(1);
i=fread(&c,sizeof(WORD),100,fdes); /* cita 100 podataka i pise u c */
fflush(fdes);
printf("\nUcitao sam ukupno %hd podataka\n",i);
usleep(500000);
for(i=0;i<100;i++) {
printf("\nSignal generator : c[%d]=%d",i,c[i]);
}
sleep(5);
puts("\n\tCLIENT: Saljem serveru signal SIGUSR2 !!!");
fflush(stdout);
kill(proces_id,SIGUSR2); /* posalje signal SIGUSR2 procesu proces_id */
sleep(1);
i=fread(&c,sizeof(WORD),1000,fdes); /* cita 1000 podataka i pise u c */
fflush(fdes);
printf("\nUcitao sam ukupno %hd podataka\n",i);
usleep(500000);
for(i=0;i<1000;i++) {
printf("\nSignal generator : c[%d]=%d",i,c[i]);
}
sleep(5);
puts("\n\tCLIENT: Saljem serveru signal SIGINT !!!");
fflush(stdout);
kill(proces_id,SIGINT); /* posalje signal SIGINT procesu proces_id */
sleep(1);
i=fread(&c,sizeof(WORD),10,fdes); /* cita 10 podataka i pise u c */
fflush(fdes);
printf("\nUcitao sam ukupno %hd podataka\n",i);
usleep(500000);
for(i=0;i<11;i++) {
printf("\nPotenciometar : c[%d]=%d",i,c[i]);
}
sleep(2);

}

fclose(fdes);
close(fd);
return(0);
}


Ovaj program služi samo da se ispita komunikacija sa fserverom. Sve je proradilo i to skoro iz prve. Zbog načina na koji programi rade potrebno je prvo pokrenuti fserver jer on prvo mora zapisati svoj pid u imenovani cjevovod, a fclient tada nezna kome slati signale. Mi smo pokretali svaki program u svojoj konzoli.

Koga zanima što je rađeno te želi ove datoteka neka pogleda u linux labosu na prvom katu D zgrade. Datoteke se nalaze u /home/projekt direktoriju na linlab8 tj. onome raskljopljenom računalu. Nije dozvoljeno ništa brisati. Ostatak dokumentacije već postoji na stranicama predmeta pod Projekt - Software.

Ovdje su linkovi na ovaj dokument u Windows Word-u Zadatak 1.doc zatim c-kod fserver.c i fclient.c

Za sva pitanja i nejasnoće raspoloživa je sljedeća trojka. Pošaljite na mail pa ako znamo mi ćemo vam odgovoriti i pokušati pomoći.

Zadatak izvršili Alen Radošević, Marin Babić i Krunoslav Pavić.