First put the code:
Character Device driver code:
/**
*file NAME:LED.C
*/
#include <linux/sched.h>#include<linux/signal.h>#include<linux/spinlock.h>#include<linux/errno.h>#include<linux/random.h>#include<linux/poll.h>#include<linux/init.h>#include<linux/slab.h>#include<linux/module.h>#include<linux/wait.h>#include<linux/mutex.h>#include<linux/io.h>#include<linux/fs.h>Static struct class*led_class;//Create ClassStatic structClass_device *led_class_devs[4];//Create a device that corresponds to a Class 1 total device files 3 single lamp device filesvolatileUnsignedLong*gpfcon =NULL;volatileUnsignedLong*gpfdat =NULL;intLed_open (structInode *inode,structFile *FP) { intMinor = minor (inode->I_rdev); //Get the secondary device number to open the device file Switch(minor) { Case 0: *gpfcon &= ~ ((0x3<< (4*2))| (0x3<< (5*2))| (0x3<< (6*2))); *gpfcon |= (0x1<< (4*2))| (0x1<< (5*2))| (0x1<< (6*2)); Break; Case 1: *gpfcon &= ~ (0x3<< (4*2)); *gpfcon |= (0x1<< (4*2)); Break; Case 2: *gpfcon &= ~ (0x3<< (5*2)); *gpfcon |= (0x1<< (5*2)); Break; Case 3: *gpfcon &= ~ (0x3<< (6*2)); *gpfcon |= (0x1<< (6*2)); Break; } return 0;} ssize_t Led_read (structFile *FP,Char__user *c, size_t *t) {int minor = minor (Fp->f_dentry->d_inode->i_rdev);
Char Leds_status;
Switch (minor)
{
Case 0:
Leds_status = ((*gpfdat & ((1<<4) | ( 1<<5) | (1<<6))) >>4)) &0x7;
Copy_to_user (buff, (const void *) &leds_status,1);//Copy data from user to kernel space
Break
Case 1:
Leds_status = (~ (*gpfdat>>4)) &0x1;
Copy_to_user (buff, (const void *) &leds_status,1);
Break
Case 2:
Leds_status = (~ (*gpfdat>>5)) &0x1;
Copy_to_user (buff, (const void *) &leds_status,1);
Break
Case 3:
Leds_status = (~ (*gpfdat>>6)) &0x1;
Copy_to_user (buff, (const void *) &leds_status,1);
Break
}}ssize_t Led_write (structFile *FP,Const Char__user *buf, size_t count, loff_t *PPOs) { intMinor = minor (fp->f_dentry->d_inode->I_rdev); intVal; Copy_from_user (&val, BUF,1); Switch(minor) { Case 0: Val&=0x1; *gpfdat &= ~ ((1<<4)| (1<<5)| (1<<6)); *gpfdat |= (val<<4)| (val<<5)| (val<<6); Break; Case 1: *gpfdat &= ~ (1<<4); *gpfdat |= (val&0x1) <<4; Break; Case 2: *gpfdat &= ~ (1<<5); *gpfdat |= (val&0x1) <<5; Break; Case 3: *gpfdat &= ~ (1<<6); *gpfdat |= (val&0x1) <<6; Break; }}structFile_operations led_fops={. Owner=this_module,. Open=Led_open,. Write=Led_write,};intMajor;Static intLed_init (void){ intMinor; Major= Register_chrdev (0,"Led_drv", &led_fops); The system automatically generates a device number when the specified device number is 0 o'clock led_class= Class_create (This_module,"my_leds"); if(Is_err (led_class))returnPtr_err (Led_class); led_class_devs[0] = Class_device_create (Led_class,null,mkdev (Major,0), NULL,"my_leds"); //Create a device file if(Unlikely (Is_err (Led_class_devs)))returnPtr_err (Led_class_devs); for(minor=1; minor<4; minor++) {Led_class_devs[minor]= Class_device_create (Led_class,null,mkdev (Major,minor), NULL,"my_led%d", minor); if(Unlikely (Is_err (Led_class_devs)))returnPtr_err (Led_class_devs); } Gpfcon= (volatileUnsignedLong*) Ioremap (0x56000050, -); //Physical address mapped to virtual address Gpfdat= Gpfcon +1; PRINTK ("led Install module\n"); return 0;}Static voidLed_exit (void) {Unregister_chrdev (major,"Led_drv" ); Class_device_unregister (led_class_devs[0]); //Unregister device file class_device_unregister (led_class_devs[1]); Class_device_unregister (led_class_devs[2]); Class_device_unregister (led_class_devs[3]); Class_destroy (Led_class); //Destroy Class Iounmap (Gpfcon); //de-Physical Address mapping PRINTK ("led Module exit\n");} Module_init (Led_init); Module_exit (Led_exit); Module_license ("GPL");
Makefile of the module:
obj-m:=led.okerneldir:=/home/jz2440/linux-2.6. 22.6 pwd:=$ (Shell PWD)default: -C $ (kerneldir) m=$ (PWD) Modulesclean: -rf *.o *.mod.c *.mod.o *.ko *.symvers
Test file:
#include <sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>intMainintargcChar**argv) { intFD; intval =1; if(ARGC! =3) {printf ("Please input righ data\n"); printf ("eg:/dev/my_leds <on\ "off>\n"); return 0; } FD= Open (argv[1], O_RDWR); if(fd<0) {printf ("Open failed\n"); return 0; } if(strcmp (argv[2]," on")==0) {Val=0; } Else{val=1; } write (FD,&val,4);
Read (fd, &val,1);
printf ("LED status =%d\n", Val); return 0;}
Finish
Linux Embedded Drive Learning path ⑩ character device driver-my_led