當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]建議讀一讀《嵌入式系統(tǒng)Boot Loader技術(shù)內(nèi)幕》(詹榮開著),google一下就會找到一片。什么是Bootloader就不再這里廢話了,看看上面的文章就明了了。 Bootloader有很多種,如本文將要閱讀的vivi,除此之外還有uboot,r

建議讀一讀《嵌入式系統(tǒng)Boot Loader技術(shù)內(nèi)幕》(詹榮開著),google一下就會找到一片。什么是Bootloader就不再這里廢話了,看看上面的文章就明了了。 Bootloader有很多種,如本文將要閱讀的vivi,除此之外還有uboot,redboot,lilo等等。Vivi 是韓國mizi公司專門為三星s3c2410芯片設(shè)計的Bootloader。

先來看看vivi的源碼樹:

vivi-+-arch-+-s3c2410

|-Documentation

|-drivers-+-serial

| ‘-mtd-+-maps

| |-nor

| ‘-nand

|-include-+-platform

| |-mtd

| ‘-proc

|-init

|-lib-+-priv_data

|-scripts-+-lxdialog

|-test

|-util

可以google一下,搜到源碼vivi.tar.gz。

前面提到的文件已經(jīng)系統(tǒng)的分析了bootloader的,這里就按源代碼來具體說事。vivi也可以分為2個階段,階段1的代碼在arch/s3c2410/head.S中,階段2的代碼從init/main.c的main函數(shù)開始。

階段1

階段1從程序arch/s3c2410/head.S開始,按照head.S的代碼執(zhí)行順序,一次完成了下面幾個任務(wù):

1、關(guān)WATCH DOG (disable watch dog timer)

上電后,WATCH DOG默認(rèn)是開著的

2、禁止所有中斷 (disable all interrupts)

vivi中不會用到中斷,中斷是系統(tǒng)的事,bootloader可不能去干這事的(不過這段代碼實在多余,上電后中斷默認(rèn)是關(guān)閉的)

3、初始化系統(tǒng)時鐘(initialise system clocks)

啟動MPLL,F(xiàn)CLK=200MHz,HCLK=100MHz,PCLK=50MHz,“CPU bus mode”改為“Asynchronous bus mode”。

4、初始化內(nèi)存控制寄存器(memsetup)

S3c2410共有15個寄存器,在此開始初始化13個寄存器。

5、檢查是否從掉電模式喚醒(Check if this is a wake-up from sleep)

若是,則調(diào)用WakeupStart函數(shù)進(jìn)行處理。

6、點亮所有LED (All LED on)

點一下燈,通知外面的同志,告訴他們有情況發(fā)生。

7、初始化UART0 (set GPIO for UART & InitUART)

a.設(shè)置GPIO,選擇UART0使用的引腳

b.初始化UART0,設(shè)置工作方式(使用FIFO)、波特率115200 8N1、無流控等。這可是使用串口與s3c2410通信的條件啊,在終端也要如此設(shè)置。

8、跳到內(nèi)存測試函數(shù)(simple memory test to find some DRAM flaults)

當(dāng)然要定義了CONFIG_BOOTUP_MEMTEST這個參數(shù)才會跳到內(nèi)存測試。

9、如果定義了以Nand flash方式啟動(#ifdef CONFIG_S3C2410_NAND_BOOT),則此時要將vivi所有代碼(包括階段1和階段2)從Nand flash復(fù)制到SDRAM中(因為在Nand flash中是不能執(zhí)行程序的,它只能做為程序和數(shù)據(jù)的存儲器,而Nor flash可就不同了,Nor flash可以執(zhí)行程序,但貴是它發(fā)展得瓶頸):

a.設(shè)置nand flash控制寄存器

b.設(shè)置堆棧指針

c.設(shè)置即將調(diào)用的函數(shù)nand_read_ll的參數(shù):r0=目的地址(SDRAM的地址),r1=源地址(nand flash的地址),r2=復(fù)制的長度(以字節(jié)為單位)

d.調(diào)用nand_read_ll進(jìn)行復(fù)制

  10、跳到bootloader的階段2運行,亦即調(diào)用init/main.c中的main函數(shù)(get read to call C functions)

a.重新設(shè)置堆棧

b.設(shè)置main函數(shù)的參數(shù)

c.調(diào)用main函數(shù)

head.S有900多行,都是些arm匯編,看的云山霧罩,匯編看來是忘的差不多了,所以這部分代碼也看的相當(dāng)糙,只知道大概在干什么,至于個中緣由就不是很了解。先學(xué)學(xué)arm匯編再回來看。

階段2

從init/main.c中的main函數(shù)開始,終于步入C語言的世界了。Main函數(shù)總共有8步(8 steps),先看看源代碼:

int main(int argc, char *argv[])

{

int ret;

/*

* Step 1:

*/

putstr("rn");

putstr(vivi_banner); //vivi_banner是vivi執(zhí)行開始的顯示信息,vivi_banner在文件version.c中定義

reset_handler();

/*

* Step 2:

*/

ret = board_init();

if (ret) {

putstr("Failed a board_init() procedurern");

error();

}

/*

* Step 3:

*/

mem_map_init();

mmu_init();

putstr("Succeed memory mapping.rn");

/*

* Now, vivi is running on the ram. MMU is enabled.

* Step 4:

*/

/* initialize the heap area*/

ret = heap_init();

if (ret) {

putstr("Failed initailizing heap regionrn");

error();

}

/* Step 5:

* MTD

*/

ret = mtd_dev_init();

/* Step 6:

*/

init_priv_data();

/* Step 7:

*/

misc();

init_builtin_cmds();

/* Step 8:

*/

boot_or_vivi();

return 0;

}

下面按照上面的步驟逐步來分析一下。

1、Step 1:reset_handler()

reset_handler用于將內(nèi)存清零,代碼在lib/reset_handle.c中。

1 void

2 reset_handler(void)

3 {

4 int pressed;

5 pressed = is_pressed_pw_btn(); /*判斷是硬件復(fù)位還是軟件復(fù)位*/

6 if (pressed == PWBT_PRESS_LEVEL) {

7 DPRINTK("HARD RESETrn");

8 hard_reset_handle(); /*調(diào)用clear_mem對SDRAM清0*/

9 } else {

10 DPRINTK("SOFT RESETrn");

11 soft_reset_handle(); /*此函數(shù)為空*/

12 }

13 }

在上電后,reset_handler調(diào)用第8行的hard_reset_handle(),此函數(shù)在lib/reset_handle.c中:

[main(int argc, char *argv[]) -> reset_handler() -> hard_reset_handle()]

1 static void

2 hard_reset_handle(void)

3 {

4 #if 0

5 clear_mem((unsigned long)(DRAM_BASE + VIVI_RAM_ABS_POS),

6 (unsigned long)(DRAM_SIZE - VIVI_RAM_ABS_POS));

7 #endif

/*lib/memory.c,將起始地址為USER_RAM_BASE,長度為USER_RAM_SIZE的內(nèi)存清0*/

8 clear_mem((unsigned long)USER_RAM_BASE, (unsigned long) USER_RAM_SIZE);

9 }

先寫到這兒吧。

(未完待續(xù))

S3C2410 bootloader ----VIVI閱讀筆記2(續(xù)筆記1)

2、Step 2:board_init()

board_init調(diào)用2個函數(shù)用于初始化定時器和設(shè)置各GPIO引腳功能,代碼在arch/s3c2410/smdk.c中:

[main(int argc, char *argv[]) > board_init()]

1 int board_init(void)

2 {

3 init_time(); /*arch/s3c2410/proc.c*/

4 set_gpios(); /*arch/s3c2410/smdk.c */

5 return 0;

6 }

init_time() 這個函數(shù)對寄存器進(jìn)行了簡單的操作:

void init_time(void)

{

TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(15) | TCFG0_PRE0(0));

/*s3c2410 data sheet P298*/

/*TCFG0 = 0 | 0xf00 | 0 */

}

寄存器TCFG0由三部分組成,prescaler0,prescaler1,deadzone和reserve四部分,前三部分分別對應(yīng) TCFG0_PRE0、TCFG0_PRE1、TCFG0_DZONE,TCFG0_PRE0(0)實際值為0x00,TCFG0_PRE1(15)實際值為0x0f00,而TCFG0_DZONE(0)實際值為 0x000000。實際中,vivi并未使用定時器,這個函數(shù)就可以忽略。set_gpios()用于選擇GPA至GPH端口各引腳的功能及是否使用各引腳的內(nèi)部上拉電阻,并設(shè)置外部中斷源寄存器EXTINT0-2(vivi中未使用外部中斷)。

1 void set_gpios(void)

2 {

3 GPACON = vGPACON;

4 GPBCON = vGPBCON;

5 GPBUP = vGPBUP;

6 GPCCON = vGPCCON;

7 GPCUP = vGPCUP;

8 GPDCON = vGPDCON;

9 GPDUP = vGPDUP;

10 GPECON = vGPECON;

11 GPEUP = vGPEUP;

12 GPFCON = vGPFCON;

13 GPFUP = vGPFUP;

14 GPGCON = vGPGCON;

15 GPGUP = vGPGUP;

16 GPHCON = vGPHCON;

17 GPHUP = vGPHUP;

18 EXTINT0 = vEXTINT0;

19 EXTINT1 = vEXTINT1;

20 EXTINT2 = vEXTINT2;

21 }

以第三行為例,vGPACON的值為0x007fffff,查找s3c2410用戶手冊可知,該參數(shù)將GPACON的23位全部置1。各位功能需察看s3c2410用戶手冊

3、Step 3:建立頁表和啟動MMU

mem_map_init();

mmu_init();

mem_map_init函數(shù)用于建立頁表,vivi使用段式頁表,只需要一級頁表。它調(diào)用3個函數(shù),代碼在arch/s3c2410/mmu.c中:

[main(int argc, char *argv[]) > mem_map_init(void)]

1 void mem_map_init(void)

2 {

3 #ifdef CONFIG_S3C2410_NAND_BOOT

/*CONFIG_S3C2410_NAND_BOOT = y ,在文件include/autoconf.h中定義*/

4 mem_map_nand_boot();

/* 最終調(diào)用mem_mepping_linear, 建立頁表 */

5 #else

6 mem_map_nor();

7 #endif

8 cache_clean_invalidate();/* 清空cache,使無效cache */

9 tlb_invalidate(); /* 使無效快表TLB */

10 }

第9、 10行的兩個函數(shù)可以不用管它,他們做的事情在下面的mmu_init函數(shù)里又重復(fù)了一遍。對于本開發(fā)板,在.config中定義了 CONFIG_S3C2410_NAND_BOOT。mem_map_nand_boot()函數(shù)調(diào)用mem_mapping_linear()函數(shù)來最終完成建立頁表的工作。頁表存放在SDRAM物理地址0x33dfc000開始處,共16K:一個頁表項4字節(jié),共有4096個頁表項;每個頁表項對應(yīng) 1M地址空間,共4G。mem_map_init先將4G虛擬地址映射到相同的物理地址上,NCNB(不使用cache,不使用write buffer)――這樣,對寄存器的操作跟未啟動MMU時是一樣的;再將SDRAM對應(yīng)的64M空間的頁表項修改為使用cache。 mem_mapping_linear函數(shù)的代碼在arch/s3c2410/mmu.c中:

[main(int argc, char *argv[]) > mem_map_init(void) > mem_map_nand_boot( ) > mem_mapping_linear(void)]

1 static inline void mem_mapping_linear(void)

2 {

3 unsigned long pageoffset, sectionNumber;

4 putstr_hex("MMU table base address = 0x", (unsigned long)

mmu_tlb_base);

5 /* 4G 虛擬地址映射到相同的物理地址. not cacacheable, not bufferable */

6 /* mmu_tlb_base = 0x33dfc000*/

7 for (sectionNumber = 0; sectionNumber < 4096; sectionNumber++) {

8 pageoffset = (sectionNumber << 20);

9 *(mmu_tlb_base + (pageoffset >> 20)) = pageoffset |

MMU_SECDESC;

10 }

11 /* make dram cacheable */

12 /* SDRAM物理地址0x3000000-0x33ffffff,

13 DRAM_BASE=0x30000000,DRAM_SIZE=64M

14 */

15 for (pageoffset = DRAM_BASE; pageoffset < (DRAM_BASE+DRAM_SIZE);

16 pageoffset += SZ_1M) {

17 //DPRINTK(3, "Make DRAM section cacheable: 0x%08lxn", pageoffset);

18 *(mmu_tlb_base + (pageoffset >> 20)) =

pageoffset | MMU_SECDESC | MMU_CACHEABLE;

19 }

20 }

mmu_init()函數(shù)用于啟動MMU,它直接調(diào)用arm920_setup()函數(shù)。arm920_setup()的代碼在arch/s3c2410/mmu.c中:

[main(int argc, char *argv[]) > mmu_init( ) > arm920_setup( )]

1 static inline void arm920_setup(void)

2 {

3 unsigned long ttb = MMU_TABLE_BASE;

/* MMU_TABLE_BASE = 0x33dfc000 */

4 __asm__(

5 /* Invalidate caches */

6 "mov r0, #0n"

7 "mcr p15, 0, r0, c7, c7, 0n" /* invalidate I,D caches on v4 */

8 "mcr p15, 0, r0, c7, c10, 4n" /* drain write buffer on v4 */

9 "mcr p15, 0, r0, c8, c7, 0n" /* invalidate I,D TLBs on v4 */

10 /* Load page table pointer */

11 "mov r4, %0n"

12 "mcr p15, 0, r4, c2, c0, 0n" /* load page table pointer */

13 /* Write domain id (cp15_r3) */

14 "mvn r0, #0n" /* Domains 0b01 = client, 0b11=Manager*/

15 "mcr p15, 0, r0, c3, c0, 0n"

/* load domain access register,write domain 15:0

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

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉