IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 关于设备树里面pinctrl的属性不能生效的问题 -> 正文阅读

[系统运维]关于设备树里面pinctrl的属性不能生效的问题

Linux下gpio(旧API)和gpiod(新API)子系统主要负责配置GPIO的输入/输出方向,读取输入的电平,和设置输出的电平。
pinctrl子系统主要负责设置gpio其他方面的东西,比如配置复用功能(alternate function),配置上下拉电阻,推挽输出或开漏输出,配置输出速度等等。

本人阅读了正点原子imx6ull开发板手册“【正点原子】阿尔法Linux开发板(A盘)-基础资料/09、文档教程(非常重要)/【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.6.pdf”里面的“第四十五章 pinctrl 和 gpio 子系统实验”,实验的设备树文件中有如下语句:

pinctrl_led: ledgrp {
  fsl,pins = <
    MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */
  >;
}

笔者将0x10b0修改为0x1031后,运行程序,发现SW_PAD_GPIO1_IO03寄存器(0x020e02f4)的值读出来后并不是0x1031,设备树里面有关pinctrl的内容全部都没有生效!!

后来笔者研究了linux内核相关源码发现,某个节点要使用pinctrl-names和pinctrl-0属性,这个节点就必须要有compatible属性,而且编写的驱动程序必须要绑定到这个compatible属性,例如将struct platform_driver结构体的driver.of_match_table[0].compatible的值设置为和设备树compatible属性相同的字符串。
(请注意是driver.of_match_table[X].compatible成员和设备树的compatible属性匹配,不是driver.name成员)
正点原子实验里面只有led_init函数,没有用到platform_driver框架,也没有probe函数,所以pinctrl-names和pinctrl-0属性无法生效!这算是正点原子教程里面非常大的一个失误!


测试用的设备树文件arch/arm/boot/dts/myboard.dts:

#include "imx6ull-14x14-emmc-4.3-800x480-c.dts"

/ {
	alphaled {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "myleddevice";
		status = "okay";
		reg = <0x020c406c 0x04 // CCM_CCGR1
			   0x020e0068 0x04 // SW_MUX_GPIO1_IO03
			   0x020e02f4 0x04 // SW_PAD_GPIO1_IO03
			   0x0209c000 0x04 // GPIO1_DR
			   0x0209c004 0x04 // GPIO1_GDIR
		>;
		hello = "hello world";
		
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_mytest>;
		gpios = <&gpio1 3 GPIO_ACTIVE_LOW
		         &gpio1 18 GPIO_ACTIVE_LOW>;
	};
	
	/delete-node/leds;
	/delete-node/gpio_keys@0;
};

&iomuxc {
	imx6ul-evk {
		/delete-node/gpio-leds;
		/delete-node/gpio-keys;
	
		pinctrl_mytest: testgrp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x1031
			>;
		};
	};
};

&i2c1 {
	ap3216c@1e {
		compatible = "myap3216c";
	};
};

设备树里面用/delete-node语法把正点原子原有设备树里面的pinctrl属性和leds灯节点全部删掉了。
设备树文件编写好之后,make dtbs编译设备树源码,生成arch/arm/boot/dts/myboard.dtb文件,重启开发板,在uboot中加载这个dtb设备树。

sudo mount /dev/mmcblk0p2 /mnt/sdlinux -t vfat
sudo cp /home/oct1158/learn_drivers/kernel/arch/arm/boot/dts/myboard.dtb /mnt/sdlinux
sudo umount /mnt/sdlinux
sudo reboot

setenv mmcroot "/dev/mmcblk0p4 rootwait rw"
setenv loadfdt "fatload mmc 0:2 ${fdt_addr} myboard.dtb"
boot

测试用的linux驱动:

#include <asm/io.h> // readl()
#include <linux/module.h>
#include <linux/of_address.h> // of_iomap
#include <linux/platform_device.h>

struct led5_data
{
	int num;
	char str[100];
};

static int led5_probe(struct platform_device *pdev)
{
	struct led5_data *data;
	u32 regval;
	void *__iomem sw_pad;
	
	pr_err("%s(0x%p);\n", __FUNCTION__, pdev);
	data = devm_kzalloc(&pdev->dev, sizeof(struct led5_data), GFP_KERNEL);
	if (data == NULL)
	{
		pr_err("devm_kzalloc() failed!\n");
		return -ENOMEM;
	}
	strlcpy(data->str, "hello world", sizeof(data->str));
	strlcat(data->str, "!!!", sizeof(data->str));
	data->num = strlen(data->str);
	platform_set_drvdata(pdev, data);
	
	sw_pad = of_iomap(pdev->dev.of_node, 2);
	if (sw_pad == NULL)
	{
		pr_err("of_iomap() failed!\n");
		return -ENODEV;
	}
	regval = readl(sw_pad);
	pr_err("sw_pad=0x%04x\n", regval);
	iounmap(sw_pad);
	return 0;
}

static int led5_remove(struct platform_device *pdev)
{
	struct led5_data *data = platform_get_drvdata(pdev);
	
	pr_err("%s(0x%p);\n", __FUNCTION__, pdev);
	pr_err("num=%d, str=%s\n", data->num, data->str);
	return 0;
}

static const struct of_device_id of_led5_match[] = {
	{.compatible = "myleddevice"},
	{}
};

MODULE_DEVICE_TABLE(of, of_led5_match);

static struct platform_driver led5_driver = {
	.driver = {
		.name = "myled5",
		.of_match_table = of_led5_match
	},
	.probe = led5_probe,
	.remove = led5_remove
};

module_platform_driver(led5_driver);

MODULE_AUTHOR("Oct1158");
MODULE_LICENSE("GPL");

程序运行结果:
(备注:开发板安装的是uboot2016.03+linux4.1.15内核+ubuntu18.04根文件系统)

oct1158@alientek:~/learn_drivers/led$ ls
Makefile        led.o       led3.ko     led4.mod.o  led_noop.sh
Module.symvers  led2.c      led3.mod.c  led4.o      led_off.sh
key_test.sh     led2.ko     led3.mod.o  led5.c      led_on.sh
led.c           led2.mod.c  led3.o      led5.ko     led_test.sh
led.ko          led2.mod.o  led4.c      led5.mod.c  modules.order
led.mod.c       led2.o      led4.ko     led5.mod.o  stop_blinking.sh
led.mod.o       led3.c      led4.mod.c  led5.o
oct1158@alientek:~/learn_drivers/led$ make
make -C /home/oct1158/learn_drivers/kernel M=/home/oct1158/learn_drivers/led EXTRA_CFLAGS=-fno-pic modules
make[1]: Entering directory '/home/oct1158/learn_drivers/kernel'
  CC [M]  /home/oct1158/learn_drivers/led/led5.o
  Building modules, stage 2.
  MODPOST 5 modules
  CC      /home/oct1158/learn_drivers/led/led5.mod.o
  LD [M]  /home/oct1158/learn_drivers/led/led5.ko
make[1]: Leaving directory '/home/oct1158/learn_drivers/kernel'
oct1158@alientek:~/learn_drivers/led$ sudo insmod led5.ko
[sudo] password for oct1158:
[ 1036.945408] led5_probe(0x940ffc00);
[ 1036.948949] sw_pad=0x1031
oct1158@alientek:~/learn_drivers/led$ sudo rmmod led5.ko
[ 1040.441553] led5_remove(0x940ffc00);
[ 1040.445343] num=14, str=hello world!!!
oct1158@alientek:~/learn_drivers/led$

通过实验可以发现,platform_driver_register后,我们去访问0x020e02f4寄存器,读出来的值确实是0x1031。说明pinctrl的设置成功生效了。


pinctrl要点:

(1)在根节点下任选一个节点,设置好compatible属性,pinctrl-names属性以及pinctrl-0属性。
(2)在&iomuxc的imx6ul-evk节点下新建一个节点,通过fsl,pins属性配置GPIO引脚。pinctrl-0属性要引用这个节点。
(3)编写的linux驱动必须要用到platform_driver,通过of_match_table与设备树中的compatible属性匹配。如果匹配不了,pinctrl的设置将无法生效!

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 12:16:02  更:2022-04-26 12:20:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 19:40:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码