打开芯片参考手册,找到iomux,Linux内核源码,打开imxull.dtsi,搜索iomux
有3个寄存器地址:IOMUXC SNVS寄存器、IOMUXC控制器、gpr控制器。
打开板子对应的设备树文件,imx6ull-alientek-emmc.dts,搜索iomux。
1、pintcl/gpio子系统原理
1.1、pintcl
如何找到IMX6UL对应的pinctrl子系统设备?通过compatible,此属性是字符串列表。驱动文件里面有一个描述驱动兼容性的东西,当设备树节点的compatible属性和驱动里面的兼容性字符串匹配时,也就是一摸一样的时候就表示设备和驱动匹配了。所以只需要全局搜索,设备节点里面的compatible属性的值,看看在哪个.c我呢见里面有,那么此.c文件就是驱动文件。找到pinctrl-imx6ull.c文件,此文件就是6ULL/6UL的pinctrl驱动文件。
1.2、gpio子系统
如何从设备树中获取要使用的GPIO信息。of函数。
驱动中对gpio的操作函数:
(1)首先呢,获取到GPIO所处的设备节点。比如:of_find_node_by_path。
(2)获取GPIO编号,of_get_named_gpio函数,返回值就是GPIO编号。
(3)请求此编号的GPIO,gpio_request函数。
(4)设置GPIO,输入或者输出,gpio_direction_input/output。
(5)如果是输入,那么通过gpio_get_value函数读取GPIO值。如果是输出,通过gpio_set_value设置GPIO值。
应用层API:gpio_request();
链接层:gpiolib,在linux内核中的GPIO核心;
底层:原厂,比如6ull、stm,在这里是gpio_mxc.c(NXP)
2、实验
Ubuntu下:
cd /limux/IMX6ULL/Linux_Drivers/
mkdir 6_gpioled
cp 5_dtsled/ * 6_gpioled/
cp 5_dtsled/.vscode 6_gpioled/ -r
rm dtsled.code-workspace
rm dtsled.c
打开vscode,新建一个gpioled.c文件。将上一节的头文件拷贝过来。
2.1、修改设备树
打开linux源码,在imx6ull-alientek-emmc.dts文件。在根节点的最下面添加一个子节点。参考其他外设(使用引脚的)来添加。
alphaled{
}
gpioled{
compatible = "alientek, gpioled";
pinctrl-name = "default";
pinctrl-0 = <&pinctrl_gpioled>;
led-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;//gpio子系统
status = "okay";
};
在305行,&iomuxc{}中的318行pinctrl_csil:csilgrp{}前面添加(创建一个节点):
在imx6ull-pinfun.h文件中找到GPIO1_IO03复用为gpio功能。
pinctrl_gpioled: ledgrp{
fsl, pins = <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10b0
>;
};
编译设备树,用新编译的设备树启动我们的系统:
make dtbs
sudo cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /home/yang/linux/tftpboot/ -f
启动开发板,查看创建的节点(gpioled)存在不?
/ #
/ # cd /proc/device-tree/
/proc/device-tree/ # ls
/sys/firmwave/devicetree/base # cd gpioled/
/sys/firmwave/devicetree/base/gpioled/ # ls
2.2、编写驱动框架
将Makefile中的.o文件改为gpioled.o
/* 驱动入口函数 */
static int __init led_init(void)
{
return 0;
}
/* 驱动出口函数 */
static void __exit led_exit(void)
{
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("yang");
make编译一下,检车有没有错误;
要注册,就要创建设备结构体。
注册设备号;
初始化cdev;在结构体里面添加一个cdev,使用cdev_init()ÿ