nboot是從NAND flash讀image到記憶體並執行,eboot是從乙太網(用tftp)下載image到記憶體並執行。將nboot.nb0燒到第0塊,將eboot.nb0燒到第2塊。啟動時nboot從flash讀出eboot並執行之,如何就可以透過pb把nk.bin下載到目標板上執行了,開發機和目標板可以用交叉線直接連線。 nboot是nand flash bootloader的意思。S3C2410可以直接從nand flash 啟動,但是不能超過4k。nboot是系統啟動後最先執行的程式碼,它有兩種,一種是跳轉到eboot;一種是跳轉到nk。 主要的功能其實是在eboot裡。 NBOOT的結構以及生成方法 以前的nboot都是用ADS編譯連結,簡單明瞭。這次BSP包含的nboot是WinCE的工具鏈生成,結果出來的.nb0竟然有12KB,而三星的Steppingstone只有4KB,怎麼剪裁涅?花了點時間把.log .map .rel .bib .bin .nb0仔細看了下,終於搞清楚12KB的nboot包含了些東西。 startup.s檔案: OPT 2 INCLUDE kxarm.h OPT 1 OPT 128 IMPORT main STARTUPTEXT LEAF_ENTRY StartUp b main END main.c檔案: #include <windows.h> #include <pehdr.h> #include <romldr.h> ROMHDR * volatile const pTOC = (ROMHDR *)-1; static int gI1; static char *gBuf = "global str"; static int gI2 = 2; int test(char *str) { int ret = 0; while(*str) { ret += *str++; } return ret; } void main(void) { gI1 = 1; test("is .rdata str?"); test(gBuf); } .map資訊: Preferred load address is 00010000 Start Length Name Class 0001:00000000 00000004H .astart CODE 0001:00000010 0000003bH .rdata CODE 0001:0000004c 00000024H .rdata$debug CODE 0001:00000070 0000004cH .text CODE 0001:000000bc 00000000H .edata CODE 0002:00000000 00000008H .data DATA 0002:00000008 00000004H .bss DATA 0003:00000000 00000008H .pdata DATA entry point at 0001:00000000 其中 .rdata:pTOC、2個字串 .data:gBuf、gI2 .bss:gI1 build.log資訊: Module Section Start Length psize vsize Filler nk.exe .text 00001000 4096 512 188 o32_rva=00001000 nk.exe .pdata 00002000 4096 512 8 o32_rva=00003000 nk.exe .data 000010bc 5 5 12 FILLER->33ff0000 nk.exe E32 000010c4 112 FILLER nk.exe O32 00001134 72 FILLER Module Section Start Length psize vsize Filler nk.exe FileName 0000117c 7 FILLER Unfilled ROM holes (address, length): 00002008 4088 00001184 3708 total space 7796 in 2 ranges 結合.map資訊可知: .text包含:.astart .rdata .rdata$debug .text .edata,也就是0xBC(188) .pdata包含:.pdata .data包含:.data .bss,psize之所以是5,是因為"static int gI2 = 2"只佔1B 注意:.bin檔案的.text和.data節是連續的。 檢視.bin的record info: Image Start = 0x00000000, length = 0x00002008 Record [ 0] : Start = 0x00000000, Length = 0x00000004, Chksum = 0x000001EB Record [ 1] : Start = 0x00000040, Length = 0x00000008, Chksum = 0x000001A5 Record [ 2] : Start = 0x00000048, Length = 0x00000004, Chksum = 0x00000095 Record [ 3] : Start = 0x00001000, Length = 0x00000184, Chksum = 0x000046D8 Record [ 4] : Start = 0x00001184, Length = 0x00000054, Chksum = 0x000007B2 Record [ 5] : Start = 0x000011D8, Length = 0x00000030, Chksum = 0x000008F6 Record [ 6] : Start = 0x00002000, Length = 0x00000008, Chksum = 0x000000C3 Record [ 7] : Start = 0x00000000, Length = 0x00001000, Chksum = 0x00000000 Start address = 0x00001000 Checking record #4 for potential TOC (ROMOFFSET = 0x00000000) Found pTOC = 0x00001184 ROMOFFSET = 0x00000000 用ADS反彙編展開後的.nb0: 0KB~4KB:REC[0]是 b 0x1000 跳轉指令;REC[1/2]似乎是簽名之類。 4KB~8KB:REC[3]包含所有Section(除.pdata外);REC[4]是ROMHDR;REC[5]未知 8KB~12KB:REC[6]是.pdata REC[7]的Start和Chksum都是0,則Length指明EntryPoint。 假如不考慮重定位,把.nb0的0x1000開始的4KB燒入NAND Flash就大功告成了。 簡化main.c檔案: #include <windows.h> #include <pehdr.h> #include <romldr.h> ROMHDR * volatile const pTOC = (ROMHDR *)-1; void test(char * str) { while(*str) { *(volatile unsigned char *)0x1234 = *str++; } } void main(void) { test("Step ldr\r\n"); } .rel資訊: 0003 0001 00001088 00000000 也就是0x1088處需要重定位。 用ADS反彙編展開後的.nb0: 0x1064 ldr r2,0x00001088 ; = #0x00000030 0x1088的值是0x30,根據.map檔案可知0x1030存放字串"Step ldr\r\n" 因此去掉.nb0的開始4KB頁後,0x30就是字串的地址。 假如把.bib檔案中的,RAMIMAGE的Start和ROMSTART都從0->0x1000,則0x1088的值是0x2030,就不能去掉.nb0的開始4KB頁 Nboot (Nand flash bootloader) 主要的作用就是初始化硬體,把後面的功能比較完善的載入程式像eboot之類的映像複製到SDRAM中讓後跳到SDRAM中繼續跑eboot。 為什麼要有nboot這個東西呢,其實主要是因為現在的soc上考慮到成本的問題,基本是都是自帶一個nand flash的控制器並支援開機nand flash引導來取代相對來說昂貴的nor flash。 一般來說nand flash的控制器都會內建一個SRAM之類的buffer來支援nand flash的開機引導,在nand啟動的方式下,板子上電的時候,nand控制器會自動把nand flash最前面的buffer大小的資料自動複製到buffer中然後讓pc指標可以從buffer中直接讀取指令。一般來說這個buffer不會很大,2410的晶片是4k,而像freescale的imx21更是隻有2k,所以由於這個侷限性,我們只能把bootloader拆分成兩部分,前面一部分來完成基本初始化功能,而後面一部分來完成比較完善的功能,讓控制器自動複製前一部分,然後前一部分再複製後一部分到RAM中,這樣載入程式就可以做任何它想做的事情了。 其實,實現一個nboot並沒有多大難度,以下是一個大概流程: 1. 當然是配置時鐘了,沒這個系統跑不起來啊 o(∩_∩)o… 2. 不用說SDRAM的配置也是少不了,不然我們怎麼把程式複製到SDRAM中。 3. 就是flash控制器的配置了,一般來說就是GPIO和相應的控制器暫存器配一下。 4. 複製檔案從nand到SDRAM中,nand flash讀的話一般來說都是先拉片選位,然後發命令,接著是地址,最後就是讀數了。 上面幾步做完,其實整個nboot也就差不多了,不過在WinCE下開發的話有幾個點需要特別注意: 1. 因為要用PB來編譯,所以為了能生成.nb0檔案,所以一定要在 程式碼里加上: pTOC DCD -1 EXPORT pTOC 這個是讓ROMIMG.exe做image時用的. 2. 生成.nb0檔案,bib檔案也是不能少的。 3. 因為微軟編譯器的原因,導致了我們按一般方法來編譯.nb0時,前面的4K都是空的,所以如果直接把編譯出來的.nb0燒進去的話是不能用的,所以的在bib改一下: 把: NBOOT 00000000 00002000 RAMIMAGE 這個定義成8k的大小,然後後面的 ROMSTART=00001000 ROMSIZE=1000 把start地址往後移一下,然後大小改為4k,這樣出來的nb0就會 把前面空的4k給截掉了。 以上的都做完的話,基本上應該不會有什麼問題了。
nboot是從NAND flash讀image到記憶體並執行,eboot是從乙太網(用tftp)下載image到記憶體並執行。將nboot.nb0燒到第0塊,將eboot.nb0燒到第2塊。啟動時nboot從flash讀出eboot並執行之,如何就可以透過pb把nk.bin下載到目標板上執行了,開發機和目標板可以用交叉線直接連線。 nboot是nand flash bootloader的意思。S3C2410可以直接從nand flash 啟動,但是不能超過4k。nboot是系統啟動後最先執行的程式碼,它有兩種,一種是跳轉到eboot;一種是跳轉到nk。 主要的功能其實是在eboot裡。 NBOOT的結構以及生成方法 以前的nboot都是用ADS編譯連結,簡單明瞭。這次BSP包含的nboot是WinCE的工具鏈生成,結果出來的.nb0竟然有12KB,而三星的Steppingstone只有4KB,怎麼剪裁涅?花了點時間把.log .map .rel .bib .bin .nb0仔細看了下,終於搞清楚12KB的nboot包含了些東西。 startup.s檔案: OPT 2 INCLUDE kxarm.h OPT 1 OPT 128 IMPORT main STARTUPTEXT LEAF_ENTRY StartUp b main END main.c檔案: #include <windows.h> #include <pehdr.h> #include <romldr.h> ROMHDR * volatile const pTOC = (ROMHDR *)-1; static int gI1; static char *gBuf = "global str"; static int gI2 = 2; int test(char *str) { int ret = 0; while(*str) { ret += *str++; } return ret; } void main(void) { gI1 = 1; test("is .rdata str?"); test(gBuf); } .map資訊: Preferred load address is 00010000 Start Length Name Class 0001:00000000 00000004H .astart CODE 0001:00000010 0000003bH .rdata CODE 0001:0000004c 00000024H .rdata$debug CODE 0001:00000070 0000004cH .text CODE 0001:000000bc 00000000H .edata CODE 0002:00000000 00000008H .data DATA 0002:00000008 00000004H .bss DATA 0003:00000000 00000008H .pdata DATA entry point at 0001:00000000 其中 .rdata:pTOC、2個字串 .data:gBuf、gI2 .bss:gI1 build.log資訊: Module Section Start Length psize vsize Filler nk.exe .text 00001000 4096 512 188 o32_rva=00001000 nk.exe .pdata 00002000 4096 512 8 o32_rva=00003000 nk.exe .data 000010bc 5 5 12 FILLER->33ff0000 nk.exe E32 000010c4 112 FILLER nk.exe O32 00001134 72 FILLER Module Section Start Length psize vsize Filler nk.exe FileName 0000117c 7 FILLER Unfilled ROM holes (address, length): 00002008 4088 00001184 3708 total space 7796 in 2 ranges 結合.map資訊可知: .text包含:.astart .rdata .rdata$debug .text .edata,也就是0xBC(188) .pdata包含:.pdata .data包含:.data .bss,psize之所以是5,是因為"static int gI2 = 2"只佔1B 注意:.bin檔案的.text和.data節是連續的。 檢視.bin的record info: Image Start = 0x00000000, length = 0x00002008 Record [ 0] : Start = 0x00000000, Length = 0x00000004, Chksum = 0x000001EB Record [ 1] : Start = 0x00000040, Length = 0x00000008, Chksum = 0x000001A5 Record [ 2] : Start = 0x00000048, Length = 0x00000004, Chksum = 0x00000095 Record [ 3] : Start = 0x00001000, Length = 0x00000184, Chksum = 0x000046D8 Record [ 4] : Start = 0x00001184, Length = 0x00000054, Chksum = 0x000007B2 Record [ 5] : Start = 0x000011D8, Length = 0x00000030, Chksum = 0x000008F6 Record [ 6] : Start = 0x00002000, Length = 0x00000008, Chksum = 0x000000C3 Record [ 7] : Start = 0x00000000, Length = 0x00001000, Chksum = 0x00000000 Start address = 0x00001000 Checking record #4 for potential TOC (ROMOFFSET = 0x00000000) Found pTOC = 0x00001184 ROMOFFSET = 0x00000000 用ADS反彙編展開後的.nb0: 0KB~4KB:REC[0]是 b 0x1000 跳轉指令;REC[1/2]似乎是簽名之類。 4KB~8KB:REC[3]包含所有Section(除.pdata外);REC[4]是ROMHDR;REC[5]未知 8KB~12KB:REC[6]是.pdata REC[7]的Start和Chksum都是0,則Length指明EntryPoint。 假如不考慮重定位,把.nb0的0x1000開始的4KB燒入NAND Flash就大功告成了。 簡化main.c檔案: #include <windows.h> #include <pehdr.h> #include <romldr.h> ROMHDR * volatile const pTOC = (ROMHDR *)-1; void test(char * str) { while(*str) { *(volatile unsigned char *)0x1234 = *str++; } } void main(void) { test("Step ldr\r\n"); } .rel資訊: 0003 0001 00001088 00000000 也就是0x1088處需要重定位。 用ADS反彙編展開後的.nb0: 0x1064 ldr r2,0x00001088 ; = #0x00000030 0x1088的值是0x30,根據.map檔案可知0x1030存放字串"Step ldr\r\n" 因此去掉.nb0的開始4KB頁後,0x30就是字串的地址。 假如把.bib檔案中的,RAMIMAGE的Start和ROMSTART都從0->0x1000,則0x1088的值是0x2030,就不能去掉.nb0的開始4KB頁 Nboot (Nand flash bootloader) 主要的作用就是初始化硬體,把後面的功能比較完善的載入程式像eboot之類的映像複製到SDRAM中讓後跳到SDRAM中繼續跑eboot。 為什麼要有nboot這個東西呢,其實主要是因為現在的soc上考慮到成本的問題,基本是都是自帶一個nand flash的控制器並支援開機nand flash引導來取代相對來說昂貴的nor flash。 一般來說nand flash的控制器都會內建一個SRAM之類的buffer來支援nand flash的開機引導,在nand啟動的方式下,板子上電的時候,nand控制器會自動把nand flash最前面的buffer大小的資料自動複製到buffer中然後讓pc指標可以從buffer中直接讀取指令。一般來說這個buffer不會很大,2410的晶片是4k,而像freescale的imx21更是隻有2k,所以由於這個侷限性,我們只能把bootloader拆分成兩部分,前面一部分來完成基本初始化功能,而後面一部分來完成比較完善的功能,讓控制器自動複製前一部分,然後前一部分再複製後一部分到RAM中,這樣載入程式就可以做任何它想做的事情了。 其實,實現一個nboot並沒有多大難度,以下是一個大概流程: 1. 當然是配置時鐘了,沒這個系統跑不起來啊 o(∩_∩)o… 2. 不用說SDRAM的配置也是少不了,不然我們怎麼把程式複製到SDRAM中。 3. 就是flash控制器的配置了,一般來說就是GPIO和相應的控制器暫存器配一下。 4. 複製檔案從nand到SDRAM中,nand flash讀的話一般來說都是先拉片選位,然後發命令,接著是地址,最後就是讀數了。 上面幾步做完,其實整個nboot也就差不多了,不過在WinCE下開發的話有幾個點需要特別注意: 1. 因為要用PB來編譯,所以為了能生成.nb0檔案,所以一定要在 程式碼里加上: pTOC DCD -1 EXPORT pTOC 這個是讓ROMIMG.exe做image時用的. 2. 生成.nb0檔案,bib檔案也是不能少的。 3. 因為微軟編譯器的原因,導致了我們按一般方法來編譯.nb0時,前面的4K都是空的,所以如果直接把編譯出來的.nb0燒進去的話是不能用的,所以的在bib改一下: 把: NBOOT 00000000 00002000 RAMIMAGE 這個定義成8k的大小,然後後面的 ROMSTART=00001000 ROMSIZE=1000 把start地址往後移一下,然後大小改為4k,這樣出來的nb0就會 把前面空的4k給截掉了。 以上的都做完的話,基本上應該不會有什麼問題了。