一、写在前面
WinCE 6.0涉及到2个关键二进制烧录文件:eboot.nb0和nk.bin。其中eboot是CE的bootloader,主要工作是初始化芯片的各寄存器和外设,比如sdram、串口、网络等,然后把nk.bin从flash copy到sdram启动;nk.bin是CE内核映像文件。
当系统采用NORFlash+S3C2410架构时,上电时,NORFlash被映射到0x0000_0000-0x0800_0000地址,可以直接执行烧录在NORFlash的eboot,启动系统。
当系统采用NandFlash+S3C2410架构时(NandFlash便宜),由于NandFlash的特殊设计(没有地址线,采用地址、数据、命令复用8根数据线来读写),S3C2410无法把NandFlash映射到某个地址。因而,上电时,S3C2410以硬件的方式将NandFlash前4K的数据copy到internal RAM(叫作steppingstone)执行,然后以软件的方式,在4K数据中编写程序把NandFlash中其他更多的数据copy到外部sdram来执行。
直接从WinCE6.0 Emulator Clone出来的eboot,其"first 4k”没有包含从NandFlash copy 数据的程序,因此需要手动来添加。一种方式为:修改startup.s文件,编写汇编程序(eboot的main函数入口地址已远远超过4K,无法用C语言来实现);另一种方式为:做个简单程序,大小不超过4K,把eboot从Flash copy到sdram来执行。这个简单的程序被叫做"nboot"。
因此,nboot的功能仅包括:1,启动CPU(禁watch dog,初始化clock,sdram,NandFlash controller等);2,copy data from Flash to sdram and lauch eboot in sdram。
下面介绍以VS2005来编写nboot的过程(另注:以ADS来做nboot会简单得多)
二、建立nboot工程
在S3C2410的BSP中,"\src\bootloader\"新建nboot文件夹,并从eboot目录下copy文件:source,boot.bib,makefiel,makefile.inc,startup.s,main.c文件;
1、修改source文件,TARGETNAME就是要生成.exe的文件名(nboot.exe);TARGETLIBS只保留fulllibc.lib(除法运算有用到它),其他lib用不到删除;SOURCE先添加startup.s和main.c
1 TARGETNAME = nboot
2 ......
3 TARGETLIBS = \
4 $(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\fulllibc.lib
5 ......
6 SOURCES = \
7 startup.s \
8 main.c \
2、修改boot.bib文件。bib文件的修改在我另一篇文章里有详细介绍。
1 MEMORY
2 ; Name Start Size Type
3 ; ------- -------- -------- ----
4 NBOOT 30000000 00004000 RAMIMAGE
5 STACK 30004000 00004000 RESERVED
6 RAM 30008000 00004000 RAM
7
8
9 CONFIG
10 COMPRESSION = OFF
11 PROFILE = OFF
12 KERNELFIXUPS = ON
13
14 SRE = ON
15 ROMSTART = 30001000
16 ROMWIDTH = 32
17 ROMSIZE = 00002000
18
19 MODULES
20 ; Name Path Memory Type
21 ; -------------- ---------------------------------------------- -----------
22 nk.exe $(_TARGETPLATROOT)\target\$(_TGTCPU)\$(WINCEDEBUG)\nboot.exe NBOOT
3、修改makefile.inc,把eboot改为nboot即可。
1 ! IF " $(NOLINK) " == ""
2 romimage boot.bib
3
4 ! IF " $(WINCEREL) " == " 1 "
5 copy $(_PLATFORMROOT)\$(_TGTPLAT)\target\$(_TGTCPU)\$(WINCEDEBUG)\nboot.nb0 $(_FLATRELEASEDIR)
6 copy $(_PLATFORMROOT)\$(_TGTPLAT)\target\$(_TGTCPU)\$(WINCEDEBUG)\nboot.bin $(_FLATRELEASEDIR)
7 copy $(_PLATFORMROOT)\$(_TGTPLAT)\target\$(_TGTCPU)\$(WINCEDEBUG)\nboot.sre $(_FLATRELEASEDIR)
8 ! ENDIF
9 ! ENDIF
4、修改main.c;其中,pTOC这个全局变量必须声明,pTOC是个大有来头的结构指针。build过程中,romimage.exe 会查找pTOC指针,然后将boot.bib中定义的RAM、ROM等地址信息填充到nb0文件的TOC结构中。因此,这个全局变量不定义,就无法生产nb0文件,只有bin文件(bin文件不采用TOC结构,而是直接在文件头保存,more information please refer:Windows Embedded CE Binary Image Data Format in MSDN)。
1
2 #include < windows.h >
3 #include < blcommon.h >
4
5 ROMHDR * volatile const pTOC = (ROMHDR * ) - 1 ; // Gets replaced by RomLoader with real address
6
7 void main( void )
8 {
9 // to be added
10 }
11
5、进过以上步骤,nboot subproject 的框架已实现,build project可生成nboot.nb0,只是还未实现具体功能。下面将实现系统初始化,串口通讯、NANDFLASH读写等功能。
三、CPU初始化,修改startup.s
nboot采用物理地址,把startup.s文件内mmu部分代码删除,line320-lin420;
starup.s文件内的sleep和poweroff相关代码没用删除(留着也无妨);
整理余下的代码,关键的部分如下,其中PHYBASE改为0x3000_0000,即boot.bib中的RAMIMAGE START值 PHYBASE EQU 0x30000000
代码的line16作用是跳到SDRAM去执行,若用mov pc, r0执行,将会从头(0x3000_1000)开始又执行一编,没必要。
代码的line20-21设置的堆栈地址,等于boot.bib定义的STACK地址。
startup.s的部分代码如下:
startup.s的部分代码如下:
1 ; ------------------------------------------------------------------------------
2 ; Copy boot loader to memory
3
4 ; This is the loop that perform copying.
5 ldr r0, = 0x1000 ; the first 4K of nb0 file
6 add r0, r0, #PHYBASE ; add physical base
7 mov r1, r0 ; (r1) copy destination
8 ldr r2, = 0x0 ; (r2) flash started at physical address 0
9 ldr r3, = 0x10000 ; counter ( 0x40000 / 4 )
10 10 ldr r4, [r2], # 4
11 str r4, [r1], # 4
12 subs r3, r3, # 1
13 bne % b10
14
15 ; Restart from the RAM position after copying.
16 add pc, pc, r0 ; R0 = PHYBASE + 0x1000
17 nop
18 nop
19
20 20 mov sp, # 0x30000000
21 add sp, sp, # 0x4000
22 b main
转自:http://www.cnblogs.com/wincee/articles/1688869.html