ARM驱动学习之 IOremap实现GPIO 读

server/2024/9/23 4:22:10/

                        ARM驱动学习之 IOremap实现GPIO 读

前面介绍了虚拟地址和物理地址。
读写GPIO,控制GPIO的寄存器都是使用系统做好的虚拟地址
本期介绍如何自己实现物理地址到虚拟地址的转化
iounmap和ioremap函数可以实现物理地址到虚拟地址的转化1.根据原理图找核心板对应的寄存器地址
1.硬件KP_COL0→GPL2_0datasheet物理地址GPL2CON = 0x1100_0000+0x0100 = 0x11000000+0x0100=0x11000100GPL2DAT = 0x11000104GPL2PUD = 0x11000108寄存器不一定都是32位的,也有16位和8位在前一次文件中修改:
1.修改文件名和Makefile.
2.将宏定义的驱动部分删除。
3.建立led_gpl2_init(),led_gpl2_exit();
4.led_gpl2_init() 定义gpl2_device_init();
5.gpl2_device_init();//实现gpio初始化;
6.gpl2_config();//实现Gpio输出模式;
7.gpl2_on();//实现led亮;
8.led_off();//实现led灭;
9.volatile unsigned long virt_addr,phys_addr;//定义存放虚拟地址和物理地址;
10.volatile unsigned long *GPL2CON,*GPL2DAT,*GPL2PUD;//定义存放三个寄存器地址
11.gpl2_device_init();定义物理起始地址和转换为虚拟地址;
phys_addr = 0x11000100;
virt_addr = ioremap(phys_addr,0x10);
12.指定操作的寄存器地址:
GPL2CON = (unsigned long *)(virt_addr + 0x00);
GPL2DAT = (unsigned long *)(virt_addr + 0x04);
GPL2PUD = (unsigned long *)(virt_addr + 0x08);
13.配置为输出模式,gpl2_config():
将*GPL2CON[0][3:0] = 0x1
将*GPL2PUD[0:7]    = 0x3
14.在将gpl2_on() 中*GPL2DAT |= 0x01;
15.在将gpl2_off() 中*GPL2DAT &= 0xfe;

源码:

#include <linux/init.h>
#include <linux/module.h>
#include <asm/io.h>volatile unsigned long virt_addr,phys_addr;//定义存放虚拟地址和物理地址;
volatile unsigned long *GPL2CON,*GPL2DAT,*GPL2PUD;//定义存放三个寄存器地址void gpl2_on(void)
{*GPL2DAT |= 0x01;
}void led_off(void)
{*GPL2DAT &= 0xfe;
}void gpl2_device_init(void)
{phys_addr = 0x11000100;virt_addr = (unsigned long)ioremap(phys_addr,0x10);GPL2CON = (unsigned long *)(virt_addr + 0x00);GPL2DAT = (unsigned long *)(virt_addr + 0x04);GPL2PUD = (unsigned long *)(virt_addr + 0x08); //配置GPIO为输出模式;*GPL2CON &= 0xfffffff1;*GPL2CON |= 0x00000001; //配置GPIO为Disables Pull-up;*GPL2PUD |= 0x0003;
}static int led_gpl2_init(void)
{printk("led_gpl2_init\r\n");gpl2_device_init();gpl2_on();return 0;
}static void led_gpl2_exit(void)
{printk("led_gpl2_exit\r\n");led_off();}module_init(led_gpl2_init);//这边打错了浪费半小时!!!
module_exit(led_gpl2_exit);MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");

Makefile:

#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译itop4412_hello.c这个文件编译成中间文件itop4412_hello.o
obj-m += dri_ioremap.o #源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/android4.0下并解压的
KDIR := /home/topeet/Android4.0/iTop4412_Kernel_3.0#当前目录变量
PWD ?= $(shell pwd)#make命名默认寻找第一个目标
#make -C就是指调用执行的路径
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
#modules要执行的操作
all:make -C $(KDIR) M=$(PWD) modules#make clean执行的操作是删除后缀为o的文件
clean:rm -rf *.o


http://www.ppmy.cn/server/118369.html

相关文章

PostgreSQL的流复制断点续传

PostgreSQL的流复制断点续传 PostgreSQL的流复制&#xff08;Streaming Replication&#xff09;具有断点续传的能力&#xff0c;这意味着当主节点和备用节点之间的连接由于网络故障等原因中断后&#xff0c;备用节点会自动从中断点继续接收WAL&#xff08;Write-Ahead Loggin…

python生成器原理

#2-使用生成器生成斐波那契数列&#xff08;无限序列&#xff09; def fibonacci(): a, b 0, 1 while True: yield a a, b b, a b gen fibonacci() for _ in range(10): print(next(gen),end,) #第一次next后&#xff0c;执行fibonacci函数&#xff0c;到yield a处停止&a…

【笔记】时间复杂度

文章目录 时间复杂度概念常见的时间复杂度时间复杂度的衡量常数时间例子线性时间例子平方时间例子对数时间例子 时间复杂度概念 时间复杂度&#xff1a;衡量算法随着输入量增长&#xff0c;执行时间的增长速度。 一般来说&#xff0c;肯定是希望时间复杂度小点比较好。 常见…

Cesium 问题:视角漫游时添加的无人机模型飞行时有抖动

文章目录 问题分析1. 调整飞机模型的高度,比如漫游视角飞行时是1500米,那么可以试着设置飞机模型的高度是1000米或300米,就不会看到抖动了2. 在给飞机新坐标时用如下方式问题 Cesium 问题:视角漫游时添加的无人机模型飞行时有抖动,飞行不太流畅 分析 不太平滑飞行有这两…

使用docker的小例子

演示一个简单的 Node.js 应用的 Docker 化过程。假设我们要创建一个简单的 Node.js 应用&#xff0c;它会在启动时输出 “Hello, Docker!”。 1. 创建 Node.js 项目 步骤 1: 创建项目目录和文件 mkdir my-node-app cd my-node-app 步骤 2: 初始化 Node.js 项目 npm init …

【重学 MySQL】二十七、七种 join 连接

【重学 MySQL】二十七、七种 join 连接 union 的使用UNION 的基本用法示例UNION ALL 的用法 七种 join 连接代码实现语法格式小结 union 的使用 UNION 在 SQL 中用于合并两个或多个 SELECT 语句的结果集&#xff0c;并默认去除重复的行。如果希望包含重复行&#xff0c;可以使…

MySQL——数据类型(二)

目录 一、日期与时间类型 1.1 date 1.2 datetime 1.3 timestamp 二、枚举和联合 2.1 enum 2.2 set 2.2.1 set 的插入 2.2.2 set 的查找 思维导图可以参考如下链接&#xff1a; 数据类型.xmind 夜夜亮晶晶/MySQL - Gitee.com 一、日期与时间类型 1.1 date 日期 yyy…

HTTP 协议的基本格式

HTTP协议("超文本传输协议")&#xff0c;是一个被广泛使用应用层协议&#xff0c;自1991年正式发布HTTP协议以来&#xff0c;HTTP协议就一直在更新&#xff0c;目前已经更新到3.0版本&#xff0c;但是目前主流的依旧是1.1版本&#xff0c;但依旧是一个最主流使用的应…