第二部 按pinctrl的方式编写GPIO的驱动程序

1、先说点废话,之前的MT65xx系列平台上所使用GPIO控制函数,在MT67xx平台上API均没有了。

怀念之前在任意一个设备中任意控制GPIO的时候。

随之而来的是使用Pinctrl的替代。在kernel中引入Pinctrl子系统,是linux系统为了统一各SOC厂家pin管理,目的是为了减少SOC厂家系统移植工作量。通常通过设备树初始化pinctrl,并提供调用io接口。

在对应的proj.dts文件中填充之前的mygpio设备节点。kernel-3.18/arch/arm64/boot/dts/Projxxx.dts(别天真的认为Projxxx是实际的名称):

就是一个编号为96的GPIO,两个名为:"my_state_io96_output0", "my_state_io96_output1"状态。一个输出高点评,一个输出低电平。

#include <linux/slab.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <generated/autoconf.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>#include "mt-plat/mtgpio.h"
#include <linux/types.h>
#include <mt-plat/mt_gpio.h>
#include <mt-plat/mt_gpio_core.h>
#include <mach/gpio_const.h>/* 生命函数定义 */
static int mygpio_probe(struct platform_device *pdev);
static int mygpio_remove(struct platform_device *pdev);struct pinctrl *pinctrlio96;
struct pinctrl_state *pio96_output0, *pio96_output1;static const struct of_device_id mygpio_of_match[] = {{ .compatible = "mykgpio", },{},
};static struct platform_driver mygpio_driver = {.remove = mygpio_remove,.probe = mygpio_probe,.driver = {.name = "myGPIO",.owner = THIS_MODULE,.of_match_table = mygpio_of_match,},
};/* 设置管教的状态  level=1 输出高电平 level=0 输出低电平*/
void my673x_gpio_output(int level)
{printk("[myGPIO]my673x_gpio_output level = %d\n", level);/* 设置名字为"my_state_io96_output0"这个pinctrl对应引脚的pin state */if (level)pinctrl_select_state(pinctrlio96, pio96_output1);elsepinctrl_select_state(pinctrlio96, pio96_output0);
}static int mygpio_misc_open(struct inode *inode, struct file *file)
{printk("MyGPIO OPen. \r\n");return 0;
}static int mygpio_misc_release(struct inode *inode, struct file *file)
{printk("MyGPIO Release. \r\n");return 0;
}static long mygpio_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{printk("MyGPIO Ioctl. \r\n");printk("MyGPIO cmd=%d \r\n", cmd);/* 根据命令执行相应的操作 */switch(cmd) {/* 输出GPIO96高电平 */case 1:my673x_gpio_output(1);break;/* 输出GPIO96低电平 */case 0:my673x_gpio_output(0);break;default:return -EINVAL;}return 0;
}static const struct file_operations mygpio_fops = {/* .owner = THIS_MODULE, */.open = mygpio_misc_open,.release = mygpio_misc_release,.unlocked_ioctl = mygpio_unlocked_ioctl,
};static struct miscdevice mygpio_misc_device = {.minor = MISC_DYNAMIC_MINOR,     //动态设备号.name = "myGPIO",.fops = &mygpio_fops,
};/* My GPIO probe */
static int mygpio_probe(struct platform_device *pdev)
{int ret = 0;printk("MyGPIO Probe. \r\n");/* 注册一个misc设备 */ret = misc_register(&mygpio_misc_device);if (ret != 0 )printk("myGPIO: mygpio_device register failed\n");/* 获取pin control state holder 的句柄 */pinctrlio96 = devm_pinctrl_get(&pdev->dev);if (IS_ERR(pinctrlio96)) {ret = PTR_ERR(pinctrlio96);printk("fwq Cannot find mygpio pinctrlio96!\n");return ret;}/* dts中 pinctrl-names = "my_state_io96_output0", "my_state_io96_output1"; *//* 得到设备树中名字为 my_state_io96_output0和 my_state_io96_output1对应的pin state */pio96_output0 = pinctrl_lookup_state(pinctrlio96, "my_state_io96_output0");if (IS_ERR(pio96_output0)) {ret = PTR_ERR(pio96_output0);printk("fwq Cannot find touch pinctrl my_state_io96_output0!\n");return ret;}pio96_output1 = pinctrl_lookup_state(pinctrlio96, "my_state_io96_output1");if (IS_ERR(pio96_output1)) {ret = PTR_ERR(pio96_output1);printk("fwq Cannot find touch pinctrl my_state_io96_output1!\n");return ret;}return ret;
}static int mygpio_remove(struct platform_device *pdev)
{int err;printk("MyGPIO remove. \r\n");err = misc_deregister(&mygpio_misc_device);if (err)printk("deregister gpio\n");return err;
}static int __init my_gpio_init(void)
{int ret = 0;printk("Register MyGPIO platform_driver. \r\n");ret = platform_driver_register(&mygpio_driver);if(ret != 0 )printk("unable to register MyGPIO driver.\n");return ret;
}/*---------------------------------------------------------------------------*/
static void __exit my_gpio_exit(void)
{platform_driver_unregister(&mygpio_driver);
}subsys_initcall(my_gpio_init);
/*module_init(my_gpio_init);*/
module_exit(my_gpio_exit);MODULE_AUTHOR("zue");
MODULE_DESCRIPTION("MY General Purpose Driver (GPIO)");
MODULE_LICENSE("GPL v2");

主要核心数据结构体就是:

主要使用 devm_pinctrl_get函数获取DTS中的设备节点;使用 pinctrl_lookup_state获取dts中pinctrl的设置;使用 pinctrl_select_state函数设置pinctrl的设置。

3、只有驱动并不知道这个驱动是否能使用,好需要写一个驱动测试程序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define DEVICE_NAME "/dev/myGPIO" //所对应的设备名   int binstr_to_int(char *binstr)
{int ret = 0;int i = 0;char bnum[2];memset(bnum,'0',1);int len = strlen(binstr);if(len > 1) strcpy(bnum,binstr + len - 1);else strcpy(bnum + 1 - len,binstr);for(i = 0;i < 1;i ++)  {   ret <<= 1;   ret += (bnum[i] == '0' ? 1 : 0);} return ret;}int main(int argc, char **argv)
{   int fd=0,arg=0;printf("myGPIO argc: %d.\n",argc);printf("myGPIO argv[1]: %s.\n",argv[1]);arg = binstr_to_int(argv[1]);printf("myGPIO arg: %d.\n",arg);/* 打印用法 */if(argc > 2)    {       printf("Usage: %s <binary code>\n"  "example: %s -- Will turn on 0, and turn off 1.\n",argv[0],argv[1]);_exit(EXIT_FAILURE);  }/* 打开设备 */if((fd = open(DEVICE_NAME, O_RDWR)) == -1)    {printf("Open dev error!\n"); _exit(EXIT_FAILURE);}//输出高电平if(arg == 1)      {   ioctl(fd,1,&arg);       printf("myGPIO dat: %d.\n",arg);  }//输出低电平if(arg == 0)  {   ioctl(fd,0,&arg);   printf("myGPIO dat: %d.\n",arg);  }_exit(EXIT_SUCCESS);}

测试程序很简单,首先打开我们之前注册的杂项设备,所在路径/dev/myGPIO,剩下的只要使用 ioctl函数,向cmd参数中传入控制字节就可以了。在Android中编译应用已经不能简单使用make或者gcc命令了,当然最终还是它们干活。有更简单的工具了,那就是mmm。在使用mmm工具时,要先写一个Android.mk文件,这样mmm才能按图索骥的编译好我们的测试程序。

将其存在项目根目录下的packages/apps/TsMyGPIO/(TsMyGPIO是我创建的目录)

在工程根目录下执行 mmm packages/apps/TsMyGPIO命令即可。

至于输出的可执行程序就别在本目录下找了,输出所在的目录

out/target/product/Projxxx/system/bin
3、执行测试程序测试。

可以使用adb push命令将测试程序上传到开发板上,可以使用chmod命令赋予可执行权限。

参数是0的时候接到96编号的GPIO的LED是灭的,反之,参数是1的时候接到96编号的GPIO的LED是亮的。LED接法是上拉接法。

编写MTK6737平台的GPIO驱动例程(二)相关推荐

  1. MTK6737平台的GPIO驱动例程(二)

    第二部 按pinctrl的方式编写GPIO的驱动程序 1.先说点废话,之前的MT65xx系列平台上所使用GPIO控制函数,在MT67xx平台上API均没有了. 怀念之前在任意一个设备中任意控制GPIO ...

  2. MTK6737平台的GPIO驱动例程(一)

    1.在dts文件中创建节点,在/kernel-3.18/arch/arm64/boot/dts/mt6735.dtsi 创建一个名mygpio的设备节点,匹配名称为"mykgpio" ...

  3. 树莓派GPIO驱动原理

    1.前言 最近认真学习了树莓派,从浅到深认真分析了wiringPi实现代码,借助树莓派学习linux收获颇丰.深入学习linux一段时间后发现它非常有魅力,一个简单的IO口输出操作尽有那么多的&quo ...

  4. 标准linux4.4--驱动开发(二)GPIO驱动编写

    标准linux4.4--驱动开发(二)GPIO驱动编写 简介 介绍GPIO DTS配置 在驱动文件中关联DTS的配置 驱动说明 中断 复用 FAQs 简介 1.什么是linux内核模块 在linux中 ...

  5. VS2019+WDK10编写xp平台的驱动

    VS2019+WDK10编写xp平台的驱动 之前自己在网上找了一堆教程,各种配置一大堆都没有成功,但是都没成功. 如何配置直接贴张图,其实非常非常简单.

  6. linux驱动:二、LED灯驱动编写

    一.地址映射 在正式编写驱动前需要先简单了解一下 MMU 这个神器,MMU 全称叫做 Memory Manage Unit,也就是内存管理单元.在老版本的 Linux 中要求处理器必须有 MMU,但是 ...

  7. linux v4l2 示例程序,linux驱动由浅入深系列:camera驱动之二(基于高通平台的V4L2结构及代码分析)...

    在上一篇文章中介绍了camera的基础知识和相关概念,我们一起来了解一下驱动相关的代码结构.本文以高通+android平台为示例,首先看一下整体框图: 这张图是从整体上来看的 1,图中最下面的是ker ...

  8. linux驱动由浅入深系列:camera驱动之二(基于高通平台的V4L2结构及代码分析)

    在上一篇文章中介绍了camera的基础知识和相关概念,我们一起来了解一下驱动相关的代码结构.本文以高通+android平台为示例,首先看一下整体框图: 这张图是从整体上来看的 1,图中最下面的是ker ...

  9. linux驱动由浅入深系列:camera驱动之二(基于高通平台的V4L2结构及代码分析

    点击打开链接 在上一篇文章中介绍了camera的基础知识和相关概念,我们一起来了解一下驱动相关的代码结构.本文以高通+android平台为示例,首先看一下整体框图: 这张图是从整体上来看的 1,图中最 ...

  10. 添加卸载驱动例程(驱动学习笔记二)

    添加卸载驱动例程 0x0 驱动卸载 管理驱动 工具使用 代码问题 0x0 驱动卸载 管理驱动 卸载驱动其实用简单的命令行就可以做到,或者使用cmd脚本即可,当然工具的便利性毋庸置疑,工具的选择也可以有 ...

最新文章

  1. http提交json格式数据自动加\
  2. 利用css‘content实现指令式tooltip文字提示
  3. Slog3_如何使用Python与Mysql进行数据交互
  4. Matlab Command Window 进度提示
  5. 织梦ajax表单提交参数错误,【织梦二次开发】织梦jquery+ajax方式提交自定义表单...
  6. android matrix 缩放,android – 如何获取任意矩阵的缩放值?
  7. LeetCode 1277. 统计全为 1 的正方形子矩阵(DP)
  8. sap crm button_正值SAP中国成立25周年之际,江苏金来奇智能科技SAPB1项目正式启动...
  9. 关于Patch应用和举例
  10. npm设置和取消代理的方法
  11. 何建坤:实施能源革命战略 促绿色低碳发展
  12. linux幻灯片制作工具,PPT2010幻灯片制作实用小技巧
  13. 笔记本电脑配置知识大全
  14. 2021高考厦门科技中学成绩查询,2021年厦门重点高中名单及排名,厦门高中高考成绩排名榜...
  15. 计算机中年级排名怎么操作,智学网年级排名查看方法规则介绍
  16. 人脸识别技术开发解决方案,人脸识别智慧工地应用开发
  17. 从输入URL到页面加载的过程?由一道题完善自己的Web前端知识体系!
  18. 学了Python不想去给别人打工,那就做做这些事儿吧!
  19. 【理解】ORB特征提取与ORBSLAM特征匹配简要剖析
  20. Big Faceless 网页PDF阅读器

热门文章

  1. 9008 能 解锁BL_手机刷入面具及twrp教程(包含解bl锁教程)
  2. css 设置图片原来大小,用CSS设置背景图像的大小?
  3. 什么是PON光模块?PON光模块有哪些作用和类型?
  4. Java基础篇--概念理解(重写、接口)
  5. 世硕科技推荐:Shockman 最新音译 登峰侠
  6. Text strings must be rendered within a Text component的一个情况
  7. i春秋web-Backdoor(.git泄露、vim备份泄露、代码审计)
  8. IDS-IPS入侵防御原理与实践
  9. nginx reopen
  10. unity 遮挡剔除