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

news2024/12/24 9:00:35

驱动函数

.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 0

static 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:hardware
    printk("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 0

static 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:hardware
    printk("myinit ok\n");
    //1.映射,内核的物理地址转换为虚拟地址paddr-->vaddr
    printk("121212\n");
    vaddr = ioremap(GPF3CON,4);
    vaddr1 = ioremap(GPF3DAT,4);
    //2.dev init
    writel((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.coloradmin.cn/o/745342.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GPU调研之TensorFlow Benchmarks测试GPU

目录 1. 查看服linux服务器信息 2. Linux系统安装pip详细步骤 3. Centos安装python3 4. 安装TensorFlow 5. TensorFlow测试结果解读 6. 参考文档 gpu的占用率为99%&#xff0c;是一种比较正常的使用状态。 gpu是图形处理器的简称&#xff0c;又称显示核心、视觉处理器、…

Java 生成图片验证码

图片验证码使用场景 登录注册&#xff1a;可以区分机器和人类的一种手段&#xff0c;其最大的作用是为了防止机器人程序暴力登录或攻击短信发送&#xff1a;可以有效避免客户网站或APP遭到恶意攻击、预防资金损失 实现方式 1.添加Maven依赖 <dependency><groupId&g…

智能制造与低代码开发:数智时代的强力合击!

说在前面 在当今数智时代的浪潮中&#xff0c;智能制造正在成为制造业的发展焦点。随着科技的不断进步和创新&#xff0c;智能制造为企业带来了全新的发展机遇和挑战。那么&#xff0c;数智时代下的制造业到底是怎样的一个发展盛况&#xff1f;智能制造的新 趋势又是如何展现的…

华为云Astro低代码平台关键能力技术浅析

1 背景介绍 低代码开发基于可视化开发的概念&#xff0c;结合了云原生和多终端体验技术&#xff0c;它可以在大多数业务场景中&#xff0c;帮助企业显著的提升效率。同时为专业开发者提供了一种全新的高生产力开发方式&#xff0c;让不懂代码的人通过“拖拉拽”开发组件来完成…

823. 排列

链接&#xff1a; 链接 题目&#xff1a; 给定一个整数 nn&#xff0c;将数字 1∼n1∼n 排成一排&#xff0c;将会有很多种排列方法。 现在&#xff0c;请你按照字典序将所有的排列方法输出。 输入格式 共一行&#xff0c;包含一个整数 nn。 输出格式 按字典序输出所有排列方案…

图像处理|思维导图|期末资料分享

关于这些思维导图 都是博主期末考试之前临时抱佛脚的时候整理的资料&#xff0c;内容涵盖应该是比较全面&#xff0c;比较详细的。资料博主都放在了Github的链接里面&#xff0c;需要的伙伴自行上我的Github下载就行。 ImageProcessing-MindMapshttps://github.com/Yufccode/…

亚马逊云科技为企业提供一站式的出海策略,为企业保驾护航

走出国门&#xff0c;寻找新的盈利空间、优化资源配置、实现创新突破&#xff0c;已经成为中国企业的战略共识。如何进行全球化布局、本地化运营&#xff0c;实现高质量出海&#xff0c;是出海企业共同面临的课题。在【潮向新世界】出海日活动上&#xff0c;亚马逊云科技分享了…

单调队列算法

原文链接&#xff1a;https://blog.csdn.net/xzerui/article/details/118684260 一、基本概念 单调队列是指&#xff1a;单调递增或单调递减的队列。所以它也有如下几个性质&#xff1a; 1.队列中的元素在原来的列表中的位置是由前往后的(随着循环顺序入队)。 2.队列中元素的…

请求响应-响应-@ResponseBody统一响应结果

ResponseBody 类型&#xff1a;方法注解&#xff0c;类注解位置&#xff1a;Controller方法上/类上作用&#xff1a;将方法返回值直接响应&#xff0c;如果返回类型是 实体对象/集合&#xff0c;将会转化为JSON格式数据后再响应说明&#xff1a;RestController Controller R…

【unity细节】为什么有时候修改了脚本中的数据但是面板中的数据还是不改变

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;unity细节和bug ⭐为什么有时候修改了脚本中的数据但是面板中的数据还是不改变⭐ 文章目录 ⭐为什…

视频直播点播平台EasyDSS增加首次登录强制修改密码等新功能

EasyDSS视频直播点播平台支持Flash、H5播放&#xff0c;可提供一站式的视频推拉流、转码、点播、直播、时移回放、存储等服务&#xff0c;支持播放H.265编码视频&#xff0c;可兼容多操作系统。搭配RTMP高清摄像头使用&#xff0c;可将设备的实时流推送到平台上&#xff0c;实现…

java 线程安全问题

一、多线程带来的问题 多线程主要解决效率问题&#xff0c;但是也带来了线程安全问题。 例如两个线程 A 和 B 同时启动执行 400 次 m m 1&#xff0c;期待 800 &#xff0c;实际 m 的结果不一定正确&#xff0c;如下&#xff1a; public static void test1() throws Interr…

【C语言】字符函数和字符串函数(一)—>库函数的介绍与模拟实现

目录 前言&#xff1a; 一、函数介绍&#xff1a; &#xff08;一&#xff09;求字符串长度 &#xff08;1&#xff09;strlen &#xff08;二&#xff09;长度不受限制的字符串函数 &#xff08;2&#xff09;strcpy &#xff08;3&#xff09;strcat &#xff08;4&a…

什么是HTML5?HTML5的含义、元素和好处

HTML5是超文本标记语言(HTML)的第五版&#xff0c;网络浏览器使用它来可视化代码。它在网站功能、网页内容开发等方面有一些改进。 HTML的发展 在万维网的早期&#xff0c;主要的网络浏览器创造者&#xff08;例如微软Internet Explorer和Mosaic Netscape&#xff09;开发了特…

std::thread和std::mutex

std::thread std::thread用来创建一个线程&#xff1a; #include <thread>void threadFun(int temp) {int i 0; }int main() {std::thread t1(threadFun, 100);t1.join();//t1.detach();return 0; }创建了一个名为t1的线程&#xff0c;调用join方法阻塞等待线程退出&a…

【leetcode】61. 旋转链表 (python)

题目链接&#xff1a;61.旋转链表 写法一&#xff1a;暴力 class Solution(object):def rotateRight(self, head, k):""":type head: ListNode:type k: int:rtype: ListNode"""# 暴力&#xff1a;每次移动一个&#xff0c;时间复杂度 O(N^2)&am…

详解汽车电磁悬架(上)

摘要&#xff1a; 从汽车发明之日起&#xff0c;人们对于汽车平稳行驶的追求步伐就不曾停止过。充气轮胎的发明让车辆能够更加平稳舒适的行驶&#xff0c;承载式车身以及加厚的底盘则进一步提高了汽车的舒适性。随着科技的发展与生活水平的提高&#xff0c;人们对汽车的舒适性…

【C】字符串函数和内存函数的介绍

库函数&#xff08;这些函数都在头文件string.h中&#xff09; 字符串函数求字符串长度strlen 长度不受限的字符串函数strcpystrcmpstrcat 长度受限的字符串函数strncpystrncmpstrncat 字符串查找strstrstrtok 错误信息报告strerror 字符操作字符分类函数字符转换函数 内存函数…

测试必备的15个docker命令,你都掌握了吗

1、Docker容器信息 ##查看docker容器版本docker version##查看docker容器信息docker info##查看docker容器帮助docker --help 2、镜像操作 提示&#xff1a;对于镜像的操作可使用镜像名、镜像长ID和短ID。 2.1、镜像查看 ##列出本地imagesdocker images##含中间映像层docke…