前言:
本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
正文:
本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第10.1讲” 的读书笔记。第10.1 讲教程介绍了使用一直NXP SDK 的头文件来给我们自己使用。
NXP I.MX6ULL 芯片的有很多的外设寄存器,如果我们像上一节中一个一个的对照的芯片参考手册来自己写,工作量很大而且很容易写错,幸运的是NXP已经写到了SDK来提供给用户使用,在NXP的SDK里已经定义好了所有 NXP I.MX6ULL 的寄存器和设置使用寄存器的API。如果使用NXP的SDK中的API,我们就可以减少很多的工作量。
这一节我们将会移植NXP官方的SDK到我们的C语言LED灯驱动程序。
0. 移植NXP I.MX6U SDK 的头文件
参考正点原子的第10.1 教程视频,安装正点原子资料盘里附带的NXP正点原子SDK安装包,这个NXP SDK安装之后会把NXP官方提供的芯片文档和芯片SDK API源码解压都指定的目录。我们在解压目录里就可以找到NXP SDK的源码文件。
参考正点原子的第10.1 教程视频,需要移植的NXP SDK 有如下几个头文件:
- fsl_common.h
- fsl_iomuxc.h
- MCIMX6y2.h
将这3个头文件放到我们的 “C语言LED驱动程序”文件夹,把这3个文件放到我们目录后,我们需要对这3个头文件进行一些修改。如果3个NXP SDK头文件直接进行编译会出现很多编译错误,原因是没有移植NXP SDK中的所有文件,我们删除头文件一些我们暂时不用内容,让文件能够通过编译。
正点原子I.MX6ULL ALPHA/Mini开发板使用的 I.MX6ULL 处理器的型号是 "MCIMX6Y2",我们到SDK NXP 的目录里找到需要移植的头文件。
nxp\SDK_2.2_MCIM6ULL\devices\MCIMX6Y2
1 | nxp\SDK_2.2_MCIM6ULL\devices\MCIMX6Y2\MCIMX6Y2.h |
2 | nxp\SDK_2.2_MCIM6ULL\devices\MCIMX6Y2\drivers\fsl_common.h |
3 | nxp\SDK_2.2_MCIM6ULL\devices\MCIMX6Y2\drivers\fsl_iomuxc.h |
参考正点原子提供的示例源码中的头文件,修改NXP SDK中的这3个头文件,删除头文件中我们暂时不需要的内容,让头文件可以通过编译。这里修改 NXP SDK 3个头文件的细节这里不再截图详细展示,主要的就是参考正点原子提供的示例程序和正点原子第10.1讲的视频教程进行修改。
1. 修改 main.c 使用 NXP SDK 里提供的GPIO寄存器配置API接口函数
1.1 调用 NXP SDK 'IOMUXC_SetPinMux()' 设置IO复用
修改 main.c 使用 NXP SDK 里提供的GPIO寄存器配置API接口函数。在上一节博文中我们使用,"IOMUX_SW_MUX->GPIO1_IO03 = 0x5" 来设置 GPIO1_IO03 寄存器的值为 0x5 来选择复用 GPIO1_IO03 芯片管脚为 GPIO 模式。本节我们使用 NXP SDK 官方定义在 'fsl_iomuxc.h' 头文件里的 api 接口函数 "void IOMUXC_SetPinMux()" ,这个函数有6个形参,在调用的时候我们需要传入6参数给这个 api 。
在main.c中调用 "void IOMUXC_SetPinMux()" 的时候怎样传入6个实参哪?在mian.c 中我们通过如下方式来调用这个api:
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0); /*复用GPIO1_IO03为GPIO模式*/
下面解释一下这种调用方式是如何展开为传递6个参数给api "IOMUXC_SetPinMux()" 的。在 ‘fsl_iomuxc.h’ 中定义了宏:
#define IOMUXC_GPIO1_IO03_GPIO1_IO03 \
0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U
这样函数展开之后就是如下形式,宏 ‘IOMUXC_GPIO1_IO03_GPIO1_IO03’ 展开为了5个参数,加上最后一个参数'0',就传递了6个参数给 api "IOMUXC_SetPinMux()",NXP SDK 定义的这种宏方式还是比较巧妙的。
IOMUXC_SetPinMux(0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U,
0); /*复用GPIO1_IO03为GPIO模式*/
再来分析宏 ‘IOMUXC_GPIO1_IO03_GPIO1_IO03’ 展开为了5个参数:
- “0x020E0068U” 就是I.MX6U 参考手册中GPIO1_IO03寄存器的地址。
- "0x05" 就是 GPIO1_IO03 中选择复用模式5 (5为GPIO模式)。
- 然后是 'inputRegister', 'iputDaisy' 这两个有有些 input 接口需要的这里我们不条轮其细节。
- 然后是 'configRegister' 展开的宏中值为 ''0x020E02F4U" 就是I.MX6U 参考手册中GPIO1_IO03 电气特性寄存器的地址。
- 最后一个参数'0' 是 'inputOnFiled' 对应着I.MX6U 参考手册中 GPIO1_IO03 寄存器中的 'SION' 域,这里关闭 'SION',所以传递的 'SION=0'值给api。
1.2 调用 NXP SDK 'IOMUXC_SetPinConfig()' 设置IO电气特性
同理,调用 NXP SDK 'IOMUXC_SetPinConfig()' 设置IO电气特性,这里需要传递给 'SDK 'IOMUXC_SetPinConfig()' api 第二个参数的值为 '0x10B0',这个值也就是前面一节中 ‘C语言LED驱动程序’中根据I.MX6U 参考手册中选择出来的GPIO 电气特性。
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10B0); /*设置GPIO1_IO03电气特性*/
1.3 修改 Makefile
修改Makefile,这一次我们使用 'CROSS_COMPILE' 和 'CC=$(CROSS_COMPILE)gcc' , 'LD=$(CROSS_COMPILE)ld' 的方式来定义makefile变量,来更方便的使用 arm 交叉编译工具,这种 makefile 也是 uboot, Kernel 编译makefile的风格。
CROSS_COMPILE ?= arm-linux-gnueabihf-
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
NAME = ledc
OBJS = start.o main.o
$(NAME).bin : $(OBJS)
$(LD) -Timx6u.lds -o $(NAME).elf $^
$(OBJCOPY) -O binary -S $(NAME).elf $(NAME).bin
$(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis
%.o : %.c
$(CC) -Wall -nostdlib -c -o $@ $<
%.o : %.s
$(CC) -Wall -nostdlib -c -o $@ $<
clean:
rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis
2. 编译移植的 NXP SDK 风格的 LED 驱动程序
执行命令来编译编译移植的 NXP SDK 风格的 LED 驱动程序,如果遇到编译错误,需要查看下编译器输出的错误提示信息来修改错误然后再次编译。我本地实验的时候遇到的编译错误比较少,很快就验证了 NXP SDK 移植编译通过。
3. 烧录SD卡验证LED灯
烧录SD卡验证LED灯,使用正点原子提供的 'imxdownload' 烧录SD卡,然后把SD卡查到正点原子 I.MX6U APLHA/Mini 开发板上验证移植的 NXP SDK LED 灯驱动程序是否运行正常,LED灯正常闪烁。我本地实验验证结果是 LED 正常闪烁。