Hi3531与Hi3520 GPIO口的对比及驱动的修改
http://blog.csdn.net/xiangpingli/article/details/7251734
1、GPIO口的对比:
3520:
应用:16路CIF,4路、8路D1
管脚总数:768pin
GPIO: 8组,GPIO0~GPIO7
GPIO基地址:从NAND、NOR、DDR映射GPIOX寄存器地址都是一样的:
3531:
应用:
单片:16D1+16CIF编码+4D1解码,8路D1同编同解,4路高清同编同解
双片(+3532):16路D1同编同解,8路720P同编同解,4路1080P实时解码
管脚总数:817pin
GPIO:19组,GPIO0~GPIO18
3520与3531GPIO对比总结:
1、3531有19组GPIO,3520有8组GPIO,两者GPIO0~7的地址是相同的。
2、各寄存器偏移地址不变
3520gpio驱动中针对3531修改:
1、首先把多出的寄存器组添加上,多了11组寄存器。
2、然后因为内核的接口变化了,修改ioctl相关的部分,记得unlocked_ioctl参数比原来的参数少了一个inode。
3、创建和初始化信号量的地方也要修改掉,DECLARE_MUTEX在linux3.0中也不存在了,取而代之的是DEFINE_SEMAPHORE
4、就是地址映射部分,哪里映射失败,要把之前映射的全部释放掉再退出:
hi_gpio.c:
#include <linux/module.h>
//#include <asm/hardware.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include "hi_gpio.h"
#define GPIO_0_BASE_ADDR 0x20150000
#define GPIO_1_BASE_ADDR 0x20160000
#define GPIO_2_BASE_ADDR 0x20170000
#define GPIO_3_BASE_ADDR 0x20180000
#define GPIO_4_BASE_ADDR 0x20190000
#define GPIO_5_BASE_ADDR 0x201a0000
#define GPIO_6_BASE_ADDR 0x201b0000
#define GPIO_7_BASE_ADDR 0x201c0000
#define GPIO_8_BASE_ADDR 0x201d0000
/* changed for 3531 */
#define GPIO_9_BASE_ADDR 0x201e0000
#define GPIO_10_BASE_ADDR 0x201f0000
#define GPIO_11_BASE_ADDR 0x20200000
#define GPIO_12_BASE_ADDR 0x20210000
#define GPIO_13_BASE_ADDR 0x20220000
#define GPIO_14_BASE_ADDR 0x20230000
#define GPIO_15_BASE_ADDR 0x20240000
#define GPIO_16_BASE_ADDR 0x20250000
#define GPIO_17_BASE_ADDR 0x20260000
#define GPIO_18_BASE_ADDR 0x20270000
#define GPIO_DIR_BASE (groupbase+0x400)
#define GPIO_INTR_MASK (groupbase+0x410)
#define GPIO_DATA_BASE data_reg_base
#define WRITE_REG(Addr, Value) ((*(volatile unsigned int *)(Addr)) = (Value))
#define READ_REG(Addr) (*(volatile unsigned int *)(Addr))
static DEFINE_SEMAPHORE(gpio_sem); /* 根据linux3.0.y 的源码,DEFINE_SEMAPHORE取代了DECLARE_MUTEX */
//static DECLARE_MUTEX(gpio_sem);
unsigned int groupbase=-1;
unsigned int data_reg_base=0;
unsigned int gpio_0_base_addr_virtual=0;
unsigned int gpio_1_base_addr_virtual=0;
unsigned int gpio_2_base_addr_virtual=0;
unsigned int gpio_3_base_addr_virtual=0;
unsigned int gpio_4_base_addr_virtual=0;
unsigned int gpio_5_base_addr_virtual=0;
unsigned int gpio_6_base_addr_virtual=0;
unsigned int gpio_7_base_addr_virtual=0;
unsigned int gpio_8_base_addr_virtual=0;
unsigned int gpio_9_base_addr_virtual=0;
unsigned int gpio_10_base_addr_virtual=0;
unsigned int gpio_11_base_addr_virtual=0;
unsigned int gpio_12_base_addr_virtual=0;
unsigned int gpio_13_base_addr_virtual=0;
unsigned int gpio_14_base_addr_virtual=0;
unsigned int gpio_15_base_addr_virtual=0;
unsigned int gpio_16_base_addr_virtual=0;
unsigned int gpio_17_base_addr_virtual=0;
unsigned int gpio_18_base_addr_virtual=0;
static void gpio_calculate_data_groupbase(unsigned int groupnum, unsigned int bitnum)
{
switch(groupnum)
{
case 0:
groupbase =gpio_0_base_addr_virtual;
break;
case 1:
groupbase =gpio_1_base_addr_virtual;
break;
case 2:
groupbase =gpio_2_base_addr_virtual;
break;
case 3:
groupbase =gpio_3_base_addr_virtual;
break;
case 4:
groupbase =gpio_4_base_addr_virtual;
break;
case 5:
groupbase =gpio_5_base_addr_virtual;
break;
case 6:
groupbase =gpio_6_base_addr_virtual;
break;
case 7:
groupbase =gpio_7_base_addr_virtual;
break;
case 8:
groupbase =gpio_8_base_addr_virtual;
break;
case 9:
groupbase =gpio_9_base_addr_virtual;
break;
case 10:
groupbase =gpio_10_base_addr_virtual;
break;
case 11:
groupbase =gpio_11_base_addr_virtual;
break;
case 12:
groupbase =gpio_12_base_addr_virtual;
break;
case 13:
groupbase =gpio_13_base_addr_virtual;
break;
case 14:
groupbase =gpio_14_base_addr_virtual;
break;
case 15:
groupbase =gpio_15_base_addr_virtual;
break;
case 16:
groupbase =gpio_16_base_addr_virtual;
break;
case 17:
groupbase =gpio_17_base_addr_virtual;
break;
case 18:
groupbase =gpio_18_base_addr_virtual;
break;
default:
break;
}
// printk("groupbase:%x !\n",groupbase);
data_reg_base=groupbase+(1<<(bitnum+2));
// printk("data_reg_base:%x !\n",data_reg_base);
}
static int gpio_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
return 0;
}
//static int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
static int gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
//这里代码没改
return 0;
}
static struct file_operations gpio_fops = {
owner:THIS_MODULE,
open:gpio_open,
// ioctl:gpio_ioctl,
unlocked_ioctl:gpio_ioctl, /* linux3.0.y 不再使用ioctl,采用unlocked_ioctl */
release:gpio_release,
};
static struct miscdevice gpio_dev = {
MISC_DYNAMIC_MINOR,
"hi_gpio",
&gpio_fops,
};
//gpio的复用关系要放在uboot下面;
static int __init hi_gpio_init(void)
{
signed int ret=0;
ret = misc_register(&gpio_dev);
if (ret)
{
printk(KERN_ERR "register misc dev for hi_gpio fail!\n");
return ret;
}
gpio_0_base_addr_virtual=(unsigned int)ioremap_nocache(GPIO_0_BASE_ADDR,0x40000);
if(!gpio_0_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
return -1;
}
gpio_1_base_addr_virtual=gpio_0_base_addr_virtual+0x10000;
gpio_2_base_addr_virtual=gpio_0_base_addr_virtual+0x20000;
gpio_3_base_addr_virtual=gpio_0_base_addr_virtual+0x30000;
gpio_4_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_4_BASE_ADDR,0x40000);
if(!gpio_4_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
/*说明gpio_0 映射成功了,但gpio_4没成功,所以要把gpio_0的释放掉*/
iounmap((void*)gpio_0_base_addr_virtual);
return -1;
}
gpio_5_base_addr_virtual=gpio_4_base_addr_virtual+0x10000;
gpio_6_base_addr_virtual=gpio_4_base_addr_virtual+0x20000;
gpio_7_base_addr_virtual=gpio_4_base_addr_virtual+0x30000;
gpio_8_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_8_BASE_ADDR,0x40000);
if(!gpio_8_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
/*说明gpio_0 和gpio_4都映射成功了,但gpio_8没映射成功,所以将之前映射的释放*/
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
return -1;
}
gpio_9_base_addr_virtual = gpio_8_base_addr_virtual + 0x10000;
gpio_10_base_addr_virtual = gpio_8_base_addr_virtual + 0x20000;
gpio_11_base_addr_virtual = gpio_8_base_addr_virtual + 0x30000;
gpio_12_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_12_BASE_ADDR,0x40000);
if(!gpio_12_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
iounmap((void*)gpio_8_base_addr_virtual);
return -1;
}
gpio_13_base_addr_virtual = gpio_12_base_addr_virtual + 0x10000;
gpio_14_base_addr_virtual = gpio_12_base_addr_virtual + 0x20000;
gpio_15_base_addr_virtual = gpio_12_base_addr_virtual + 0x30000;
gpio_16_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_16_BASE_ADDR,0x30000); /* 注意:这里不能再是0x40000了*/
if(!gpio_16_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
iounmap((void*)gpio_8_base_addr_virtual);
iounmap((void*)gpio_12_base_addr_virtual);
return -1;
}
gpio_17_base_addr_virtual = gpio_16_base_addr_virtual + 0x10000;
gpio_18_base_addr_virtual = gpio_16_base_addr_virtual + 0x20000;
return 0;
}
static void __exit hi_gpio_exit(void)
{
misc_deregister(&gpio_dev);
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
iounmap((void*)gpio_8_base_addr_virtual);
iounmap((void*)gpio_12_base_addr_virtual);
iounmap((void*)gpio_16_base_addr_virtual);
}
module_init(hi_gpio_init);
module_exit(hi_gpio_exit);
MODULE_AUTHOR("Digital Media Team ,Hisilicon crop ");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Real Time Clock interface for HI3511");
Hi3531与Hi3520 GPIO口的对比及驱动的修改相关推荐
- 写一个公用的gpio口驱动
因为项目需要控制的GPIO口比较多,如果每个GPIO口都写一个驱动就显得比骄麻烦,所以就写了一个通用的GPIO口驱动.只要dts里面配置好设备GPIO相关信息就可以自动加载了.可以很充分的体现多个设备 ...
- STM8单片机GPIO口的驱动深度解析
上一节给大家介绍了STM8标准库的移植,本节课开始学习我们单片机的外设的驱动,单片机基本的外设资料包括GPIO.外部中断.定时器.串口等,本节先给大家介绍一下STM8单片机的GPIO口. 我们先不介绍 ...
- java gpio_Java控制树莓派GPIO口-Pi4J
Pi4J(http://pi4j.com/)是专门用来控制树莓派GPIO口以及通信的Java库.它有如下功能: Export & unexport GPIO pins Configure GP ...
- stm32 gpio口的工作模式
一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定. 推挽电路是两个参数相同的三极管或M ...
- Silicon C8051F340之GPIO口配置与使用
一.背景:很久前用过C8051,现在有相关需求需要重新使用C8051,然后发现一年前开发的相关经验都忘得基本上差不多了.连最基本的GPIO口配置还得重新来看手册,所以有此文,做个记录,以备下次快速开发 ...
- 启明云端分享|ESP32学习笔记参考GPIO口操作
提示:作为Espressif(乐鑫科技)大中华区合作伙伴及sigmastar(厦门星宸)VAD合作伙伴,我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程供开发小伙伴参考.同时也用 ...
- GPIO口模拟I2C操作
/* 作者:天空 日期:2014.5.12 功能:利用GPIO口模拟I2C总线,对传感器寄存器读取数据 注意:如果需要移植些文件到其他设 ...
- MTK 驱动开发(3)---GPIO口的使用方法汇总
1简介 GPIO=General Purpose Input Output,通用输入输出.有时候简称为"IO口".通用,就是说它是万金油,干什么都行.输入输出,就是说既能当输入口使 ...
- STM32单片机在Keil5下仿真的问题解决及GPIO口初始化、使用
STM32单片机在Keil5下仿真的问题解决及GPIO口初始化.使用 参考文章: (1)STM32单片机在Keil5下仿真的问题解决及GPIO口初始化.使用 (2)https://www.cnblog ...
最新文章
- PonyAI的首份美国无人出租成绩单:总数1271趟,15%拼车
- 问题解决——使用CriticalSection后 0xXXXXXXXX处最可能的异常: 0xC0000005: 写入位置 0x00000014 时发生访问冲突
- matlab仿真随机数的产生
- 【安全漏洞】Cisco命令注入漏洞CVE-2021-1414分析
- 《众妙之门——自由网站设计师成功之道》一1.4 自由网站设计师犯的严重错误...
- python中常用的模块二
- 魔兽世界工程学技能1-375冲级攻略
- Linux磁盘及文件系统(二)Linux下磁盘命名和分区
- 后续的C++测试并不一定会成功
- java堆栈有序无序,浅谈Java并发编程系列(四)—— 原子性、可见性与有序性
- onvif协议client与server对接
- 完整简单的红黑树算法
- php学习五:数组操作
- python GUI打开文本文件代码
- 从零开始学编程——编程语言
- php网页可视化编辑器,推荐几款HTML可视化在线编辑器
- 汇川,H3U,plc程序模板和触摸屏程序模板,三个步进和三个伺服,三个伺服用的是canlink总线,适用于运动轴控制
- Ghost Win10 企业版LTSC 2020.05(32位+64位)
- 心不隔离|愿春早来,花枝春满
- 小甲鱼Python第十九讲(函数,我的地盘听我的)
热门文章
- matlab导向滤波磨皮,图像处理(七)导向滤波磨皮
- mysql 存储过程 模糊查询_Mysql之存储过程“模糊查询drop表”
- java 数组group by_java Group by分组算法
- transformer模型_【经典精读】Transformer模型深度解读
- jupyter下使用conda环境
- centos 卸载自带的 java
- openstack swift middleware开发
- 十四、中文词向量训练一
- 突发!Windows XP源代码泄露
- 你以为文言编程只是闹着玩?三个月后,人家IDE、教程、包管理器都有了