?? u-bootsourcecode.txt
字號:
digging u-boot source code (s3c44b0)
下一次,接著就去看看U-BOOT的源程序了。當然是基于S3C44B0的BOOTLOADER進行的。
上一次說到要學習UBOOT的代碼,但在看之前,首先要知道目標機器的編程資源,這里的資源,是指S3C44B0所提供的
運行程序的資源,對任何嵌入式軟件開發,都首先要對硬件有一個很好的了解,這跟PC機的編程是大不一樣的。因為
PC機都已經發展了30多年,但整個編程的體系是沒有很大的變化,就是說現在的PC都是在虛擬機上編寫了,跟硬件打
交道的機會很少,所以不用去了解它。但是在嵌入式的軟件里,每樣硬件都是千差萬別的,所以一定要去看原版的
S3C44B0說明手冊,一定要看英文原版的,不能看那種中文版的,哈哈,為什么要看英文原版的呢?第一,每個CPU都
有很多特別寄存器,而這些寄存器都是用英文縮寫的,看中文,就不知道它是什么意思了,并且還要死記,沒有英文
整句好記。第二,中文是經過翻譯的,并且都不是三星廠家進行翻譯,都是一些業余水平的人來做,很難保證按原文
的意思進行。有一次,我看中文的S3C44B0資料找特別寄存器,就找不到,我說為什么沒有呢,原來別人都不翻譯那些
,結果在英文原版中,一看就找到了。因此,喜歡看英文原版的。并且只要學習過幾個CPU之后,發現嵌入式軟件就那
幾樣東西了。
對開發軟件的人來說,最重要的東西是什么呢?哈哈,當然是存儲器和寄存器了。每次拿到開發板之后,一定要去了
解存儲器是怎么樣分配的,是從什么地址開始,存儲器有多大。是什么樣的存儲器,是FLASH的,還是SDRAM的。FLASH
的存儲器映射在S3C44B0的什么地址空間呢?SDRAM又是映射在什么地址空間呢?一定要把這些問題搞清楚,否則就很
難對它開發軟件。所以看S3C44B0的手冊時,就要注意看它的存儲管理。目前,S3C44B0的存儲器管理,分為很多BANK
的。BANK0一般用來映射FLASH存儲器,并且在BANK0后面一段空間里進行特別寄存器映射,它的空間是4M大小。并且一
般的開發板,都是把FLASH存儲器映射在0x0000_0000 到 0x001F_FFFF,這里的地址空間,就是2M大小。把SDRAM映射在
BANK6里面,地址空間就是0x0c00_0000 到 0x0c7f_ffff,這里就是8M的SDRAM了。
特別寄存器的地址空間是從 0x01c0_0000到0x0200_0000的4M空間里,這里的寄存器,大多數都是跟IO有關的。比如串
行通訊,DMA,PWM,看門狗,IO口等等。
看懂了存寄器和存儲器,就可以進行匯編練習。當然S3C44B0它還有ARM標準的寄存器,共有37個吧。這些是所有ARM的
CPU都具有的。
把CPU和S3C44B0特別的功能深入了解之后,就可以去看UBOOT代碼。
目前我的引導程序是在UBOOT1.1.2上修改過來的,大家可以下載UBOOT的源程序,也許你們會問在那里有下呢?這個問
題不用我回答了,用GOOGLE,直接找u-boot,就可以找到了。
由于這個引導程序是從u-boot1.1.2修改過來的,所以還是采用uboot的編譯工具,它就是
arm-linux-tools-20031127.tar.gz,這個可以uboot的網站下載,然后在linux下安裝好,就可以編譯引導程序。
編譯命令主要:
make clean 是清空所有臨時文件,一般是用來清空目錄,用來重新編譯程序。
make XXXX_config 是編譯本引導程序,XXXX是自己定義的開發板,在board目錄下。
make backup 是備份引導程序的源程序。
UBOOT編譯環境建立起來,就可以去修改和學習UBOOT的源程序,就可以開發自己的boot。源程序已經下載,就可以解
開壓縮包,在目錄u-boot-1.1.3,因目前最新的UBOOT是1.1.2,那個1.1.3是我自己的UBOOT源程序,如果自己想改為
1.1.3名稱,在LINUX下編譯是有點問題的,自己去試試吧。哈哈。。。
接著,我到目錄cpu\s3c44b0,這個目錄,就是S3C44B0的CPU引導程序,最開始運行的代碼就是從這里開始的。那我看
代碼,也要從這里開始。
看一下這個目錄,包括文件有:
G:\Downloads\lichee\lichee\boot\src\u-boot-1.1.3\cpu\s3c44b0 的目錄
2005-07-18 12:47 .
2005-07-18 12:47 ..
2005-07-16 04:35 4,154 .depend
2004-02-24 08:16 1,066 config.mk
2004-10-18 05:12 9,878 cpu.c
2004-02-24 08:16 4,843 interrupts.c
2004-02-24 08:16 1,303 Makefile
2004-10-18 05:12 4,378 serial.c
2005-07-17 23:48 4,820 start.S
2005-07-17 23:47 4,784 start.S.bak
有好幾個文件,它們的作用,大家自己先想想,不懂的再問我,目前我要開始看start.S文件,這個最開始運行的文件
。
這個文件是匯編寫的,但它是經過c的預處理的,所以像在頭文件.h中的宏,也可以使用的,這就是GCC的博大之處。
大家看到我的目錄,也許很奇怪,為什么會有“lichee”這個名稱?我來告知各位,這個是我起的名稱,叫做“荔枝
”,我的BOOT代碼和我的uClinux的代號,都叫“荔枝”。吃過“荔枝”的人,都知道外面紅紅的,里面的肉是白的,
清甜可口。我的BOOT和OS都是外面看起來很好看,里面的功能,就是難看了,但要深入去了解,才會嘗到新鮮的味道
。
好了,下面就要開始品嘗我的“荔枝”了,第一段代碼:
/** S3C44B0 CPU啟動代碼。* 蔡軍生 2005/07/17 **/
/** 包含配置文件。*/
#include /*添加版本說明.2005/07/16*/
#include /** 中斷向量表.*/
/* 聲明標量是全局函數,CPU加電啟動后,就從這里執行代碼。 */
.globl _start
_start: b reset /* 跳到復位中斷開始位置。 */
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
.balignl 16,0xdeadbeef
上面這段代碼,看懂了嗎?如果有什么不懂,就發問題過來。
這里用到ARM指令,b指令就是無條件地跳到reset的地方運行,reset是一個標記,并且它是相對量。
add pc, pc, #0x0c000000,這句用到了4G空間跳轉技術,因為ARM的CPU下一次值是根據PC的值來進行的。這里
修改了PC的值,就相當跳到對應的地址運行了。又由ARM的指令的寬度是4字節的,所以這里的PC值就是0x0c000004。
如果這里直接用b指令是不行的,因為它不超出32M的尋址空間,只有修改PC值才可以達到目的,因此采用ADD指令來修
改PC值。
.balignl 16,0xdeadbeef
上面這句,就是填充多少字節在后面。
整段代碼實現建立中斷向量表,這個根據ARM的CPU來編寫的。
第一段代碼看完了,再接著看第二段代碼。
/******************************************************************
* 啟動代碼。
** 如果不作內存初始化,就只建立堆棧,重新定位代碼到RAM位置。
* 然后就可以跳到第二階段的代碼運行了。
**********************************************************************/
/* 保存變量的數據區 */
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word _start
/** These are defined in the board-specific linker script.*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
上面這段代碼,主要保存一些全局變量,用于BOOT程序從FLASH拷貝到RAM,或者其它的使用。還有一些變量的長度是
通過連接腳本里得到,實際上由編譯器算出來的。
看了數據區,這次要看從引導那里跳到這里執行時,運行什么東西了。
/** 實際運行的復位代碼。從一開始運行的代碼,就跳到這里運行。*/
reset:
/* * 設置cpu運行在SVC32模式。*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0x13
msr cpsr,r0
具體分析如下:
/** 實際運行的復位代碼。從一開始運行的代碼,就跳到這里運行。*/
reset:
/** 設置cpu運行在SVC32模式。S3C44B0共有7種模式。 */
mrs r0,cpsr
取得當前程序狀態寄存器cpsr到r0。
bic r0,r0,#0x1f
這里使用位清除指令,把中斷全部清除,只置位模式控制位。
orr r0,r0,#0x13
計算為超級保護模式。
msr cpsr,r0
設置cpsr為超級保護模式。
通過設置ARM的CPSR寄存器,讓CPU運行在操作系統模式,為后面進行其它操作作好準備了。后面的代碼如下:
/* * 當是從FLASH啟動時,就要進行內存測試,當
* 是從RAM啟動時,一般就是開發本源程序時,就
* 可以跳過。
*
*/
#ifdef CONFIG_INIT_CRITICAL
bl cpu_init_crit
/*
* 在重新定位之前,要進行RAM訪問時間測試,因為每個開發
* 都是不一樣的。
* 可以在文件memsetup.S里看到它的說明。
*/
bl memsetup
#endif
/* 進行重定位 */
relocate: /* 重定位Boot代碼到RAM內存,比如從FLASH移到RAM */
adr r0, _start /* 把_start的相對地址移到r0 */
ldr r1, _TEXT_BASE /* 把_TEXT_BASE地址,就是BOOT在RAM中運行地址 */
cmp r0, r1 /* 比較兩個地址是否相同,如果相同,就已經在RAM運行,否則就是FLASH中運行。*/
beq stack_setup
/* 是在FLASH中運行,要把FLASH中的BOOT代碼移到RAM中,然后再運行. */
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2保存引導代碼大小 */
add r2, r0, r2 /* r2保存引導代碼最后地址 */
copy_loop:
ldmia r0!, {r3-r10} /* 從源地址[r0]讀取8個字節到寄存器,每讀一個就更新一
次r0地址 */
stmia r1!, {r3-r10} /* 拷貝寄存器r3-r10的值保存到 [r1]指明的地址,每寫一
個字節,就增加1. */
cmp r0, r2 /* 判斷是否拷貝到[r2]地址,就是引導代碼結束位置。 */
ble copy_loop /* 循環拷貝 */
/*拷貝中斷向量表,實際是建立起二級中斷向量表,當CPU中斷時,先運行FLASH中斷,接著就轉移到實際中向表執行
中斷程序。*/
adr r0, real_vectors
add r2, r0, #1024
ldr r1, =0x0c000000
add r1, r1, #0x08
vector_copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble vector_copy_loop
/* 建立起堆棧 */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
ldr pc, _start_armboot /* 已經準備好了堆棧,就可跳到C寫的代碼里,由于我的代碼是ARM,就是
跳到lib_arm\board.c(208):void start_armboot (void)中運行。 */
_start_armboot: .word start_armboot
/**************************************************************************
* CPU_init_critical臨界區寄存器
* 設置一些重要的寄存器,并進行內存測試。
*************************************************************************
*/
#define INTCON (0x01c00000+0x200000) /* 中斷控制器 */
#define INTMSK (0x01c00000+0x20000c) /* 中斷控制屏蔽寄存器 */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -