NUC980开源项目33-自动分配设备号和设备节点

2023-11-16

上面是我的微信和QQ群,欢迎新朋友的加入。

本来是为点灯准备的驱动,不过现在还没正常操作IO口,就是分配节点和设备号

驱动代码

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
 
#define ON  0
#define OFF 1
 
/* 寄存器物理地址 */
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO5_IO08_BASE (0x02290028)
#define SW_PAD_GPIO5_IO08_BASE (0x0229006c)
#define GPIO5_DR_BASE (0X020AC000)
#define GPIO5_GDIR_BASE (0X020AC004)
 
/* 映射后的寄存器虚拟地址指针 */
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO5_IO08;
static void __iomem *SW_PAD_GPIO5_IO08;
static void __iomem *GPIO5_DR;
static void __iomem *GPIO5_GDIR;
 
#define DEVICE_NAME "board_led"
#define DEVICE_CNT 1
 
static int major = 0; /* 静态设备号方式的默认值 */
static int minor = 0; /* 静态设备号方式的默认值 */
 
module_param(major, int, S_IRUGO);
module_param(minor, int, S_IRUGO);
 
struct cdev *led; /* cdev 数据结构 */
static dev_t devno; /* 设备编号 */
static struct class *led_class;
 
void led_switch(u8 sta)
{
	u32 val = 0;
	if(sta == ON) {
		val = readl(GPIO5_DR);
		val &= ~(1 << 8);
		writel(val, GPIO5_DR);
	}else if(sta == OFF) {
		val = readl(GPIO5_DR);
		val|= (1 << 8);
		writel(val, GPIO5_DR);
	}
}
 
static int led_open(struct inode *inode, struct file *file )
{ 
	printk(KERN_INFO DEVICE_NAME " opened!\n");
	return 0;
}
 
static int led_release(struct inode *inode, struct file *file )
{
	printk(KERN_INFO DEVICE_NAME " closed!\n");
	return 0;
}
 
static ssize_t led_read(struct file *file, char *buf,size_t count, loff_t *f_pos)
{
	printk(KERN_INFO DEVICE_NAME " read method!\n");
	return count;
}
 
static ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)
{
	int retvalue;
	unsigned char databuf[1];
	unsigned char ledstat;
	//retvalue = copy_from_user(databuf, buf, count);
	//if(retvalue < 0) {
	//	printk("kernel write failed!\r\n");
	//	return -EFAULT;
	//}
	//ledstat = databuf[0]; /* 获取状态值 */
	//if(ledstat == ON) {
	//	led_switch(ON); /* 打开 LED 灯 */
	//} else if(ledstat == OFF) {
	//	led_switch(OFF); /* 关闭 LED 灯 */
    //}
	return count;
}
 
//static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long led_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
	printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
	return 0;
}
 
struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = led_read,
.write = led_write,
.open = led_open,
.release = led_release,
.unlocked_ioctl = led_ioctl
};
 
static int __init led_init(void)
{
	u32 val = 0;
	int ret;
	
	///* 初始化 LED */
	///* 1、寄存器地址映射 */
	//IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
	//SW_MUX_GPIO5_IO08 = ioremap(SW_MUX_GPIO5_IO08_BASE, 4);
	//SW_PAD_GPIO5_IO08 = ioremap(SW_PAD_GPIO5_IO08_BASE, 4);
	//GPIO5_DR = ioremap(GPIO5_DR_BASE, 4);
	//GPIO5_GDIR = ioremap(GPIO5_GDIR_BASE, 4);
	///* 2、使能 GPIO1 时钟 */
	//val = readl(IMX6U_CCM_CCGR1);
	//val &= ~(3 << 26); /* 清除以前的设置 */
	//val |= (3 << 26); /* 设置新值 */
	//writel(val, IMX6U_CCM_CCGR1);
	///* 3、设置 GPIO1_IO03 的复用功能,将其复用为
	//* GPIO1_IO03,最后设置 IO 属性。
	//*/
	//writel(5, SW_MUX_GPIO5_IO08);
	///* 寄存器 SW_PAD_GPIO5_IO08 设置 IO 属性 */
	//writel(0x10B0, SW_PAD_GPIO5_IO08);
	///* 4、设置 GPIO1_IO03 为输出功能 */
	//val = readl(GPIO5_GDIR);
	//val &= ~(1 << 8); /* 清除以前的设置 */
	//val |= (1 << 8); /* 设置为输出 */
 //
	//writel(val, GPIO5_GDIR);
	///* 5、默认关闭 LED */
	//val = readl(GPIO5_DR);
	//val |= (0 << 8);
	//writel(val, GPIO5_DR);
 
	/* 注册字符设备驱动 */
	if (major > 0) { /* 静态设备号 */
		devno = MKDEV(major, 0);
		ret = register_chrdev_region(devno, DEVICE_CNT, DEVICE_NAME);
	} else { /* 动态设备号 */
		ret = alloc_chrdev_region(&devno, 0, DEVICE_CNT, DEVICE_NAME); /* 从系统获取主设备号 */
		major = MAJOR(devno);
		minor = MINOR(minor);
	}
	
	if (ret < 0) {
		printk(KERN_ERR "cannot get major %d \n", major); 
		return -1;
	}
	printk(KERN_ALERT " major:%d! minor:%d\n",major,minor);
	
	led = cdev_alloc(); /* 分配 led 结构 */
	if (led != NULL) { 
		cdev_init(led, &led_fops); /* 初始化 led 结构 */
		led->owner = THIS_MODULE;
		if (cdev_add(led, devno, DEVICE_CNT) != 0) { /* 增加 led 到系统中 */
			printk(KERN_ERR "add cdev error!\n");
			goto error;
		}
	} else {
		printk(KERN_ERR "cdev_alloc error!\n"); 
		return -1;
	}
 
	led_class = class_create(THIS_MODULE, DEVICE_NAME);
	if (IS_ERR(led_class)) { 
		printk(KERN_INFO "create class error\n");
		return -1;
	}
 
	device_create(led_class, NULL, devno, NULL, DEVICE_NAME);
    printk(KERN_ALERT "mod init!\n"); 
	return 0;
 
	error:
	unregister_chrdev_region(devno, DEVICE_CNT); /* 释放已经获得的设备号 */
	return ret;
}
 
static void __exit led_exit(void)
{
	/* 取消映射 */
	iounmap(IMX6U_CCM_CCGR1);
	iounmap(SW_MUX_GPIO5_IO08);
	iounmap(SW_PAD_GPIO5_IO08);
	iounmap(GPIO5_DR);
	iounmap(GPIO5_GDIR);
	
	/* 注销字符设备 */
	cdev_del(led);/*移除字符设备*/
	unregister_chrdev_region(devno,DEVICE_CNT);/*释放设备号*/
	device_destroy(led_class,devno);
	class_destroy(led_class);
}
 
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jun,2839084093@qq.com");

 makefile

obj-m := board_led.o
 
KERNEL_SRC := /home/jun/nuc980/nuc980bsp/linux-master
SRC := $(shell pwd)
 
all:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC)
 
modules_install:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
 
clean:
	rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
	rm -f Module.markers Module.symvers modules.order
	rm -rf .tmp_versions Modules.symvers

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
 
#define DEV_NAME "/dev/board_led"
 
int main(int argc, char *argv[])
{
	int i;
	int fd = 0;
	int dat = 0;
	fd = open (DEV_NAME, O_RDWR);
	if (fd < 0) {
		perror("Open "DEV_NAME" Failed!\n"); 
		exit(1);
	}
 
	i = read(fd, &dat, 1);
	if (!i) {
		perror("read "DEV_NAME" Failed!\n");
		exit(1);
	}
 
	dat = 0;
	i = write(fd, &dat, 1);
	if (!i) {
	perror("write "DEV_NAME" Failed!\n");
	exit(1);
	}
 
	close(fd);
	return 0;
}

//arm-linux-gcc board_led_test.c -o board_led_test

编译生成可执行文件

先加载驱动,再运行测试代码

 自动分配成功

 能进入读写操作 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NUC980开源项目33-自动分配设备号和设备节点 的相关文章

  • libspark,不懂日文怎么学……

    由于工作的需求 还有我未来的规划 决心研究 AR 这必然要研究 FLARToolKit 于是我找到了 libspark 接着我发现 这里面的东西太多了太强大了 而且是日本人的开源项目 所以里面很多源码注释都是日文的 于是我今天申请了goog
  • 微分方程(人口预测与传染病模型)

    一 定义 微分方程 含导数或微分的方程 微分方程的阶数 所含导数或微分的最高阶数 如y 2y 2x 0是三阶微分方程 微分方程的解 使得微分方程成立的函数 例如y 2x 0的解可以为x 或者x 1 微分方程的通解和特解 特解为满足等式条件即
  • React 的七个值得推荐的动画库

    今天 Web 应用程序用户界面有许多吸引用户的元素 为了满足这些需求 开发人员不得不寻找新的方法来实现带有动画和过渡的 UI 因此 开发了专门的库和工具来处理 Web 应用程序中的动画 在本文中 将讨论一些优秀的 React 动画库 以便于

随机推荐

  • 基于大数据的智能消防可视化平台

    0 前言 Hi 大家好 今天给大家介绍一个大数据可视化项目 大家可以用于自己的课设或毕设 可以灵活耦合任意数据 为自己的项目添加灵活的可视化动态效果 今天要分享的是 基于大数据的智能消防可视化平台 包含内容 完整可视化实现源码 html一键
  • redis5以上集群环境搭建

    1 系统环境及安装包准备 1 1 服务器 一台Centos7 服务器或虚拟机 ip地址 192 168 56 55 1 2 网络规划 master节点 slave节点 192 168 56 55 8001 192 168 56 55 800
  • 什么是接口测试呢

    什么是接口测试呢 测试人员通常所说的 接口测试 是针对系统各组件之间接口的一种测试 它属于功能测试 接口能测出普通界面操作难以发现的问题 如 我们都知道系统是由前端后端组成 一些数据在前端做了校验 后端同样也需要校验才能保证安全 界面操作显
  • 机器入门学习方法与学习路径

    机器学习方法与学习路径 1 数学基础 有无数激情满满大步向前 誓要在机器学习领域有一番作为的同学 在看到公式的一刻突然就觉得自己狗带了 是啊 机器学习之所以相对于其他开发工作 更有门槛的根本原因就是数学 每一个算法 要在训练集上最大程度拟合
  • 当四款AI大模型遇上考公真题,谁被难倒了?

    在当今社会 人工智能 AI 正以不可思议的速度发展 并在各个领域崭露头角 给人们的生活和工作带来许多便利 AI大模型被誉为人类 第二大脑 成为人们学习 生活 工作的 智能助手 公务员考试在我国教育领域独具特色 受到了众多考生的关注和青睐 众
  • postcss-px-to-viewport-8-plugin 适配

    postcss px to viewport 8 plugin 适配 简述 postcss px to viewport 8 plugin 是一个PostCSS插件 用于将以像素为单位的样式转换为视口单位 如vw vh 的样式 实现移动端适
  • java 输出编码_从代码看java输入输出中的编码和解码

    在java中 采用Unicode编码 英文字符和汉字都占两个字节 下面的代码都是在中文操作系统上执行的 系统采用GBK编码 1 看一下下面这段代码的编码和解码 当我们在键盘上敲入字符的时候 其采用的是GBK编码 比如我们敲入 b 它占两个字
  • 进度条类组件SeekBar

    介绍 拖动条与进度条类似 所不同的是 拖动条允许用户拖动滑块来改变值 通常用于实现对某种数值的调节 基本语法
  • 【数据结构】图解八大排序(下)

    文章目录 一 前言 二 快速排序 1 hoare 版 2 挖坑法 3 前后指针法 4 快排的非递归实现 5 时空复杂度分析 三 归并排序 1 递归实现 2 非递归实现 四 计数排序 一 前言 在上一篇文章中 我们已经学习了五种排序算法 还没
  • 【Linux】基础命令

    操作系统OS 向下直接控制硬件 向上能够支持软件的运行 是个软件 一 操作系统 英语 operating system 缩写作 OS 是管理计算机硬件与软件资源的计算机程序 同时也是计算机系统的内核与基石 操作系统需要处理如管理与配置内存
  • QT 一个控件的坐标怎么相对固定显示在另一个控件上(坐标系)

    先给子控件设置它依赖于哪一个控件上显示 void setTableViewParent QWidget parent 0 void ComplexCombox setTableViewParent QWidget parent m tabl
  • 第十一届蓝桥杯——矩阵(应试做法---卡特兰数)

    前言 直接把它当做一道规律题来做 矩阵 问题描述 把 1 2020 放在 2 1010 的矩阵里 要求同一行中右边的比左边大 同一列中下边的比上边的大 一共有多少种方案 答案很大 你只需要给出方案数除以 2020 的余数即可 答案提交 这是
  • [Pyecharts]数据可视化 大屏展示

    Pyecharts 大屏展示 练习 前言 1 条件 2 代码及展示 时间序列曲线图 时间轮播 24小时轮播 1 2 3 拥堵路段词云图 拥堵榜 通畅榜 水球图 标题 交通流量预测可视化大屏 合并 调整 3 总结 前言 参考 pyechart
  • NumPy通用函数、利用NumPy数组进行数据处理

    文章目录 一 NumPy通用函数 1 什么是通用函数 2 常见的一元通用函数如下 3 常见的二元通用函数如下表 二 利用NumPy数组进行数据处理 1 将条件逻辑转为数组运算 2 数组统计运算 3 数组排序 sort 方法没有返回值 4 检
  • Qt信号接收不到

    问题 emit signal 语句执行后 相应的对象控件接收不到信号 方法 创建了多个对象 一个对象发送信号 但是另一个不同的控件接收不到
  • 【团体程序设计天梯赛-练习集】L2-009 抢红包(25分)

    团体程序设计天梯赛 练习集 L2 009 抢红包 25分 题目 题目链接 L2 009 抢红包 25 分 没有人没抢过红包吧 这里给出N个人之间互相发红包 抢红包的记录 请你统计一下他们抢红包的收获 输入格式 输入第一行给出一个正整数N 1
  • Go语言模拟实现简单的区块链

    一 创建项目 按照Go语言最佳实践的思路 在工作空间下的src目录下创建 github com hangzhou huxin blokcchain目录作为我们的项目目录 然后用GoLand工具选中这个项目并打开 二 项目源码 先在项目目录下
  • Android弹簧动画 Rebound实战

    转载请注明出处 http blog csdn net ym4189 article details 77099881 前言 之前需要做一个弹簧效果的动画 网上一看 大家都用Rebound框架 这里简单写一下 rebound是facebook
  • 前端 Leader 如何做好团队规划?阿里内部培训总结公开

    行成于思 毁于随 韩愈 在阿里从一线前端工程师到技术 TL Team Leader 也三年有余了 最重要最难的就是做规划 你可能会遇到如下几个问题 业务压力巨大 前端是瓶颈 如何做合适的规划 如何提高规划的成功率 规划的雷区是什么 如何寻找
  • NUC980开源项目33-自动分配设备号和设备节点

    上面是我的微信和QQ群 欢迎新朋友的加入 本来是为点灯准备的驱动 不过现在还没正常操作IO口 就是分配节点和设备号 驱动代码 include