9.13作业

#include <linux/init.h>

#include <linux/module.h>

#include <linux/cdev.h>

#include <linux/fs.h>

#include <linux/device.h>

#include <linux/uaccess.h>

#include <linux/slab.h>

struct cdev *cdev

char kbuf[128]=0;

unsigned int major=0;

unsigned int minor=0;

dev_t devno;

module-param(major,unit,0664); //方便在命令行传递major的值

struct class*cls;

struct device *dev;

struct mutex mutex; //定义互斥体

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

{

mutex_lock(&mutex);//上锁

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

return 0;

}

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

{

int which;

//获取arg对应的用户空间中的值

int ret=copy_from_user(&which,(void *)arg,4);

if(ret)

{

printk("从用户空间获取数据失败\n");

return -EIO;

}

switch (cmd)

{

case LED_ON:

switch(which)

{

case 1: //LED1

vir_led1->ODR |= 1 << 10;

break;

case 2:

vir_led2->ODR |= 1 << 10;

break;

case 3:

vir_led3->ODR |= 1 << 8;

break;

}

break;

case LED_OFF:

switch(which)

{

case 1: //LED1

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

break;

case 2:

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

break;

case 3:

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

break;

}

break;

}

return 0;

}

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

{

mutex_unlock(mutex);//解锁

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

return 0;

}

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

struct file_operation fops={

.open=mycdev_open,

.read=mycdev_read,

.write=mycdev_write,

.realease=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) |= (0x3<<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_led3->MODER |= (1<<16;

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

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

return 0;

}

static int __init mycdev_init(void)

{

int ret;

//为字符设备驱动对象申请空间

cdev=cdev_alloc();

if(cdev==NULL)

{

printk(" 字符设备驱动对象申请空间失败\n");

ret=-EFAULT;

goto out1;

}

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

//初始化字符设备驱动对象

cdev------init(cdev,&fops);

//申请设备号

if(major>0)//静态指定设备号

{

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

if(ret)

{

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

goto out2;

}

}

else if(major==0)//动态申请设备号

{

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

if(ret)

{

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

goto out2;

}

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

major=MINOR(devno);//获取次设备号

}

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

mutex_init(&mutex);//初始化互斥体

//字符设备驱动对象注册

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

if(ret)

{

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

goto out3;

}

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

//寄存器映射以及初始化

all_led_init();

//向上提交目录

cls=class_create(THIS_MODULE,"myled");

if(IS_ERR(cls))

{

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

return -PTR_ERR(cls);

goto out4;

}

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

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

int i;

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

{

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

if(IS_ERR(dev))

{

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

return -PTR_ERR(dev);

}

}

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

return 0;

}

out5:

//释放前一次提交成功的设备信息

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

{

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

}

class_destory(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;

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

{

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

}

//销毁目录信息

class_destory(cls);

//取消地址映射

iounmap(vir_led1);

iounmap(vir_led2);

iounmap(vir_rcc);

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

cdev_del(cdev);

//释放设备号

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

//释放对象空间

kfree(cdev);

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

相关推荐
无限进步_16 小时前
深入理解 C/C++ 内存管理:从内存布局到动态分配
c语言·c++·windows·git·算法·github·visual studio
liu****17 小时前
9.二叉树(一)
c语言·开发语言·数据结构·算法·链表
铁手飞鹰17 小时前
[HAL库分析—GPIO]
c语言·stm32·单片机·嵌入式硬件
水饺编程17 小时前
第3章,[标签 Win32] :处理 WM_PRINT 消息
c语言·c++·windows·visual studio
虚假程序设计18 小时前
pythonnet 调用C接口
c语言·python
松涛和鸣19 小时前
DAY27 Linux File IO and Standard IO Explained: From Concepts to Practice
linux·运维·服务器·c语言·嵌入式硬件·ubuntu
myw07120520 小时前
湘大oj-数码积性练习笔记
c语言·数据结构·笔记·算法
了一梨20 小时前
网络编程:TCP Socket
linux·c语言·tcp/ip
EXtreme3520 小时前
【数据结构】手撕队列(Queue):从FIFO底层原理到高阶应用的全景解析
c语言·数据结构·链表·队列
程序喵大人20 小时前
Duff‘s device
c语言·开发语言·c++