本帖最后由 简单侶途 于 2015-11-13 16:12 编辑
第五个程序目的是控制不同的LED实现方法是利用程序里面申请主设备号:
major = register_chrdev(0, "led", &leddrv_fops);
利用自动分配申请的major主设备号,接着利用major下自我分配利用的次设备号实现匹配同一类的不同minor,系统自动分配完major后,默认分配次设备号minor = 0,接着我们就在minor那里作文章了,minor使用范围是0~255
这个minor就可以让我们识别同一类设备类下的不同led设备节点
下图所示:242为major,242后面的0,1,2就是minor了
1.驱动程序部分:- #include<linux/fs.h>
- #include<linux/module.h>
- #include<linux/errno.h>
- #include<linux/kernel.h>
- #include<linux/init.h>
- #include<linux/cdev.h>
- #include<linux/uaccess.h>
- #include<linux/device.h>
- #include<linux/types.h>
- #include <asm/gpio.h>
- #include <linux/gpio.h>
- #include <plat/sys_config.h>
- #include <linux/delay.h>
- #include <asm/irq.h>
- #include <asm/io.h>
- #include <linux/moduleparam.h>
- #include <linux/poll.h>
- #include <linux/sched.h>
- #include <linux/spinlock.h>
- #include <linux/slab.h>
- #include <linux/ipmi.h>
- #include <linux/mutex.h>
- #include <linux/compat.h>
- /*两种方法寻找GPIO寄存器地址*/
- //#define PIO_BASE 0x01C20800
- #define PH_BASE (PIO_BASE + 7*0x24)
- #define PH_CFG2 (PH_BASE + 0x08)
- #define PH_DAT (PH_BASE + 0x10)
- //#define PH_BASE (PIO_BASE + 0xFC)
- //#define PH_CFG2 (PIO_BASE + 0x104)
- //#define PH_DAT (PIO_BASE + 0X10C)
- static volatile unsigned int *ph_cfg2;
- static volatile unsigned int *ph_dat;
- //设备类
- static struct class *leddrv_class;
- //分配 cdev
- static struct class_device *leddrv_class_dev[3];
- //主设备号
- static int major;
- static int led_open(struct inode *inode, struct file *file)
- {
- /*bit20[18:16],bit21[22:20]
- *open the roange_led and blue_led GPIO output
- *Output is 001
- */
- *ph_cfg2 &= ~((7<<16) | (7<<20));//清零000,这个步骤很重要,注释掉可以看下效果如何blue_led不能控制了
- *ph_cfg2 |= ((1<<16) | (1<<20));//设置001
- return 0;
- }
- static ssize_t led_write (struct file *file,char __user *buf,
- size_t count,loff_t *f_pos)
- {
- int val;
- int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- /*1.从用户空间读取数据到内核空间*/
- copy_from_user(&val,buf,4);
- /*2.判断传入值val,进行GPIO电平控制*/
- switch (minor){
- case 0: /*/dev/leds*/
- {
- if(val == 1)
- *ph_dat |= ((1<<20) | (1<<21));
- else
- *ph_dat &= ~((1<<20) | (1<<21));
- }
- break;
- case 1:/*/dev/led1*/
- {
- if(val == 1)
- *ph_dat |= (1<<20);
- else
- *ph_dat &= ~(1<<20);
- }
- break;
- case 2: /*/dev/led2*/
- {
- if(val == 1)
- *ph_dat |= (1<<21);
- else
- *ph_dat &= ~(1<<21);
- }
- break;
- }
- return 0;
- }
- //分配驱动操作
- static struct file_operations leddrv_fops = {
- .owner = THIS_MODULE,
- .open = led_open,
- .write = led_write,
- };
- static int led_init(void)
- {
- int minor = 0;
-
- ph_cfg2 = ioremap(PH_CFG2, 4);
- ph_dat = ioremap(PH_DAT, 4);
-
- major = register_chrdev(0, "led", &leddrv_fops);
- leddrv_class = class_create(THIS_MODULE, "led");
- leddrv_class_dev[0] = device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "led0"); /* /dev/ledwht */
-
- for(minor=1;minor<3;minor ++)
- leddrv_class_dev[minor] = device_create(leddrv_class, NULL, MKDEV(major, minor), NULL,
- return 0;
- }
- static void led_exit(void)
- {
- int minor;
-
- unregister_chrdev(major,"led");
- /*2.删除设备节点*/
- for(minor = 0; minor<3; minor++)
- device_destroy(leddrv_class, MKDEV(major, minor));
- class_destroy(leddrv_class);
- iounmap(ph_cfg2);
- iounmap(ph_dat);
- }
- module_init(led_init);
- module_exit(led_exit);
- MODULE_LICENSE("GPL");
复制代码 2.应用程序部分:- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- /* 测试方法
- * /led_test on
- * /led_test off
- */
- int main(int argc, char *argv[])
- {
- int fd;
- int val = 1;
- char* filename;
- if (argc != 3) {
- printf("usage:\n%s </dev/led?> <on|off>\n", argv[0]);
- return 0;
- }
- filename = argv[1];
- fd = open(filename, O_RDWR);
- if (fd < 0) {
- printf("open led failed.\n");
- return 0;
- }
- if (strcmp(argv[2], "on") == 0) {
- //开灯
- val = 1;
- }
- else if (strcmp(argv[2], "off") == 0) {
- //关灯
- val = 0;
- }
- write(fd, &val, 4);
- return 0;
- }
复制代码 3.show图ing
操作步骤如下
LED操作显示
|