当前位置: 首页 > article >正文

ARM驱动学习之 IOremap实现GPIO 读

                        ARM驱动学习之 IOremap实现GPIO 读

前面介绍了虚拟地址和物理地址。
读写GPIO,控制GPIO的寄存器都是使用系统做好的虚拟地址
本期介绍如何自己实现物理地址到虚拟地址的转化
iounmap和ioremap函数可以实现物理地址到虚拟地址的转化

1.根据原理图找核心板对应的寄存器地址
1.硬件
	KP_COL0→GPL2_0
	datasheet物理地址
	GPL2CON = 0x1100_0000+0x0100 = 0x11000000+0x0100=0x11000100
	GPL2DAT = 0x11000104
	GPL2PUD = 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.kler.cn/news/310622.html

相关文章:

  • 安卓13去掉下拉菜单的Dump SysUI 堆的选项 android13删除Dump SysUI 堆
  • react hooks--概述
  • Linux从入门到开发实战(C/C++)Day12-ICMP协议
  • linux-软件包管理-编译与安装源码包
  • 人工智能-GPU版本机器学习、深度学习模型安装
  • swc 编译 es6为commonjs
  • 「数组」堆排序 / 大根堆优化(C++)
  • 双端队列double-ended queue
  • c/c++语言中extern的用法(VS编译)
  • 代码结构之结构体
  • 算法面经手撕系列(2)--手撕BatchNormlization
  • 【每日一诗】【诗词创作】【诗】《雨前秋夜》
  • 浅谈Linux中的环回设备
  • C++将32位深图片处理成灰度图
  • 构建自己的文生图工具:Python + Stable Diffusion + CUDA
  • 基于PHP+MySQL组合开发的在线客服源码系统 聊天记录实时保存 带完整的安装代码包以及搭建部署教程
  • JAVA-集合相关
  • 功能测试干了三年,快要废了。。。
  • 工号不够用了怎么办? - 华为OD统一考试(E卷)
  • 【代码随想录训练营第42期 续Day58打卡 - 图论Part8 - Dijkstra算法
  • 在 Linux 系统中目录架构说明
  • c语言--力扣简单题目(最后一个单词的长度)讲解
  • 【毕设】基于Java的超市管理系统
  • SQL:DATEDIFF函数
  • Java网络编程:构建高性能的TCP/IP服务
  • OpenAI草莓正式发布,命名o1
  • SEW变频器的组成
  • 十一,Spring Boot 当中配置拦截器的“两”种方式
  • 函数调用与作用域
  • 下载 llama2-7b-hf 全流程【小白踩坑记录】