Under uClinux platform, we use static compilation method as follows, because of its limitation of functionality.
1. Wrote driver function file(s).
-added some statements (such as includes, micro definitions, static global variables) necessary:
#define __NO_VERSION__ //if no version information of my driver needs to be declared.
#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/arch/s3c4510B.h> //the specific chip registers’ micro definition file
char kernel_version[] = UTS_RELEASE;
Other information such as author, date, etc followed by GNU standard
-defined major device number, eg: int Major_No = 254;
-wrote driver function (eg: dt_open, dt_ioctl, etc)
-wrote structure variable to setup the association between my driver functions and system driver calls,
eg: struct file_operations test_fops ={
open: dt_open,
ioctl: dt_ioctl,
};
-wrote initial function (eg: int test_init(void)), which calls system function register_chrdev(Major_No, “test”, &test_fops) to register my driver device(character-type device) into system. These parameters stand for major device number, driver name, the association of driver functions. Note that if Major_No is 0, the return value of function register_chrdev is the major number assigned by system.
-wrote cleanup function with void cleanup_module(void) prototype, which calls system function unregister_chrdev(Major_No, “test”) .
2. Stored in the proper folder, eg: character driver stored in folder drivers/char/
3. Modified Makefile in this folder (eg: drivers/char/).
-added configuration at somewhere: type like that "obj-$(CONFIG_TESTDRIVER) += testdriver.o"
4. Modified config.in in the same folder.
-added configuration at somewhere: type like that "bool ‘Mytestdriver’ CONFIG_TESTDRIVER"
5. Modified mem.c in the same folder
-added initial function of my driver (eg: test_init()) into mem.c with same rule within it.
5. Added device node in Makefile in folder vendors/Samsung/4510B
-added parameters(same as command mknod’ s parameters) in DEVICES section, eg: test, c, 254, 0, which stands for the register driver name, device type(char), major device number, minor device number
6. Used command make menuconfig at linux root folder(eg: uClinux-dist) to let my driver choice available
7. re-compiled linux with some commands
That's all!
Ps:
1. File operations API of Linux is defined as follows:
struct file_operations {
int (*seek) (struct inode * ,struct file * , off_t ,int);
int (*read) (struct inode * ,struct file * , char ,int);
int (*write) (struct inode * ,struct file * , off_t ,int);
int (*readdir) (struct inode * ,struct file * , struct dirent * ,int);
int (*select) (struct inode * ,struct file * , int ,select_table *);
int (*ioctl) (struct inode * ,struct file * , unsined int ,unsigned long);
int (*mmap) (struct inode * ,struct file * , struct vm_area_struct *);
int (*open) (struct inode * ,struct file *);
int (*release) (struct inode * ,struct file *);
int (*fsync) (struct inode * ,struct file *);
int (*fasync) (struct inode * ,struct file * ,int);
int (*check_media_change) (struct inode * ,struct file *);
int (*revalidate) (dev_t dev);
}
2. There are two methods for driver implementation: static compilation method and dynamic compilation method. uClinux usually uses static compilation method, because of limitation of functionality. Linux usually uses dynamic compilation method which added/removed driver device as a module into system by command insmod/rmmod.
3. Note that we use uClinux 2.4 version for implementation here.