
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include "mycdev.h"
- #define CNAME "myled"
- struct cdev *cdev;
- struct class *cls;
- struct device *device;
- dev_t dev;
- int *virt_RCC;
- gpio_t *virt_GPIOE;
- gpio_t *virt_GPIOF;
- unsigned int major;
- unsigned int minor = 0;
- unsigned int count=3;
- char buf[128]={0};
- int myc_open(struct inode *inode, struct file *file)
- {
- minor = MINOR(inode->i_rdev);
- file->private_data = (void*)minor;
-
- return 0;
- }
- ssize_t myc_read(struct file *file, char __user *user, size_t size, loff_t *ft)
- {
- return 0;
- }
- ssize_t myc_write(struct file *file, const char __user *user, size_t size, loff_t *ft)
- {
- int ret;
- minor = ((int*)file->private_data);
- if(size > sizeof(user)) size = sizeof(buf);
- ret = copy_from_user(buf,user,sizeof(user));
- if(ret)
- {
- printk("copy from user is error\n");
- return -EIO;
- }
- switch(minor)
- {
- case LED1:
- if(buf[0]=='1')
- {
- virt_GPIOE->ODR |=(0x1<<10);
- }
- else
- {
- virt_GPIOE->ODR &=(~(0x1<<10));
- }
- break;
-
- case LED2:
- if(buf[0]=='1')
- {
- virt_GPIOF->ODR |=(0x1<<10);
- }
- else
- {
- virt_GPIOF->ODR &=(~(0x1<<10));
- }
- break;
- case LED3:
- if(buf[0]=='1')
- {
- virt_GPIOE->ODR |=(0x1<<8);
- }
- else
- {
- virt_GPIOE->ODR &=(~(0x1<<8));
- }
- break;
- }
- return 0;
- }
- int myc_close(struct inode *inode, struct file *file)
- {
- return 0;
- }
- const struct file_operations fops ={
- .open=myc_open,
- .read=myc_read,
- .write=myc_write,
- .release=myc_close,
- };
- static int __init mycdev_init(void)
- {
- int ret;
- int i;
- //映射虚拟地址
- virt_RCC = ioremap(RCC_ENABLE,sizeof(int));
- virt_GPIOE = ioremap(GPIOE,sizeof(gpio_t));
- virt_GPIOF = ioremap(GPIOF,sizeof(gpio_t));
- //1.分配cdev结构体
- cdev = cdev_alloc();
- if(NULL == cdev)
- {
- printk("cdev alloc is error\n");
- printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
- ret = -EIO;
- goto ERR1;
- }
- //2.初始化结构体
- cdev_init(cdev,&fops);
- //3.申请设备号
- ret = alloc_chrdev_region(&dev,minor,count,CNAME);
- if(ret)
- {
- printk("alloc chrdev region is filed\n");
- printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
- ret = -ENOMEM;
- goto ERR2;
- }
- //4.驱动的注册
- ret = cdev_add(cdev,dev,count);
- if(ret)
- {
- printk("cdev add is filed\n");
- printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
- ret = -ENOMEM;
- goto ERR3;
- }
- //5.自动创建设备节点
- //向上层提交目录信息
- cls = class_create(THIS_MODULE,CNAME);
- if(IS_ERR(cls))
- {
- printk("class create is failed\n");
- ret = PTR_ERR(cls);
- goto ERR4;
- }
- //向上层提交设备节点
- major = MAJOR(dev);
- minor = MINOR(dev);
- for(i=0;i
- {
- device = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
- if(IS_ERR(device))
- {
- printk("device create is error\n");
- ret = PTR_ERR(device);
- goto ERR5;
- }
- }
- //LED灯初始化
- //将PE10引脚初始化
- //RCC使能
- *virt_RCC |=(0x1<<4);
- //将GPIOE_MODER设置为输出模式
- virt_GPIOE->MODER &=(~(0x3<<20));
- virt_GPIOE->MODER |=(0x1<<20);
- //将GPIOE_ODR设置为低电平
- virt_GPIOE->ODR &=(~(0x1<<10));
- //将PF10引脚初始化
- //RCC使能
- *virt_RCC |=(0x1<<5);
- //将GPIOE_MODER设置为输出模式
- virt_GPIOF->MODER &=(~(0x3<<20));
- virt_GPIOF->MODER |=(0x1<<20);
- //将GPIOE_ODR设置为低电平
- virt_GPIOF->ODR &=(~(0x1<<10));
- //将PE8引脚初始化
- //RCC使能
- *virt_RCC |=(0x1<<4);
- //将GPIOE_MODER设置为输出模式
- virt_GPIOE->MODER &=(~(0x3<<16));
- virt_GPIOE->MODER |=(0x1<<16);
- //将GPIOE_ODR设置为低电平
- virt_GPIOE->ODR &=(~(0x1<<8));
- return 0;
- ERR5:
- for(--i;i>=0;i--)
- {
- device_destroy(cls,MKDEV(major,i));
- }
- class_destroy(cls);
- ERR4:
- cdev_del(cdev);
- ERR3:
- unregister_chrdev_region(dev,count);
- ERR2:
- kfree(cdev);
- ERR1:
- return -EIO;
- }
- static void __exit mycdev_exit(void)
- {
- int i;
- //取消映射
- iounmap(virt_GPIOE);
- iounmap(virt_GPIOF);
-
- //1.销毁设备节点信息
- for(i=0;i
- {
- device_destroy(cls,MKDEV(major,i));
- }
- //2.销毁目录信息
- class_destroy(cls);
- //3.驱动的注销
- cdev_del(cdev);
- //4.销毁设备号
- unregister_chrdev_region(dev,count);
- //5.释放cdev结构体
- kfree(cdev);
- }
- module_init(mycdev_init);
- module_exit(mycdev_exit);
- MODULE_LICENSE("GPL");
- #ifndef __MYCDEV_H__
- #define __MYCDEV_H__
- typedef struct{
- volatile unsigned int MODER;
- volatile unsigned int OTYPER;
- volatile unsigned int OSPEEDR;
- volatile unsigned int PUPDR;
- volatile unsigned int IDR;
- volatile unsigned int ODR;
- }gpio_t;
- typedef enum{
- LED1,
- LED2,
- LED3
- }led_t;
- #define RCC_ENABLE 0x50000A28
- #define GPIOE 0x50006000
- #define GPIOF 0x50007000
- #endif
- #指定架构变量名
- ARCH?=x86
- #指定编译文件名
- modname?=demo
-
- ifeq ($(ARCH),arm)
- #定义一个变量,存放linux内核源码的路径,编译完成之后,生成ARM架构,在开发板运行
- KERNEDIR:=/home/ubuntu/linux-5.10.61
- else
- #定义一个变量,存放ubuntu中linux内核源码的路径,编译完成之后,生成X86架构,在开发板运行
- KERNEDIR:=/lib/modules/$(shell uname -r)/build
- endif
- #PWD是自己定义的一个变量,$(shell pwd)开启一个终端,执行pwd命令,将执行的结果赋值给PWD变量
- PWD:=$(shell pwd)
- KBUILD_EXTRA_SYMBOLS:=/home/ubuntu/驱动/drivers/mydriver/02_EXPORT/demoA/Module.symvers
- all:
- make -C $(KERNEDIR) M=$(PWD) modules
- clean:
- make -C $(KERNEDIR) M=$(PWD) clean
- #指定模块化方式编译的文件
- obj-m:=$(modname).o
现象实现:
LED1:

LED2:


LED3:
-
相关阅读:
java中String,StringBuilder,StringBuffer实现原理,优化
STM32F103实现激光测距传感器测距WT-VL53L0 L1
手把手教你用nodejs+SQL Server2012做增删改查
Python 推导式
增速冠军 | 超云AI与信创实践典范,引领IDC中国服务器市场
adb调试系统app
蓝/紫/红色光油溶性钙钛矿/近红外发射光油溶性PbS/CdS量子点制备
【React】表单
【最佳实践】瀚高数据库企业版v6.0.2在Centos7.8安装过程
苹果Mac优化清理工具CleanMyMac X2023版本
-
原文地址:https://blog.csdn.net/qq_58538047/article/details/127936732