I3CPAC+Exercise+4

toc =Øvelse 4: Linux Kerne Moduler=

Lav dit første Kernemodul
//Lav et ”hello_world” kerne modul og indsæt det i kernen. //

Til denne opgave har vi lavet et simpelt program, som kan udskrive "hello world" når det indsættes i kernen, og "goodbye cruel world når det tages ud af kernen

Uddrag fra vores kode:

code format="cpp" static int hello_init(void) {  printk(KERN_ALERT "Hello, world\n"); }

static void hello_exit(void) {  printk(KERN_ALERT "Goodbye, cruel world\n"); }

module_init(hello_init); module_exit(hello_exit); code

Vi har også lavet Makefilen vist herunder. Vi havde lidt problemer med at få den til at virke, dette viste sig at skyldes at vi ikke havde en tab på linjen hvor $(MAKE) står. Efter at have rettet dette virkede Makefilen efter hensigten og vi kunne få genereret de nødvendige filer.

code format="cpp" ifeq ($(KERNELRELEASE),) KERNELDIR = /home/stud/source/linux-2.6.28-omap PWD := $(shell pwd)
 * 1) If we are NOT invoked from the
 * 2) kernel build system

default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

else obj-m := hello.o endif code
 * 1) called from kernel build system:
 * 2) just declare what our modules are

Vi overførte så vores hello.ko fil til target, og indsatte modulet i kernen med kommandoen 'insmod hello.ko'. For at kontrollere at der blev skrevet hello world, brugte vi 'dmesg'. Derefter fjernede vi modulet fra kernen med rmmod, og kontrollerede med dmesg På billedet ses at vores modul skrev både Hello og Goodbye world da det blev indsat/fjernet.

Få lysdioden fra sidste øvelse til at lyse
//Du skal nu bruge ioread32/iowrite32 til at tænde for SYS_LED når modulet indsættes og slukke for den når det tages ud. Du kan bruge LED3 (GPIO 164). Den benytter GPIO bank 6 bit 4.//

Vores kode modificeres til at tænde for en LED på boardet. For at tænde for dioden AND'er vi det vi læser fra addressen med ~(1 << 4), altså 1 bit shiftet 4 gange mod venstre som inverteres. Vores init funktion ser sådan her ud: code format="cpp" < >

MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) {  printk(KERN_ALERT "Hello, world\n");

// Pointere til IO6 Registre volatile unsigned long *REG_GPIO6_OE; volatile unsigned long *REG_GPIO6_DIN; volatile unsigned long *REG_GPIO6_DOUT;

// Bede kernen om lov til at benytte memory området if (request_mem_region (0x49058034, 12, "hello") == NULL) { printk ("Allocation for I/O memory range is failed\n"); return 0; }

// Tildele addresser til pointere (mappet til en anden end den fysiske) REG_GPIO6_OE = ioremap( 0x49058034, 1); REG_GPIO6_DIN = ioremap(0x49058038, 1); REG_GPIO6_DOUT = ioremap(0x4905803c, 1);

// Skrive 32-bit

iowrite32( ioread32(REG_GPIO6_OE) & ~(1 << 4), REG_GPIO6_OE); iowrite32( ioread32(REG_GPIO6_DOUT) & ~(1 << 4), REG_GPIO6_DOUT);

return 0; } code

For at slukke for dioden, OR'er vi det vi læser fra addressen med 1 bit shiftet 4 gange til venstre. Vores exit funktion ser sådan her ud:

code format="cpp" static void hello_exit(void) {      volatile unsigned long *REG_GPIO6_DOUT; REG_GPIO6_DOUT = ioremap(0x4905803c, 1); printk(KERN_ALERT "Goodbye, cruel world\n"); // Frigiv memory

iowrite32((ioread32(REG_GPIO6_DOUT) | (1 << 4)), REG_GPIO6_DOUT); release_mem_region (0x49058034, 12); } module_init(hello_init); module_exit(hello_exit); code

Lav en C-applikation
Vi har skrevet et program hvori vi åbner filen der justerer lysstyrken, skriver "1" for at tænde, venter 1 sekund og slukker. Denne proces gentages 10 gange.

code format="cpp" int main {   int brightfile; int i;   for(i = 0; i < 10; i++) {       brightfile = open("/sys/class/leds/ledB/brightness", O_WRONLY); write(brightfile, "1", 1); printf("\nPassing the value 1!"); sleep(1); write(brightfile, "0", 1); printf("\nPassing the value 0!"); sleep(1); close(brightfile); }   return 0; } code