日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 單片機 > 單片機
[導讀] 當我們編譯u-boot的時候,大家鍵入make smdk2410_config,make的時候都作了那些動作呢,這里我先大概介紹一下Makefile的內容,然后在大概理解一下命令執(zhí)行的流程。如果有錯的地方,希望大家指正,謝謝。

當我們編譯u-boot的時候,大家鍵入make smdk2410_config,make的時候都作了那些動作呢,這里我先大概介紹一下Makefile的內容,然后在大概理解一下命令執(zhí)行的流程。如果有錯的地方,希望大家指正,謝謝。

1.u-boot頂層目錄的Makefile分析:

31 HOSTARCH := $(shell uname -m |

32 sed -e s/i.86/i386/

33 -e s/sun4u/sparc64/

34 -e s/arm.*/arm/

35 -e s/sa110/arm/

36 -e s/powerpc/ppc/

37 -e s/macppc/ppc/)

首先執(zhí)行uname -m查看機器硬件名,得到i686,然后sed將i686替換成i386,最后HOSTARCH=i386

39 HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' |

40 sed -e 's/(cygwin).*/cygwin/')

首先執(zhí)行uname -s查看開發(fā)平臺的內核,結果為Linux,然后tr將大寫符串轉化為小寫字符linux ,最后的結果是HOSTOS=linux

export HOSTARCH HOSTOS

export是Makefile的語法關鍵詞,將這些變量傳遞給下一層的Makefile.總控Makefile的變量可以傳遞到下級的Makefile中(如果你顯示的聲明),但是不會覆蓋下層的Makefile中所定義的變量,除非指定了“-e”參數(shù)。

如果你要傳遞變量到下級Makefile中,那么你可以使用這樣的聲明:
export ;


如果你不想讓某些變量傳遞到下級Makefile中,那么你可以這樣聲明:
unexport ;


69 ifdef O

70 ifeq ("$(origin O)", "command line")

71 BUILD_DIR := $(O)

72 endif

73 endif

上面意思是:如果在make命令中有O選項內把BUILD_DIR設為O的指定的值

這里主要說明origin的語法:

origin函數(shù)不像其它的函數(shù),他并不操作變量的值,他只是告訴你你的這個變量是哪里來的?其語法是:$(origin ;)
注意,;是變量的名字,不應該是引用。所以你最好不要在;中使用“$”字符。Origin函數(shù)會以其返回值來告訴你這個變量的“出生情況”,下面,是origin函數(shù)的返回值:

“undefined”:如果;從來沒有定義過,origin函數(shù)返回這個值“undefined”。
“default”: 如果;是一個默認的定義
“environment” :如果;是一個環(huán)境變量,并且當Makefile被執(zhí)行時,“-e”參數(shù)沒有被打開。
“file”: 如果;這個變量被定義在Makefile中。
“command line” : 如果;這個變量是被命令行定義的。
“override” : 如果;是被override指示符重新定義的。
“automatic” : 如果;是一個命令運行中的自動化變量。

75 ifneq ($(BUILD_DIR),)

76 saved-output := $(BUILD_DIR)

ifneq如果BUILD_DIR不為空,則把saved-output設為BUILD_DIR

79 $(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})

-d檢查BUILD_DIR文件夾是否存在,不存在則創(chuàng)建

82 BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)

83 $(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))

84 endif # ifneq ($(BUILD_DIR),)

確認BUILD_DIR是否己經創(chuàng)建.假設BUILD_DIR不存在,cd $(BUILD_DIR)為假不執(zhí)行后面/bin/pwd,$(shell cd $(BUILD_DIR) && /bin/pwd)返回值為空, 下面的if為假則會打印outpud directory … does not exist, 同時make退出。

這里主要說明if的語法:

$(if ,,)

如果為真(非空字符串) ,那個會是整個函數(shù)的返回值,如果為假(空字符串) ,那么會是整個函數(shù)的返回值,此時如果沒有被定義,那么,整個函數(shù)返回空字串。

86 OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))

87 SRCTREE := $(CURDIR)

88 TOPDIR := $(SRCTREE)

89 LNDIR := $(OBJTREE)

90 export TOPDIR SRCTREE OBJTREE

91

92 MKCONFIG := $(SRCTREE)/mkconfig

93 export MKCONFIG

CURDIR是makefile中的一個關鍵字,指明當前路徑。

最后TOPDIR SRCTREE OBJTREE這三個變量一樣,都是u-boot源碼目錄的根目錄路徑。然后設置MKCONFIG腳本的路徑。
95 ifneq ($(OBJTREE),$(SRCTREE))

96 REMOTE_BUILD := 1

97 export REMOTE_BUILD

98 endif

如果當前路徑和生成OBJ目錄路徑不一樣,則會設置REMOTE_BUILD為1

103 ifneq ($(OBJTREE),$(SRCTREE))

104 obj := $(OBJTREE)/

105 src := $(SRCTREE)/

106 else

107 obj :=

108 src :=

109 endif

110 export obj src

如果當前路徑和生成OBJ目錄路徑不一樣,則設置src與obj變量的值,代表了最終src與obj的路徑

114 ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))

//通過wildcard文件名函數(shù)判斷是否有include/config.mk文件,也就是執(zhí)行make smdk2410_config以后產生的文件.

$(wildcard pattern)
參數(shù)pattern是一個文件名格式,包含有通配符。函數(shù)wildcard的結果是一列和格式匹配且真實存在的文件的名稱,文件名之間用一個空格隔開。
比如當前目錄下有文件1.c,2.c,1.h,2.h則
c_src := $(wildcard *.c)
結果為:1.c 2.c

# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk//包含這個文件.這里obj為空

export ARCH CPU BOARD VENDOR SOC//將include/config.mk里的變量申明給其他的Makefile使用.

# load other configuration
include $(TOPDIR)/config.mk//然后包含根目錄的config.mk文件.

這些config.mk將在以后介紹

ifndef CROSS_COMPILE//確實沒有定義CROSS_COMPILE變量
ifeq ($(HOSTARCH),ppc)//HOSTARCH為i386,CROSS_COMPILE所以不為空
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = powerpc-linux-
endif
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
......

首先沒有定義CROSS_COMPILE,然后我們的HOSTARCH=i386,然后在判斷ARCH,由于在前面已經指定ARCH=arm.所以CROSS_COMPILE=arm-linux-.通過這個可以選擇不同平臺下的交叉編譯器.

include $(TOPDIR)/config.mk//包含根目錄下的config.mk文件,這個文件以后會分析到。

OBJS = cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS = cpu/$(CPU)/start16.o
OBJS = cpu/$(CPU)/reset.o
endif ........

OBJS := $(addprefix $(obj),$(OBJS)) //將OBJS賦值給OBJ
$(addprefix src/,foo bar)
結果:src/foo src/bar

由于start.S是我們啟動代碼,所以首先編譯.OBJ=cpu/arm920t/start.o

LIBS = lib_generic/libgeneric.a
LIBS = board/$(BOARDDIR)/lib$(BOARD).a
LIBS = cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS = cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
LIBS = lib_$(ARCH)/lib$(ARCH).a
........

.PHONY : $(LIBS)

添加相應的靜態(tài)庫.

__OBJS := $(subst $(obj),,$(OBJS)
__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))

(1) $(subst from,to,text).
在文本“text”中使用to替換每一處的from。
比如:
$(subst ee,EE,feet on the street)
結果為:fEET on the strEET

ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) //這個是最后要生成的文件。$(U_BOOT_NAND) $(U_BOOT_ONENAND)要添加相應的宏定義即可。

$(obj)u-boot.hex: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@將u-bootELF格式文件生成16進制格式的文件
$(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@將u-bootELF格式文件生成另一種S-Record格式的文件

unconfig:
@rm -f $(obj)include/config.h $(obj)include/config.mk
$(obj)board/*/config.tmp $(obj)board/*/*/config.tmp $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep
//刪除以前的配置文件
以上是一些Makefile的大概信息,這里就說到這里。感興趣的可以再深入了解。

//當我們執(zhí)行make smdk2410_config的時候,要作的事情如下:
Makefile文件里面可以看出支持好多種體系結構,并有相應開發(fā)板的配置信息。這里主要研究的是ARM,開發(fā)板是smdk2410.
當我們執(zhí)行:make smdk2410_config的時候,首先執(zhí)行:
smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
首先執(zhí)行unconfig這個標簽,主要是刪除以前的配置信息。
然后執(zhí)行$(MKCONFIG),也就是mkconfig腳本,并傳遞6個參數(shù)。
$(@:_config=)他的作用就是將smdk2410_config中的_config設置為空,結果為smdk2410.
這個命令也就是:./mkconfigsmdk2410 arm arm920t smdk2410 NULL s3c24x0.
$0 $1 $2 $3 $4 $5 $6
接下來看看mkconfig的源代碼:
1.確定開發(fā)板的名稱
11 APPEND=no # Default: Create new config file

12 BOARD_NAME="" # Name to print in make output

13

14 while [ $# -gt 0 ] ; do

15 case "$1" in

16 --) shift ; break ;;

17 -a) shift ; APPEND=yes ;;

18 -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;

19 *) break ;;

20 esac

21 done
由于參數(shù)里沒有-- -a -n等參數(shù),所以這個while沒有執(zhí)行。然后APPEND BOARD_NAME沒有改變。
23 [ "${BOARD_NAME}" ] || BOARD_NAME="$1"
這個時候BOARD_NAME的值就等于"smdk2410".

25 [ $# -lt 4 ] && exit 1//參數(shù)的個數(shù)小于4退出

26 [ $# -gt 6 ] && exit 1//參數(shù)的個數(shù)大于6退出

2.創(chuàng)建開發(fā)板相關的頭文件的連接
//判斷源代碼目錄和目標文件目錄是否一樣,由于直接我們都是在源代碼目錄編譯,所以將執(zhí)行else分之的代碼。
33 if [ "$SRCTREE" != "$OBJTREE" ] ; then

34 mkdir -p ${OBJTREE}/include

35 mkdir -p ${OBJTREE}/include2

36 cd ${OBJTREE}/include2

37 rm -f asm

38 ln -s ${SRCTREE}/include/asm-$2 asm

39 LNPREFIX="../../include2/asm/"

40 cd ../include

41 rm -rf asm-$2

42 rm -f asm

43 mkdir asm-$2

44 ln -s asm-$2 asm

45 else

46 cd ./include

47 rm -f asm

48 ln -s asm-$2 asm

49 fi
進入include目錄,刪除asm文件(這是上一次的配置時建立的連接文件),然后再次建立asm文件,并令它連接向asm-$2目錄,也就是asm-arm目錄。

rm -f asm-$2/arch //刪除asm-$2即asm-arm目錄

if [ -z "$6" -o "$6" = "NULL" ] ; then //-z表示:[ -zSTRING ] “STRING”的長度為零則為真。

ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch
fi
//對于$6就是s3c24x0,不為空,也不是NULL,所以將執(zhí)行else分之。LNPREFIX為空,所以連接的命令就是ln -s arch-$6 asm-$2/arch,也就是ln -s arch-s3c24x0 asm-arm/arch

if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi
重新建立asm-arm/proc文件,并讓它連接向proc-armv目錄。

3.創(chuàng)建頂層Makefile包含的文件include/config.mk
echo "ARCH = $2" > config.mk //“>”,“>>”如果有config.mk文件,并將ARCH輸入到config.mk文件里。如果沒有首先創(chuàng)建然后將ARCH輸入。
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk

//將ARCH,CPU,BOARD變量重定向到include/config.mk文件里

[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk

[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
//將VENDOR,SOC變量重定向到include/config.mk文件里
這樣include/config.mk文件里的內容如下:
ARCH = arm
CPU = arm920t
BOARD = smdk2410
SOC = s3c24x0
#
# Create board specific header file
#
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file //創(chuàng)建include/config.h文件
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include " >>config.h //將#include
exit 0
這樣include/config.h里的內容如下:
/* Automatically generated - do not edit */
#include

3.u-boot的編譯和連接過程
首先在Makefile里包含了include/config.mk和根目錄的config.mk兩個文件。第一個主要是那6個參數(shù)。第二個config.mk文件的內容如下:
BOARDDIR = $(BOARD)
endif
ifdef BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
endif //包含board/smdk2410/config.mk,里面主要定義了TEXT_BASE=0x33f80000
........
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
。。。。
LDFLAGS = -Bstatic -T $(LDSCRIPT) $(PLATFORM_LDFLAGS)//加入連接文件為以后使用。LDFLAGS有“-T board/smdk2410/u-boot.lds -Ttext 0x33f80000”字樣。首先我們的u-boot.lds告訴我們的代碼的分布狀況,而-Ttext 0x33f80000告訴我們text段放在0x33f80000.待會會講到u-boot.lds的內容。對于OBJS,LIBS的每個成員,都將進入相應的子目錄執(zhí)行make命令。當所有的OBJS,LIBS所表示的.o,.a文件生成后,就剩下最后的連接了,這對應Makefile的如下幾行:
$(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) |
sed -n -e 's/.*($(SYM_PREFIX)__u_boot_cmd_.*)/-u1/p'|sort|uniq`;
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS)
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS)
-Map u-boot.map -o u-boot
首先使用下面的語句連接得到ELF格式的u-boot.最后轉化為二進制格式的u-boot.bin,S-Record格式的u-boot.srec。LDFLAGS確定了連接的方式,其中“-T board/smdk2410/u-boot.lds -Ttext 0x33f80000”字樣指定了程序的布局和地址。u-boot.lds的文件如下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
/*指定輸出可執(zhí)行文件是elf格式,32位ARM指令,小端*/
OUTPUT_ARCH(arm)
/*指定輸出可執(zhí)行文件的平臺為ARM*/
ENTRY(_start)
/*指定輸出可執(zhí)行文件的起始代碼段為_start*/
(.globl _start _start: b start_code//cpu/arm920t/start.S)
SECTIONS
{
/*指定可執(zhí)行image文件的全局入口點,通常這個地址都放在ROM(flash)0x0位置。必須使編譯器知道這個地址,通常都是修改此處來完成*/
. = 0x00000000; /*;從0x0位置開始*/
. = ALIGN(4);/*代碼以4字節(jié)對齊*/
.text :
{
cpu/arm920t/start.o (.text) /*代碼的第一個代碼部分*/
*(.text) /*其它代碼部分*/
}
. = ALIGN(4);
.rodata : { *(.rodata) } /*指定只讀數(shù)據(jù)段*/

. = ALIGN(4);
.data : { *(.data) }/*指定讀/寫數(shù)據(jù)段*/

. = ALIGN(4);
.got : { *(.got) } /*指定got段, got段是uboot自定義的一個段,非標準段*/

. = .;
/*把__u_boot_cmd_start賦值為當前位置,即起始位置*/
__u_boot_cmd_start = .;
/*指定u_boot_cmd段, uboot把所有的uboot命令放在該段.*/
.u_boot_cmd : { *(.u_boot_cmd) }
/*把__u_boot_cmd_end賦值為當前位置,即結束位置*/
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .; /*把__bss_start賦值為當前位置,即bss段的開始位置*/
.bss (NOLOAD) : { *(.bss) } /*指定bss段,告訴加載器不要加載這個段*/
_end = .; /*把_end賦值為當前位置,即bss段的結束位置*/

這樣代碼的都是以0x33f80000 0x0為基準開始,如果你從nandflash啟動,測試前4K的代碼的地址都是在0x0,那么4K的代碼的實現(xiàn)可以通過位置無關指令b來實現(xiàn)。b指令的程序不依賴代碼存儲的位置-即不管這條代碼放在什么位置,B指令都可以跳轉到正確的位置。
bootloader,內核等程序剛開始運行時。他們所處的地址通常不等于運行地址

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉