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

这篇具有很好参考价值的文章主要介绍了【Linux】【驱动】第一个相对完整的驱动编写。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这个章节会讲述去直接控制一个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

【Linux】【驱动】第一个相对完整的驱动编写,linux,运维,服务器文章来源地址https://www.toymoban.com/news/detail-665637.html

到了这里,关于【Linux】【驱动】第一个相对完整的驱动编写的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 14_Linux设备树下的platform驱动编写

    目录 设备树下的platform驱动简介 运行测试 platform驱动框架分为总线、设备和驱动 , 其中总线不需要我们这些驱动程序员去管理,这个是Linux内核提供的 , 我们在编写驱动的时候只要关注于设备和驱动的具体实现即可。在没有设备树的Linux内核下 , 我们需要分别编写并注册plat

    2024年02月16日
    浏览(34)
  • 运维 | 查看 Linux 服务器 IP 地址

    大多数在操作 Linux 系统时,我们经常需要知道服务器的 IP 比便于后续的一系列操作,这时候有快速查看主机 IP 的命令行操作,能够有效的帮助我们 本章节主要记录一些常用查看服务器 IP 的命令,希望对大家有所帮助。 查看 Linux 服务器的 IP 地址的命令大体上有以下几种。

    2024年04月27日
    浏览(52)
  • 【运维】Linux 跨服务器复制文件文件夹

    如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来

    2024年02月08日
    浏览(46)
  • i.MX 6ULL 驱动开发 二十九:向 Linux 内核中添加自己编写驱动

    Linux 内核编译流程如下: 1、配置 Linux 内核。 2、编译 Linux 内核。 说明:进入 Linux 内核源码,使用 make help 参看相关配置。 1、 menuconfig 它本身是一个软件,只提供图形界面配置的一些逻辑,并不负责提供内容。 2、 menuconfig 是内核源码树的各目录下的 kconfig 提供的。 3、 m

    2023年04月10日
    浏览(64)
  • 【Linux】编写一个 shell 脚本&执行

    在Linux中编写和执行脚本相对简单。下面是一个基本的步骤指南,帮助你创建一个简单的bash脚本并运行它: 1. 创建脚本文件 首先,你需要使用文本编辑器创建一个新的文件。这个文件通常会有 .sh 的扩展名,以表明它是一个shell脚本。例如,你可以创建一个名为 myscript.sh 的文

    2024年04月26日
    浏览(28)
  • 12.5在Linux中编写队列模式的SPI控制器驱动

    在Linux内核中更加推荐使用队列模式的SPI控制器驱动,而且队列模式的SPI控制器驱动也更加简单,只需要在驱动中实现单个spi_transfer的传输即可,将spi_message拆解为spi_transfer、片选GPIO控制、统计信息更新等均由SPI核心去完成。 实现设置SPI总线的函数setup,用于设置SPI总线,若

    2024年01月20日
    浏览(37)
  • 【Linux 服务器运维】定时任务 crontab 详解 | 文末送书

    本文思维导图概述的主要内容: 1.1 什么是 crontab Crontab 是一个在 Unix 和 Linux 操作系统上 用于定时执行任务 的工具。它允许用户创建和管理计划任务,以便在特定的时间间隔或时间点自动运行命令或脚本。Crontab 是 cron table 的缩写, cron 指的是 Unix 系统中的一个后台进程,它

    2024年02月08日
    浏览(62)
  • 【Linux】编写第一个小程序:进度条

    1.1.1 sleep() 作用:让程序休眠指定秒数,如: sleep(3); //让程序休眠3秒 与 Windows 上的 Sleep() 函数不同 需要包含头文件 unistd.h 1.1.2 fflush() 作用:刷新缓冲区 需要传入一个流 需要包含头文件 stdio.h 1.1.3 usleep() 作用:让程序休眠指定微秒,如: usleep(100000); //让程序休眠100000微秒(

    2024年02月02日
    浏览(32)
  • Linux驱动之系统移植----uboot移植(有设备树版本),完整移植.

    uboot版本:uboot2020.04 开发板:100ask_imx6ull_pro 拿到官方uboot后第一步先编译烧写测试, 查看哪些驱动可用, 哪些不可用. 根据开发板厂商提供的资料: 使用mx6ull_14x14_evk_defconfig配置进行修改 编译完成后将uboot设备树以及uboot.imx烧写到开发板中运行 显然网络不通, phy无法找到, 其次LCD需

    2024年01月25日
    浏览(25)
  • 【Linux运维】shell脚本检查服务器内存和CPU利用率

    在管理服务器时候写了一个 shell脚本,在服务上实现每天凌晨3点查系统的指定文件夹下的容量大小,如果超过10G就要删除3天前的内容,还要时刻查询内存和cpu利用率,如果超过80%就要提示用户出现过载 将以上代码保存为一个.sh文件,然后通过crontab在每天凌晨3点运行即可:

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包