helloyesyes 发表于 2013-2-4 14:10:31

Linux驱动修炼之道-流水灯

哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处
http://blog.csdn.net/woshixingaaa/archive/2011/04/02/6299318.aspx
module.h包含可装载模块需要的大量符号和函数定义,包含init.h的目的是指定初始化和清除代码,struct file是在<linux/fs.h>中定义的。
注册字符设备使用
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
移除字符设备使用
int unregister_chrdev(unsigned int major, const char *name);
init函数是在insmod时被调用的,exit函数是在rmmod时被调用的。
使用命令 cat /proc/devices 可以查看设备的主设备号。
如果内核没有为我们生成设备文件,我们需要手动生成:
mknod /dev/led_driver c 234 0
__init标记表示该函数只在初始化期间使用,在模块被装载后,模块装载器就会将初始化函数扔掉,这样可将函数占用的内存释放出来。
__exit修饰的函数只在模块卸载或系统关闭时被调用,如果模块被直接内嵌到内核中,或者内核的配置不允许卸载模块,则被标记为__exit
的模块将被简单丢弃。
驱动程序:
#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#define LED_MAJOR 234#define DEVICE_NAME "led_driver"static unsigned long led_table[]={S3C2410_GPF3,S3C2410_GPF4,S3C2410_GPF5,S3C2410_GPF6,};static unsigned long led_cfg_table[]={S3C2410_GPF3_OUTP,S3C2410_GPF4_OUTP,S3C2410_GPF5_OUTP,S3C2410_GPF6_OUTP,};int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg){switch(cmd){case 0:s3c2410_gpio_setpin(led_table,0);s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,1);break;case 1:s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,0);s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,1);break;case 2:s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,0);s3c2410_gpio_setpin(led_table,1);break;case 3:s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,1);s3c2410_gpio_setpin(led_table,0);break;default:return -EINVAL;break;}return 0;}struct file_operations led_ops = {.owner = THIS_MODULE,.ioctl = led_ioctl,};static int __init init_led(void){int i, ret;ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&led_ops);if(ret < 0){printk(DEVICE_NAME, "can't register major number\n");}for(i = 0; i < 4; i++){s3c2410_gpio_cfgpin(led_table,led_cfg_table);s3c2410_gpio_setpin(led_table,1);}printk(DEVICE_NAME "initialized\n");return 0;}static void __exit exit_led(void){unregister_chrdev(LED_MAJOR,DEVICE_NAME);}module_init(init_led);module_exit(exit_led);MODULE_LICENSE("GPL");MODULE_AUTHOR("liwanpeng");
测试程序:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>int main(){int fd, ret;char *i;fd = open("/dev/led_driver",0);if(fd < 0){printf("open device error");}else{while(1){ioctl(fd,0);printf("led0 is on!\n");sleep(1);ioctl(fd,1);printf("led1 is on!\n");sleep(1);ioctl(fd,2);printf("led2 is on!\n");sleep(1);ioctl(fd,3);printf("led3 is on!\n");sleep(1);}close(fd);}return 0;}
效果:此时LED灯也轮流闪烁。
http://hi.csdn.net/attachment/201104/2/0_1301752175hpXu.gif
页: [1]
查看完整版本: Linux驱动修炼之道-流水灯