【Linux】【驱动】第一个相对完整的驱动编写

news2025/3/10 18:36:53

【Linux】【驱动】第一个相对完整的驱动编写

  • 1.驱动部分的代码
  • 2 app 代码
  • 3 操作相关的代码

这个章节会讲述去直接控制一个GPIO,高低电平。

因为linux不允许直接去操作寄存器,所以在操作寄存器的时候就需要使用到函数:ioremap 和iounmap
来作为寄存器的声明和注销

ioremap 做为地址的声明,如下图使用
CCM_CCGR1 = ioremap(0x20C406C, 4);

iounmap 作为取消声明。
iounmap(CCM_CCGR1);

1.驱动部分的代码

  1. 在函数的前面对寄存器的名称进行了说明,
  2. misc_init 中实现对GPIO的配置, 使能 GPIO5,设置 GPIO5_IO03 用于 GPIO,设置 GPIO5_IO03 作为 output 引脚
  3. 在misc_write 中实现了对GPIO的控制

PS:此代码还有一些不完善的地方,所以在实际的使用中可能会出现一些异常,带之后改正

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>	
#include <linux/uaccess.h>
#include <linux/io.h>


unsigned int *vir_gpio5_dr ;
 static volatile unsigned int *CCM_CCGR1 ;
static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
static volatile unsigned int *GPIO5_GDIR ;
 static volatile unsigned int *GPIO5_DR ;

int misc_open(struct inode *inode, struct file *file)
{
	printk("misc_open\n");

	return 0;
}

int misc_release(struct inode *inode, struct file *file)
{
	printk("misc_release\n");
	return 0;

}

ssize_t misc_read(struct file *file,char __user *ubuf,size_t size,loff_t *loff_t)
{
	char kbuf[512] = "haha";

	if(copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
	{
		printk("error copying\n");
		return -1;
	}

	return 0;

}

ssize_t misc_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loff_t)
{

	char kbuf[512] = {0};	
	if(copy_from_user(kbuf,ubuf,size)!= 0)
	{
		printk("misc_write error\n");
		return -1;

	}

	printk("kbuf = %d\n",kbuf[0]);
	if(kbuf[0] == 1)
		{
			*GPIO5_DR |=(1<<3);//设置GPIO
			printk(" kbuff  = 1\n");
		}
	else if(kbuf[0] == 0)
	{
		*GPIO5_DR &= ~(1<<3);//设置GPIO
		printk(" kbuff  = 0\n");
	}


	return 0;

}

struct file_operations misc_fops = {
	.owner	= THIS_MODULE,
	.open	= misc_open,
	.release = misc_release,
	.read	= misc_read,
	.write	= misc_write
};


struct miscdevice misc_dev = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = "hello_misc",
	.fops = &misc_fops
};


//drivers for init
static int misc_init(void)
{
	unsigned int val;
	int ret = 0;
	ret = misc_register(&misc_dev);
	if(ret<0) 
	{
		printk("misc_register is failed\n");
		return -1;
	}
	printk("misc registe is succeed \n");
	
	//vir_gpio5_dr  = ioremap(GPIO5_DR,4);
	CCM_CCGR1 = ioremap(0x20C406C, 4);
	IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(0x2290014, 4);
	GPIO5_GDIR = ioremap(0x020AC000 + 0x4, 4);
	GPIO5_DR = ioremap(0x020AC000 + 0, 4);
	*CCM_CCGR1 |= (3<<30);//使能 GPIO5
	//设置 GPIO5_IO03 用于 GPIO
	val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
	val &= ~(0xf);
	val |= (5);
	*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = val;

	//设置 GPIO5_IO03 作为 output 引脚
	*GPIO5_GDIR |= (1<<3);
/*
	if(vir_gpio5_dr==NULL)
	{
		printk("vir_gpio5_dr ioremap error ");
		return -EBUSY;
	}*/
	printk("GPIO5_DR ioremap ok\n");	
	
	return 0;
}


//drivers for exit 
static void misc_exit(void)
{
//
	misc_deregister(&misc_dev);

	iounmap(CCM_CCGR1);
	iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3);
	iounmap(GPIO5_GDIR);
	iounmap(GPIO5_DR);


	printk("misc exit \n");

}

module_init(misc_init);
module_exit(misc_exit);

MODULE_LICENSE("GPL");

2 app 代码

  1. 通过atoi 函数实现对命令框指令的读写,
  2. 通过write来是线对buf数字的传递
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"


/*
 * @description		: main主程序
 * @param - argc 	: argv数组元素个数
 * @param - argv 	: 具体参数
 * @return 			: 0 成功;其他 失败
 */
int main(int argc, char *argv[])
{
	int fd;
	char buf[64] = {0};

	//fd = open(argv[1], O_RDONLY);
	fd = open("/dev/hello_misc", O_RDWR);

	if(fd < 0)
	{
		perror("open error");
		return fd;

	}
	buf[0] = atoi(argv[1]);

	write(fd,buf,sizeof(buf));
	close(fd);
	return 0;
}

3 操作相关的代码

编译app 代码

arm-buildroot-linux-gnueabihf-gcc -o miscApp miscApp.c

编译驱动代码
make

清除驱动代码
make clean

挂载nfs

mount -t nfs -o nolock,vers=3 192.168.5.15:/home/book/nfs_rootfs /mnt

删除文件

rm -f + chrdevbase.ko

传递文件,将misc.ko 传到 /home/book/nfs_rootfs/

cp misc.ko /home/book/nfs_rootfs/

允许PrintK

echo "7 4 1 7"> /proc/sys/kernel/printk

安装驱动

insmod misc.ko

列出驱动列表

lsmod

移除驱动

 rmmod misc

给驱动传递数据1

./miscApp 1

在这里插入图片描述

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

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

相关文章

RedisTemplate和StringRedisTemplate的区别、对比

学习 Jedis、RedisTemplate、StringRedisTemplate之间的比较 博客中提到&#xff1a;一. Jedis是Redis官方推荐的面向Java的操作Redis的客户端。 二. RedisTemplate,StringRedisTemplate是SpringDataRedis中对JedisApi的高度封装。SpringDataRedis相对于Jedis来说可以方便地更…

Qt+C++动力监控动画仿真SCADA上位机

程序示例精选 QtC动力监控动画仿真SCADA上位机 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC动力监控动画仿真SCADA上位机>>编写代码&#xff0c;代码整洁&#xff0c;规则…

心理与神经生物工程交叉学科国际论坛—暨第17届复合医学工程国际会议(CME2023)

心理与神经生物工程交叉学科国际论坛—暨第17届复合医学工程国际会议&#xff08;CME2023&#xff09; International Forum on the Intersection of Psychology and Neuromedical Engineering -17th International Conference on Complex Medical Engineering (CME2023) 心…

字节跳动 从需求到上线全流程 软件工程流程 需求评估 MVP

走进后端开发流程 整个课程会带大家先从理论出发&#xff0c;思考为什么有流程 大家以后工作的团队可能不一样&#xff0c;那么不同的团队也会有不同的流程&#xff0c;这背后的逻辑是什么 然后会带大家按照走一遍从需求到上线的全流程&#xff0c;告诉大家在流程的每个阶段&am…

功率放大器在电子实验中的作用是什么

功率放大器在电子实验中扮演着重要的角色&#xff0c;它具有多种作用和应用。在本文中&#xff0c;我们将详细介绍功率放大器在电子实验中的作用。 信号放大&#xff1a;功率放大器能够将输入信号的功率放大到更高的水平。在电子实验中&#xff0c;信号放大是非常常见的需求。通…

冒险岛 vcruntime140.dll 丢失问题的多种方法,几种解决方法都有效

当您尝试启动冒险岛游戏时&#xff0c;可能会遇到一个名为“vcruntime140.dll 丢失”的错误提示。vcruntime140.dll 是冒险岛游戏所需的一个重要系统文件&#xff0c;如果系统无法找到或加载该文件&#xff0c;您将无法正常启动游戏。在本文中&#xff0c;我们将详细介绍解决冒…

用友T3T6登录报错检测公共组件softcop.dll时未能通过,公共组件可能被破坏。

导致原因&#xff0c;windows 10操作系统&#xff0c;预制验证证书更新故障。 操作系统原因导致的。大量客户报错。 临时解决方法&#xff1a;把电脑系统日期改为 2023-08-01日以前。 根治解决方法&#xff0c;重置windows 预制证书&#xff0c;刷新签名证书。

【C++/C 实现球球大作战】

目录 1.引言2.游戏设计&#xff1a;概述游戏的玩法和操作方式。3.游戏实现&#xff08;1&#xff09;函数 GameInit() 初始化游戏的函数。&#xff08;2&#xff09;函数 GameDraw() 用于绘制游戏场景的函数。&#xff08;3&#xff09;函数 keyControl(int speed) 负责处理键盘…

新能源汽车技术的最新进展和未来趋势

文章目录 电池技术的进步智能驾驶与自动驾驶技术充电基础设施建设新能源汽车共享和智能交通未来趋势展望结论 &#x1f389;欢迎来到AIGC人工智能专栏~探索新能源汽车技术的最新进展和未来趋势 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客…

请注意:名字里千万不要有凶数

人与人之间相处&#xff0c;最重要的就是信任二字。 而被人相信和被人欣赏一样&#xff0c;都是值得我们喜乐和感动的事情。 曾经&#xff0c;峰民在常德工作室接待一位预约福主&#xff0c; 这位福主一见面就给了峰民一个感恩红包&#xff0c;峰民非常感动。 这位福主是非常的…

RISC-V公测平台发布 · 在SG2042上配置Jupiter+Octave科学计算环境

简介 JupyterHub是一个开源的共享计算平台&#xff0c;它为每个用户管理一个单独的 Jupyter 环境&#xff0c; 可以用于学生班级、企业数据科学小组或科学研究小组。它是一个多用户中心&#xff0c;可以生成、管理和代理多个单用户Jupyter笔记本服务器的实例。 GNU Octave是一…

分布式下的session共享问题

首页我们确定在分布式的情况下session是不能共享的。 1.不同的服务&#xff0c;session不能共享&#xff0c;也就是微服务的情况下 2.同一服务在分布式情况&#xff0c;session同样不能共享&#xff0c;也会是分布式情况 分布式下session共享问题解决方案(域名相同) 1.session复…

基于 Android 剧院购票APP的开发与设计

摘要&#xff1a;近年来&#xff0c;随着社会的发展和科技方面的创新&#xff0c;越来越多的人选择使用手机应用程序来购买剧场票。本文将探讨基于 Android 平台的剧院购票应用程序的开发和设计。该应用程序将为用户提供浏览剧场列表、查看剧场详情、选择座位并购买剧场票的功能…

sas数据转pandas

1999年以后的nhanes数据都是以xpt文件格式发布的&#xff0c;而更早的数据有很多是以dat原始数据格式发布&#xff0c;需要将原始数据转为数据表以做进一步统计分析。 以 NHANES III 为例&#xff0c;其中有一个数据Household Youth File&#xff0c;包含3个数据文件youth.dat…

Type C接口的PCB布局布线要求

USB Type C&#xff0c;又称为USB-C。需要注意的是Type-C只是一种接口&#xff0c;和USB的版本没有任何关系。该接口的亮点在于更加纤薄的设计、更快的传输速度&#xff08;最高10Gbps以及更强悍的电力传输&#xff08;最高100W)。 Type-C双面可插接口最大的特点的支持USB接口…

【 OpenGauss源码学习 —— 列存储(Insert)】

列存储&#xff08;Insert&#xff09; 概述相关函数ExecInsertRelationData 结构体FormData_pg_class 结构体HeapInsertCStore函数InsertArg 结构体CStoreInsert 类CStoreInsert::InitInsertArg函数heap_deform_tuple 函数bulkload_rows 结构体append_one_tuple 函数bulkload_…

在线图片怎么转换成PDF?在线图片转换成PDF步骤介绍

文件格式要转化不知道怎么办?想要网上下载文件格式转换软件&#xff0c;但是却不知道下载哪个好?今天小编小编就给大家分享一下靠谱的小圆象PDF转换器工具&#xff0c;想知道这款软件好不好用?在线图片怎么转换成PDF?那就进来看看吧。 在线图片怎么转换成PDF 小圆象PDF转换…

LeetCode——二叉树篇(八)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 目录 236. 二叉树的最近公共祖先 235. 二叉搜索树的最近公共祖 迭代 递归 701. 二叉搜索树中的插入操作 450. 删除二叉搜索树中的节点 236. 二叉树的最近公共祖先 给定一个二…

数据加密技术——对称加密和非对称加密

一、数据加密技术 加密是指对数据进行编码变换&#xff0c;使其看起来毫无意义&#xff0c;但同时却仍可以保持其可恢复的形式的过程。在这个过程中&#xff0c;被变换的数据称为明文&#xff0c;它可以是一段有意义的文字或者数据&#xff0c;变换后的数据称为密文。加密机制有…

学习笔记|认识数码管|控制原理|数码管实现0-9的显示|段码跟位码|STC32G单片机视频开发教程(冲哥)|第九集:数码管静态显示

文章目录 1.认识数码管2.控制原理十进制转换为任意进制其它进制转十进制 3.数码管实现0-9的显示1.用数组定义0-9的内码段码跟位码的区别2.尝试用延时实现0-9的循环显示3.用按键控制数字的加或者减。 总结课后练习&#xff1a; 1.认识数码管 数码管按段数可分为七段数码管和八段…