前言:
本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
正文:
本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第11.1讲, 11.2讲” 的读书笔记。第11.1,11.2讲介绍如何将我们写的C语言LED驱动程序组织成为一个业界典型的BSP目录的形式。
1. 将C语言LED驱动程序组织为BSP目录形式
上一节中移植了NXP SDK的文件到 C 语言LED驱动程序中,并调用 NXP SDK 里定义的api接口来设置GPIO 接口的IO接口复用模式和IO接口的电气特性,最后在 main.c 文件里调用api接口函数来实现 I.MX6ULL APLHA/Mini 开发板的 LED 指示灯闪烁。
在上一节的C语言LED驱动程序中,在 main.c 源文件中声明并定义了 'clk_init()', 'led_init()', 'delay_short()' , 'delay()' 这些函数并在 main.c 源文件中直接调用了这些函数。并且移植的 .h 头文件和 main.c 文件都是放在根目录下面的。在后续学习开发过程中,随着项目越来越复杂,项目的源文件也会越来越多,大量的源文件混在同一个根目录下面会让项目的管理变得混乱。本节中我们将会使用芯片驱动开发业界通用的模式,把项目的源码文件组织成BSP形式的目录形式,分门别类的把项目的源文件和头文件放到专门的目录里。按照BSP的方式来组织项目源码,项目的源码文件管理就变得清晰有条理。使用BSP的方式来管理项目的源码也从侧面反映出开发人员的是否有成熟专业素养。
BSP目录组织中的主要目录如下:
目录 | 描述 |
bsp | 该目录存放项目的 BSP 开发 api 接口源码,和芯片底层相关的API接口的文件都放在该目录下 |
imx6u | 该目录存放项目存放特定处理器相关的文件,例如 I.MX6ULL 芯片的寄存器地址文件。 |
obj | 项目编译出来的 .o 中间文件放在这个目录 |
project | 项目的主体源码文件存放在该目录下,如 main.c start.s |
2. 根据BSP目录格式写Makefile
按照BSP的方式来组织项目源码,项目的源码文件按照类别分别放在了不同的目录里,例如 'bsp/', 'project', 'imx6u'等,之前的Makefile就不能满足当前这种多层目录结构的项目组织形式,我们需要修改 Makefile 来编译 BSP这种多层目录结构的源码。
本节Makefile将使用多用的make函数语法,本节写的是一个通用的makefile,在后续的正点原子 I.MX6U 裸机开发例程中都将使用本节写的Makefile,仅仅需要多Makefile做很小的修改就能适应不同的I.MX6U开发实验例程。
本节会使用到的makefile语法,主要有以下几种:
makefile函数: | 描述: |
$(foreach <var>,<list>,<text>) | 这个函数的意思是,把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。 |
$(patsubst <pattern>,<replacement>,<text>) | 查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”, 表示任意长度的字串 |
$(wildcard $(dir)/*.c) | wildcard 函数在定义变量的地方将通配符‘*’进行扩展,如果有符合通配符的格式字符串就返回改字符串,如果没有符合通配符格式的字符串就返回空。 |
通过这些makefile 模式匹配,模式替换,模式扩展函数,我们的新Makefile的内容如下,这是一种通用的 makefile 格式,它通过对 BSP 子目录里源文件的匹配替换,makefile语法格式中的模式替换函数对字符串的操作,实现了对BSP子目录中“*.c”,"*.s" 源文件的自动搜索并生成以来关系。在后续的正点原子I.MX6ULL APHAP/Mini开发例程实验里,只需要在makefile里加上BSP的子目录,就可以自动的生成编译目标的以来关系。
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET := ledc
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
INCLUDEDIRS := bsp/clk \
bsp/delay \
bsp/led \
imx6ull
SRCDIRS := bsp/clk \
bsp/delay \
bsp/led \
project
INCLUDE := $(patsubst %, -I %, $(INCLUDEDIRS))
#SFILES := $(patsubst %.s,%.s,$(wildcard $(SRCDIRS)/*.s))
#CFILES := $(patsubst %.c,%.c,$(wildcard $(SRCDIRS)/*.c))
#SFILES := $(wildcard $(SRCDIRS)/*.s)
#CFILES := $(wildcard $(SRCDIRS)/*.c)
#错误的语法格式,因为 $(wildcard $(SRCDIRS)/*.c) 展开之后为 "$(wildcard bsp/clk bsp/delay bsp/led project/*.c)",这样只有最后一个展开为了 $(wildcard project/*.c)的形式
#按照我们的预期,应该使用 Makefile 的 $(foreach var,list,text) 函数
##
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.s))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
SOBJS := $(patsubst %, obj/% ,$(SFILENDIR:%.s=%.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:%.c=%.o))
OBJS := $(SOBJS) $(COBJS)
VPATH := $(SRCDIRS)
$(TARGET).bin : $(OBJS)
echo $(LD) $(TARGET).elf
$(LD) -Timx6u.lds -o $(TARGET).elf $^
$(OBJCOPY) -O binary -S $(TARGET).elf $(TARGET).bin
$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
# #%.o : %.s
$(SOBJS) : obj/%.o : %.s
$(CC) -Wall -nostdlib $(INCLUDE) -c -o $@ $<
#%.o : %.c
$(COBJS) : obj/%.o : %.c
$(CC) -Wall -nostdlib $(INCLUDE) -c -o $@ $<
clean:
rm -rf obj/*.o $(TARGET).bin $(TARGET).elf
.PHONY : print clean
print:
@echo "INCLUDE=" $(INCLUDE)
@echo "SFILES=" $(SFILES)
@echo "CFILES=" $(CFILES)
@echo "SFILENDIR=" $(SFILENDIR)
@echo "CFILENDIR=" $(CFILENDIR)
@echo "SOBJS=" $(SOBJS)
@echo "COBJS=" $(COBJS)
@echo "OBJS=" $(OBJS)
3. 修改 imx6u.lds 链接文件
修改Makefile之后,执行编译项目,编译器输出如下错误:
错误提示信息显示,实在链接阶段 'ld' 找不到 'start.o'文件,因为本节中我们把LED驱动源程序组织成了 BSP 目录格式形式,所以在 imx6u.lds 链接文件中之前指定的 'start.o' ,在当前目录下就找不到 start.o 文件,在新的编译目录该文件的路径是 './obj/start.o' 所以需要修改 imx6u.lds 链接文件,执行 start.o 的文件目录为新的位置。
修正 imx6u.lds 链接文件之后,重新执行“make”命令进行编译,项目可以正确的编译成功并生成 .bin 文件。
4. 烧录SD卡,并验证LED灯是否正常闪烁
烧录SD卡验证LED灯,使用正点原子提供的 'imxdownload' 烧录SD卡,然后把SD卡查到正点原子 I.MX6U APLHA/Mini 开发板上验证移植的 NXP SDK LED 灯驱动程序是否运行正常,LED灯正常闪烁。我本地实验验证结果是 LED 正常闪烁。