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.oelseall: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_versionsKDIR=/usr/src/linux-headers-3.3.0-omapl138endif

这里比较重要的:

  • 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· 尊重成果,本文将用的参考文献全部给出,向无私的工程师,爱好者致敬。

转载于:https://www.cnblogs.com/sigma0/p/8284147.html

Linux GPIO键盘驱动开发记录_OMAPL138相关推荐

  1. Android系统 linux内核按键驱动开发

    Android系统 linux内核按键驱动开发 前言 刚入门的小白,在csdn的帮助下完成了第一个按键驱动,特写此文记录学习并分享给有需要的人. 1.修改设备树.dts 我是用的开发板是rp-rk32 ...

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

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

  3. Linux SD卡驱动开发(五) —— SD 卡驱动分析Core补充篇

    Core层中有两个重要函数 mmc_alloc_host 用于构造host,前面已经学习过,这里不再阐述:另一个就是 mmc_add_host,用于注册host 前面探测函数s3cmci_probe, ...

  4. Linux基础入门--驱动开发--USB

    Linux基础入门--驱动开发--USB 1.基本概念 2.组成结构 2.1 设备描述符 2.2 配置描述符 2.3 接口描述符 2.4 端点描述符 2.5 字符串描述符 3.管道 4.端点分类 4. ...

  5. Linux 中的驱动开发的初学者体会

    Linux 中的驱动开发的初学者体会 很多年前,心里就存下这样一个愿望.就是把Linux 的驱动开发搞清楚. 但是一开始上上这样的开发难度天大了,对着一堆的寄存器发愁. 于是就从简单的STM8,PIC ...

  6. Android 系统(4)---Android HAL层与Linux Kernel层驱动开发简介

    Android HAL层与Linux Kernel层驱动开发简介 近日稍微对Android中的驱动开发做了一些简要的了解,稍稍理清了一下Android驱动开发的套路,总结一下笔记. HAL:Hardw ...

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

    Android HAL层与Linux Kernel层驱动开发简介 阅读数:5070 近日稍微对Android中的驱动开发做了一些简要的了解,稍稍理清了一下Android驱动开发的套路,总结一下笔记. ...

  8. linux下IIC驱动开发分析

    1.  IIC规范 IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.IIC总线产生于在80年代,最初为音频和 ...

  9. Linux X86 PS/2键盘驱动分析记录

    1,Linux X86 PS/2 键盘驱动框架流程(以下均已Intel 8042键盘控制器为例): 1.1 设备初始化注册流程: 键盘控制器硬件驱动(i8042.c) -> 串口驱动核心(ser ...

最新文章

  1. OC高效率52之理解消息转发机制
  2. 好技术领导和差技术领导区别在哪里
  3. ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB
  4. @autowired注解原理_SpringBoot注解大全,收藏一波!!!
  5. 可逆素数编程c语言,巧用C语言求四位的可逆素数
  6. python判断字符串在元祖_Python基础(2)——字典、元祖、字符串方法、非空即真、文件...
  7. oracle、sqlserver创建表、删除表、创建索引的sql
  8. python教程视频下载-python怎么下载视频
  9. 高密度椒盐噪声的多方向加权均值滤波算法-附代码
  10. 短视频解析,去水印原理整理汇总
  11. Mysql 日历数据表
  12. Android Studio 开发实践——简易版音游APP(一)
  13. DID会固定年份吗_互助问答第31期:固定效应与随机效应选择和面板数据处理
  14. 微信小程序上传图片后 开发者工具自动刷新问题
  15. 读书笔记:《群论彩图版》
  16. 【CG物理模拟系列】开篇:介绍(下)
  17. 英特尔530和535哪个好_2020年终好物推荐,英特尔Evo平台认证更出彩
  18. matlab 图像处理技术
  19. 转换罗马数字,输入一串数字字符串,将其转化为希腊字符串。
  20. DY-Tiva-PB 资料 电路图

热门文章

  1. 面向程序员的GPGPU技术系列(1) 为什么要理解GPU体系结构?
  2. 比尔盖茨:有种事你永远不能等待!
  3. Linux下搭建DHCP服务器 【2020.12.01】
  4. java获取web项目的绝对路径的方法总结
  5. [转] python中的高效迭代器函数
  6. [转]caffe-ssd中 net.forward()返回值
  7. 大数据时代下的“管理”要素数据化
  8. mysql 查询时间之内_MySQL 查询时间段内的数据
  9. html中一个页面大概多少px,当屏幕 (浏览器窗口) 小于 768px, 每一列的宽度是 100% -HTML教程_小白教程_css5.net...
  10. swoole mysql 协程_swoole-orm: 基于swoole的mysql协程连接池,简单封装。实现多个协程间共用同一个协程客户端。参考thinkphp-orm...