4412 GPIO读 和 ioremap控制GPIO寄存器
一、配置GPIO读
在视频14的基础上做
1.利用拨码开关来实现GPIO输入
所以AP_SLEEP对应GPC0_3,然后在drivers/gpio/gpio-exynos4.c中对应EXYNOS4_GPC0(0)
XEINT6→GPX0_6→EXYNOS4_GPX0(6)
读寄存器手册分析流程:
- 设置寄存器为输入 GPC0CON
- 读寄存器值 GPC0DAT
- 不上拉,不下拉 GPC0PUD
2.GPIO的输入需要哪些函数,从arch\arm\plat-samsung\gpio-config.c中找
- 申请gpio_request
- 读寄存器gpio_get_value
- 设置GPIO为输入模式s3c_gpio_cfgpin S3C_GPIO_INPUT
- 设置上拉下拉s3c_gpio_setpull S3C_GPIO_PULL_NONE
- 释放GPIO gpio_free
3.平台文件中设备注册
在文件arch/arm/mach-exynos/mach-itop4412.c中:
struct platform_device s3c_device_read_gpio_ctl = {
.name = "read_gpio_ctl",
.id = -1,
};
&s3c_device_read_gpio_ctl,
在init_lcd_type函数中request了GPIO。所以在get_lcd_type需要释放GPIO
gpio_free(EXYNOS4_GPC0(3));
gpio_free(EXYNOS4_GPX0(6));
4.Makefile修改
TARGET_NAME = read_gpio
APP_NAME = app_read_gpio
obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3. PWD ?= $(shell pwd) all:app
make -C $(KDIR) M=$(PWD) modules app:$(APP_NAME)
arm-none-linux-gnueabi-gcc $(APP_NAME).c -o $(APP_NAME) -static clean:
rm -rf *.o *.ko *.mod.c *.symvers *.order \
.$(TARGET_NAME)* $(APP_NAME)
Makefile
5.驱动的修改
#include <linux/init.h>
#include <linux/module.h> /*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include <linux/platform_device.h>
/*注册杂项设备头文件*/
#include <linux/miscdevice.h>
/*注册设备节点的文件结构体*/
#include <linux/fs.h> /*Linux中申请GPIO的头文件*/
#include <linux/gpio.h>
/*三星平台的GPIO配置函数头文件*/
/*三星平台EXYNOS系列平台,GPIO配置参数宏定义头文件*/
#include <plat/gpio-cfg.h>
#include <mach/gpio.h>
/*三星平台4412平台,GPIO宏定义头文件*/
#include <mach/gpio-exynos4.h> #define DRIVER_NAME "read_gpio_ctl"
#define DEVICE_NAME "read_gpio_ctl" MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET"); static long read_gpio_ioctl( struct file *files, unsigned int cmd, unsigned long arg)
{
printk("cmd is %d,arg is %d\n",cmd,arg); if(cmd > ){
printk(KERN_EMERG "cmd is 0 or 1\n");
}
if(arg > ){
printk(KERN_EMERG "arg is only 1\n");
} //if cmd is 0, return GPC(3)>>switch3
//if cmd is 1, return GPX(6)>>switch4
if(cmd == ) {
return gpio_get_value(EXYNOS4_GPC0());
}
if(cmd == ) {
return gpio_get_value(EXYNOS4_GPX0());
} return ;
} static int read_gpio_release(struct inode *inode, struct file *file)
{
printk(KERN_EMERG "read_gpio release\n");
return ;
} static int read_gpio_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG "read_gpio open\n");
return ;
} static struct file_operations read_gpio_ops = {
.owner = THIS_MODULE,
.open = read_gpio_open,
.release = read_gpio_release,
.unlocked_ioctl = read_gpio_ioctl,
}; static struct miscdevice read_gpio_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &read_gpio_ops,
}; static int read_gpio_probe(struct platform_device *pdv)
{
int ret; printk(KERN_EMERG "\tinitialized\n"); ret = gpio_request(EXYNOS4_GPC0(),"Switch3");
if(ret < ){
printk(KERN_EMERG "gpio_request EXYNOS4_GPL2(0) failed!\n");
return ret;
} else {
s3c_gpio_cfgpin(EXYNOS4_GPC0(), S3C_GPIO_INPUT);
s3c_gpio_setpull(EXYNOS4_GPC0(), S3C_GPIO_PULL_NONE); } ret = gpio_request(EXYNOS4_GPX0(),"Switch4");
if(ret < ){
printk(KERN_EMERG "gpio_request EXYNOS4_GPL2(0) failed!\n");
return ret;
} else {
s3c_gpio_cfgpin(EXYNOS4_GPX0(), S3C_GPIO_INPUT);
s3c_gpio_setpull(EXYNOS4_GPX0(), S3C_GPIO_PULL_NONE); } misc_register(&read_gpio_dev); return ;
} static int read_gpio_remove(struct platform_device *pdv)
{
printk(KERN_EMERG "\tremove\n");
gpio_free(EXYNOS4_GPC0());
gpio_free(EXYNOS4_GPX0());
misc_deregister(&read_gpio_dev);
return ;
} static void read_gpio_shutdown(struct platform_device *pdv)
{ ;
} static int read_gpio_suspend(struct platform_device *pdv,pm_message_t pmt)
{ return ;
} static int read_gpio_resume(struct platform_device *pdv)
{ return ;
} struct platform_driver read_gpio_driver = {
.probe = read_gpio_probe,
.remove = read_gpio_remove,
.shutdown = read_gpio_shutdown,
.suspend = read_gpio_suspend,
.resume = read_gpio_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
}
}; static int read_gpio_init(void)
{
int DriverState; printk(KERN_EMERG "read_gpio enter!\n");
DriverState = platform_driver_register(&read_gpio_driver); printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
return ;
} static void read_gpio_exit(void)
{
printk(KERN_EMERG "read_gpio exit!\n"); platform_driver_unregister(&read_gpio_driver);
} module_init(read_gpio_init);
module_exit(read_gpio_exit);
read_gpio.c
应用程序:
#include <stdio.h> #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h> #include <string.h> #define GPIOS 32 int main(int argc, char *argv[])
{
int fd, i, cmd = ;
char *read_gpio = "/dev/read_gpio_ctl";
char *cmd0 = "";
char *cmd1 = "";
printf("argv[0] is %s;argv[1] is %s;\n", argv[], argv[]); if(strcmp(argv[], cmd0) == ) {
cmd = ;
}
if(strcmp(argv[], cmd1) == ) {
cmd = ;
} if((fd = open(read_gpio, O_RDWR|O_NDELAY)) < ) {
printf("APP open %s failed\n", read_gpio);
} else {
printf("APP open %s success!\n", read_gpio);
printf("%d io value is %d\n", cmd, ioctl(fd, cmd, ));
} close(fd);
}
app_read_gpio
测试结果:
[root@iTOP-]# ./app_read_gpio
argv[] is ./app_[ 312.514145] read_gpio open
[ 312.516876] cmd is ,arg is
[ 312.519870] read_gpio release
read_gpio;argv[] is ;
APP open /dev/read_gpio_ctl success!
io value is
[root@iTOP-]# ./app_read_gpio
argv[] is ./app_[ 314.786489] read_gpio open
[ 314.789131] cmd is ,arg is
[ 314.792307] read_gpio release
read_gpio;argv[] is ;
APP open /dev/read_gpio_ctl success!
io value is
[root@iTOP-]# ./app_read_gpio
argv[] is ./app_[ 321.786146] read_gpio open
[ 321.788790] cmd is ,arg is
[ 321.791899] read_gpio release
read_gpio;argv[] is ;
APP open /dev/read_gpio_ctl success!
io value is
[root@iTOP-]# ./app_read_gpio
argv[] is ./app_[ 323.449833] read_gpio open
[ 323.452526] cmd is ,arg is
[ 323.455489] read_gpio release
read_gpio;argv[] is ;
APP open /dev/read_gpio_ctl success!
io value is
测试结果
二、ioremap控制GPIO寄存器
上面使用的是直接通过软件转换好了的,其实内核也是可以自己做转化的。
自己实现物理地址到虚拟地址的转化,iounmap和ioremap函数可以实现物理地址到虚拟地址的转化
1.硬件
- 原理图部分
- datasheet物理地址
- GPL2CON = 0x1100 0000 + 0x0100 = 0x1100 0100
- GPL2DAT = 0x1100 0000 + 0x0104 = 0x1100 0104
- GPL2PUD = 0x1100 0000 + 0x0108 = 0x1100 0108
- 寄存器不一定是32位的,也有16位或8位的
2.软件
#include <linux/init.h>
#include <linux/module.h>
#include <asm/io.h> MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Topeet"); //用于存放虚拟地址和物理地址
volatile unsigned long virt_addr, phys_addr;
//用户存放三个寄存器的地址
volatile unsigned long *GPL2CON, *GPL2DAT, *GPL2PUD; static void gpl2_device_init(void)
{
//物理地址起始地址0x1100 0100
phys_addr = 0x11000100;
//0x11000100是GPL2CON的物理地址
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寄存器
static void gpl2_configure(void)
{
//配置为输出模式
*GPL2CON &= 0xFFFFFFF0;
*GPL2CON |= 0x00000001;
//GPL2PUD &= 0xfff0;
//GPL2PUD寄存器,bit[0:1]设为0x03,上拉模式
*GPL2PUD |= 0x0003;
} //点灯
static void gpl2_on(void)
{
*GPL2DAT |= 0x01;
} //灭灯
static void gpl2_off(void)
{
*GPL2DAT &= 0xfe;
} static int led_gpl2_init(void)
{
printk(KERN_EMERG "led enter!\n");
gpl2_device_init(); //实现IO内存映射
gpl2_configure(); //配置GPL2为输出模式
gpl2_on();
printk("led dgp2 open\n");
return ;
} static void led_gpl2_exit(void)
{
gpl2_off();
printk(KERN_EMERG "led exit!\n");
} module_init(led_gpl2_init);
module_exit(led_gpl2_exit);
ioremap_leds.c
makefile文件:
TARGET_NAME = ioremap_leds
obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3. PWD ?= $(shell pwd) all:
make -C $(KDIR) M=$(PWD) modules clean:
rm -rf *.o *.ko *.mod.c *.symvers *.order \
.$(TARGET_NAME)*
Makefile
3.编译测试
[root@iTOP-]# insmod ioremap_leds.ko
[ 6116.064904] led enter!
[ 6116.065940] led dgp2 open
[root@iTOP-]# rmmod ioremap_leds
[ 6122.913415] led exit!
[root@iTOP-]# insmod ioremap_leds.ko
[ 6133.090595] led enter!
[ 6133.091567] led dgp2 open
[root@iTOP-]# rmmod ioremap_leds
[ 6137.830391] led exit
测试结果
加载驱动,小灯亮
卸载驱动,小灯灭
4412 GPIO读 和 ioremap控制GPIO寄存器的更多相关文章
- iTOP-4412嵌入式开发板ioremap控制GPIO寄存器
转自迅为电子技术论坛:http://bbs.topeetboard.com GPIO 的寄存器通过 ioremap函数转换之后,可以通过直接控制虚拟地址来控制物理地址(寄存器的实际地址),这样就实现 ...
- EasyARM i.mx287学习笔记——通过modbus tcp控制GPIO
0 前言 本文使用freemodbus协议栈,在EasyARM i.mx287上实现了modbus tcp从机. 在该从机中定义了线圈寄存器.当中线圈寄存器地址较低的4位和EasyARM的P2 ...
- rk3128 通过串口控制 GPIO
2019-04-24 关键字: rk平台控制GPIO功能.rk串口控制引脚电平 本篇文章介绍了如何通过串口来控制 RK3128.RK3288 平台的 GPIO . 我们可以很便捷地通过串口命令来控制 ...
- Android(Java)控制GPIO的方法及耗时分析
前面两篇分别介绍了通过脚本和C代码读写/sys/class/gpio以控制GPIO.实际项目调试时经常还需要在Java代码里控制GPIO,其实现与C代码类似,唯一不同是Android权限.本文重点介绍 ...
- Android(Linux)控制GPIO方法二
前文<Android(Linux)控制GPIO的方法及实时性分析>主要使用Linux shell命令控制GPIO,该方法可在调试过程中快速确定GPIO硬件是否有问题,即对应的GPIO是否受 ...
- Android(Linux)控制GPIO的方法及实时性分析
Linux下控制GPIO的方法有N种,详细请参考<RPi GPIO Code Samples>,文中用十多种语言演示了如何控制GPIO,非常全面详尽.因此,这里不再多做赘述,仅把调试过程中 ...
- 树莓派控制GPIO(Python)
如果你的raspi没有安装python那么先 sudo apt-get update sudo apt-get install python-dev 例如想要控制35管脚的亮灭: 先建一个文本 ...
- 树莓派.使用Node.js控制GPIO
树莓派上的40个GPIO是最好玩的东西 它们可以被C,/C++, Python, Java等语言直接控制 现在就来看看怎么用Node.js做到同样的事情 在试验之前, 请先安装好Node.js, 具体 ...
- RaspberryPi2B使用bcm2835c库控制GPIO
RaspberryPi2B使用bcm2835c库控制GPIO 网上有很多RaspberryPi控制GPIO的方法,有Python.WiringPi.bcm2835 C library 使用bcm283 ...
随机推荐
- p4593 [TJOI2018]教科书般的亵渎
分析 我们发现$Ans = \sum_i \sum_j (j-p_i)^{m+1}$ 因此直接套用622f的方法即可 代码 #include<bits/stdc++.h> using na ...
- 在Mac OS X 10.11 EI Capitan 中提取iso镜像
到Apple store上下载最新的OS X El Capitan ,下载完成后就可以进行iso镜像提取操作了. 步骤一:挂载El Capitan 的安装镜像文件 1 hdiutil attach / ...
- 深入学习Keras中Sequential模型及方法
https://www.cnblogs.com/wj-1314/p/9579490.html
- vm虚拟机用批处理启动和关闭
title vmware 虚拟机开启中 cls&&echo 正在开启VMware虚拟机,请稍候... "D:\vmware\vmware.exe" -x " ...
- Linux——管道与重定向
参考资料: 极客学院IBMdeveloperWorks 重定向标准I/O Linux shell(比如Bash)接收或发送序列和字符串流形式的输入或输出.每个字符都独立于与之相邻的字符.字符没有被组织 ...
- (转载)如何在 Github 上发现优秀的开源项目?
转载自:传送门 之前发过一系列有关 GitHub 的文章,有同学问了,GitHub 我大概了解了,Git 也差不多会使用了,但是还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? 问到 ...
- Python3数据科学入门与实践学习教程
整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的时候可以关注下面几点: 1.为了追求精 ...
- mysql 主从复制 (2)
今天说一下MySQL的主从复制如何做到! 准备工作: 1.两个虚拟机:我这里用的是CentOS5.5,IP地址分别是192.168.1.101 和192.168.1.105: 101做主服务器,105 ...
- Python入门习题8.羊车门问题
例8. 羊车门问题描述:有3扇关闭的门,一扇后停着汽车,另外两扇门后是山羊,主持人知道每扇门后是什么.参赛者首先选择一扇门.在开启它之前,主持人会从另外两扇门中打开一扇门,露出门后的山羊.此时,允许参 ...
- Linux服务器安全配置小结(转)
众所周知,网络安全是一个非常重要的课题,而服务器是网络安全中最关键的环节.Linux被认为是一个比较安全的Internet服务器,作为一种开放源代码操作系统,一旦Linux系统中发现有安全漏洞,Int ...