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灯熄灭

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "led.h"#define CNAME "myled"struct cdev* cdev;
struct class *cls;
struct device* dev;#if 1
unsigned int major=0;
#else
unsigned int majo=500;
#endif
int minor=0;
const int count=3;
char kbuf;volatile unsigned int* virt_rcc;
volatile gpio_t* virt_gpioe;
volatile gpio_t* virt_gpiof;int mycdev_open(struct inode *inode,struct file *file)
{dev_t i_rdev;dev_t i_minor;i_rdev=inode->i_rdev;                        //获取设备号i_minor = MINOR(i_rdev);                       //获取次设备号file->private_data = (void*)i_minor;           //私有数据传参printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *loffs)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loffs)
{int ret;if(size > sizeof(kbuf)) size = sizeof(kbuf);ret = copy_from_user(&kbuf,ubuf,size);minor=0;minor = (int)file->private_data;   //私有数据传参if(minor == 0)                     //操作灯1 PE10{if(kbuf == '1'){virt_gpioe->ODR |= (0x1 << 10); //led1输出高电平}else if(kbuf == '0'){virt_gpioe->ODR &= (~(0x1 << 10));//led1输出低电平}}else if(minor == 1) //操作灯2 PF10{if(kbuf == '1'){virt_gpiof->ODR |= (0x1 << 10); //led2输出高电平}else if(kbuf == '0'){virt_gpiof->ODR &= (~(0x1 << 10));//led2输出低电平}}else if(minor == 2)                       //操作灯3 PE8{if(kbuf == '1'){virt_gpioe->ODR |= (0x1 << 8);    //led3输出高电平}else if(kbuf == '0'){virt_gpioe->ODR &= (~(0x1 << 8)); //led3输出低电平}}//printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
int  mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
}
const struct file_operations fops={.open=mycdev_open,.read=mycdev_read,.write=mycdev_write,.release=mycdev_close,
};//入口
static int __init mycdev_init(void)
{int ret;dev_t devno;int i;//1.分配cdev结构体cdev=cdev_alloc();if(NULL==cdev){printk("cdev alloc is error\n");ret=-EIO;goto ERR1;}//2.初始化结构体cdev_init(cdev,&fops);//3.申请设备号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(&devno,0,count,CNAME);if(ret){printk("alloc chrdev region is error\n");ret = -ENOMEM;goto ERR2;}//获取主设备号major=MAJOR(devno);//获取次设备号minor=MINOR(devno);}//4.驱动的注册ret=cdev_add(cdev,MKDEV(major,minor),count);if(ret){printk("cdev add is error\n");ret = -EIO;goto ERR3;}//5.自动创建设备节点//向上层提交目录信息cls=class_create(THIS_MODULE,CNAME);if(IS_ERR(cls)){printk("class create is error\n");ret=PTR_ERR(cls);goto ERR4;}//向上层提交设备节点信息for(i=0;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;}}//2.将GPIOE和GPIOF物理地址映射为虚拟地址//1)将rcc地址进行映射virt_rcc = ioremap(PHY_RCC,4);if(NULL == virt_rcc){printk("rcc ioremap is error\n");return -ENOMEM;}//2)将GPIOE物理地址进行映射virt_gpioe = ioremap(GPIOE,sizeof(gpio_t));if(NULL == virt_gpioe){printk("gpio moder ioremap is error\n");return -ENOMEM;}//3)将GPIOF物理地址进行映射virt_gpiof = ioremap(GPIOF,sizeof(gpio_t));if(NULL == virt_gpiof){printk("gpio odr ioremap is error\n");return -ENOMEM;}//PE10----->LED1初始化*virt_rcc |= (0x1 << 4); //设置GPIOE组时钟使能virt_gpioe->MODER &= (~(0x3 << 20)); //设置PE10引脚为输出模式virt_gpioe->MODER |= (0x1  << 20);virt_gpioe->ODR &= (~(0x1 << 10)); //设置灯的初始化默认为低电平//PF10----->LED2初始化*virt_rcc |= (0x1 << 5); //设置GPIOF组时钟使能virt_gpiof->MODER &= (~(0x3 << 20)); //设置PF10引脚为输出模式virt_gpiof->MODER |= (0x1  << 20);virt_gpiof->ODR &= (~(0x1 << 10)); //设置灯的初始化默认为低电平//PE8----->LED3初始化virt_gpioe->MODER &= (~(0x3 << 16)); //设置PE8引脚为输出模式virt_gpioe->MODER |= (0x1  << 16);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(MKDEV(major,minor),count);
ERR2:kfree(cdev);
ERR1:return -EIO;
}
//出口
static void __exit mycdev_exit(void)
{int i;//1.销毁设备节点信息for(i=0;i<count;i++){device_destroy(cls,MKDEV(major,i));}//2.销毁目录信息class_destroy(cls);//3.驱动的注销cdev_del(cdev);//4.销毁设备号unregister_chrdev_region(MKDEV(major,minor),count);//5.释放cdev结构体kfree(cdev);
}
//指定入口地址
module_init(mycdev_init);
module_exit(mycdev_exit);
//指定出口地址
//许可证
MODULE_LICENSE("GPL");
#ifndef __LED_H__
#define __LED_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 PHY_RCC   0x50000A28#endif

22071驱动day5相关推荐

  1. 22071驱动day1

  2. 驱动笔记(自己总结的)

    vscode: https://note.youdao.com/ynoteshare/index.html?id=ea4796f0aa4344e11bae0d5bdfe32cc8&type=n ...

  3. 嵌入式Linux设备驱动程序:在运行时读取驱动程序状态

    嵌入式Linux设备驱动程序:在运行时读取驱动程序状态 Embedded Linux device drivers: Reading driver state at runtime 在运行时了解驱动程 ...

  4. 0、Spring 注解驱动开发

    0.Spring注解驱动开发 0.1 简介 <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作 ...

  5. 安装 Python MySQL 驱动(mysql-connector-python、MySQL-python)

    1. 安装 由于 MySQL 服务器以独立的进程运行,并通过网络对外服务,所以,需要支持 Python 的MySQL 驱动来连接到 MySQL 服务器. 目前,有两个MySQL驱动: mysql-co ...

  6. Linux驱动框架之framebuffer驱动框架

    1.什么是framebuffer? (1)framebuffer帧缓冲(一屏幕数据)(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备.帧缓冲 ...

  7. [Ubuntu] 安装/卸载 声卡驱动

    卸载 sudo apt-get --purge remove linux-sound-base alsa-base alsa-utils 安装 sudo apt-get install linux-s ...

  8. pci串口驱动安装失败_TSC TTP-243E Pluse装LTP并口驱动无法安装

    一.前言描述 接到客户报修说,电脑无法开机,即到哥上门维修立即安排人员到现场查看原因,到现场后,查看的确是电脑系统问题,重新安装系统,安装完成系统后,发现打印机无法使用.这个打印机型号是TSC TTP ...

  9. linux mipi驱动分析_寒武纪社招内推数字IC设计、DSI驱动、软件架构、产品经理、芯片架构、工具链开发、深度学习、FAE工程师...

    点击上方蓝字关注我吧! 为什么内推更靠谱?内推是基于人脉关系链的推荐,其背后有一定的信用背书,靠谱的人推荐的人相对也会比较靠谱,所以企业一般职位都是从内部开始分享的,相较于自己海投简历,内推的效率和成 ...

最新文章

  1. 流氓网站5599.net修改ie主页分析
  2. python输出数据格式_这串数据有什么方法用python输出我想要的格式?
  3. java静态路由_Linux添加静态路由两种实现方法解析
  4. 一款监控网络状态的好工具- Smokeping
  5. java outlook 发送邮件_基于java使用JavaMail发送邮件
  6. 组件注入 # 注入的属性_注入域对象而不是基础结构组件
  7. linux的NetworkManager服务(转)
  8. svg 自己做动画图片 GSAP真的好用
  9. 服务器项目白名单设置
  10. 本地上传文件到Linux云服务器
  11. 这些大佬告诉你,在先进计算与AI领域该往哪个方向冲!
  12. Unity 置顶点击的对象
  13. 双十一电商对决,拍拍微店这次会怎么玩?
  14. 【线性代数·浅学】(一)行列式——n阶行列式定义,行列式性质,行列式展开定理,拉普拉斯定理,范德蒙德行列式,克拉默法则
  15. mysql大小写转换函数_MySQL字母大小写转换函数UPPER(s)、UCASE(s)、LOWER(s)和LCASE(s)
  16. 换肤 技术 (转载)
  17. MySQL插入数据时,如果记录不存在则insert,如果存在则update
  18. 分布式事务的BASE理论
  19. DUM 与 SIPstack多线程
  20. C语言《位段结构体、联合体》

热门文章

  1. xpdf转换pdf文件
  2. 提示“windows无法配置此无线连接,如果您已经起用其他程序管理此无线连接,请使用该软件.....”解决方法
  3. java mail 保存邮件_JavaMail保存为草稿邮件
  4. 用递归方法建立二叉树
  5. html之文本框的onkeydown()响应Enter键——键盘事件
  6. java+磁盘io监控_jmeter服务器监控磁盘IO、网络-PerfMon Metrics Collector
  7. stylus在vue中的安装及使用
  8. c语言arctan函数输出角度,请问反正切函数arctanx用c语言怎么表示?
  9. MongoDB Sharding
  10. 金蝶应收应付模块流程_金蝶KIS财务业务模块操作流程[整理版]