bsp管理模式及Makefile
1. bsp管理
bsp管理,说白了,就是只将相同内容或属性的文件放在同一个目录下,不同属性的文件分开存放,这样可以方便文件管理及查找。
以imx6ull芯片实现跑马灯为例:
--led亮灭过程实现三步骤:时钟使能,led初始化(GPIO管脚功能设定),延时设定;
--bsp管理:
1)将三部分的文件分别存放不同文件夹下:clk.c/clk.h放于clk文件夹,led.c/led.h存放于led文件夹下,delay.c/delay.h存放于delay文件夹下;
2)我们用到的,对应芯片厂商的sdk包可以放于imx6ull文件夹下;
3)主函数main.c以及汇编(编写C运行环境等内容)存放于project文件夹下。
如上即为bsp管理模式。
2. Makefile编写
对于bsp管理模式而言,各个目录下都可能会存放不同的.c和.h文件,所以进行Makefile编写的时候就需要表明.c和.h的路径,否则会在make时找不到相关文件而报错;
仍以跑马灯为例,Makefile相关代码如下,下面会对Makefile各个部分进行解释:
COMPILE := arm-linux-gnueabihf-
TARGET := led
GCC := $(COMPILE)gcc
LD := $(COMPILE)ld
OBJCOPY := $(COMPILE)objcopy
OBJDUMP := $(COMPILE)objdump
INCDIRS := imx6ull\
bsp/clk\
bsp/led\
bsp/delay\
project
SRCDIRS := project\
bsp/clk\
bsp/led\
bsp/delay
//上方内容很简单,只是通过:=进行赋值操作(:=意义在于符号左方变量只能等于右方变量之前定义过的值,即使右方变量在下文重新定义,左方变量不受到影响)
//$()作用:取括号内变量的值
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
//目的将所有文件夹前方添加-I符号,这样相当于gcc -I + 路径操作,就是查找头文件时也会到指令路径取查找。
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
//遍历所有的.S和.c文件(获取的名称包含路径+文件名),详细会在下方解释
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
//去掉路径,只要.S和.c文件名称
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
//将.S和.c文件后缀改为.o,(这里只是改名字,不是真正编译后的.o文件,名称后续需用于依赖)
OBJS := $(SOBJS)$(COBJS)
VPATH := $(SRCDIRS)
//表明依赖所在路径,当当前系统找不到相关依赖时,会往该路径下去找
$(TARGET).bin: $(OBJS)
$(LD) -Timx6ull.lds $^ -o $(TARGET).elf
$(OBJCOPY) -O binary -S $(TARGET).elf $@
$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
$(SOBJS): obj/%.o: %.S
$(GCC) -Wall -nostdlib -c $(INCLUDE) -o $@ $<
$(COBJS): obj/%.o: %.c
$(GCC) -Wall -nostdlib -c $(INCLUDE) -o $@ $<
.PHONY: clean:
//伪目标,只有在“make + 伪目标名称”命令下才会执行到
rm obj/*.o $(TARGET).bin $(TARGET).elf $(TARGET).dis
.PHONY: print:
@echo $(OBJS)
Makefile中相关函数解释
– patsubst函数(模式字符串替换函数)
用法:$(patsubst <pattern>,<replace>, <text>)
<pattern>:待替换字符串,
<replace>:替换后的字符串,
<text>:需替换字符串的集合,以空格,"Tab","\","回车"分隔,将值依次提供给<pattern>进行替换
以上述代码为例:INCLUDE := $(patsubst %, -I %, $(INCDIRS))
通过上述代码中伪目标print的方式进行打印观察:每一个目标字符串前都加了一个-I。
raydiumtouch@raydiumtouch-VirtualBox:~/Driver Development/5_led_bsp_manage$ make print
INCLUDE = -I imx6ull -I bsp/clk -I bsp/led -I bsp/delay -I project
–foreach函数(循环函数)
用法:$(foreach <var>, <list>, <text>)
功能:将list中的元素依次赋给var,然后在执行text的表达式并返回执行后的内容,返回的每个字符串以空格间隔。
以上述代码为例:CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
该部分作用就是将每个文件夹传给dir,然后再每个dir下找所有.c的文件;
执行函数内容中还包含wildcard,这个的作用为使通配符有效,函数返回可以展开所有.c文件,并以空格间隔。(默认下通配符有效,但在函数中,通配符失效)。
make print观察返回信息:
raydiumtouch@raydiumtouch-VirtualBox:~/Driver Development/5_led_bsp_manage$ make print
CFILES = project/main.c bsp/clk/clk.c bsp/led/led.c bsp/delay/delay.c
–notdir(去掉文件前的路径,只保留文件名)
举例:CFILENDIR := $(notdir $(CFILES))
打印观察发现:无路径信息,只有文件名
raydiumtouch@raydiumtouch-VirtualBox:~/Driver Development/5_led_bsp_manage$ make print
CFILENDIR = main.c clk.c led.c delay.c