Linux GPIO键盘驱动开发记录_OMAPL138

Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些。看了一下Linux3.3内核文件下的driver目录,点开里面的C文件,感觉底层的Linux驱动机制还是很复杂的,还需要一段漫长时间的学习。现在开发的也不能说是叫做驱动,也只能说是驱动的应用,我们学习驱动也从应用逐步开始,往里面深入吧。

0.开发准备

  • 内核源文件(当时我们编译内核时候的目录,很重要,编译驱动的时候需要依赖这些内核源文件)
  • Makefile文件(编译驱动的Makefile文件)
  • 驱动源程序
  • 应用程序(有main函数的)

1.键盘的接线图

我们主要使用USER0和USER1 KEY,两个按键,完成Linux GPIO键盘驱动开发。从图中可以看出GPIO0_6和GPIO6_1主要采集键盘按下的信息。

2. key.c驱动文件

驱动结构可以看上图,主要是在注册Linux内核设备,我们使用platform_device进行内核注册。我们从思维到图上看,从后往前的顺序进行一个一个定义。

2.1 gpio_key_buttons结构体

Linux提供的标准结构体,在#include <linux/gpio_key.h>头文件中。这里面就要定义按键的行为信息和指定GPIO口,这个是和上面的硬件原理图打交道的一个结构体。以下是和这个结构体有关的定义。

#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <mach/da8xx.h> // 板子的头文件 #define OMAPL138_KEYS_BEBOUNCE 10
#define OMAPL138_GPIO_KEYS_POLL_MS 200 #define OMAPL138_USER_KEY0 GPIO_TO_PIN( 0,6 )
#define OMAPL138_USER_KEY1 GPIO_TO_PIN( 6,1 ) static const short omapl138_user_key_pins[] = {
DA850_GPIO0_6, DA850_GPIO6_1, -1
}; static struct gpio_keys_button omapl138_user_keys[] = {
[0] = {
.type = EV_KEY,
.active_low = 1,
.wakeup = 0,
.debounce_interval = OMAPL138_KEYS_BEBOUNCE,
.code = KEY_PROG1,
.desc = "user_key0",
.gpio = OMAPL138_USER_KEY0
},
[1] = {
.type = EV_KEY,
.active_low = 1,
.wakeup = 0,
.debounce_interval = OMAPL138_KEYS_BEBOUNCE,
.code = KEY_PROG2,
.desc = "user_key1",
.gpio = OMAPL138_USER_KEY1
}
};

在其他的平台可能GPIO口的定义不同,我用的是OMAPL138,使用的内核文件是OMAPL138提供的,他的里面定义了da8xx.h定义了相关GPIO的宏定义,你需要找到你自己平台GPIO结构体的定义,修改这个宏定义即可。这个结构提十分具备可读性,一看就能看懂了,其中的.code就是我们写应用程序的时候,按键读出来的值,就可以判断了。

2.2 gpio_keys_platform_data结构体

platform_data结构体顾名思义,基本上就是和我们整个驱动开发数据相关的。

static struct   gpio_keys_platform_data     omapl138_user_keys_pdata    =   {
.buttons = omapl138_user_keys,
.nbuttons = ARRAY_SIZE( omapl138_user_keys )
};

里面的成员,.buttons就是刚才我们定义gpio_keys_button数组,.nbuttons就是长度,我们使用宏函数ARRAY_SIZE完成取值。

2.3 platform_device结构体

思维导图在向前,我们就需要定义platform_device结构体了,这个结构体就是要和Linux内核打交道的结构提了。里面有设备名称.name,.id,dev

static void     omapl138_user_keys_release( struct device *dev ) {

}
static struct platform_device omapl138_user_keys_device = {
// you can find mount root by command "dmesg | grep gpio-keys ";
// cat /proc/bus/input/devices look the where the device is.
.name = "gpio-keys",
.id = 1,
.dev = {
.platform_data = &omapl138_user_keys_pdata,
.release = omapl138_user_keys_release,
},
};

.name中当驱动程序向linux注册后通过dmesg | grep gpio-keys命令就可以看到这个名字,在内核调试输出中可以看到。.id设备挂载节点的id,同样的设备id不能重复。.dev给定data和release函数(可以为空)。

2.4 初始化函数和退出函数

最后就是初始化函数和退出函数,最终要的就是resigster这个函数了。向内核注册设备。

static int __init omapl138_user_keys_init( void )
{
int reg;
reg = platform_device_register( &omapl138_user_keys_device );
if( reg ) {
pr_warning( "Could not register baseboard GPIO tronlong keys!" );
}else {
printk( KERN_INFO "User keys register successful!" );
}
return reg;
} static void __exit omapl138_user_keys_exit( void )
{
platform_device_unregister( &omapl138_user_keys_device );
printk( KERN_INFO "user keys unregister ! \n" );
} module_init( omapl138_user_keys_init );
module_exit( omapl138_user_keys_exit ); MODULE_DESCRIPTION( "user keys platform driver," );
MODULE_AUTHOR("Carlos Wei");
MODULE_LICENSE( "GPL" );

当我们使用insmod name.ko的时候,自动调用module_init()里面写入的函数了,当我们rmmod name.ko的时候,自动调用module_exit()里面写入的函数。

3 编译内核或者以模块形式加载

我们可以把这个驱动程序静态编译到内核代码树中也可以以模块的形式加载到内核中,我建议一开始开发的时候使用模块的形式加入到内核中,等着编译成熟之后,在编译到内核里面。

3.1 编译

制定内核源码文件的路径,写好Makefile文件,编译后上传到目标板的任意路径。

3.1.1 Makefile文件

ifneq ($(KERNELRELEASE),)

obj-m := key.o

else

all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi- clean:
rm -rf *.ko *.o *.mod.o *.mod.c *.symvers modul* .button.* .tmp_versions KDIR=/usr/src/linux-headers-3.3.0-omapl138 endif

这里比较重要的:

  • KDIR=? 这个位置就是你Linux源码文件的路径,(内核事先编译一定要正确
  • CROSS_COMPILE= 这个指定交叉编译器,我的交叉编译器名字比较怪异arm-arago-linux-gnueabi-

3.1.2 Make一下生成key.ko

编译完成之后,通过ls命令,查看生成了key.ko文件。

通过scp或者ftp把key.ko文件传输到目标板子上。

3.2 加载驱动与查看挂载节点

1) insmod key.ko

2) 通过dmesg查看内核输出是否成功

3)通过cat /proc/bus/input/devices命令查看挂在详情

重点是event1,一会儿我们编辑应用程序需要打开/dev/input/event1这个设备节点进行对GPIO键盘操作。

4)测试键盘输入

在没有编写应用程序的时候,我们也可以通过简单的方法对GPIO键盘进行一个简单的测试。GPIO挂载节点是Handlers = event1 则输入:

cat /dev/input/event1

然后我们按键盘,如果当我们点击键盘的时候 终端输出乱码则代表我们的驱动是编写成功的。

5) 解挂驱动

如果我们不需要驱动了,则需要进行解挂驱动:

rmmod key.ko

也可以通过dmesg命令查看内核输出日志。

4 应用程序开发

建立文件:key_app.c


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <time.h>
#include <fcntl.h>
#include <linux/input.h> int main( int argc, char **argv )
{
int key_state;
int fd;
int ret;
int code;
struct input_event buf; fd = open( "/dev/input/event1", O_RDONLY );
if( fd < 0 ) {
printf( "Open GPIO_keys failed!!\n" );
return -1;
} printf( "Open GPIO keys successful! \n" );
while( 1 ) {
ret = read( fd, &buf, sizeof( struct input_event ) );
if( ret <= 0 ) {
printf( "read failed! \n" );
return -1;
}
code = buf.code;
key_state = buf.value;
printf("wait...... \n");
switch( code ) {
case KEY_PROG1: code = '1';
printf( "KEY1 state = %d\n", key_state );
break;
case KEY_PROG2: code = '2';
printf( "KEY2 state = %d\n", key_state );
break;
} }
printf("key test finished.\n");
close(fd);
return 0;
}

一个非常简单的程序,就是输出案件之。我们编译它:

arm-arago-linux-gnueabi-gcc key_app.c -o key_app.o

生成的key_app.o文件放入目标板的Linux目录,然后运行即可。

5 调试结果

通过按键就可以输出这些值,意味着我们的驱动开发成功了。

附录:源程序

链接: https://pan.baidu.com/s/1pNcEBEj 密码: xpsq


版权声明:

1. 本文为MULTIBEANS团队研发跟随文章,未经允许不得转载。

2· 文中涉及的内容若有侵权行为,请与本人联系,本人会及时删除。

3· 尊重成果,本文将用的参考文献全部给出,向无私的工程师,爱好者致敬。

Linux GPIO键盘驱动开发记录_OMAPL138的更多相关文章

  1. Linux 下wifi 驱动开发(三)—— SDIO接口WiFi驱动浅析

    SDIO-Wifi模块是基于SDIO接口的符合wifi无线网络标准的嵌入式模块,内置无线网络协议IEEE802.11协议栈以及TCP/IP协议栈.可以实现用户主平台数据通过SDIO口到无线网络之间的转 ...

  2. Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析

    源: Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析

  3. 基于335X平台Linux交换芯片驱动开发

    基于335X平台Linux交换芯片驱动开发   一.软硬件平台资料 1.开发板:创龙AM3359核心板,网口采用RMII形式. 2.Kernel版本:4.4.12,采用FDT 3.交换芯片MARVEL ...

  4. 转: 嵌入式linux下usb驱动开发方法--看完少走弯路【转】

    转自:http://blog.csdn.net/jimmy_1986/article/details/5838297 嵌入式linux下的usb属于所有驱动中相当复杂的一个子系统,要想将她彻底征服,至 ...

  5. Android HAL层与Linux Kernel层驱动开发简介

    近日稍微对Android中的驱动开发做了一些简要的了解. HAL:Hardware Abstract Layer 硬件抽象层,由于Linux Kernel需要遵循GPL开源协议,硬件厂商为了保护自己硬 ...

  6. Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动【转】

    本文转载自:https://blog.csdn.net/zqixiao_09/article/details/50858776 版权声明:本文为博主原创文章,未经博主允许不得转载.    https: ...

  7. Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作

    前面对SD卡控制器有了一个主要的介绍.事实上SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法.当然不同的控制器对硬件控制的方法不尽同样,可是他们终于都能像core层提交一个统一的封 ...

  8. linux内核中驱动开发常见的相似多态

    #include<stdio.h> #include<stdlib.h> struct test { char name[20]; void (*func)(char *); ...

  9. (57)Linux驱动开发之三Linux字符设备驱动

    1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...

随机推荐

  1. 微软发布Azure Stack第一个技术预览版

    为了提升商业灵敏度和加快创新步伐,各个企业都在迅速地转向云服务.在微软,我们已经见到微软智能云Azure的飞速发展和使用,每月我们都有近十万的新增订阅量.然而,我们也了解到还有很多企业在完全移到公有云 ...

  2. 【Leetcode】【Medium】Longest Substring Without Repeating Characters

    Given a string, find the length of the longest substring without repeating characters. For example, ...

  3. 【深入理解JAVA虚拟机】第4部分.程序编译与代码优化.1.编译期优化。这章编译和实战部分没理解通,以后再看。

    1.概述 1.1.编译器的分类 前端编译器:Sun的Javac. Eclipse JDT中的增量式编译器(ECJ)[1].  把*.java文件转变成*.class文件 JIT编译器:HotSpot ...

  4. java学习第一步,使用IntelliJ IDEA编写自己的第一个java程序

    首先下载java的jdk,然后说一下IDEA的配置 IntelliJ IDEA目前公认的最好的java开发工具,不过一般的学校的教学还是使用eclipse来进行java的开发.所以老师一般只会教你如何 ...

  5. UVA151 Power Crisis

    嘟嘟嘟 这道题被评为紫题完全是在假(虽然我也跟风评了紫题),顶多黄题难度. 评黄题的主要原因是得知道约瑟夫递推公式,即fn = (fn - 1 +m) % n.表示n个人报数最后的获胜者,需要注意的是 ...

  6. log4net快速使用流程

    以下内容大部分来自这里,对原作者流子表示感谢 1.Nuget安装,当前版本2.0.8 2.创建log4net.config文件,文件内容如下: <?xml version="1.0&q ...

  7. PAT——1005. 继续(3n+1)猜想

    pat原题目:https://www.patest.cn/contests/pat-b-practise/1005 原题目: 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况 ...

  8. 【Node.Js】npm国内被墙的解决方法

    移动网就是坑,有VPN也上不去,真操蛋~先吐槽一下@中国移动 折腾了一晚上,总是报连接错误,导致我npm安装不上,查了半天资料,找到个靠谱的,粘贴过来备用. 原文地址:http://snoopyxdy ...

  9. javascript入门教程 (2)

    这篇我就不铺垫和废话了,我们开始正式进入JS核心语法的学习… 首先我们从基础入手... 一. 基础语法 1.1 区分大小写 JS语法规定变量名是区分大小写的 比如: 变量名 learninpro 和变 ...

  10. Notes 20180306 : 变量与常量

    1.1 变量与常量 我们在开发中会经常听到常量和变量,那么常量和变量指的又是什么呢?顾名思义,在程序执行过程中,其值不能被改变的量称为常量,其值能被改变的量称为变量.变量与常量的命名都必须使用合法的标 ...