22071班(11月18日)
创始人
2024-01-30 14:55:36

1.在串口工具进行输入:   
    echo 1 > /dev/myled0 ---->led1灯点亮
    echo 0 > /dev/myled0 ---->led1灯熄灭
    echo 1 > /dev/myled1 ---->led1灯点亮
    echo 0 > /dev/myled1 ---->led1灯熄灭
    echo 1 > /dev/myled2 ---->led1灯点亮
    echo 0 > /dev/myled2 ---->led1灯熄灭
要求:
    1)分部实现注册字符设备驱动
    2)自动创建设备节点
    3)通过结构体对led灯地址进行映射
    4)次设备号完成私有数据传参

driver.c:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "myled.h"#define CNAME "myled"struct cdev* cdev;
dev_t devnum;
struct device* dev;
struct class* cls;#if 0
unsigned int major = 0;
#else
unsigned int major = 500;
#endifint minor=1;
const int count=3;int k_open(struct inode *inode, struct file *file)
{//终端在传参时会打开对应的驱动文件,相当于调用了open和write函数,//inode结构体中存放着该驱动的设备号,次设备号不同,通过私有数据传参到write函数中进行判断file->private_data=(void*)MINOR(inode->i_rdev);printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t k_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t K_write (struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
{char ch;int ret;int kminjor;//接收终端传入的字符(控制led的亮灭)ret=copy_from_user(&ch,ubuf,sizeof(char));if(ret){printk("copy from user is error\n");return -EIO;}printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);//接收k_open函数传递的私有数据(次设备号)kminjor=(int)file->private_data;if(ch=='1'){if(kminjor==1){gpioe->ODR |= (0x1 << 10);}if(kminjor==2){gpiof->ODR |= (0x1 << 10);}if(kminjor==3){gpioe->ODR |= (0x1 << 8);}}else{if(kminjor==1){gpioe->ODR &= (~(0x1 << 10));}if(kminjor==2){gpiof->ODR &= (~(0x1 << 10));}if(kminjor==3){gpioe->ODR &= (~(0x1 << 8));}}return size;
}
int  k_close (struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
//初始化操作方法结构体
const struct file_operations fops=
{.open=k_open,.read=k_read,.write=K_write,.release=k_close,
};
//入口,安装驱动时执行
static int __init k_init(void)
{int ret,i;//分配字符设备驱动cdev=cdev_alloc();if(cdev==NULL){printk("cdev_alloc is error\n");ret=-EIO;goto ERR1;}//初始化设备驱动cdev_init(cdev,&fops);//申请设备号if(major>0){ret=register_chrdev_region(MKDEV(major,minor),count,CNAME);if(ret){printk("register_chrdev_region is error\n");ret=-ENOMEM;goto ERR2;}  }else{ret=alloc_chrdev_region(&devnum,1,count,CNAME);if(ret){printk("alloc_chrdev_region is error\n");ret=-ENOMEM;goto ERR2;}major=MAJOR(devnum);minor=MINOR(devnum);}//驱动的注册ret=cdev_add(cdev,MKDEV(major,minor),count);if(ret){printk("cdev add is error\n");ret = -EIO;goto ERR3;}//自动创建设备节点cls = class_create(THIS_MODULE,CNAME);if(IS_ERR(cls)) {printk("class create is error\n");ret = PTR_ERR(cls); goto ERR4;}for(i=1;i<=count;i++){dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);if(IS_ERR(dev)){printk("device create is error\n");ret = PTR_ERR(dev);goto ERR5;}}//RCC寄存器地址映射rcc=ioremap(RCC,4);if(NULL == rcc){printk("rcc ioremap is error\n");return -ENOMEM;}//GPIOE寄存器地址映射gpioe=ioremap(GPIOE,sizeof(gpio_t));if(NULL == gpioe){printk("gpioe ioremap is error\n");return -ENOMEM;}//GPIOF寄存器地址映射gpiof=ioremap(GPIOF,sizeof(gpio_t));if(NULL == gpiof){printk("gpiof ioremap is error\n");return -ENOMEM;}//LED1--->PE10引脚初始化*rcc|= (0x1 << 4);gpioe->MODER &= (~(0x3 << 20));gpioe->MODER |= (0x1 << 20);gpioe->ODR &= (~(0x1 << 10));// LED2--->PF10初始化*rcc|= (0x1 << 5);gpiof->MODER &= (~(0x3 << 20));gpiof->MODER |= (0x1 << 20);gpiof->ODR &= (~(0x1 << 10));//LED3--->PE8初始化*rcc|= (0x1 << 4);gpioe->MODER &= (~(0x3 << 16));gpioe->MODER |= (0x1 << 16);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(MKDEV(major,minor),count);
ERR2:kfree(cdev);
ERR1:return -EIO;
}
//出口,卸载驱动时执行
static void __exit k_exit(void)
{int i;//销毁设备节点信息for(i=1;i<=count;i++){device_destroy(cls,MKDEV(major,i));}//销毁目录信息class_destroy(cls);//驱动的注销cdev_del(cdev);//销毁设备号unregister_chrdev_region(MKDEV(major,minor),count);//释放cdev结构体kfree(cdev);//取消地址映射iounmap(rcc);iounmap(gpioe);iounmap(gpiof);
}module_init(k_init);
module_exit(k_exit);
MODULE_LICENSE("GPL");

myled.h:

#ifndef __MYLED__H__
#define __MYLED__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;
#define GPIOE 0x50006000
#define GPIOF 0x50007000
#define RCC 0x50000A28
volatile unsigned int* rcc;
gpio_t* gpioe;
gpio_t* gpiof;#endif

实验现象:

 串口工具如图:

 

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
最安全的匿名举报方式 匿名12... 来源:中安在线8月9日,河北邢台小伙张钊(化名)在河北政务服务网12345平台举报楼上邻居涉嫌非法开...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
中国光棍有多少人 2020年9... 我国是世界上人口最多的国家,庞大的人口基数为我国的发展带来了许多的益处。但是同时,我国也是出生人口性...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...