基础知识:
Makefile常用函数:
http://blog.csdn.net/l0605020112/article/details/38944825
strip :去空格函数
$(strip string)
功能:去掉<string>字串中开头和结尾的空字符。
返回:返回被去掉空格的字符串值
$(findstring ,)
名称:查找字符串函数——findstring。
功能:在字串中查找字串。
返回:如果找到,那么返回,否则返回空字符串。
http://blog.csdn.net/liangkaiming/article/details/6267357
1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )
在user@instant-contiki:~/contiki/examples/hello-world$ 路径中执行make TARGET=srf06-cc26xx BOARD=srf06/cc26xx即可完成helloworld工程的编译,并且输出bin,hex,elf类型可执行文件。
user@instant-contiki:~/contiki/examples/hello-world$ make <span style="color:#ff0000;">TARGET</span>=srf06-cc26xx <span style="color:#ff0000;">BOARD</span>=srf06/cc26xx
1. 根目录的Makefile
命令中主要是通过执行make命令完成对目标的编译的。#Makefile:
CONTIKI_PROJECT = hello-world
all: $(CONTIKI_PROJECT)
CONTIKI = ../..
include $(CONTIKI)/Makefile.include
Makefile 中指定输出目标是hello-world,这样就会编译hello-world.c文件。但是要知道helloworld.c中包含的有contiki.h文件,那么就需要指定路径进行索引。并且helloworld文件中的宏定义展开后引申出线程相关的函数。
最后一行,引入contiki目录下的Makefile.include文件,里面包含了大量的内容,逐级展开包含内核、协议栈、处理器相关等内容。
include $(CONTIKI)/Makefile.include
2. Contiki根目录下的Makfile.include文件
2.1 make命令预处理
首先是判断是做了变量的初始化,即make的时候后面跟的TARGET等。# -*- makefile -*-
ifndef CONTIKI
${error CONTIKI not defined! You must specify where Contiki resides}
endif
ifeq ($(TARGET),)
-include Makefile.target
ifeq ($(TARGET),)
${info TARGET not defined, using target 'native'}
TARGET=native
else
${info using saved target '$(TARGET)'}
endif
endif
其中${info xxx},$(warning xxx),$(error xxxx),@echo xxx均为信息打印,其中$后的括号可以是大括号也可以是小括号。
其中feq ($(TARGET),)是说TARGET变量是否为空,即make的时候没有指定此变量。
2.2 预处理结果输出
usage:
@echo "make MAKETARGETS... [TARGET=(TARGET)] [savetarget] [targets]"
targets:
@ls -1 $(CONTIKI)/platform $(TARGETDIRS) | grep -v CVS
savetarget:
-@rm -f Makefile.target
@echo "saving Makefile.target"
@echo >Makefile.target "TARGET = $(TARGET)"
savedefines:
-@rm -f Makefile.$(TARGET).defines
@echo "saving Makefile.$(TARGET).defines"
@echo >Makefile.$(TARGET).defines "DEFINES = $(DEFINES)"
这里做一些信息打印,主要是预处理后的信息打印。
@表示后面的是个命令,如echo,ls -l等。
2.3编译所用的主要变量的定义、赋值
OBJECTDIR = obj_$(TARGET)
LOWERCASE = -abcdefghijklmnopqrstuvwxyz
UPPERCASE = _ABCDEFGHIJKLMNOPQRSTUVWXYZ
TARGET_UPPERCASE := ${strip ${shell echo $(TARGET) | sed y!$(LOWERCASE)!$(UPPERCASE)!}}
CFLAGS += -DCONTIKI=1 -DCONTIKI_TARGET_$(TARGET_UPPERCASE)=1
<span style="color:#ff0000;">MODULES </span>+= core/sys core/dev core/lib
OBJECTDIR开始指定了一些非常有用的信息,object变量赋值,Modules变量赋值。第一次定义MODULES变量,并把内核相关文件路径赋值给MODULES。
2.4协议栈的选择
协议栈的定义,根据是否声明了协议栈类型:IPV4,IPV6或Rime。默认是IPV6。# Include IPv6, IPv4, and/or Rime
HAS_STACK = 0
ifeq ($(CONTIKI_WITH_IPV4),1)
HAS_STACK = 1
CFLAGS += -DNETSTACK_CONF_WITH_IPV4=1
MODULES += core/net/ipv4 core/net/ip
endif
ifeq ($(CONTIKI_WITH_RIME),1)
HAS_STACK = 1
CFLAGS += -DNETSTACK_CONF_WITH_RIME=1
MODULES += core/net/rime
endif
# Make IPv6 the default stack
ifeq ($(HAS_STACK),0)
ifneq ($(CONTIKI_WITH_IPV6),0)
CONTIKI_WITH_IPV6 = 1
endif
endif
ifeq ($(CONTIKI_WITH_IPV6),1)
CFLAGS += -DNETSTACK_CONF_WITH_IPV6=1
ifneq ($(CONTIKI_WITH_RPL),0)
CONTIKI_WITH_RPL = 1
endif
MODULES += core/net/ipv6 core/net/ip
endif
ifeq ($(CONTIKI_WITH_RPL),1)
CFLAGS += -DUIP_CONF_IPV6_RPL=1
MODULES += core/net/rpl
else
CFLAGS += -DUIP_CONF_IPV6_RPL=0
endif
2.5 contiki内核、网络协议相关的文件包含
把需要编译的内容放到CONTIKI_OBJECTFILES和PROJECT_OBJECTFILES变量中。然后创建相应的用于存放编译输输出的文件夹,为编译准备环境。这些在执行make clean的时候会被删除,不过加上TARGET BOARD 才行,不然会被默认为native。
<span style="color:#ff0000;">CONTIKI_SOURCEFILES </span>+= $(CONTIKIFILES)
<span style="color:#ff0000;">CONTIKIDIRS </span>+= ${addprefix $(CONTIKI)/core/,dev lib net net/llsec net/mac net/rime \
net/rpl sys cfs ctk lib/ctk loader . }
<span style="color:#ff0000;">oname </span>= ${patsubst %.c,%.o,${patsubst %.S,%.o,$(1)}}
<span style="color:#ff0000;">CONTIKI_OBJECTFILES </span>= ${addprefix $(OBJECTDIR)/,${call oname, $(CONTIKI_SOURCEFILES)}}
<span style="color:#ff0000;">PROJECT_OBJECTFILES </span>= ${addprefix $(OBJECTDIR)/,${call oname, $(PROJECT_SOURCEFILES)}}
# Provide way to create $(OBJECTDIR) if it has been removed by make clean
$(OBJECTDIR):
mkdir $@
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
这里不清楚CONTIKIFILES变量在哪里定义的。第一次定义CONTIKI_SOURCEFILES变量CONTIKI_OBJECTFILES变量, PROJECT_OBJECTFILES变量和CONTIKIDIRS变量。定义oname,uniq。
这里addprefix为加前缀函数,把contiki所在路径增加到后面的dev lib等前面。
2.6 获取目标平台的makefile文件
target_makefile := $(wildcard $(CONTIKI)/platform/$(TARGET)/Makefile.$(TARGET) ${foreach TDIR, $(TARGETDIRS), $(TDIR)/$(TARGET)/Makefile.$(TARGET)})
:=为覆盖赋值。$(wildcard)是通配符函数,该句展开所有的Makefile.srf06-cc26xx,并将这些文件赋值为target_makefile变量。
此处应该先了解3~5小节内容。之后再看2.7
2.7 Nothing
懒没有写
3. Makefile.srf06-cc26xx
# srf06-cc26xx platform makefile
ifndef CONTIKI
$(error CONTIKI not defined! You must specify where CONTIKI resides!)
endif
### Board and BSP selection
ifeq ($(BOARD),)
BOARD=srf06/cc26xx
endif
CONTIKI_TARGET_DIRS += .
### Include the board-specific makefile
PLATFORM_ROOT_DIR = $(CONTIKI)/platform/$(TARGET)
-include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(notdir $(BOARD))
CONTIKI_TARGET_SOURCEFILES += contiki-main.c
CONTIKI_TARGET_SOURCEFILES += sensors.c leds.c
CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES)
CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
CLEAN += *.srf06-cc26xx
### Unless the example dictates otherwise, build with code size optimisations
ifndef SMALL
SMALL = 0
endif
### Define the CPU directory and pull in the correct CPU makefile. This will
### be defined by one of the makefiles included above and it can be either
### Makefile.cc26xx or Makefile.cc13xx
CONTIKI_CPU=$(CONTIKI)/cpu/cc26xx-cc13xx
include $(CONTIKI_CPU)/Makefile.$(CPU_FAMILY)
MODULES += core/net core/net/mac core/net/mac/contikimac core/net/llsec
这里把Platform路径添加到CONTIKI_TARGET_DIRS,定义了PLATFORM_ROOT_DIR,platform路径下的.c,.h文件增加到CONTIKI_TARGET_SOURCEFILES和CONTIKI_SOURCEFILES。定义CONTIKI_CPU,并将cpu/cc26xx-cc13xx下的makefile文件包含进来。网络协议相关的mac层文件增加到MODULES变量中。
下一步就是看cpu/cc26xx-cc13xx下的makefile的了,可是这里的CPU_FAMILY不知道在哪里定义的,根据注释应该是Makefile.cc26xx。
4. Makefile.cc26xx
TI_XXWARE_PATH = lib/cc26xxware
include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx
定义变量TI_XXWARE_PATH,并赋值固件路径。包含了Makefile.cc26xx-cc13xx文件。
5. Makefile.cc26xx-cc13xx
5.1 gcc设定
CC = arm-none-eabi-gcc
CPP = arm-none-eabi-cpp
LD = arm-none-eabi-gcc
AR = arm-none-eabi-ar
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
NM = arm-none-eabi-nm
SIZE = arm-none-eabi-size
SREC_CAT = srec_cat
5.2 固件相关变量定义
CPU_ABS_PATH = cpu/cc26xx-cc13xx
TI_XXWARE = $(CONTIKI_CPU)/$(TI_XXWARE_PATH)
### cc26xxware sources under driverlib will be added to the MODULES list
TI_XXWARE_SRC = $(CPU_ABS_PATH)/$(TI_XXWARE_PATH)/driverlib
### The directory with startup sources will be added to the CONTIKI_CPU_DIRS
### and the sources therein are added to the sources list explicitly. They are
### also listed explicitly in the linker command (through TARGET_STARTFILES),
### to make sure they always get linked in the image
TI_XXWARE_STARTUP_DIR = $(TI_XXWARE_PATH)/startup_files
TI_XXWARE_STARTUP_SRCS = ccfg.c startup_gcc.c
5.3 指定CPU依赖关系
### CPU-dependent cleanup files
CLEAN += symbols.c symbols.h *.d *.elf *.hex
### CPU-dependent directories
CONTIKI_CPU_DIRS = . dev rf-core rf-core/api $(TI_XXWARE_STARTUP_DIR)
### Use the existing debug I/O in cpu/arm/common
CONTIKI_CPU_DIRS += ../arm/common/dbg-io
### CPU-dependent source files
CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c
CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c aux-ctrl.c
CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c
CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c
CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c
CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c
DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c
CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES)
并将所有依赖文件添加到CONTIKI_SOURCEFILES变量中。
5.4设定编译规则
### Compilation rules
CUSTOM_RULE_LINK=1
%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT)
$(TRACE_LD)
$(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@
%.i16hex: %.elf
$(OBJCOPY) -O ihex $< $@
%.hex: %.i16hex
$(SREC_CAT) $< -intel -o $@ -intel
%.bin: %.elf
$(OBJCOPY) $(OBJCOPY_FLAGS) $< $@
%.lst: %.elf
$(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@
### We don't really need the .hex and .bin for the .$(TARGET) but let's make
### sure they get built
%.$(TARGET): %.elf %.hex %.bin
cp $< $@
5.5 硬件相关配置
# a target that gives a user-friendly memory profile, taking into account the RAM
# that is statically occupied by the stack as defined in the linker script
# see $(LDSCRIPT)
RAM_SIZE = 0x00003E00
FLASH_SIZE = 0x0001E000
STACK_SIZE = 0
%.size: %.$(TARGET)
@$(SIZE) -A $< | egrep "data|bss" | awk '{s+=$$2} END {s=s+$(STACK_SIZE); f=$(RAM_SIZE)-s; printf "[RAM] used %6d, free %6d\n",s,f;}'
@$(SIZE) -A $< | egrep "text|isr_vector" | awk '{s+=$$2} END {f=$(FLASH_SIZE)-s; printf "[Flash] used %6d, free %6d\n",s,f;}'
ifeq ($(BOARD_SUPPORTS_BSL),1)
%.upload: %.bin
ifeq ($(wildcard $(BSL)), )
@echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?"
else
$(PYTHON) $(BSL) $(BSL_FLAGS) $<
endif
else
%.upload:
@echo "This board cannot be programmed through the ROM bootloader and therefore does not support the .upload target."
endif
# Check if we are running under Windows
ifeq ($(HOST_OS),Windows)
SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-windows
else
ifeq ($(HOST_OS),Darwin)
SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-macos
else
# Else assume Linux
SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-linux
endif
endif
UART_BAUDRATE = 115200
login:
$(SERIALDUMP) -b$(UART_BAUDRATE) $(PORT)
配置RAM,配置FLash、Stack,串口波特率等与硬件相关内容。