绑定设备文件与设备

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");

相关推荐
riveting21 分钟前
SD2351核心板:重构AI视觉产业价值链的“超级节点”
大数据·linux·图像处理·人工智能·重构·智能硬件
易保山1 小时前
MIT6.S081 - Lab10 mmap(文件&内存映射)
linux·操作系统·c
NoneCoder1 小时前
HTML 模板技术与服务端渲染
服务器·servlet·html
禅与Bug的修复艺术1 小时前
JAVA后端开发常用的LINUX命令总结
java·linux·面试·java面试·后端开发·java后端·面试经验
Cloud_Air7541 小时前
从零开始使用SSH链接目标主机(包括Github添加SSH验证,主机连接远程机SSH验证)
运维·ssh
李詹2 小时前
Steam游戏服务器攻防全景解读——如何构建游戏级抗DDoS防御体系?
服务器·游戏·ddos
你熬夜了吗?2 小时前
spring中使用netty-socketio部署到服务器(SSL、nginx转发)
服务器·websocket·spring·netty·ssl
joke_xiaoli2 小时前
tomcat Server 连接服务器 进展
java·服务器·tomcat
Hello.Reader2 小时前
基于 Nginx 的 WebSocket 反向代理实践
运维·websocket·nginx
北冥有鱼被烹2 小时前
【微知】/proc中如何查看Linux内核是否允许加载内核模块?(/proc/sys/kernel/modules_disabled)
linux·服务器