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

相关推荐
云泽8085 小时前
STM32 USART 详解(八):C I/O 串口重定向原理与实现
c语言·stm32·嵌入式硬件
ThornArmor5 小时前
重铸1996|肉体渲染:关节的裂缝:分段模型积木拼装与未成熟的 RSP 矩阵骨骼动画形变
c语言·汇编·c++·python·硬件架构·游戏机
T1mzhou5 小时前
ARM64 Linux 6.10 内核驱动(12):dd.c:probe/ remove、延迟 probe
linux·服务器·c语言·arm开发·arm
白色的北极熊7 小时前
c语言 scanf 输入流有空格,逗号 说明
c语言
Logic1017 小时前
C语言/数据结构位运算题解:异或XOR找出货船中的“独特载货量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
xx~t11 小时前
嵌入式——51单片机3
linux·c语言·嵌入式硬件·51单片机
山下梅子酒22512 小时前
洛谷-入门-B2042
c语言
ysu_031412 小时前
08-二叉树遍历:四种方式详解
c语言·数据结构·算法·leetcode
ocean210312 小时前
2025-2026年C语言专题面试高频知识点洞察
c语言·面试·面试经验
Lzh编程小栈13 小时前
STM32 DMA深度解析|原理、完整工作流程、寄存器、中断联动,嵌入式面试高频考点(F1系列)
c语言·stm32·单片机·mcu·面试