Øvelse+8+-+Linux+Device+Driver+med+Timer

**Forberedelser**
toc Følgende skal være opfyldt for at du kan komme i gang: • Kopiér din GPIO LDD til et nyt passende navn. ( Vi har kopieret driveren fra øvelse 6 til en ny mappe)

=**Implementer ioctl kald**= -Start med at implementere et ioctl kald og et lille tilhørende testprogram. Du kan evt blot udskrive til kernen.

I vores struct tilføjer vi: code format="c" .ioctl  = mygpio_ioctl code

I .c-filen indsætter vi følgende kode: code format="c" ssize_t mygpio_ioctl(struct inode *Inode, struct file *filep,                          unsigned int cmd, unsigned long arg) {   int minor = MINOR(filep->f_dentry->d_inode->i_rdev);

// Note! arg is passed by value switch(cmd) {      case SET_PGA_GAIN: // Set PGA gain for a channel //ads7870_setPgaGain(minor, arg); printk(KERN_ALERT "SET_PGA_GAIN\n"); break; case SET_INPUT_MODE_GAIN: // Set the input mode to diff-/single ended //ads7870_setInputMode(minor, arg); printk(KERN_ALERT "SET_INPUT_MODE\n"); break; default: printk(KERN_ALERT "Unknowm ioctl-command: %d \n", cmd); }   return 0; } code Vi har defineret "SET_PGA_GAIN" og "SET_INPUT_MODE_GAIN" øverst code format="c" code Herefter kører vi "make", inden vi laver vores test program
 * 1) define SET_PGA_GAIN       1101
 * 2) define SET_INPUT_MODE_GAIN 1102

code format="c" // til brug af prinf //til brug af open // til brug af close //til brug af ioctl (control device)
 * 1) include 
 * 1) include 
 * 1) include 
 * 1) include 

int main(int narg, char *argp[]) {
 * 1) define EN 1
 * 2) define TO 2
 * 3) define SET_PGA_GAIN       1101
 * 4) define SET_INPUT_MODE_GAIN 1102

int fd; char str[12];

fd = open("/dev/mygpio", O_RDWR);

ioctl(fd, SET_PGA_GAIN, EN); ioctl(fd, SET_INPUT_MODE_GAIN, TO);

close(fd); } code Herefter bygges programmet til target. Vi indsætter kernen med insmod og opretter en node inden vi køre programmet.

=**Implementer toggler**=

I main ændres vores defines til "START_TIMER" og "STOP_TIMER", ligesom de gøres i mygpio.c (ligesom overfor) Vi laver en ny user space application, kaldet **mytoggler.c**. hvor navnene sættes på case'ene. code format="c" code samt vores ioctl kald bliver ændret til, med en sleep på 10 sek. code format="c" ioctl(fd, START_TIMER, EN); printf("ioctl kaldet med start-timer\n"); //sleep et stykke tid sleep(10);
 * 1) define START_TIMER     1101
 * 2) define STOP_TIMER      1102

ioctl(fd, STOP_TIMER, TO); printf("ioctl kaldet med stop-timer\n"); code

For at kunne bruge er der øverst i .c filen defineret denne linje:. code format="c" case START_TIMER: printk("UDSKRIV: Timer startes   %i\n", arg);

// initier timeren init_timer(&my_timer);

// timer expires in delay ticks my_timer.expires = jiffies + 1*HZ;

//fortæller timeren hvilken funktion den skal køre my_timer.function = timer_funct;

// aktivering af timer add_timer(&my_timer);

// argument(parametre) to the handler i vores tilfælde til timer_funk my_timer.data = minor;

break; case STOP_TIMER: printk("UDSKRIV: Timer stoppes %i\n", arg); // stop timer del_timer(&my_timer); break;

code

Timer-funktionen sætter først værdien af den ønskede gpio[] (se opg 5, for flere detaljer omkring gpio[]) til det modsatte af det den var. Hvorefter den starter timeren så den toggler gpio[] hvert sekund.

code format="c" static void timer_funct{

//sætter værdien til det modsatte af hvad den var før, f. eks hvis der er valgt GPIO-139 vil den ene lysdiode blinke. gpio_set_value(gpio[my_timer.data].num, !gpio_get_value(gpio[my_timer.data].num));

// Re-schedule the timer, for at sikre at den kaldes igen og igen og. my_timer.expires = jiffies + 1*HZ; add_timer(&my_timer); } code

Efter indsættelse af modulet og oprettelse af node, kan main eksekveres. code code
 * 1) root@DevKit8000:~/cpac# ./target_timer
 * 2) ioctl kaldet med start-timer
 * 3) ioctl kaldet med stop-timer