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

相关推荐
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
xiaobobo333011 小时前
C语言中宏定义宏名和宏值之间的关系
c语言·宏定义·语义型
a44931536215 小时前
MacBook USB-C不充电故障诊断:从PD握手到主板供电链路
c语言·开发语言·macos·电脑
a44931536216 小时前
iPhone 充电故障的全链路诊断——从 Lightning/USB-C 接口到 Tristar 充电 IC
c语言·macos·ios·电脑·硬件架构·iphone
qq_4480111616 小时前
C语言中的getchar()
c语言·开发语言
天空'之城16 小时前
C 语言工业级通用组件手写 15:累加和校验
c语言·嵌入式开发·工业级组件·累加和校验
碎光拾影1 天前
i.MX6ULL时钟系统配置指南
c语言·arm开发·嵌入式硬件
GeekArch1 天前
第28讲:避坑——AI堆栈分配错误、栈溢出BUG
c语言·人工智能·stm32·mcu·学习·bug
wuyk5551 天前
59.嵌入式C语言高级宏定义实战:多行宏、字符串化与符号拼接
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网·51单片机
无相求码1 天前
C程序的内存到底怎么分的?栈、堆、全局区一张图讲清楚
c语言