文章目录

  • 全系列传送门
  • 1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找
  • 2. 在设备树配置文件中添加设备节点定义以及其引脚定义
  • 3. 修改设备树文件添加配置
  • 4. drivers/gpio目录下添加gpio驱动
    • 新建driver/gpio/gpio-user.c
    • 在`driver/gpio/Makefile`添加:
    • 在driver/gpio/Kconfig添加:
  • 5. 通过make menuconfig来进行配置
    • 加载环境变量
    • 清除之前的编译
    • 复制arch/arm/config/imx_v7_defconfig ->.config
    • make menuconfig
    • 复制 .config 到 arch/arm/config/imx_v7_defconfig
    • 执行编译
    • 查看验证
  • 验证

全系列传送门

Linux嵌入式驱动开发01——第一个驱动Hello World(附源码)

Linux嵌入式驱动开发02——驱动编译到内核

Linux嵌入式驱动开发03——杂项设备驱动(附源码)

Linux嵌入式驱动开发04——应用层和内核层数据传输

Linux嵌入式驱动开发05——物理地址到虚拟地址映射

Linux嵌入式驱动开发06——第一个相对完整的驱动实践编写

Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

Linux嵌入式驱动开发08——字符设备(步步为营)

Linux嵌入式驱动开发09——平台总线详解及实战

Linux嵌入式驱动开发10——设备树开发详解

Linux嵌入式驱动开发11——平台总线模型修改为设备树实例

Linux嵌入式驱动开发12——pinctl和gpio子系统实践操作

Linux嵌入式驱动开发13——ioctl接口(gpio控制使用)

Linux嵌入式驱动开发14——中断的原理以及按键中断的实现(tasklet中断下文)

Linux嵌入式驱动开发15——等待队列和工作队列

Linux嵌入式驱动开发16——按键消抖实验(内核定时器)

Linux嵌入式驱动开发17——输入子系统

Linux嵌入式驱动开发18——I2C通信

1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找

/arch/arm/boot/dts


打开头文件

imx6q-pinfunc.h

查找EIM_A17

#define MX6QDL_PAD_EIM_A16__GPIO2_IO22              0x0f4 0x408 0x000 0x5 0x0

2. 在设备树配置文件中添加设备节点定义以及其引脚定义

然后,我们要在设备树中添加引脚定义,打开imx6qdl-sabresd.dtsi

imx6qdl-sabresd.dtsi

添加下面的两部分代码

 gpio_user: gpios{pinctrl-names = "default";pinctrl-0 = <&pinctrl_user>;compatible = "gpio-user";gpio0{label = "D01";gpios = <&gpio3 15 1>;default-direction = "out";};gpio1{label = "D02";gpios = <&gpio2 21 1>;default-direction = "out";};};


保证这些引脚没有被定义,把复用去掉

     pinctrl_user: usergrp {fsl,pins = <MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x0b0b10MX6QDL_PAD_EIM_A17__GPIO2_IO21   0x0b0b10>;};

3. 修改设备树文件添加配置

arch/arm/boot/dts/imx6q-c-sabresd.dts

添加代码

&gpio_user {pinctrl-names = "default";pinctrl-0 = <&pinctrl_user>;fsl,user;status = "okay";
};

4. drivers/gpio目录下添加gpio驱动

drivers/gpio目录下

添加gpio驱动gpio-user.c,名字需要与节点定义里的驱动名字保持相同,客户也可以自己编写驱动。

新建driver/gpio/gpio-user.c

Linux嵌入式飞凌开发板GPIO驱动模块modules_gpio_test

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/fs.h>#define GPIO_U_IOCTL_BASE 'x'
#define GPIOC_OPS   _IOWR(GPIO_U_IOCTL_BASE,0,int)#define MAX_GPIO_NR 32struct gpio_user_data{const char *label;bool input;unsigned gpio;unsigned dft;
};
static struct gpio_misc{struct miscdevice misc;struct gpio_user_data *data;int gpio_count;
} *gpio_misc;static int gpio_user_open(struct inode *inodp, struct file *filp)
{if(!gpio_misc)return -ENODEV;return 0;
}static int gpio_user_release(struct inode *inodp, struct file *filp)
{if(!gpio_misc)return -ENODEV;return 0;
}static long gpio_user_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)
{int no, offset;unsigned long val;unsigned long __user *p = (void __user *)arg;struct gpio_user_data *data;unsigned long get_value;if(!gpio_misc)return -ENODEV;data = gpio_misc->data;if(_IOC_TYPE(cmd) != GPIO_U_IOCTL_BASE)return -EINVAL;switch(_IOC_NR(cmd)){case 0:if(get_user(val,p))return -EFAULT;if(data[val].input){val = gpio_get_value(data[val].gpio);put_user(val,p);} else {gpio_set_value(data[val].gpio,val >> 31);}break;default:return -ENOTTY;}return 0;
}static const struct file_operations gpio_user_fops = {.owner = THIS_MODULE,.open = gpio_user_open,.release = gpio_user_release,.unlocked_ioctl = gpio_user_ioctl,
};static void gpio_user_init_default(void)
{int i,ret;struct gpio_user_data *data;data = gpio_misc->data;for(i = 0;i < gpio_misc->gpio_count;i++){if(!gpio_is_valid(data[i].gpio)){continue;}ret = gpio_request(data[i].gpio,data[i].label);if(ret < 0){continue;}if(data[i].input){gpio_direction_input(data[i].gpio);}else{gpio_direction_output(data[i].gpio,data[i].dft);}}
}
static void gpio_user_free_default(void)
{int i;struct gpio_user_data *data;data = gpio_misc->data;for(i = 0;i < gpio_misc->gpio_count;i++){if(!gpio_is_valid(data[i].gpio)){continue;}gpio_free(data[i].gpio);}
}
static int gpio_user_probe(struct platform_device *pdev)
{int index;struct device_node *node = pdev->dev.of_node, *child;gpio_misc = devm_kzalloc(&pdev->dev,sizeof(*gpio_misc),GFP_KERNEL);if(!gpio_misc){return -ENOMEM;}gpio_misc->gpio_count = of_get_available_child_count(node);if(!gpio_misc->gpio_count){return -ENODEV;}if(gpio_misc->gpio_count > MAX_GPIO_NR){gpio_misc->gpio_count = MAX_GPIO_NR;}gpio_misc->data = devm_kzalloc(&pdev->dev,sizeof(struct gpio_user_data) * gpio_misc->gpio_count,GFP_KERNEL);if(!gpio_misc->data){return -ENOMEM;}index = 0;for_each_available_child_of_node(node,child){const char *input;struct gpio_user_data *data = &gpio_misc->data[index++];        data->label = of_get_property(child,"label",NULL) ? : child->name;input = of_get_property(child,"default-direction",NULL) ? : "in";if(strcmp(input,"in") == 0)data->input = true;data->gpio = of_get_gpio_flags(child,0,&data->dft);}gpio_user_init_default();gpio_misc->misc.name = "gpio";gpio_misc->misc.minor = MISC_DYNAMIC_MINOR;gpio_misc->misc.fops = &gpio_user_fops;return misc_register(&gpio_misc->misc);
}
static int gpio_user_remove(struct platform_device *pdev)
{gpio_user_free_default();misc_deregister(&gpio_misc->misc);return 0;
}static const struct of_device_id of_gpio_user_id_table[] = {{ .compatible = "gpio-user",},{},
};MODULE_DEVICE_TABLE(of,of_gpio_user_id_table);static struct platform_driver gpio_user_driver = {.probe = gpio_user_probe,.remove = gpio_user_remove,.driver = {.owner = THIS_MODULE,.name = "gpio-user",.of_match_table = of_gpio_user_id_table,},
};
module_platform_driver(gpio_user_driver);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-user");

同时修改Kconfig和Makefile文件。

修改dirver/gpio目录下的Kconfig和Makefile文件:

driver/gpio/Makefile添加:

obj-$(CONFIG_GPIO_USER_INTF) += gpio-user.o

在driver/gpio/Kconfig添加:

config GPIO_USER_INTFtristate "gpio user interface"---help---this driver for all gpio control

5. 通过make menuconfig来进行配置

在目录linux-4.1.15下,首先进行的操作

加载环境变量

 . /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa9hf-neon-poky-linux-gnueabi

然后,

清除之前的编译

make distclean

复制arch/arm/config/imx_v7_defconfig ->.config

arch/arm/config/imx_v7_defconfig

到目录linux-4.1.15下,修改名字为

.config

make menuconfig

然后运行

make menuconfig


修改完成后,保存,然后打开 .config 文件,可以看到我们的gpio已经加载了过来

然后

复制 .config 到 arch/arm/config/imx_v7_defconfig

cp  .config arch/arm/config/imx_v7_defconfig

最后

执行编译

make distclean
make imx_v7_defconfig
make zImage -j16
make dtbs
make modules -j16

编译结束后

查看验证


验证

复制我们的测试程序到开发板

我们的测试程序,测试的是DO1,也就是EIM_AD15,out是输出,0是选择了第一个DO1对应的EIM_AD15,1的话就是选择DO2对应的EIM_A17,最后的0或者1就是输出的高低电平

Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)相关推荐

  1. 海康Camera MVS Linux SDK二次开发封装ROS packge过程记录(c++)

    Livox Lidar  + HIKROBOT Camera系列 最近在开发相机和激光雷达融合的slam算法,主要用于三维重建,想实时的得到彩色点云地图,传感器选择了海康威视的工业相机和大疆的固态激光 ...

  2. 关于NXP官网i.mx6q与飞凌开发板i.mx6q之间的差异

    首先介绍一下他们都是使用的i.mx6q处理芯片,飞凌是根据NXP官网上的开发板设计的核心板,但是飞凌的debug调试串口不是和NXP官网的开发板使用的一个口,大家要特别注意,在将飞凌的信息下载到NXP ...

  3. 【WinCE】流设备驱动简介及GPIO驱动的实现

    流设备驱动实际上就是导出标准的流接口函数的驱动,这是文档上面的定义.在WinCE中,所有的流设备都导出流设备接口,这样WinCE中的Device Manager可以加载和管理这些流设备驱动.  流设备 ...

  4. WinCE流设备驱动简介及GPIO驱动的实现

    作者:ARM-WinCE 流设备驱动实际上就是导出标准的流接口函数的驱动,这是文档上面的定义.在WinCE中,所有的流设备都导出流设备接口,这样WinCE中的Device Manager可以加载和管理 ...

  5. 开发人员学Linux(1):VirtualBox中安装CentOS7过程记录

    2019独角兽企业重金招聘Python工程师标准>>> 在开发过程中常常需要进行一些预研,而有些操作对操作系统可能具有破坏性且是不可恢复的,或者需要在不同的操作系统中去观察结果,虽然 ...

  6. LINUX驱动开发(二)GPIO驱动框架

    1. 驱动框架 pinctrl子系统+gpio子系统+设备树+platform总线. pinctrl子系统重点在设置引脚复用,gpio子系统用于初始化引脚. Linxu提供总线-设备-驱动模型,用于将 ...

  7. linux -- 嵌入式2.6.37wifi-vnt6656移植驱动

    [A]          2.6.32.2内核下的移植 这里是友善之臂提供的2.6.32.2内核 + VNT6656 WLAN源代码 1.20.03的编译和使用方法: 1.编译驱动模块 目前1.20. ...

  8. s3c2440 ARM9 裸机驱动第一篇-GPIO驱动(汇编)

    一 开发环境: 1.ubuntu 2.JZ2440开发板 二 硬件部分 JZ2440开发板上将GPF4-7四个引脚外接LED,从电路图可以得知,IO口为低电平时LED灯亮. 查询s3c2440 数据数 ...

  9. linux系统中离线安装python3.7过程记录

    最近公司新弄来一台linux  redhat 4.4.7服务器,准备在上面离线安装python3.7,安装过程中出现一些问题,特此记录下来. 首先在python官网上下载了 Python-3.7.3. ...

最新文章

  1. 导师对帮助研究生顺利完成学业提出了20条劝告:第一,不要有度假休息的打算.....
  2. 讲真,上班路上 1 小时算很幸福了!
  3. Android 10.0 PackageManagerService(三)APK扫描-[Android取经之路]
  4. flex 3 使用手册
  5. 第一行代码第一章——你的第一行Android代码
  6. 深入Java关键字null
  7. myeclipse中添加Oracle数据库
  8. 7.请解释泛型list集合的长度为什么动态的?_Java面试题集合篇一
  9. UVA 1411 - Ants(二分图完美匹配)
  10. Vue项目中如何实现用户登录及token验证?
  11. 极光推送源码api封装改造
  12. 常见内网穿透工具使用总结
  13. 西南交大计算机绘图b,网络大学西南交大离线作业计算机绘图B
  14. 英语好不好,不影响做外贸
  15. 风车网陈晓峰回忆录:我的两个月倒闭史
  16. 使用XML表达表格数据
  17. python简单成绩录入,python实现简单成绩录入系统
  18. cocos2d-x 使用 CCScale9Sprite 实现微信对话框
  19. 云主机安全防护服务有哪些
  20. Python :18Python计算器

热门文章

  1. 唐诗词组频率,高频字居然跟宋词相似
  2. 【企业邮箱注册申请】网易企业邮箱教你如何防止开发信被反垃圾系统拦截
  3. java翻牌游戏_js实现翻牌小游戏
  4. 分数优先遵循志愿php源码_高考志愿分数优先遵循志愿是什么意思
  5. python+django车辆违章信息查询管理系统pycharm项目
  6. Tapdata 唐建法:什么是数据即服务(Data as a Service)?
  7. 第一期练习题 - 第七题
  8. 渗透测试技术----提权(第三方提权和WCE)
  9. js 获取音乐的音频音铺
  10. 提高 48V 配电性能?听专家怎么说