I. Overview
The Linux kernel is composed of a variety of drivers, the kernel source code in about 85% of the various channels of program codes. In general, the general process for writing Linux device drivers is as follows:
1, view the schematic, data sheet, understand the operation method of the equipment.
2. Find the similar driver in the kernel, and develop it for the template.
3, the implementation of the initialization of the driver: such as the kernel to register the driver
4, design to achieve the operation: Open,close,read,write, etc.
5. Implement interrupt Service (not required)
6. Compile the driver into the kernel, or the insmod command to load
7, test the driver.
Second, the driver loading and unloading
Module_init (My_init); Module_exit (My_clearup);
Three, character device driver main data structure
1. System call: The application cannot directly manipulate the hardware, but instead uses a unified interface function to invoke the hardware driver. These interfaces become system calls. In the library function is defined, can be found in GILBC fcntl.h, unistd.h,sys/ioctl.h and other files. Open,wirite,read and so on.
2, data structure file_operations is in the kernel, in the include/linux/fs.h. Defined as follows:
/** Note: * Read, Write, poll, Fsync, Readv, Writev, Unlocked_ioctl and Compat_ioctl * can be called without the big Ke Rnel Lock held in all filesystems. */structfile_operations {structModule *owner; loff_t (*llseek) (structFile *, loff_t,int); ssize_t (*read) (structFile *,Char__user *, size_t, loff_t *); ssize_t (*write) (structFile *,Const Char__user *, size_t, loff_t *); ssize_t (*aio_read) (structKIOCB *,Const structIovec *, unsignedLong, loff_t); ssize_t (*aio_write) (structKIOCB *,Const structIovec *, unsignedLong, loff_t); int(*readdir) (structFile *,void*, filldir_t); unsignedint(*poll) (structFile *,structPoll_table_struct *); int(*IOCTL) (structInode *,structFile *, unsignedint, unsignedLong); Long(*UNLOCKED_IOCTL) (structFile *, unsignedint, unsignedLong); Long(*COMPAT_IOCTL) (structFile *, unsignedint, unsignedLong); int(*mmap) (structFile *,structVm_area_struct *); int(*open) (structInode *,structFile *); int(*flush) (structFile *, fl_owner_t ID); int(*release) (structInode *,structFile *); int(*fsync) (structFile *,structDentry *,intDatasync); int(*aio_fsync) (structKIOCB *,intDatasync); int(*fasync) (int,structFile *,int); int(*Lock) (structFile *,int,structFile_lock *); ssize_t (*sendfile) (structFILE *, loff_t *, size_t, read_actor_t,void*); ssize_t (*sendpage) (structFile *,structPage *,int, size_t, loff_t *,int); unsignedLong(*get_unmapped_area) (structFile *, unsignedLong, unsignedLong, unsignedLong, unsignedLong); int(*check_flags) (int); int(*dir_notify) (structFile *filp, unsignedLongArg); int(*flock) (structFile *,int,structFile_lock *); ssize_t (*splice_write) (structPipe_inode_info *,structFILE *, loff_t *, size_t, unsignedint); ssize_t (*splice_read) (structFILE *, loff_t *,structPipe_inode_info *, size_t, unsignedint);};
3, the equipment of the primary and secondary equipment number =
The kernel relies on this to find the corresponding driver. When the application operates the device file, the Linux system will be based on the device file type, the main device number is registered in the kernel file_operation (for the block device number is the block_device_operations structure), the secondary device number to distinguish it is the first of the same device.
4. Registration function and unload function
Register_chrdev;unregister_chrdev;
Four, LED driver
#include <linux/module.h>#include<linux/kernel.h>#include<linux/fs.h>#include<linux/init.h>#include<linux/delay.h>#include<asm/uaccess.h>#include<asm/irq.h>#include<asm/io.h>#include<asm/arch/regs-gpio.h>#include<asm/hardware.h>//Defining RegistersvolatileUnsignedLong*gpfcon=NULL;volatileUnsignedLong*gpfdat=NULL;Static struct class*myfird_class;//in order to automatically create MdevStatic structClass_device *Myfird_class_dev;//OpenStatic intMyfird_open (structInode *inode,structFile *file) {PRINTK ("Myfird has open\n"); //Configuring IO Ports*gpfcon &= ~ ((0x3<< (4*2)) | (0x3<< (5*2)) | (0x3<< (6*2)));//facies*gpfcon |= ((0x1<< (4*2)) | (0x1<< (5*2)) | (0x1<< (6*2)));//phase or return 0;}//WriteStaticssize_t Myfird_write (structFile *file,Const Char__user *buf, size_t count, loff_t *PPOs) { intVal; //PRINTK ("first_drv_write\n");Copy_from_user (&val, buf, Count);//Copy_to_user (); if(val = =1) { //Lighting*gpfdat &= ~ ((1<<4) | (1<<5) | (1<<6)); } Else { //extinguishing lamp*gpfdat |= (1<<4) | (1<<5) | (1<<6); } return 0;}//Define a structureStatic structFile_operations Myfird_fops ={. Owner= This_module,/*This is a macro that is automatically created when you push the module to compile the __this_module variable*/. Open=Myfird_open,. Write=Myfird_write,};//the structure needs to be told to the kernel using a function. Registering DriversintMajor//Main device numberintMyfird_init (void) {Major=register_chrdev (0,"Myfird", &myfird_fops);//Tell the kernelMyfird_class = Class_create (This_module,"Myfird");//build a class//EquipmentMyfird_class_dev = Class_device_create (Myfird_class, NULL, MKDEV (Major,0), NULL,"XYZ"); Gpfcon=(volatileunsigned *) Ioremap (0x56000050, -); Gpfdat= Gpfcon +1;; return 0;}voidMyfird_exit (void) {Unregister_chrdev (major,"Myfird");//Tell the kernelClass_device_unregister (Myfird_class_dev); Class_destroy (Myfird_class); Iounmap (Gpfcon);} Module_init (Myfird_init); Module_exit (Myfird_exit); Module_license ("GPL");
V.. makefile file
Kern_dir =/work/system/linux-2.6. 22.6 #内核所在的目录all: -C $ (kern_dir) m=' pwd ' modules clean :-C $ (kern_dir) m=' pwd ' modulesclean-RF Modules.orderobj-M + = MYFIRD.O
LED driver learning record for character device drivers