瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。
【公众号】迅为电子
【粉丝群】824412014(加群获取驱动文档+例程)
【视频观看】嵌入式学习之Linux驱动(第七期_设备树_全新升级)_基于RK3568
【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板
第61章 实例分析:pinctrl
61.1 pinmux介绍
Pinmux(引脚复用)是指在系统中配置和管理引脚功能的过程。在许多现代集成电路中,单个引脚可以具有多个功能,例如作为 GPIO、UART、SPI 或 I2C 等。通过使用引脚复用功能,可以在这些不同的功能之间切换。
引脚复用通过硬件和软件的方式实现。硬件层面,芯片设计会为每个引脚提供多个功能的选择。这些功能通常由芯片厂商在芯片规格文档中定义。通过编程设置寄存器或开关,可以选择某个功能来连接引脚。这种硬件层面的配置通常是由引脚控制器(Pin Controller)或引脚复用控制器(Pin Mux Controller)负责管理。
软件层面,操作系统或设备驱动程序需要了解和配置引脚的功能。它们使用设备树(Device Tree)或设备树绑定(Device Tree Bindings)来描述和配置引脚的功能。在设备树中,可以指定引脚的复用功能,将其连接到特定的硬件接口或功能。操作系统或设备驱动程序在启动过程中解析设备树,并根据配置对引脚进行初始化和设置。
那我们要怎样知晓每一个管脚都可以复用成什么功能呢,一般在核心板原理图都会标注出每个管脚的复用功能,如下图(图 61-1)所示:
图 61-1
从上图可以看到UART4_RX_M1对应的引脚可以复用为以下6个功能LCDC_D16、VOP_BT1120_D7、GMAC1_RXD0_M0、UART4_RX_M1、PWM8_M0、GPIO3_B1_d,对应的BGA引脚标号为AG1,那这里的AG1是如何定位的呢。
在 BGA(Ball Grid Array,球栅阵列)封装中,引脚标号是用于唯一标识每个引脚的标识符。这些标号通常由芯片制造商定义,并在芯片的规格文档或数据手册中提供。
BGA 芯片的引脚标号通常由字母和数字的组合构成。它们用于在芯片的封装底部的焊盘上进行标记。每个引脚标号都与芯片内部的功能或信号相对应,以便正确连接到印刷电路板(PCB)上的目标位置。RK3568的引脚标号图如下(图 61-2)所示:
图 61-2
可以看到纵向为A-AH的28个字母类型标号,横向为1-28的28个字母类型标号,瑞芯微也在对应的3568数据手册中加入了根据BGA位置制作的复用功能图,部分内容如下图(图 61-3)所示:
图 61-3
其中黑色框代表被保留的引脚,其他有颜色的框一般为电源和地,白色的框代表有具体复用功能的引脚。
脚复用提高了芯片的灵活性和可重用性,通过允许同一个引脚在不同的功能之间切换,可以减少硬件设计的复杂性和成本。此外,引脚复用还使得在使用相同芯片的不同应用中可以更加灵活地配置和定制引脚功能。
会在下一个小节中讲解如何使用pinctrl在设备树中配置引脚的复用。
61.2使用pinctrl设置复用关系
pinctrl(引脚控制)用于描述和配置硬件设备上的引脚功能和连接方式。它是设备树的一部分,用于在启动过程中传递引脚配置信息给操作系统和设备驱动程序,以便正确地初始化和控制引脚。
在设备树中,pinctrl(引脚控制)使用了客户端和服务端的概念来描述引脚控制的关系和配置。
61.2.1客户端(Client)
接下来将使用三个例子对客户端要用到的属性进行讲解。
例1:
node {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
}
在例1中,pinctrl-names 属性定义了一个状态名称:default。
pinctrl-0 属性指定了第一个状态 default 对应的引脚配置。
<&pinctrl_hog_1> 是一个引脚描述符,它引用了一个名为 pinctrl_hog_1 的引脚控制器节点。这表示在 default 状态下,设备的引脚配置将使用 pinctrl_hog_1 节点中定义的配置。
例2:
node {
pinctrl-names = "default", "wake up";
pinctrl-0 = <&pinctrl_hog_1>;
pinctrl-1 = <&pinctrl_hog_2>;
}
在例2中,pinctrl-names 属性定义了两个状态名称:default 和 wake up。
pinctrl-0 属性指定了第一个状态 default 对应的引脚配置,引用了 pinctrl_hog_1 节点。
pinctrl-1 属性指定了第二个状态 wake up 对应的引脚配置,引用了 pinctrl_hog_2 节点。
这意味着设备可以处于两个不同的状态之一,每个状态分别使用不同的引脚配置。
例3:
node {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1 &pinctrl_hog_2>;
}
在这个例子中,pinctrl-names 属性仍然定义了一个状态名称:default。
pinctrl-0 属性指定了第一个状态 default 对应的引脚配置,但与之前的例子不同的是,它引用了两个引脚描述符:pinctrl_hog_1 和 pinctrl_hog_2。
这表示在 default 状态下,设备的引脚配置将使用 pinctrl_hog_1 和 pinctrl_hog_2 两个节点中定义的配置。这种方式可以将多个引脚控制器的配置组合在一起,以满足特定状态下的引脚需求。
至此关于客户端的内容就讲解完成了,低于客户端的内容,不同厂家的编写格式是相同的,而服务端每个厂家就有区别了,在下一个小节将以rk3568的pinctrl服务端为例进行讲解。
61.2.2 服务端(Server)
服务端是设备树中定义引脚配置的部分。它包含引脚组和引脚描述符,为客户端提供引脚配置选择。服务端在设备树中定义了 pinctrl 节点,其中包含引脚组和引脚描述符的定义。
这里以瑞芯微的RK3568为例进行pinctrl服务端的讲解,瑞芯微原厂BSP工程师为了方便用户通过pinctrl设置管脚的复用关系,将包含所有复用关系的配置写在了内核目录下的“arch/arm64/boot/dts/rockchip/rk3568-pinctrl.dtsi”设备树中,具体内容如下(图61-4)所示:
图61-4
在pinctrl节点中就是每个节点的复用功能,然后我们以uart4的引脚复用为例进行讲解,uart4的pinctrl服务端内容如下(图61-5)所示:
图61-5
其中<3 RK_PB1 4 &pcfg_pull_up>和<3 RK_PB2 4 &pcfg_pull_up>分别表示将GPIO3的PB1引脚设置为功能4,将GPIO3的PB2也设置为功能4,且电器属性都会设置为上拉。通过查找原理图可以得到两个引脚在BGA封装位置分别为AG1和AF2,如下图(图 61-6)所示:
图 61-6
然后在rk3568的数据手册中找到引脚复用表对应的位置,具体内容如下图所示:
图 61-7
可以看到功能4对应串口4的发送端和接收端,pinctrl服务端的配置和数据手册中的引脚复用功能是一一对应,那如果要将RK_PB1和RK_PB2设置为GPIO功能要如何设置呢,从上图可以看到GPIO对应功能0,所以可以通过以下pinctrl内容将设置RK_PB1和RK_PB2设置为GPIO功能(事实上如果不对该管脚进行功能复用该引脚默认就会设置为GPIO功能):
<3 RK_PB1 0 &pcfg_pull_up>,
<3 RK_PB2 0 &pcfg_pull_up>;
最后来看客户端对uart4服务端的引用,具体内容在内核源码目录“arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-linux.dts”:
图 61-8
通过在客户端中引用服务端的引脚描述符,设备树可以将客户端和服务端的引脚配置关联起来。这样,在设备树被解析和处理时,操作系统和设备驱动程序可以根据客户端的需求,查找并应用适当的引脚配置。
61.3 pinctrl实例编写
本小节将通过上面学到的pinctrl相关知识,将led的控制引脚复用为GPIO模式。
首先来对rk3568的设备树结构进行以下介绍,根据sdk源码目录下的“device/rockchip/rk356x/BoardConfig-rk3568-evb1-ddr4-v10.mk”默认配置文件可以了解到编译的设备树为rk3568-evb1-ddr4-v10-linux.dts,整理好的设备树之间包含关系列表如下所示:
顶层设备树 | rk3568-evb1-ddr4-v10-linux.dts | ||
第二级设备树 | rk3568-evb1-ddr4-v10.dtsi | rk3568-linux.dtsi | |
第三级设备树 | rk3568.dtsi rk3568-evb.dtsi topeet_screen_choose.dtsi topeet_rk3568_lcds.dtsi |
Led在rk3568-evb.dtsi设备树中已经被正常配置了,如下图(图61- 9)所示:
图61- 9
这时候可能大家就有问题了,这里也并没有配置pinctrl呀,那为什么led最后能正常使用呢,这个原因在上节课中其实我们已经提到了,当一个引脚没有被复用为任何功能时,默认就是GPIO功能,所以这里没有pinctrl led功能也可以正常使用。
但这里我们仍旧使用pinctrl对led进行配置,从而熟练pinctrl,首先注释掉leds节点,注释完成如下(图61- 10)所示:
图61- 10
保存退出之后,然后进入到rk3568-evb1-ddr4-v10.dtsi设备树中,找到rk_485_ctl节点,如下图(图61- 11)所示:
图61- 11
这是根节点的最后一个节点,而且也是用来控制一个GPIO的,我们完全可以仿照该节点,在该节点下方编写led控制节点,仿写完成的设备树内容如下所示:
my_led: led {
compatible = "topeet,led";
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&rk_led_gpio>;
};
第1行:节点名称为 led,标签名为my_led。
第2行:compatible 属性指定了设备的兼容性标识,即设备与驱动程序之间的匹配规则。在这里,设备标识为 "topeet,led",表示该 LED 设备与名为 "topeet,led" 的驱动程序兼容。
第3行:gpios 属性指定了与LED相关的GPIO(通用输入/输出)引脚配置。
第4行:pinctrl-names 属性指定了与引脚控制相关的命名。default表示状态 0
第5行:pinctrl-0 属性指定了与 pinctrl-names 属性中命名的引脚控制相关联的实际引脚控制器配置。<&rk_led_gpio> 表示引用了名为 rk_led_gpio 的引脚控制器配置。
添加完成如下图(图61- 12)所示:
图61- 12
然后继续找到在同一设备树文件的485 pinctrl服务端节点,具体内容如下(图61- 13)所示:
图61- 13
然后在该节点下方仿写led控制引脚pinctrl服务端节点,仿写完成的节点内容如下所示:
rk_led{
rk_led_gpio:rk-led-gpio {
rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
添加完成之后如下图(图61- 14)所示:
图61- 14
至此,led的控制引脚就通过pinctrl被复用为了GPIO功能,保存退出之后,重新编译内核,没有报错就证明我们的实验完成了。