在最近一段时间内,自己开始了在linux系统下的简单驱动程序的编写及学习。由于对于arm开发板之前用过,在上面进行上层应用的编程,开始时真不知道怎样将其与驱动连接起来。
在学长的指导下,知道一个简单的驱动其实就是实现read、write、ioctl,填充file operation结构体。
我近期把对于led 、数码管的驱动进行了编写,下面是驱动代码。
led 部分:
led在我的开发板上只要用GPO05控制,板子是smartarm3250,用P3输出引脚相关寄存器控制,
在程序中用io_p2v进行物理地址到逻辑地址的转换。在手册中可以得到寄存器的地址信息。
下面是led的简单模块:
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/irq.h>
4
5 #include <asm/io.h>
6 #include <mach/hardware.h>
7 #include <mach/platform.h>
8 #include <linux/delay.h>
9
10 #define p3_set1 io_p2v(0x40028004)
11 #define p3_clr1 io_p2v(0x40028008)
12 //#define sic2_er io_p2v(SIC2_BASE)
13 //#define sic2_clr io_p2v(0x40010004)
14 //#define KEY_IRQ IRQ_GPI_07
15
16 MODULE_LICENSE("Dual BSD/GPL");
17
18 static int __init hello_init(void)
19 {
20 int i=0;
int tmp=10;
22 while(tmp)
23 {
24 //__raw_writel(1<<15,sic2_er);
25 //set_irq_type(KEY_IRQ,IRQ_TYPE_EDGE_FALLING);
26 //__raw_writel(1<<7,p3_clr1);
27 __raw_writel(1<<5,p3_set1);
28 for(i=100;i>0;i--)
29 udelay(1000);
30 // __raw_writel(1<<15,sic2_clr);
31 // __raw_writel(1<<7,p3_set1);
32 __raw_writel(1<<5,p3_clr1);
33 for(i=100;i>0;i--)
34 udelay(1000);
35 tmp--;
36 }
37 printk(KERN_INFO"insert the hello module!!");
38 return 0;
39 }40
41 static void __exit hello_exit(void)
42 {
43 //free_irq(KEY_IRQ,NULL);
44 printk(KERN_INFO"exit the module!");
45 }
46 module_init(hello_init);
47 module_exit(hello_exit);
这个简单的模块是在简单的hello world 模块基础上改进的;
让后写了一个简单的Makefile
1 # Makefile2.6
2 ifneq ($(KERNELRELEASE),)
3 #kbuild syntax. dependency relationshsip of files and target modules are listed here.
4 obj-m := hello.o
5 else
6 PWD := $(shell pwd)
7 KVER = 2.6.27.8
8 KDIR := /home/rendan/lpc3250/linux-2.6.27.8-smartarm3250/
9 all:
10 $(MAKE) -C $(KDIR) M=$(PWD) modules
11
12 clean:
13 rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
14 endif
接下来,进行模块的编译,用make命令。
编译完后,就会生成后缀为.ko的文件,下来是加载模块,由于要在开发板上运行,用minicom进行串口通信,利用nfs,将共享文件挂载,成功后加载模块,就可以看见led的闪烁。
加载模块用insmod led.ko
卸载模块用rmmod led.