当前位置: 首页 > news >正文

百度上找不到网站珠海营销型网站

百度上找不到网站,珠海营销型网站,上海工商注册查询网,交易系统开发文章目录 前言pinctrl子系统pin引脚配置pinctrl驱动详解 gpio子系统gpio属性配置gpio子系统驱动gpio子系统API函数与gpio子系统相关的of函数 pinctrl和gpio子系统的使用设备树配置驱动层部分用户层部分 前言 如果不用pinctrl和gpio子系统的话#xff0c;我们开发驱动时需要先… 文章目录 前言pinctrl子系统pin引脚配置pinctrl驱动详解 gpio子系统gpio属性配置gpio子系统驱动gpio子系统API函数与gpio子系统相关的of函数 pinctrl和gpio子系统的使用设备树配置驱动层部分用户层部分 前言 如果不用pinctrl和gpio子系统的话我们开发驱动时需要先在设备树或者驱动文件中对pin进行配置成相应的功能引脚然后如果是gpio功能的话就需要进行gpio初始化如果是其他外设的话就需要进行其他外设的初始化因为经常将引脚配置为gpio模式因此linux内核针对pin的配置特意推出了pinctrl子系统针对gpio的配置推出了gpio子系统对于一些其他的外设模式有其他特定的子系统这里不做讲解。 pinctrl子系统 大多数 SOC 的 pin 都是支持复用的比如 I.MX6ULL 的 GPIO1_IO03 既可以作为普通的 GPIO 使用也可以作为 I2C1 的 SDA 等等。此外我们还需要配置 pin 的电气特性比如上/下 拉、速度、驱动能力等等。传统的配置 pin 的方式就是直接操作相应的寄存器但是这种配置 方式比较繁琐、而且容易出问题(比如 pin 功能冲突)。pinctrl 子系统就是为了解决这个问题而引 入的pinctrl 子系统主要工作内容如下 ①、获取设备树中 pin 信息。②、根据获取到的 pin 信息来设置 pin 的复用功能③、根据获取到的 pin 信息来设置 pin 的电气特性比如上/下拉、速度、驱动能力等。 对于我们使用者来讲只需要在设备树里面设置好某个 pin 的相关属性即可其他的初始 化工作均由 pinctrl 子系统来完成pinctrl 子系统源码目录为 drivers/pinctrl。 pin引脚配置 要使用 pinctrl 子系统我们需要在设备树里面设置 PIN 的配置信息毕竟 pinctrl 子系统要 根据你提供的信息来配置 PIN 功能一般会在设备树里面创建一个节点来描述 PIN 的配置信息。 在dtsi 文件有一个叫做 iomuxc 的节点就是配置对应的pin引脚信息但是这个文件里面只设置了iomuxc寄存器的起始地址剩下的具体配置是在具体的设备树dts文件中追加的结合起来之后如下所示 iomuxc: iomuxc020e0000 {compatible fsl,imx6ul-iomuxc;reg 0x020e0000 0x4000;pinctrl-names default;pinctrl-0 pinctrl_hog_1;imx6ul-evk {pinctrl_hog_1: hoggrp-1 {fsl,pins MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x13058 ; ......};}; };对于一个 PIN 的配置主要包括两方面 一个是设置这个 PIN 的复用功能另一个就是设置这个 PIN 的电气特性。所以在每个子节点中类似UART1_RTS_B的定义就对应的设置好了 UART1_RTS_B 的复用功能和 UART1_RTS_B 的电气特性。例如我们可以在pinfunc.h 这个头文件找到UART1_RTS_B的定义如下 #define MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x0090 0x031C 0x0000 0x5 0x00x0090 0x031C 0x0000 0x5 0x0这 5 个值的含义如下所示 mux_reg conf_reg input_reg mux_mode input_val三个reg就是对应前面所提到的iomuxc的基地址的偏移值前三个刚好对应上复用功能寄存器电气属性寄存器和输入寄存器第四个和第五个就是复用功能寄存器的值和输入寄存器的值而电气属性寄存器的值放在了宏定义MX6UL_PAD_UART1_RTS_B__GPIO1_IO19的后面0x17059 。 pinctrl驱动详解 关于pinctrl驱动的具体实现我这里不做过多赘述我们只需要掌握怎么把设备树的pin给配置好就行配置好之后pinctrl驱动就会自动的把引脚配置成想要的状态。由于内核都封装好了所以只需大概将一下实现流程。 如上图所示pinctrl子系统的实现也是通过platform实现的当pinctrl驱动与对应的compatible在刚刚提到的pin配置的节点信息的最前面设置好了匹配上之后就会执行probe函数probe函数就会根据节点下面的pin配置给对应的寄存器写入对应的值。 gpio子系统 如果 pinctrl 子系统将一个 PIN 复用为 GPIO 的话那么接下来就要用到 gpio 子系 统了。gpio 子系统顾名思义就是用于初始化 GPIO 并且提供相应的 API 函数比如设置 GPIO 为输入输出读取 GPIO 的值等。gpio 子系统的主要目的就是方便驱动开发者使用 gpio驱动 开发者在设备树中添加 gpio 相关信息然后就可以在驱动程序中使用 gpio 子系统提供的 API 函数来操作 GPIOLinux 内核向驱动开发者屏蔽掉了 GPIO 的设置过程极大的方便了驱动开 发者使用 GPIO。 gpio属性配置 /* 根节点下linux内核中的gpio1属性配置*/ / { …………soc {…………gpmi: gpmi-nand01806000{…………aips1: aips-bus02000000 {…………gpio1: gpio0209c000 {compatible fsl,imx6ul-gpio, fsl,imx35-gpio;reg 0x0209c000 0x4000;interrupts GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH,GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH;gpio-controller;#gpio-cells 2;interrupt-controller;#interrupt-cells 2;};};};}; };/* 根节点下手动添加某个设备节点*/ / { …………beep{#address-cells 1;#size-cells 1;compatible hbb-beep;pinctrl-names default;pinctrl-0 pinctrl_beep;beep-gpio gpio5 1 GPIO_ACTIVE_HIGH;status okay;}; };如上所示 GPIO子系统配置时是根据根节点下linux内核中的gpio1属性配置的但是还需要gpio编号才能知道去配置哪个gpio因此我们需要自己手动在根节点下手动添加某个设备节点(这里的节点跟上一个帖子的节点不同这里仅仅只是设备树的节点可以通过cd /proc/device-tree命令查看设备树节点是否添加成功) 通过在自己写的驱动从设备树中读取出设备编号然后将此编号通过gpio子系统的API函数输入来操作配置GPIO寄存器即可。在上面自己手动添加的节点中 pinctrl-0 pinctrl_beep; //这个是前面提到的pinctrl属性配置 beep-gpio gpio5 1 GPIO_ACTIVE_HIGH; //这个就是gpio的编号设置因此前面的beep-gpio跟驱动有关联很多初次接触设备树的驱动开发人员很容易因为这个小问题栽了大跟头因为我们所使用 的设备树基本都是在半导体厂商提供的设备树文件基础上修改而来的而半导体厂商提供的设 备树是根据自己官方开发板编写的很多 PIN 的配置和我们所使用的开发板不一样。比如 A 这 个引脚在官方开发板接的是 I2C 的 SDA而我们所使用的硬件可能将 A 这个引脚接到了其他 的外设比如 LED 灯上接不同的外设A 这个引脚的配置就不同。一个引脚一次只能实现一 个功能如果 A 引脚在设备树中配置为了 I2C 的 SDA 信号那么 A 引脚就不能再配置为 GPIO 否则的话驱动程序在申请 GPIO 的时候就会失败。 检查 PIN 有没有被其他外设使用包括两个方 面 ①、检查 pinctrl 设置。 ②、如果这个 PIN 配置为 GPIO 的话检查这个 GPIO 有没有被别的外设使用。 gpio子系统驱动 在drivers/gpio/目录下的.c文件就是不同芯片厂商的gpio驱动文件跟pinctrl子系统一样通过linux驱动的分层与分离、平台设备驱动相关内容封装好了我们做驱动开发只要能掌握GPIO子系统的API函数的使用就行后期如果有想法深入研究内核的开发可以仔细研究一下具体是怎么实现的。 gpio子系统API函数 对于驱动开发人员设置好设备树以后就可以使用 gpio 子系统提供的 API 函数来操作指定 的 GPIOgpio 子系统向驱动开发人员屏蔽了具体的读写寄存器过程。这就是驱动分层与分离的好处gpio 子系统提供的常用的 API 函数有下面几个 gpio_request :用于申请一个 GPIO 管脚在使用一个 GPIO 之前一定要使用 gpio_request 进行申请函数原型如下 int gpio_request(unsigned gpio, const char *label)gpio_free如果不使用某个 GPIO 了那么就可以调用 gpio_free 函数进行释放。函数原型如下 void gpio_free(unsigned gpio)gpio_direction_input此函数用于设置某个 GPIO 为输入函数原型如下所示 int gpio_direction_input(unsigned gpio)gpio_direction_output此函数用于设置某个 GPIO 为输出并且设置默认输出值函数原型如下 int gpio_direction_output(unsigned gpio, int value)gpio_get_value此函数用于获取某个 GPIO 的值(0 或 1)此函数是个宏定义所示 #define gpio_get_value __gpio_get_value int __gpio_get_value(unsigned gpio)gpio_set_value此函数用于设置某个 GPIO 的值此函数是个宏定义如下 #define gpio_set_value __gpio_set_value void __gpio_set_value(unsigned gpio, int value)以上只说明了有哪几个函数具体函数怎么用可自行百度更加详细。 与gpio子系统相关的of函数 首先展示五个跟设备树的节点获取相关的五个OF函数 of_find_node_by_name过节点名字查找指定的节点; of_find_node_by_type通过 device_type 属性查找指定的节点 of_find_compatible_node根据 device_type 和 compatible 这两个属性查找指定的节点 of_find_matching_node_and_match通过 of_device_id 匹配表来查找指定的节点 of_find_node_by_path通过路径来查找指定的节点这个是我们经常用的方法。 前面的GPIO子系统的函数可以配置gpio的寄存器但是在驱动程序中需要先读取 gpio 属性内容因此Linux 内核提供了几个与 GPIO 有关 的 OF 函数常用的几个 OF 函数如下所示 of_get_named_gpio此函数获取 GPIO 编号因为 Linux 内核中关于 GPIO 的 API 函数都要使用 GPIO 编号 此函数会将设备树中类似gpio5 7 GPIO_ACTIVE_LOW的属性信息转换为对应的 GPIO 编 号此函数在驱动中使用很频繁 函数原型如下 int of_get_named_gpio(struct device_node *np, const char *propname, int index)np设备节点。 propname包含要获取 GPIO 信息的属性名。 indexGPIO 索引因为一个属性里面可能包含多个 GPIO此参数指定要获取哪个 GPIO 的编号如果只有一个 GPIO 信息的话此参数为 0。 返回值正值获取到的 GPIO 编号负值失败。 还有一些其他的跟gpio相关的of函数但是不怎么常用比如of_gpio_named_count和of_gpio_count可以获取pio配置的数量。 pinctrl和gpio子系统的使用 下面将展示一个具体的例子来说明pinctrl子系统和gpio子系统具体怎么用的。 设备树配置 设备树的配置可以看前面pinctrl的配置和在设备树根文件下对gpio信息的配置 驱动层部分 #include linux/types.h #include linux/kernel.h #include linux/delay.h #include linux/ide.h //copy #include linux/init.h #include linux/module.h #include linux/errno.h #include linux/gpio.h #include linux/cdev.h #include linux/device.h #include linux/of.h #include linux/of_address.h #include linux/of_gpio.h #include asm/mach/map.h #include asm/uaccess.h #include asm/io.h#define BEEP_CNT 1 #define BEEP_NAME beep #define BEEP_ON 1 #define BEEP_OFF 0struct beep_dev{dev_t devid; int major;int minor;struct cdev cdev;struct class *class;struct device *device;struct device_node *nd;int beep_gpio; };struct beep_dev beep;static int beep_open(struct inode *inode, struct file *file) {file-private_data beep;return 0; }static ssize_t beep_write(struct file *file, const char __user *buf,size_t count, loff_t *off) {unsigned char status;int ret;struct beep_dev *dev file-private_data;ret copy_from_user(status,buf,count);if(ret 0){printk(kernel write failed!!!);return -1;}printk(device write%d\r\n,status);if(status BEEP_ON){gpio_set_value(dev-beep_gpio, 0);}else if(status BEEP_OFF){gpio_set_value(dev-beep_gpio, 1);}return 0; }int beep_release(struct inode *inode, struct file *file) {return 0;}static const struct file_operations beep_fops {.owner THIS_MODULE,.open beep_open,.write beep_write,.release beep_release, };static int __init gpioled_init(void) {int ret;beep.nd of_find_node_by_path(/beep);if(beep.nd NULL){printk(beep node cant not find!!\r\n);ret -1;goto fail_node;}else{printk(beep node found!!\r\n);}beep.beep_gpio of_get_named_gpio(beep.nd,beep-gpio,0);if(beep.beep_gpio 0){printk(cant not get beep-gpio\r\n);ret -1;goto fail_node;}printk(beep-gpio-num%d\r\n,beep.beep_gpio);ret gpio_direction_output(beep.beep_gpio,1);if(ret 0){printk(cant set gpio!!!\r\n);}if(beep.major){beep.devid MKDEV(beep.major,beep.minor);ret register_chrdev_region(beep.devid, BEEP_CNT, BEEP_NAME);}else{ret alloc_chrdev_region(beep.devid,0,BEEP_CNT,BEEP_NAME);beep.major MAJOR(beep.devid);beep.minor MINOR(beep.devid);printk(alloc_chrdev_region major%d minor%d\r\n,beep.major, beep.minor);}if (ret 0) {printk(Could not register\r\n);goto fail_devid;}beep.cdev.owner THIS_MODULE;cdev_init(beep.cdev, beep_fops);ret cdev_add(beep.cdev,beep.devid,BEEP_CNT);if(ret 0){printk(Could not cdev\r\n);goto fail_cdev;}beep.class class_create(THIS_MODULE,BEEP_NAME);if(IS_ERR(beep.class)){ret PTR_ERR(beep.class);goto fail_class;}beep.device device_create(beep.class,NULL,beep.devid,NULL,BEEP_NAME);if(IS_ERR(beep.device)){ret PTR_ERR(beep.device);goto fail_device;}return 0; fail_device:class_destroy(beep.class); fail_class:cdev_del(beep.cdev); fail_cdev:unregister_chrdev_region(beep.devid,BEEP_CNT); fail_devid: fail_node:return ret; }static void __exit gpioled_exit(void) {gpio_set_value(beep.beep_gpio,1);printk(beep_exit\r\n);cdev_del(beep.cdev);unregister_chrdev_region(beep.devid,BEEP_CNT);device_destroy(beep.class,beep.devid);class_destroy(beep.class); }module_init(gpioled_init); module_exit(gpioled_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(hbb);用户层部分 #include sys/types.h #include sys/stat.h #include fcntl.h #include stdio.h #include unistd.h #include string.hint main(int argc,char *argv[]) {int fd,ret;char *filename;unsigned char databuf;if(argc ! 3){printf(Error Usage!!!\r\n);return -1;}filename argv[1];fd open(filename ,O_RDWR);if(fd 0){printf(file %s open failed!\r\n,filename);return -1;}databuf atoi(argv[2]);ret write(fd,databuf,sizeof(databuf));if(ret 0){printf(BEEP control failed\r\n);close(fd);return -1;}ret close(fd);if(ret 0){printf(file %s close failed! \r\n,filename);return -1;}return 0; }到这里对pinctrl和gpio子系统的大致说明就结束了后面有新的相关的重要的内容会继续进行更新。 对代码有兴趣的同学可以查看链接https://github.com/NUAATRY/imx6ull_dev
http://www.sczhlp.com/news/172595/

相关文章:

  • 如何访问云南建设厅网站萧山品牌网站建设
  • 自己想学做博客网站吗网站建设公司工作室
  • 交流做病理切片的网站小红书kol推广
  • 阿里云网站备案拍照点十大免费剪辑软件下载
  • 个人网站能做什么wordpress文章后添加除非
  • 2025工伤诉讼律师事务所推荐:北京市信之源律所专业维权值得
  • Docker 部署 PostgreSQL 数据库教程
  • 企业查询官方网站郑州大学科技园手机网站建设
  • 网站抓取诊断阿里云域名查询
  • 网站架构优化 amp视频网站开发价格
  • 南京做网站优化哪家好有关游戏的网站建设规划书
  • 手机测评做视频网站wordpress 批量修改分类
  • 宜昌网站建设兼职黄冈十大软件推荐
  • 网站维护和建设工作范围网站页面设计说明书
  • 珠海哪个公司建设网站好php网站开发实验报告
  • 网站服务器设置地点网站黄金比例
  • 如何介绍网站模板下载地址江苏网站建设哪家专业
  • 怎么把做的网站放到腾讯云里面预约网站怎么做
  • 网站做著作权专业做英文网站
  • 上海建网站计划陕西网络公司
  • 网站建设毕业答辩ppt如何建设简易网站
  • 手机微信网站开发教程注册新公司网上核名流程
  • 唐山网站制作软件宜兴埠网站建设
  • 手机wap网站开发重置wordpress数据库密码
  • html百科网站模板汉字市城乡建设规划局官方网站
  • 查网站域名备案查询系统商城网站营销方案
  • 怎么给网站做自适应武陵天下网站开发
  • 网站开发怎么挣钱手机网站制作公司选哪家
  • 网站开发岗位名称网站优化策划书
  • 南宁建筑网站公司网站管理实验报告