- UID
- 133947
- 性别
- 男
|
最后一个问题。在静态加载驱动的时候,我们那个mydrv_cleanup和module_exit函数永远不会被执行,所以去掉是完全可以的,不过为了程序看起来结构清晰,也为了与动态加载的程序兼容,还是建议保留着。
下面讲一下动态加载驱动的方法。
1、运行make menuconfgi,在内核配置中进入Loadable module support,选择Enable loadable module support和Kernel module loader(NEW)两个选项。在应用程序配置中进入busybox,选择insmod, rmmod, lsmod三个选项。
2、在…vendors\Samsung\2500\Makefile中添加相应的设备节点,方法与静态加载时完全一样。
3、编写自己的驱动程序文件,在文件开始处加一句:
#define MODULE
文件最后的
mydrv_init
mydrv_cleanup
module_init(mydrv _init)
module_exit (mydrv _cleanup)
这四项必须保留。
4、仿照如下的格式写自己的Makefile文件:
KERNELDIR= /home/hexf/hardware/nHD/Design/firmware/uClinux-Samsung-2500/linux-2.4.x
CFLAGS = -D__KERNEL__ -I$(KERNELDIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-common -pipe -fno-builtin -D__linux__ -DNO_MM -mapcs-32 -mshort-load-bytes -msoft-float
CC = arm-elf-gcc
all: mydrv.o
clean:
rm -f *.o
5、编译自己的驱动程序文件。注意在动态加载时只编译不连接,所以得到的是.o文件。
6、把编译后的驱动程序的.o 文件,连同自己的测试程序(假设叫mytest,注意这个是可执行文件)一起放在编译服务器的/exports/自己的目录下。
测试程序就是一个普通的应用程序,其编写和编译的步骤这里就不讲了。
7、启动nHD板卡,用nfs的方法把编译服务器上/exports/自己的目录mount上来(假设mount 到 /mnt下)。Nfs的使用大家都很熟悉了,这里就不再说。
8、
cd /mnt
/bin/insmod mydrv.o
现在你的设备就已经被动态加载到系统里了。可以用lsmod命令查看当前已挂接的模块。
9、运行你的测试程序
10、调试完毕后用 rmmod mydrv把你的设备卸载掉。
补充几点:
1、关于建立设备节点的问题,因为大家所使用的系统不太一样,所以不需要按照我说的方法。总之只要在你自己的系统的dev目录下建立了自己的驱动程序的设备节点就可以了。
2、没有考虑动态分配主设备号的问题。所以注册设备那个地方稍微有点不严密。
3、模块加载时要把自己的.c文件编译成.o文件,CFLAGS后面那一串编译选项有时可能有点烦人,如果你没搞定,最简单的办法就是重新编译一遍内核并重定向到一个文件中(别忘了先make clean一下):make > out。
然后在out文件里随便找一个字符驱动程序的编译过程,把它的编译选项找出来,拷贝到你自己的Makefile里就可以了。我就是这么作的。
下面是一个最简单的字符设备驱动的例子。实际的驱动千差万别,但其实也就是
“填充”自己的open,close,read,write,ioctl几个函数而已。
#ifndef __KERNEL__
#define __KERNEL__
#endif
#define MODULE
#define drvtest_major 254
#include
#include
#include
#include
#include // printk()
#include // kmalloc()
#include // error codes
#include // size_t
#include // mark_bh
#include
#include
#include
#include
#include
#include
#include
static int mytest_open(struct inode *inode,struct file *filp)
{
MOD_INC_USE_COUNT;
printk("mytest open!\n");
return 0;
}
static ssize_t mytest_read(struct file *flip,char * buff,size_t count,
loff_t * f_pos)
{
char buf[10] ={0x1,0x2,0x3,0x4,0x5};
memcpy(buff,buf,5);
return 5;
}
static int mytest_close(struct inode *inode,struct file *filp)
{ MOD_DEC_USE_COUNT;
printk("mytest close!\n");
return 0;
}
static struct file_operations my_fops = {
read: mytest_read,
// write: mytest_write,
open: mytest_open,
release: mytest_close,
// ioctl: mytest_ioctl,
};
static int mytest_init(void)
{
int ret;
ret = register_chrdev(drvtest_major, "drvtest", &my_fops);
if(ret == 0) printk("register_chrdev succeed!\n");
else printk("register_chrdev fail!\n");
return 0;
}
static __exit void mytest_cleanup(void)
{
unregister_chrdev(drvtest_major, "drvtest");
printk("register_chrdev succeed!\n");
printk("bye!\n");
return ;
}
module_init(mytest_init);
module_exit(mytest_cleanup);
|
51 c8051f(f020,f040) msp430 arm(2410,2510) fpga(xc3s4000) dsp(5116 dm642) keilc vc++ matlab linux protel Ten_layerPCB mpegx h.26x Rscode Turbocode ofdm VideoBroadcasting ldpc_code(now!) |
|