绑定设备文件与设备

head.h

#ifndef HEAD_H

#define HEAD_H

typedef struct

{

unsigned int MODER;

unsigned int OTYPER;

unsigned int OSPEEDR;

unsigned int PUPDR;

unsigned int IDR;

unsigned int ODR;

} gpio_t;

#define PHY_LED1_ADDR 0X50006000

#define PHY_LED2_ADDR 0X50007000

#define PHY_LED3_ADDR 0X50006000

#define PHY_RCC_ADDR 0X50000A28

#define LED_ON _IOW('l',1,int)

#define LED_OFF _IOW('l',0,int)

#endif

test.c

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include<sys/ioctl.h>

#include <fcntl.h>

#include <unistd.h>

#include <string.h>

#include"head.h"

int main(int argc,const char * argv[])

{

char buf[128]={0};

int a,b;

printf("打开设备文件成功\n");

while(1)

{

//从终端读取

int fd;

printf("请选择要控制的灯:1(LED1)2(LED2)3(LED3)\n");

printf("请输入>");

scanf("%d",&a);

printf("请输入要实现的功能 ");

printf("0(关灯) 1(开灯)\n");

printf("请输入>");

scanf("%d",&b);

switch(a)

{

case 1:

fd=open("/dev/mycdev0",O_RDWR);

if(fd < 0)

{

printf("打开设备文件失败\n");

return -1;

}

if(b==1)

ioctl(fd,LED_ON,&b);

else if(b==0)

ioctl(fd,LED_OFF,&b);

else

b=0;

break;

case 2:

fd=open("/dev/mycdev1",O_RDWR);

if(fd < 0)

{

printf("打开设备文件失败\n");

return -1;

}

if(b==1)

ioctl(fd,LED_ON,&b);

else if(b==0)

ioctl(fd,LED_OFF,&b);

else

b=0;

break;

case 3:

fd=open("/dev/mycdev2",O_RDWR);

if(fd < 0)

{

printf("打开设备文件失败\n");

return -1;

}

if(b==1)

ioctl(fd,LED_ON,&b);

else if(b==0)

ioctl(fd,LED_OFF,&b);

else

b=0;

break;

}

close(fd);

}

return 0;

}

mycdev.c

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/uaccess.h>

#include <linux/io.h>

#include<linux/device.h>

#include<linux/cdev.h>

#include<linux/slab.h>

#include"head.h"

char kbuf[128]={0};

gpio_t *vir_led1;

gpio_t *vir_led2;

gpio_t *vir_led3;

unsigned int *vir_rcc;

struct cdev *cdev;

unsigned int major=0;

unsigned int minor=0;

dev_t devno;

struct class *cls;

struct device *dev;

int mycdev_open(struct inode *inode, struct file *file)

{

int min=MINOR(inode->i_rdev);//获取打开的的文件的次设备号

file->private_data= (void *)min;

printk("%s:%s:%d\n", FILE, func, LINE);

return 0;

}

long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

int min=(int)file->private_data;//获取到文件的次设备号

switch(min)

{

case 0://操作LED1

switch(cmd)

{

case LED_ON://开灯

vir_led1->ODR |= (0X1<<10);

break;

case LED_OFF: //关灯

vir_led1->ODR &= (~(0X1<<10));

break;

}

break;

case 1://操作LED2

switch(cmd)

{

case LED_ON://开灯

vir_led2->ODR |= (0X1<<10);

break;

case LED_OFF: //关灯

vir_led2->ODR &= (~(0X1<<10));

break;

}

break;

case 2://操作LED3

switch(cmd)

{

case LED_ON://开灯

vir_led3->ODR |= (0X1<<10);

break;

case LED_OFF://关灯

vir_led3->ODR &= (~(0X1<<10));

break;

}

break;

}

printk("%s:%s:%d\n", FILE, func, LINE);

return 0;

}

int mycdev_close(struct inode *inode, struct file *file)

{

printk("%s:%s:%d\n", FILE, func, LINE);

return 0;

}

// 定义操作方法结构体变量并赋值

struct file_operations fops = {

.open = mycdev_open,

.unlocked_ioctl = mycdev_ioctl,

.release = mycdev_close,

};

int all_led_init(void)

{

//寄存器地址的映射

vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));

if(vir_led1==NULL)

{

printk("ioremap filed:%d\n",LINE);

return -ENOMEM;

}

vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));

if(vir_led2==NULL)

{

printk("ioremap filed:%d\n",LINE);

return -ENOMEM;

}

vir_led3=vir_led1;

vir_rcc=ioremap(PHY_RCC_ADDR,4);

if(vir_rcc==NULL)

{

printk("ioremap filed:%d\n",LINE);

return -ENOMEM;

}

printk("物理地址映射成功\n");

//寄存器的初始化

//rcc

(*vir_rcc) |= (3<<4);

//led1

vir_led1->MODER &= (~(3<<20));

vir_led1->MODER |= (1<<20);

vir_led1->ODR &= (~(1<<10));

//led2

vir_led2->MODER &= (~(3<<20));

vir_led2->MODER |= (1<<20);

vir_led2->ODR &= (~(1<<10));

//led3

vir_led3->MODER &= (~(3<<16));

vir_led1->MODER |= (1<<16);

vir_led1->ODR &= (~(1<<8));

printk("寄存器初始化成功\n");

return 0;

}

static int __init mycdev_init(void)

{

int ret;

//申请一个对象空间 cdev_alloc

cdev=cdev_alloc();

if(cdev==NULL)

{

printk("申请对象空间失败\n");

ret=-EFAULT;

goto out1;

}

printk("申请对象空间成功\n");

//初始化对象 cdev_init

cdev_init(cdev, &fops);

//申请设备号

if (major==0)

{

ret=alloc_chrdev_region(&devno, minor, 3,"mychrdev");

if(ret)

{

printk("动态申请设备号失败\n");

goto out2;

}

major=MAJOR(devno);//根据设备获取主设备号

minor=MINOR(devno);//根据设备获取次设备号

printk("字符主设备驱动注册成功:major=%d\n",major);

printk("字符次设备驱动注册成功:minor=%d\n",minor);

}

else

{

ret=register_chrdev_region(MKDEV(major,minor),3,"mychrdev");

if(ret)

{

printk("静态申请设备号失败\n");

goto out2;

}

}

printk("设备号申请成功\n");

//注册驱动对象

ret=cdev_add(cdev,MKDEV(major,minor),3);

if(ret)

{

printk("注册设备驱动对象失败\n");

goto out3;

}

printk("注册设备驱动对象成功\n");

//向上提交目录

cls=class_create(THIS_MODULE,"mychrdev");

if(IS_ERR(cls))

{

printk("向上提交目录失败\n");

goto out4;

}

printk("向上提交目录成功\n");

//向上提交设备节点信息

int i;

for(i=0;i<3;i++)

{

dev=device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i);

if(IS_ERR(dev))

{

printk("向上提交设备节点失败\n");

goto out5;

}

}

printk("向上提交设备节点成功\n");

all_led_init();

return 0;

out5:

//将提交成功的信息释放

for(--i;i>=0;i--)

{

device_destroy(cls,MKDEV(major,i));

}

//将提交失败的信息销毁

class_destroy(cls);

out4:

cdev_del(cdev);

out3:

unregister_chrdev_region(MKDEV(major,minor),3);

out2:

kfree(cdev);

out1:

return ret;

}

static void __exit mycdev_exit(void)

{

//销毁设备节点信息

int i;

iounmap(vir_led1);

iounmap(vir_led2);

iounmap(vir_led3);

iounmap(vir_rcc);

for(i=0;i<3;i++)

{

device_destroy(cls,MKDEV(major,i));

}

//销毁目录

class_destroy(cls);

//注销字符设备驱动对象空间

cdev_del(cdev);

//释放设备号

unregister_chrdev_region(MKDEV(major,minor),3);

//释放申请到的字符设备驱动对象空间

kfree(cdev);

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

相关推荐
小O_好好学18 分钟前
CentOS 7文件系统
linux·运维·centos
哲伦贼稳妥41 分钟前
一天认识一个硬件之机房地板
运维·网络·经验分享·其他
john_hjy1 小时前
11. 异步编程
运维·服务器·javascript
x晕x1 小时前
Linux dlsym符号查找疑惑分析
linux·运维·服务器
活跃的煤矿打工人2 小时前
【星海saul随笔】Ubuntu基础知识
linux·运维·ubuntu
北京智和信通2 小时前
云平台和虚拟化智慧运维监控,全面提升故障感知与处置能力
运维·虚拟化·云平台·虚拟机监控
fasewer2 小时前
第五章 linux实战-挖矿 二
linux·运维·服务器
楚灵魈3 小时前
[Linux]从零开始的网站搭建教程
linux·运维·服务器
小小不董3 小时前
《Linux从小白到高手》理论篇:深入理解Linux的网络管理
linux·运维·服务器·数据库·php·dba
豆豆3 小时前
为什么用PageAdmin CMS建设网站?
服务器·开发语言·前端·php·软件构建