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],0); s3c2410_gpio_setpin(led_table[1],1); s3c2410_gpio_setpin(led_table[2],1); s3c2410_gpio_setpin(led_table[3],1); break; case 1: s3c2410_gpio_setpin(led_table[0],1); s3c2410_gpio_setpin(led_table[1],0); s3c2410_gpio_setpin(led_table[2],1); s3c2410_gpio_setpin(led_table[3],1); break; case 2: s3c2410_gpio_setpin(led_table[0],1); s3c2410_gpio_setpin(led_table[1],1); s3c2410_gpio_setpin(led_table[2],0); s3c2410_gpio_setpin(led_table[3],1); break; case 3: s3c2410_gpio_setpin(led_table[0],1); s3c2410_gpio_setpin(led_table[1],1); s3c2410_gpio_setpin(led_table[2],1); s3c2410_gpio_setpin(led_table[3],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[i],led_cfg_table[i]); s3c2410_gpio_setpin(led_table[i],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灯也轮流闪烁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值