Chinaunix首页 | 论坛 | 博客
  • 博客访问: 478504
  • 博文数量: 73
  • 博客积分: 1170
  • 博客等级: 少尉
  • 技术积分: 720
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-20 15:48
文章分类

全部博文(73)

文章存档

2013年(9)

2012年(64)

我的朋友

分类: LINUX

2013-05-03 10:29:13

这一个在OMAP3530/DM3730 ARM A8平台上,LINUX系统下,对GPIO的操作。我只是想实现简单的读写功能。
目前可以做到写,写0写1都可以。
但是读遇到了麻烦。
就是,设置为 读 的方向以后,一直没法读取状态,尽管该IO口上的的确确就是1.8V的高电平。

前后我大致使用了三种方法,一种未遂,两种只能写。

三种方法是
1 在LINUX文件系统下,有一个/sys/class/gpio文件夹,在这里可以申请GPIO口,并通过相应文件,直接操作GPIO口。这个只能写。
2 使用OMAP的头文件,但是一直不知为何没办法使用。属于 未遂。
3 通过LINUX内核,写GPIO驱动,加载入内核。再跑用户态程序,结果,还是只能写不能读。

第一种方法,操作过程其实很简单:
进入该文件夹
Cd /sys/class/gpio

申请相应Io口,比如我申请161
Echo 161 > export

检查是否生成 gpio161文件夹,有则进入。
假如不存在,说明这个Io口已经被占用,不能申请。

向direction写方向,注意这些文件都不可以通过VIM打开直接写,只能用echo 命令

Direction可写的选项有 high low out in
具体细节可以查百度。

然后是读写value,读IO时,读,写IO时,是写VALUE,当然,写的情况,可以通过direction一次完成。

但是,问题就是,写IO口的时候好好的,但是没法读。
Value里一直是0,哪怕IO端口就是1.8V。

这个时侯我们搜索了,但是一直没有找到有建设性的东西。
除了看到有的资料里说,要设置为 允许输入 或者类似于 允许改变Io口的方向(就是允许改变读和写的状态。)

但是那些大多数是用了一些头文件,类似于gpio.h之类的,问题是这个文件我从来就没用上。后来,使用第三种方法后,能用内核的gpio.h后,好像就找不到那个资料了,后悔当时没保存,怎么设都没用。
到了后来,当我写驱程,加载入内核,还是发现这个问题以后,我开始怀疑,所有问题都在于一个 设置允许输入的地方,只可惜,我怎么都找不着这个地方。
在系统里的某个文件或者某个位置?还是通过某条指令?
让我奇怪的是,在网上海搜了关于GPIO的东西,居然都没看到。

2 第二种方法,我想用gpio.h这个头文件,用一些系统的子函数直接操作gpio。
后来搜了整个虚拟机系统,找到了一个名字带omap的头文件,心想这个应该跟我的开发板有关系,于是就使用这个。

用过-I 命令。结果没用
甚至我把它拽进交叉编译器的默认路径,还是没用。
这个没用需要仔细说明一下:就是说,已经找到了这个gpio.h,但是附带了更多的找不到,我看了一下,这些都是在gpio.h中加的头文件。
于是我试过一个一个加进去,结果问题往下越来越恐怖,找不到的头文件越来越多,我终于放弃了这种方法。

3 第三种方法,就是写驱动,在tuxygood的帮助下——或者直接说就是他手把手教我的得了。
我总算用上了这个系统自带的gpio.h,不过不是那个什么omap就是了,我心想先用着再说——我之所以无视这一点,还有一个原因:如果我能够在系统的/sys/class/gpio下,(写是没问题的)操作GPIO,那就应该可以理解为,它似乎与硬件平台无关?

这个过程怪复杂的,我很难说清楚,不过当时,我把tuxygood教我的东西,我把聊天记录整理成了一个文档,一会附上。

很可惜的是,问题依然是,可写不可读。
基本知识用脑记住,具体细节用心琢磨
    


 
附上第三种方法,也就是加载内核驱动模块的过程
由于一直找不到gpio.h等各种头文件。
于是乎重新编译一个新的内核。


使用的是光盘里带的:
具体方法是:

//********************************************************************
解压linux-03.00.01.06.tar.bz2
tar xvf linux-03.00.01.06.tar.bz2

进入内核目录

cd linux-03.00.01.06

执行 make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- (有空格)omap3_stalker_defconfig

然后执行 make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage
生成内核。
//********************************************************************

这个是新生成的内核,并不需要放到SD卡上。
因为接下来会使用这个新内核来生成一个加载入开发板系统内核的一个模块。


接下来编译的是一个应用程序下面一层的一个  驱动。应用程序通过它来控制GPIO

使用的程序是:在G盘下,文件名:omap3gpio.c

#include
#include
#include
#include
这个程序里,只是一组函数,也就是说,其实,它本质上也只是相当于一个库,之所以无法加载,那只能说明一个问题,我的编译命令不对,所以,为了成功加载这个gpio.h,其实关键还是要看明白那个Makefile怎么写。
//---------------------------------------------------------------------------------------------------------------
static int gpio_open(struct inode *inode,struct file *file)
{
        printk(KERN_WARNING"gpio_open success!\n");
        return 0;
}
//-----------------------------------------------------------------------------------------------------------------
static int gpio_close(struct inode *inode,struct file *file)
{
         printk(KERN_WARNING"gpio release \n");
         return 0;
}
//---------------------------------------------------------------------------------------------------------------
static ssize_t  gpio_read(struct file *file,char __user *buf, size_t count,loff_t *offset)
{

                int i;
                i = gpio_get_value(158);
                if(1 == i)
                        copy_to_user("HIGH",buf,sizeof(buf));
                else
                        copy_to_user("LOW",buf,sizeof(buf));
                return 0;
}
//-----------------------------------------------------------------------------------------------------------------
static const struct file_operations gpio_ops = {
        .owner = THIS_MODULE,
        .open = gpio_open,
        .read = gpio_read,
        .release = gpio_close,
};
//--------------------------------------------------------------------------------------------------------------
static int __init omap3gpio_init(void)
{

        int ret = 0;
        ret = register_chrdev(0,"gpio",&gpio_ops);                 //????????
        if(ret < 0)
        {
                printk(KERN_WARNING"gpio register_chrdev faild\n");
                return ret;
        }

//????
        printk(KERN_WARNING"gpio register_chrdev success, major = %d\n", ret);
        gpio_request(158,"gpio"); //要求打开158号gpio
        gpio_direction_input(158); //设置其为输入

        return 0;
}
//---------------------------------------------------------------------------------------------------------------------
static void __exit omap3gpio_exit(void)
{
}        //??????????????????????????????

module_init(omap3gpio_init);
module_exit(omap3gpio_exit);
MODULE_AUTHOR("Seed txyugood");
MODULE_DESCRIPTION("omap3gpio  driver");
MODULE_LICENSE("GPL");


//------------------------------------------------------------------------------------------------------//------------------------------------------------------------------------------------------------------
KERNELDIR = /home/ema/linux/linux-03.00.01.06//这是新编译的内核所在路径

PWD := $(shell pwd)
all:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules      



   obj-m := omap3gpio.o

//如前所说,这个MAKEFILE是理解如何做到能够编译GPIO.H的关键。
//研究重点。


直接编译make是不行的,这个时侯,在这个文件路径下,执行如下命令,注意查看是否生成.ko文件,有即成功

make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

然后会生成 一个omap3gpio.ko文件,这就是 驱动模块





如常编译应用软件。
再也不会找不到gpio.h了

注:
应该是先编译 应用软件,然后会有一堆的错误,然后再执行上一阶段的最后一个指令,生成 驱动模块。



把这个生成的.ko模块放到开发板上。
然后加载进内核里。

insmod omap3gpio.ko

然后执行一个命令,查看它的设备号
同时也检查是否成功加载GPIO模块

Dmesg

会出现一堆的东西,检查最后一句
会是
Gpio register_chrdev success,major = 250

然后 创建节点
Mknod /dev/gpio_test c 250 0


然后运行应用程序

这个应用程序 就是 所谓的 用户态程序
阅读(1877) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~