【Linux驱动】【手把手配置3568寄存器】点亮RK3568的一颗LED

2024-06-07 15:44

本文主要是介绍【Linux驱动】【手把手配置3568寄存器】点亮RK3568的一颗LED,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【硬件】

3568的LED9 :引脚 GPIO0 B7

【配置GPIO的复用】

 找配置复用关系的寄存器基地址、偏移地址、对应配置的GPIO。

查找:io -r -4 0xfdc2000c 系统设置的默认值

结果为1,意思是只有bit 0是1,其他全都为0。所以系统默认就是配置GPIO功能,所以可以不用设置复用GPIO。

【配置GPIO的方向 Direction Register】

查找对应IO配置:io -r -4 0xfdd60008 的默认值(GPIO基地址为0xfdd60000,GPIOB地址偏移8位:0xfdd60008

结果为:0000c064

二进制 : 1100 0000 0110 0010

bit 15为1 ,所以默认已经配置为输出了

【配置GPIO数据寄存器】

查找对应IO配置:io -r -4 0xfdd60000 的默认值

结果为:8000c040

可知bit15 默认为1

PB7写1对应的数据寄存器地址:   8000c040

【问】B7的写使能位是哪一位?

bit31。

PB7写0对应的数据寄存器地址:80004040

PS   :   bit15设置为0(PB7写0),B7对应控制位bit31必须使能1(写使能) 

【驱动】 

#define GPIO_DR 0xFDD60000struct device_test{dev_t dev_num;static int major = 0;static int minor = 0;struct cdev cdev_test;struct class *class;struct device *device;char kbuf[32];  //模拟内核寄存器的数据/************************/unsigned int *vir_gpio_dr; //保存GPIO寄存器虚拟地址用的
};/* 然后定义结构体变量 */
struct device_test dev1;static int moduleparam_init()
{int ret;ret = alloc_chrdev_region(&dev1.dev_num,0,1,"HELLO");  if(ret<0){goto err_chrdev;}printk("alloc_chrdev_region ok\n");  dev1.major_num =MAJOR(dev1.dev_num); //将主设备号取出来dev1.minor_num = MINOR(dev1.dev_num);//将次设备号取出来printk("major_num = %d\n", dev1.major_num);//打印传入进来的主设备号printk("minor_num = %d\n", dev1.minor_num);//打印传入进来的次设备号dev1.cdev_test.owner = THIS_MODULE;cdev_init(dev1.cdev_test, &cdev_file_operations);ret = cdev_add(&dev1.cdev_test, dev1.dev_num, 1);if(ret<0){goto err_chradd;}dev1.class = class_creat(THIS_MODULE, "test");/* 判断创建类有没有失败 */if(IS_ERR(dev1,device)){ret = PTR_ERR(dev1,device);goto err_class_creat;           }dev1.device = device_creat( dev1.class,NULL, dev1.dev_num,,NULL,"test")  /* 判断创建类有没有失败 */if(IS_ERR(dev1.device)){ret = PTR_ERR(dev1,device);goto err_device_creat;           }                    return 0;dev1.vir_gpio_dr = ioremap(GPIO_DR, 4);if(IS_ERR(dev1.vir_gpio_dr)){ret = PTR_ERR(dev1.vir_gpio_dr);goto err_ioremap;           }                    err_ioremap:iounmap(GPIO_DR); //要取消虚拟映射的地址err_device_creat:  //设备添加失败,意味着设备类添加成功,就要把这个类删掉class_destroy( dev1.class);
err_class_creat: //类添加失败,意味着字符设备添加成功,就要把这个字符设备删掉cdev_del(& dev1.cdev_test);  //销毁字符设备        
err_chradd: //添加cdev失败,意味着添加设备号成功,就要释放这个设备号unregister_chrdev_region( dev1.dev_num,DEVICE_NUMBER);//注销设备号
err_chrdev:return ret;
}

关键:

static ssize_t cdev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{struct device_test *test_dev = (struct device_test *)file->private_data;test_dev->kbuf = {0};if(copy_from_user( test_dev->kbuf, buf ,sizeof(buf))!= 0);{printk("copy_from_user error !\n");return -1;}if(test_dev -> kbuf[0] == 1){*(test_dev->vir_gpio_dr) = 0x8000c040;else if{*(test_dev->vir_gpio_dr) = 0x80004040;        }   }return 0;            
}static void hello_exit(void)
{unregister_chrdev_region( dev1.dev_num,DEVICE_NUMBER);//注销设备号cdev_del(& dev1.cdev_test);  //销毁字符设备device_destroy( dev1.class, dev1.dev_num);class_destroy( dev1.class);iounmap(GPIO_DR);printk("gooodbye! \n");
}

【APP】

int main(int argc, char *argv[])
{int fd;char buf[32] = {0};fd1 = open("/dev/test", HELLO);  /* 打开设备节点1 */if(fd < 0){perror("open error \n");return fd;   }   buf[0] = atoi(argv[1]);write(fd, buf, sizeof(buf));close(fd);  return 0;  
}

【实验效果】

./a.out 1 可以实现点灯

./a.out 0 可以实现灭灯

这篇关于【Linux驱动】【手把手配置3568寄存器】点亮RK3568的一颗LED的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1039604

相关文章

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的