分类: LINUX
2011-08-14 21:03:15
这个led驱动程序只在linux-2.6.32.2内核中测试通过,至于其他的内核可能头文件有一些改动就不能 编译成功了。下面给出源程序: 这是友善之臂提供的源码: #include
#include #include #include
#include #include #include #include #include #include #include #include #include
#include #include #include #include #include #include #include #include #include #include #include
#define DEVICE_NAME "leds" //设备名(/dev/leds) //LED 对应的GPIO 端口列表 static unsigned long led_table[] = { S3C2410_GPB(5), S3C2410_GPB(6), S3C2410_GPB(7), S3C2410_GPB(8), }; //LED 对应端口将要输出的状态列表 static unsigned int led_cfg_table[] = { S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, };//如果内核相差不大,比如是2.6.30的内核,很可能照着这个程序写的时候这个地方会报错,原因是头文件不同 /*ioctl 函数的实现 * 在应用/用户层将通过ioctl 函数向内核传递参数,以控制LED 的输出状态 */ static int sbc2440_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case 0: case 1: if (arg > 4) { return -EINVAL; } //根据应用/用户层传递来的参数(取反),通过s3c2410_gpio_setpin 函数设置LED 对应的端口寄存 //器, s3c2410_gpio_setpin(led_table[arg], !cmd); return 0; default: return -EINVAL;
} } /* * 设备函数操作集,在此只有ioctl 函数,通常还有read, write, open, close 等,因为本LED 驱动在下面已经 * 注册为misc 设备,因此也可以不用open/close */ static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = sbc2440_leds_ioctl, }; /* * 把LED 驱动注册为MISC 设备 */ static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, //动态设备号 .name = DEVICE_NAME, .fops = &dev_fops, }; /* * 设备初始化 */ static int __init dev_init(void) { int ret; int i; for (i = 0; i < 4; i++) { //设置LED 对应的端口寄存器为输出(OUTPUT) s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); //设置LED 对应的端口寄存器为低电平输出,在模块加载结束后,四个LED 应该是全部都是发光 //状态 s3c2410_gpio_setpin(led_table[i], 0); } ret = misc_register(&misc); //注册设备 printk (DEVICE_NAME"\tinitialized\n"); //打印初始化信息 return ret; } static void __exit dev_exit(void) { misc_deregister(&misc); } module_init(dev_init); //模块初始化,仅当使用insmod/podprobe 命令加载时有用,如果设备不是通过模块方式加载,此处将不会被调用 module_exit(dev_exit);//卸载模块,当该设备通过模块方式加载后,可以通过rmmod 命令卸载,将调用此函数 MODULE_LICENSE("GPL"); //版权信息 MODULE_AUTHOR("FriendlyARM Inc."); //开发者信息
下面是makefile文件 CROSS=arm-linux- KERNELDIR = /root/doc/mini/linux-2.6.32.2//内核源码位置 #定义内核源码的路径 PWD := $(shell pwd) #获取当前路径 .PHONY: modules clean #指明modules、clean为伪目标 obj-m += mini2440_leds.o #表示要构造的模块名为s3c24xx_leds.ko modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules #-C:进入$(KERNELDIR)后再执行make,读取那里的Makefile。 #M=$(PWM):然后返回当前的位置(驱动源代码的位置)继续执行当前的Makefile。 clean: rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions #end 进入目录后,执行make,然后将ko文件通过网络或者U 盘传到板子上,lsmod一下,装载模块。 下面的是测试文件leds-test.c: #include #include #include #include int main(int argc, char **argv) { int on; int led_no; int fd; if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 || on < 0 || on > 1 || led_no < 0 || led_no > 3) { fprintf(stderr, "Usage: leds led_no 0|1\n"); exit(1); } fd = open("/dev/leds0", 0); if (fd < 0) { fd = open("/dev/leds", 0); } if (fd < 0) { perror("open device leds"); exit(1); } ioctl(fd, on, led_no); close(fd); return 0; } 将生成的.ko模块文件装载之后,运行测试文件就可以控制led的变化。 在命令行下执行: #arm-linux-gcc –o leds-test leds-test.c 将生成可执行目标文件leds-test,通过网络ftp 或者优盘把它复制到开发板中,比如放在/home/plg 目录下(注意:开发板缺省的文件系统已经有了led 测试程序,所以我们在此改名为leds-test),在开发板的命令行终端执行: #/etc/rc.d/init.d/leds stop 该命令将停止led-player 对led 的控制,关于led-player,可以在用户手册中查看详细的说明。使用leds-test 控制led 方法为: #leds-test 3 0 ;关闭LED3 #leds-test 3 1 ;打开LED3 其中第一个参数为要控制的LED 序号,第二个参数代表关闭(0)或者打开(1)对应的LED。如图 |