熟悉设备树中pinctrl 机制
学会配置pinctrl
文章目录
参考资料
Linux驱动开发—设备树描述引脚复用 Pinmux 与Pinctrl
设备树-第61章 实例分析:pinctrl
正点原子嵌入式linux驱动开发——pinctrl和gpio子系统
一、 pinmux 介绍
- Pinmux(引脚复用)
是指在系统中配置和管理引脚功能的过程。在许多现代集成电路中,单个引脚可以具有多个功能,例如作为 GPIO、UART、SPI 或 I2C 等。通过使用引脚复用功能,可以在这些不同的功能之间切换
比如如下原理图:
从右边往左边看,USB_HOST_PWREN_H_GPIO0_A6 这个引脚,它可以有四个功能预选项吧,看你自己怎么配置。 可以作为 左边:
GPU_PWREN、SATA_CP_POO、PCIE30X2_CLKREQn_MO、GPIO0_A6_d 中其中一个功能的脚,这;里USB_HOST_PWREN_H_GPIO0_A6 不就是复用的嘛,但是只能4选一。
- AG25 是什么? 它就是一个坐标系,把芯片上面的引脚标注出来,用坐标表示。
在 BGA(Ball Grid Array,球栅阵列)封装中,引脚标号是用于唯一标识每个引脚的标识符。这些标号通常由芯片制造商定义,并在芯片的规格文档或数据手册中提供。
BGA 芯片的引脚标号通常由字母和数字的组合构成。它们用于在芯片的封装底部的焊盘上进行标记。每个引脚标号都与芯片内部的功能或信号相对应,以便正确连接到印刷电路板(PCB)上的目标位置。RK3568 的引脚标号图如下(图 61-2)所示
可以看到纵向为 A-AH 的 28 个字母类型标号,横向为 1-28 的 28 个字母类型标号,瑞芯微也在对应的 3568 数据手册中加入了根据 BGA 位置制作的复用功能图,部分内容如下图
其中黑色框代表被保留的引脚,其他有颜色的框一般为电源和地,白色的框代表有具体复用功能的引脚;那为什么电源脚那么多? 如果一个芯片上面电源就一根线的话,那不就是等着烧嘛…
我自己看驱动同事开发时候,经常看这个数据手册,这个理解下,蛮重要的。
小结:
pinmux 解决了什么问题,解决了功能引脚复用的问题,一个引脚支持多个功能,开发工程师自行配置需要的那个支持的功能。
PinMux 解决的问题
- 现代微控制器集成了大量外设(UART、SPI、I2C、PWM等)
- 物理引脚数量有限
- 需要灵活地将外设功能映射到物理引脚
工作原理
- 功能选择寄存器:决定引脚当前的功能(GPIO、UART、SPI等)
- 电气特性配置:上拉/下拉电阻、驱动强度、施密特触发等
- 输入/输出方向控制
典型应用场景
- 开发板设计:允许灵活的外设布局
- 产品定制:同一芯片可适应不同硬件设计
- 功能切换:运行时动态改变引脚功能
配置方式
- 寄存器直接操作
- 厂商提供的配置工具(如TI的PinMux工具、NXP的MCUXpresso等)
- 设备树配置(Linux嵌入式系统)
这里我们了解 、掌握的就是设备树
二、 pinctrl 语法
pinctrl 的语法可以看成两部分构成,一部分是客户端client,一部分是服务端 service.
client 端语法基本固定,服务端service端根据各个芯片平台厂商不同,会有一定的区别。
Client 端
在设备树中声明 pinctrl 引用,如下:
device_node {
pinctrl-names = "default", "sleep", "active";
pinctrl-0 = <&pin_config_default>;
pinctrl-1 = <&pin_config_sleep>;
pinctrl-2 = <&pin_config_active>;
};
-
pinctrl-names: 定义状态名称
-
pinctrl-N: 引用具体的引脚配置,指向 pinctrl 节点
注意点: 这个 pinctrl-N 属性值对应的是service 端的某个节点值,一一对应的关系。 举例如下图:
Service 服务端 -主流厂商语法
几大主流厂商语法结构
NXP i.MX 系列
iomuxc: iomuxc@20e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x20e0000 0x4000>;
uart1grp: uart1grp {
fsl,pins = <
MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
>;
};
};
分析:
给人感觉 fsl,pins 写法固定,里面的值大概分为三部分来解析:
- MX6UL_PAD 厂家固定写死
- UART1_TX_DATA、UART1_RX_DATA 引脚的名字
- UART1_DCE_TX、UART1_DCE_RX 被设置的功能
上面结合起来就是 把UART1_TX_DATA 引脚设置为UART1_DCE_TX功能;把UART1_RX_DATA引脚设置为UART1_DCE_RX - 0x1b0b1、0x1b0b1 电气属性,这个寄存器地址需要查芯片的数据手册,看看是什么电气属性功能
再举例如下:
三星(Samsung)平台设备树pinctrl配置
三星平台(如Exynos系列)的设备树pinctrl配置有其特定的语法格式,主要使用samsung,pins和samsung,pin-function等属性。
&pinctrl_0 {
// UART配置示例
uart0_data: uart0-data {
samsung,pins = "gpa0-0", "gpa0-1";
samsung,pin-function = <2>; // 功能选择
samsung,pin-pud = <0>; // 上拉/下拉设置
samsung,pin-drv = <0>; // 驱动强度
};
// I2C配置示例
i2c2_bus: i2c2-bus {
samsung,pins = "gpa0-6", "gpa0-7";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
samsung,pin-drv = <0>;
};
// GPIO配置示例
sleep1: sleep-state {
samsung,pins = "gpa0-0", "gpa0-1", "gpa0-2";
samsung,pin-con-pdn = <2>; // 睡眠状态配置
samsung,pin-pud-pdn = <1>;
};
};
关键属性说明
- samsung,pins: 指定要配置的引脚列表,格式为"bank-num"(如"gpa0-0")
- samsung,pin-function: 引脚复用功能选择
数值对应芯片手册中的ALT功能编号
例如0=GPIO, 1=ALT1, 2=ALT2等
- samsung,pin-pud: 上拉/下拉电阻配置
0: 无上拉/下拉
1: 下拉
2: 上拉
3: 保留(通常表示不改变)
- samsung,pin-drv: 驱动强度设置
数值越大驱动能力越强(具体级别参考芯片手册)
- samsung,pin-val: 引脚初始输出值(用于输出配置)
- 睡眠状态相关属性
samsung,pin-con-pdn: 睡眠状态下的引脚功能配置
samsung,pin-pud-pdn: 睡眠状态下的上拉/下拉配置
Rockchip 系列
pinctrl: pinctrl {
compatible = "rockchip,rk3399-pinctrl";
uart0 {
uart0_xfer: uart0-xfer {
rockchip,pins = <
RK_GPIO1 16 RK_FUNC_1 &pcfg_pull_up
RK_GPIO1 17 RK_FUNC_1 &pcfg_pull_none
>;
};
};
};
上面的熟悉了,这里其实一样的道理:GPIO1 里面的16 和 17 引脚设置为 FUCN_1功能
下面给出其它教程里面的案例分析,可以看看参考下:
三、pinctrl 实例编写-将 led 的控制引脚复用为 GPIO 模式
去掉系统默认的led的节点
去掉RK3568 Linux源码中的led灯的节点,然后自己写一个。
路径:kernel/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
可以看到系统配置好的led 的设备数如下:
leds: leds {
compatible = "gpio-leds";
work_led: work {
lable = "user1";
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "on";
};
};
这里做如下修改,屏蔽掉 work_led 设备树配置:
发下问题
上面led灯 系统也没有通过配置pinctrl 配置gpio复用 ,为什么这个led灯还可以用?
底板原理图找gpio编号
在公开资料 topeet_rk3568_main_v1_7.pdf 底板原理图中找到gpio 是哪一个? 就是 GPIO0_B7
芯片数据手册中找到控制如上gpio的复用寄存器(引脚)
芯片手册:Rockchip RK3568 TRM Part2 V1.1-20210301.pdf
通过Name 查看它的描述怎样的:搜索PMU_GRF_GPIO0B_IOMUX_H
继续看寄存器PMU_GRF_GPIO0B_IOMUX_H 寄存器复位值 多少
所以,开发板启动的时候,默认的功能就是gpio功能:led灯对应的gpio默认就是gpio功能,所以不需要设置复用,而且软件其它位置也没有设置。
在rk平台开发板使用的设备树节点中添加自己的led gpio复用引脚功能
编辑 路径:kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v1.dts
引入了两个ditsi 文件,那么就打开其中一个,路径:vim rk3568-evb1-ddr4-v10.dtsi
写自己的client 端 led 设备树内容:
my_led: led {
compatible = "topeet,led";
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&rk_led_gpio>;
};
在这个文件中继续写Service 端代码,参考rk_485_ctl 对应的service 端,写led 相关的。
如下,我们写led 相关设备树 pinctrl 配置:
总结
- 了解pinctrl 机制,设备树中的配置
- 会手写pingctrl 设备树
- 会查芯片数据手册,会看原理图
- 因为不懂地方太多,所以磕磕绊绊,写到最后 才发下就是一个映射功能。