驱动程序设计 驱动程序函数、驱动控制LED闪烁 7.7

驱动函数

.read() .write()

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4r8OiCcY-1689158444064)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20230707115028160.png)]

驱动程序

/*===============================================*   文件名称:mod.c*   创 建 者: memories*   创建日期:2023年07月06日*   描    述:have a nice day================================================*/
//1.header
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#define MA 300
#define MI 0static dev_t no = 0;
static unsigned count = 1;
static const char *name = "mydev";
static struct cdev mydev;
static char mbuf[32]={0};int myopen(struct inode *pi,struct file *pf)
{printk("kernel open\n");return 0;
}int myrelease(struct inode *pi,struct file *pf)
{printk("kernel close\n");return 0;
}
ssize_t myread (struct file *pf, char __user *ubuf, size_t len, loff_t *poff)
{memcpy(ubuf,mbuf,len);printk("now read\n");   return len;
}
ssize_t mywrite (struct file *pf, const char __user *ubuf, size_t len, loff_t *poff)
{memcpy(mbuf,ubuf,len);printk("%s\n",ubuf);printk("now write\n");    return len;
}
static const struct file_operations myfops={.release = myrelease,.open = myopen,.read = myread,.write = mywrite,};//文件操作集
//2.init/exit fun
static int myinit(void)
{int ret = 1;//up: kernel//1.registed 把设备对象注册到系统中no = MKDEV(MA,MI);//组合主次设备号ret = register_chrdev_region(no,count,name);if(ret != 0){printk("reg is error\n");return -1;}//2.init    设备初始化,抽象出来一个对象cdev_init(&mydev,&myfops);//3.add     添加设备ret = cdev_add(&mydev,no,count);if(ret != 0){unregister_chrdev_region(no,count);return -1;}//down:hardwareprintk("myinit ok\n");return 0;
}
static int myexit(void)
{cdev_del(&mydev);unregister_chrdev_region(no,count);printk("myexit ok\n");return 0 ;
}
//3.reg kernel
module_init(myinit);
module_exit(myexit);
//4.mod info
MODULE_LICENSE("GPL");

应用程序

/*===============================================
*   文件名称:mainopen.c
*   创 建 者: memories
*   创建日期:2023年07月06日
*   描    述:have a nice day
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc, char *argv[])
{ char wbuf[20]="12122122142";char rbuf[20]={0};int ret = 0;int fd = open("/dev/mydev",O_RDWR);if(fd < 0){printf("open failed fd is %d\n",fd);return -1;}write(fd,wbuf,5);ret = read(fd,rbuf,5);if(ret < 0){perror("read");return -1;}if(ret == 0){printf("read is finish\n");}printf("%s\n",rbuf);close(fd);return 0;
} 

memcpy()

ssize_t mywrite (struct file *pf, const char __user *ubuf, size_t len, loff_t *poff)
{memcpy(mbuf,ubuf,len);printk("%s\n",ubuf);printk("now write\n");    return len;
}
其中char __user *ubuf中的ubuf对应应用程序中 write(fd,wbuf,sizeof(wbuf))的wbuf,而不是对应fd中的内容ssize_t myread (struct file *pf, char __user *ubuf, size_t len, loff_t *poff)
{memcpy(ubuf,mbuf,len);printk("now read\n");   return len;
}
其中char __user *ubuf中的ubuf对应应用程序中 read(fd,rbuf,sizeof(rbuf))的rbuf,而不是对应fd中的内容void * memcpy(void * dest, const void *src, size_t n);

copy_to_user(),copy_from_user()

static inline long copy_from_user(void *to,const void __user * from, unsigned long n);
static inline long copy_to_user(void __user *to,const void *from, unsigned long n)
类似于memcopy,但比memcopy快

ioremap() , iounmap()

自定义命令去设置---->设备特有的功能
提前协商好一个命令:
eg:led_on
应用层:ioctl(fd,cmd,..)
驱动:unlocked_ioctl( cmd );if(cmd == led_on)执行led on;void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)void iounmap(volatile void __iomem *addr_in)

writel(),readl()

writel() 往内存映射的 I/O 空间上写数据,wirtel()  I/O 上写入 32 位数据 (4字节)readl() 从内存映射的 I/O 空间读取数据,readl 从 I/O 读取 32 位数据 ( 4 字节 )

驱动控制LED闪烁

  1. 用户需求:写一个led的驱动,实现led2的闪烁

  2. 驱动需求:设备:led2 功能:亮 、灭

  3. 寄存器操作:

    1. 原理图: 设备–>pin–>设备控制芯片

      ​ 驱动需求(led2亮灭) --> 设备需求(gpx1_1高/低电平)

    2. 芯片手册:设备控制芯片–>寄存器

    人 —> 二进制代码 —> CPU芯片 —> 设备控制芯片 —> 寄存器 —> 设备

  4. 编写驱动:

    //头文件

    //函数实现

    //函数注册

    //信息描述

驱动函数

/*===============================================*   文件名称:mod.c*   创 建 者: memories*   创建日期:2023年07月06日*   描    述:have a nice day================================================*/
//1.header
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "cmd.h"#define MA 300
#define MI 0static dev_t no = 0;
static unsigned count = 1;
static const char *name = "mydev";
static struct cdev mydev;
static char mbuf[32]={0};
static int *vaddr={0},*vaddr1={0};int myopen(struct inode *pi,struct file *pf)
{printk("kernel open\n");return 0;
}int myrelease(struct inode *pi,struct file *pf)
{printk("kernel close\n");return 0;
}
ssize_t myread (struct file *pf, char __user *ubuf, size_t len, loff_t *poff)
{int ret = 0;ret = copy_to_user(ubuf,mbuf,len);if(ret != 0)return -1;printk("now read\n");   return len;
}
ssize_t mywrite (struct file *pf, const char __user *ubuf, size_t len, loff_t *poff)
{int ret = 0;ret = copy_from_user(mbuf,ubuf,len);if(ret != 0)return -1;printk("now write\n");    return len;
}
long myioctl (struct file *pf, unsigned int cmd, unsigned long arg)
{switch(cmd){case LED_ON:printk("led on\n");writel(readl(vaddr1)|(0x1<<4),vaddr1);break;case LED_OFF:printk("led off\n");writel(readl(vaddr1)&~(0x1<<4),vaddr1);break;};return 0;
}static const struct file_operations myfops={.release = myrelease,.open = myopen,.read = myread,.write = mywrite,.unlocked_ioctl = myioctl,};//文件操作集
//2.init/exit fun
static int myinit(void)
{int ret = 1;//up: kernel//1.registed 把设备对象注册到系统中no = MKDEV(MA,MI);//组合主次设备号ret = register_chrdev_region(no,count,name);if(ret != 0){printk("reg is error\n");return -1;}//2.init    设备初始化,抽象出来一个对象cdev_init(&mydev,&myfops);//3.add     添加设备ret = cdev_add(&mydev,no,count);if(ret != 0){unregister_chrdev_region(no,count);return -1;}//down:hardwareprintk("myinit ok\n");//1.映射,内核的物理地址转换为虚拟地址paddr-->vaddrprintk("121212\n");vaddr = ioremap(GPF3CON,4);vaddr1 = ioremap(GPF3DAT,4);//2.dev initwritel((readl(vaddr)) & ~(0xf<<16) | (0x1<<16),vaddr);return 0;
}
static int myexit(void)
{//和内核相关cdev_del(&mydev);unregister_chrdev_region(no,count);printk("myexit ok\n");//和硬件相关//1.解除映射iounmap(vaddr);iounmap(vaddr1);return 0 ;
}
//3.reg kernel
module_init(myinit);
module_exit(myexit);
//4.mod info
MODULE_LICENSE("GPL");

应用函数

/*===============================================
*   文件名称:mainopen.c
*   创 建 者: memories
*   创建日期:2023年07月06日
*   描    述:have a nice day
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc, char *argv[])
{ char wbuf[20]="12122122142";char rbuf[20]={0};int ret = 0;int fd = open("/dev/mydev",O_RDWR);if(fd < 0){printf("open failed fd is %d\n",fd);return -1;}write(fd,wbuf,5);ret = read(fd,rbuf,5);if(ret < 0){perror("read");return -1;}if(ret == 0){printf("read is finish\n");}printf("%s\n",rbuf);close(fd);return 0;
} 
/*===============================================
*   文件名称:cmd.h
*   创 建 者: memories
*   创建日期:2023年07月07日
*   描    述:have a nice day
================================================*/
#ifndef __cmd_H_
#define __cmd_H_#define LED_ON  _IOW('L',0,int)//某个类型,第几个,转换类型
#define LED_OFF _IOW('L',1,int)
#define GPF3CON  0x114001E0
#define GPF3DAT  0x114001E4#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/19675.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CAN转EtherNet/IP网关ethernet/ip协议

JM-EIP-CAN 是自主研发的一款 ETHERNET/IP 从站功能的通讯网关。该产品主要功能是将各种 CAN 总线和 ETHERNET/IP 网络连接起来。 本网关连接到 ETHERNET/IP 总线中做为从站使用&#xff0c;连接到 CAN 总线中根据节点号进行读写。 技术参数 ETHERNET/IP 技术参数 网关做为 E…

快速构建一个 GitLab + Jenkins + Harbor 的云原生 DevOps 环境

今天我们要搭建一条怎样的工具链呢&#xff1f;且看效果图&#xff1a; GitLab Jenkins Harbor Toolchain Workflow 首先我们需要完成 GitLab、Jenkins 和 Harbor 三个工具的部署&#xff1b; 接着我们需要在 GitLab 上创建一个代码库&#xff0c;并且在 Jenkins 上创建相应…

38. QT在工控机Linux系统上调试机器人注意事项

1. QtCreator项目编译目录问题 当使用QtCreator创建一个新项目之后,对于代码编译产生的最终文件保存路径一般也会确定下来,QtCreator会帮助我们在同级目录下创建保存路径。例如下图:带有蓝色框的文件夹为项目源码,左侧的文件夹即为项目编译后产生的文件夹 如果在某种情况…

3ds Max 建模基础教程:创建棕榈植物

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 嘿伙计们&#xff0c;在本教程中&#xff0c;我们将学习如何使用其花盆创建棕榈植物&#xff0c;首先我们将对花盆进行建模&#xff0c;然后设置叶子和纹理&#xff0c;我从谷歌搜索中找到了纹理&#xff0…

我爱学QT-QT上位机开发之串口助手-上

学习链接&#xff1a; QT上位机开发之串口助手&#xff08;上&#xff09;_哔哩哔哩_bilibili 一.QT下的串口编程 1.qt下的串口编程 2.qt下的网络编程 3.qt下操作GPIO 二.仿写串口助手 步骤一.做好UI界面 接收窗口组件&#xff1a; 选择窗口组件&#xff1a; 发送窗口组…

CUDA笔记2

1.硬件理解 1.1对应 1.2 不一定是同时执行 例如只有13个sm,每个sm有128个core,而我们创建了1百万个threads,就要同步执行 因此&#xff0c;我们倾向于在block的x维设置为32的倍数,防止浪费warp warp id打印 #include <stdio.h> #include <stdlib.h>#include &qu…

Layui关于如何添加连接数据库的选项卡(三)

目录 1.实现效果&#xff1a; 2.思路&#xff1a; 3.PermissionDao类&#xff08;增加属性&#xff09; 4.主页&#xff1a;jsp 5.简洁风格修改选项卡的样式&#xff1a; 6.关于style中的属性设置使用 7.关于Element 组件介绍&#xff1a; 8. Layui 中的页面进行更新和…

MySQL基础篇第8章(聚合函数)

文章目录 1、聚合函数介绍1.1 AVG和SUM函数1.2 MIN和MAX函数1.3 COUNT函数 2、GROUP BY2.1 基本使用2.2 使用多个分组2.3 GROUP BY中使用WITH ROLLUP 3、HAVING3.1 基本使用3.2 WHERE和HAVING的对比 4、SELECT的执行过程4.1 查询的结构4.2 SELECT执行顺序4.3 SQL的执行原理 1、…

Leetcode-每日一题【147.对链表进行插入排序】

题目 给定单个链表的头 head &#xff0c;使用 插入排序 对链表进行排序&#xff0c;并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的&#xff0c;每次只移动一个元素&#xff0c;直到所有元素可以形成一个有序的输出列表。 每次迭代中&#xff0c;插入排序…

关于VUE报错“TypeError: Converting circular structure to JSON“

关于VUE报错“TypeError: Converting circular structure to JSON" 问题&#xff1a; [Vue warn]: Error in nextTick: "TypeError: Converting circular structure to JSON--> starting at object with constructor Vue| property $options -> object wit…

SonarQube安装、汉化及使用

一、环境准备 SonarQube下载&#xff1a;https://www.sonarqube.org/downloads/Java 11 或以上版本安装 多环境共存&#xff0c;指定 SonarQube 的java运行版本&#xff08;注意地址改为自己的java路径&#xff0c;最后面必须带java&#xff09;&#xff1a; 解压目录下 &#…

第二十八章:索引优化与优化查询

第二十八章&#xff1a;索引优化与优化查询 哪些维度可以进行数据库调优 索引失效、没有充分利用到索引 —— 索引建立关联查询太多JOIN(设计缺陷或不得已的需求) —— SQL优化服务器调优及各个参数设置(缓冲、线程数等) —— 调整my.cnf数据过多 —— 分库分表 虽然SQL查询…