I3CPAC+Exercise+5

toc =Øvelse 5: GPIO Linux Device Driver= //Lav en driver som kan sætte værdien af en gpio (hvis den er output) og læse værdien fra en gpio (hvis den er et input).//

Init & Exit
//Start med at implementere koden til ”init” og ”exit”//

Structen som allerede er skrevet i det udleverede driverskelet er vist nedenfor for overskuelighedes skyld. Her er angivet gpio'ernes nummer, retning (findes på devkit wiki), samt deres label.

code format="cpp" struct gpioPort{ unsigned int num; enum direnu { in, out } dir; const char label[10]; } gpio[] = { {130, in, "gpio0_0"}, {131, in, "gpio0_1"}, {132, in, "gpio0_2"}, {133, in, "gpio0_3"}, {134, out, "gpio0_4"}, {135, out, "gpio0_5"}, {136, out, "gpio0_6"}, {137, out, "gpio0_7"}, {139, out, "gpio0_8"} }; code

INIT
gpio_request funktionen bruges til at tilgå GPIO ressourcerne, og gentages for samtlige gpio'er beskrevet i gpioPort-structen ovenfor i en for-løkke. code format="cpp" for ( int i = 0; i < gpio_len; i++) gpio_request(gpio[i].num, gpio[i].label); code

Dernæst sættes retningen ved hjælp af gpio_direction_input og gpio_direction_output funktionerne. Den gemte værdi i gpioPort structen benyttes til at bestemme om en given gpio skal bruges som input eller output.

code format="cpp" for ( int i = 0; i < gpio_len; i++) { if (gpio[i].dir == in) gpio_direction_input(gpio[i].num);

else gpio_direction_output(gpio[i].num, 0);

} code

EXIT
I exit-funktionen frigives ressourcerne igen ved brug af gpio_free funktionen og alle retninger sættes til in(default). code format="cpp" for ( int i = 0; i < gpio_len; i++) {   gpio_free(gpio[i].num); gpio_direction_input(gpio[i]num); } code

Open & Release
//Implementer koden til ”open” og ”release”.//

I hhv. open og release undersøges der om minor/major nummeret er gyldigt. code if(major != MYGPIO_MAJOR) { return -ENODEV; } if(minor < 0 || minor > gpio_len) { return -ENODEV; } code

Write
I write rutinen bruges linien code format = "cpp" copy_from_user(kbuf, ubuf, len) code til at kopiere data fra userspace til en buffer i kernelspace. Her kan det behandles og konverteres til en integer, som til sidst bruges til at bestemme om der skal skrives et 0 eller 1 til gpio'en. Til at sætte gpio'en, bruges funktionen nedenfor. Der skrives til gpio[8], da denne svarer til gpio nr 139 som er LED3 på Devkittet. code format = "cpp" gpio_set_value(gpio[8].num, value); code

Read
I read rutinen læses data fra gpio'en, som herefter konverteres til en streng og kopieres fra kernelspace til userspace. Nedenfor er vist de linier som vi selv har tilføjet til kode-skelettet.

Gpio aflæses code format ="cpp" if (gpio[minor].dir == in) {   gpio_get_value(gpio[minor].num); } code

Data kopieres fra kernel til userspace code format ="cpp" copy_to_user(buf, readBuf, len); code

Test
Driveren bygges med den udleverede Makefile, og .ko filerne kopieres til target. Modulet indsættes i kernen ved hjælp af insmod, og en node oprettes som angivet i vejledningen (mknod /dev/mygpio4 c 62 4). For at tænde og slukke for LED'en echoes hhv. 0 og 1 til noden. Dette virkede som forventet.

For at aflæse diodens tilstand, cat'es noden.