CE STEPLDR
作用:初始化CPU、内存、Flash,复制EBoot到内存并跳入EBoot中运行。
原理:S3C2416有 8-KB 的steppingstone(暂时翻译为垫脚石),在Nand启动模式下可把Nand的前8K内容在CPU上电后自动复制到物理地址(0x40000000)上面并运行。

程序入口:startup.s
OPT
INCLUDE kxarm.h
INCLUDE s3c2416.inc
OPT
OPT
; Pre-defined constants.
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0
; Amount of memory (in bytes) allocated for stacks
Len_FIQ_Stack EQU
Len_IRQ_Stack EQU
Len_ABT_Stack EQU
Len_UND_Stack EQU
Len_SVC_Stack EQU
; Offsets will be loaded as immediate values.
; Offsets must be 8 byte aligned.
Offset_FIQ_Stack EQU
Offset_IRQ_Stack EQU Offset_FIQ_Stack + Len_FIQ_Stack
Offset_ABT_Stack EQU Offset_IRQ_Stack + Len_IRQ_Stack
Offset_UND_Stack EQU Offset_ABT_Stack + Len_ABT_Stack
Offset_SVC_Stack EQU Offset_UND_Stack + Len_UND_Stack
; Stack locations.
FIQStack EQU (top_of_stacks - 0x0) ; 0x33ffff00 ~
IRQStack EQU (FIQStack - Offset_FIQ_Stack) ; 0x33fffe00 ~
AbortStack EQU (IRQStack - Offset_IRQ_Stack) ; 0x33fffd00 ~
UndefStack EQU (AbortStack - Offset_ABT_Stack) ; 0x33fffc00 ~
SVCStack EQU (UndefStack - Offset_UND_Stack) ; 0x33fffb00 ~
UserStack EQU (SVCStack - Offset_SVC_Stack) ; 0x33fff700 ~
;------------------------------------------------------------------------------
; Sleep state constants
;
; Location of sleep data
; BUGBUG - this needs to be declared as a local var.
SLEEPDATA_BASE_PHYSICAL EQU 0x30028000
; WORD_SIZE EQU 0x4
; Sleep State memory locations
SleepState_Data_Start EQU ()
SleepState_WakeAddr EQU (SleepState_Data_Start + )
SleepState_MMUCTL EQU (SleepState_WakeAddr + WORD_SIZE)
SleepState_MMUTTB EQU (SleepState_MMUCTL + WORD_SIZE)
SleepState_MMUDOMAIN EQU (SleepState_MMUTTB + WORD_SIZE)
SleepState_SVC_SP EQU (SleepState_MMUDOMAIN + WORD_SIZE)
SleepState_SVC_SPSR EQU (SleepState_SVC_SP + WORD_SIZE)
SleepState_FIQ_SPSR EQU (SleepState_SVC_SPSR + WORD_SIZE)
SleepState_FIQ_R8 EQU (SleepState_FIQ_SPSR + WORD_SIZE)
SleepState_FIQ_R9 EQU (SleepState_FIQ_R8 + WORD_SIZE)
SleepState_FIQ_R10 EQU (SleepState_FIQ_R9 + WORD_SIZE)
SleepState_FIQ_R11 EQU (SleepState_FIQ_R10 + WORD_SIZE)
SleepState_FIQ_R12 EQU (SleepState_FIQ_R11 + WORD_SIZE)
SleepState_FIQ_SP EQU (SleepState_FIQ_R12 + WORD_SIZE)
SleepState_FIQ_LR EQU (SleepState_FIQ_SP + WORD_SIZE)
SleepState_ABT_SPSR EQU (SleepState_FIQ_LR + WORD_SIZE)
SleepState_ABT_SP EQU (SleepState_ABT_SPSR + WORD_SIZE)
SleepState_ABT_LR EQU (SleepState_ABT_SP + WORD_SIZE)
SleepState_IRQ_SPSR EQU (SleepState_ABT_LR + WORD_SIZE)
SleepState_IRQ_SP EQU (SleepState_IRQ_SPSR + WORD_SIZE)
SleepState_IRQ_LR EQU (SleepState_IRQ_SP + WORD_SIZE)
SleepState_UND_SPSR EQU (SleepState_IRQ_LR + WORD_SIZE)
SleepState_UND_SP EQU (SleepState_UND_SPSR + WORD_SIZE)
SleepState_UND_LR EQU (SleepState_UND_SP + WORD_SIZE)
SleepState_SYS_SP EQU (SleepState_UND_LR + WORD_SIZE)
SleepState_SYS_LR EQU (SleepState_SYS_SP + WORD_SIZE)
SleepState_Data_End EQU (SleepState_SYS_LR + WORD_SIZE)
SLEEPDATA_SIZE EQU (SleepState_Data_End - SleepState_Data_Start) /
;---------------------------------------------------------------------------
;
; Macro to feed the LED Reg (The GPIO) with the value desired for debugging.
; Uses physical address
;
; GPFDAT [7:4] is assigned to LEDs.
IMPORT main ; C entrypoint for Steppingstone loader.
EXPORT MMU_EnableICache
EXPORT MMU_SetAsyncBusMode
STARTUPTEXT
LEAF_ENTRY StartUp
b ResetHandler ;1、进入入口函数
b .
b .
b .
b .
b .
b .
b .
;----------------------------
; 1st NAND Bootloader Entry Point
;----------------------------
ResetHandler ;2、入口函数
;------------------------
; disable the watchdog timer. ;2.1、关看门狗,此阶段用不上,若不关在指定时间内不喟狗CPU就会重启。
ldr r0, =WTCON
str r1, [r0]
;------------------------
; EBI configuration
;ldr r0, =EBICON ; EBI
;ldr r1, =EBICON_VAL ; Refer s3c2416.inc
;str r1, [r0]
;-------------------------
; Configure GPA data High
ldr r0, = GPACDH
ldr r1, = 0x1AA8A
str r1, [r0]
;------------------------
; GIPO configuration for LED
ldr r0, =GPFCON
ldr r1, =0x5500
str r1, [r0]
;------------------------
; Interrupt configuration ;2.2、屏蔽所有的中断,此阶段用不上,若不屏蔽程序运行过程会被中断且因没有填充中断处理函数会造成死循环。
ldr r0, =INTMSK1 ; mask all first-level interrupts.
ldr r1, =0xffffffff
str r1, [r0]
ldr r0, =INTMSK2 ; mask all first-level interrupts.
ldr r1, =0xffffffff
str r1, [r0]
ldr r0, =INTSUBMSK ; mask all second-level interrupts.
ldr r1, =0x1fffffff
str r1, [r0]
ldr r0, = INTMOD1
mov r1, #0x0 ; set all interrupt as IRQ
str r1, [r0]
ldr r0, = INTMOD2
mov r1, #0x0 ; set all interrupt as IRQ
str r1, [r0]
;------------------------
; Clock configuration ;2.3、设置时钟,初始时CPU的时钟为外部输入的12MHz频率的时钟信号,设置完分频后可在400MHz时钟下运行。
ldr r0, =CLKDIV0 ; Set Clock Divider
ldr r1, [r0]
bic r1, r1, #0x37 ; clear HCLKDIV, PREDIV, PCLKDIV
bic r1, r1, #(0xf<<) ; clear ARMCLKDIV
ldr r2, =((Startup_ARMCLKdiv<<)+(Startup_PREdiv<<)+(Startup_PCLKdiv<<)+(Startup_HCLKdiv))
orr r1, r1, r2
str r1, [r0]
ldr r0, =LOCKCON0 ; Set lock time of MPLL. added by junon
mov r1, #0xe10 ; Fin = 12MHz -0x800, 16.9844MHz -0xA00
str r1, [r0]
ldr r0,=LOCKCON1 ; Set lock time of EPLL. added by junon
mov r1,#0x800 ; Fin = 12MHz - 0x800, 16.9844MHz - 0xA00
str r1,[r0]
ldr r0, =MPLLCON ; Set MPLL
ldr r1,=((<<)+(Startup_Mdiv<<)+(Startup_Pdiv<<)+(Startup_Sdiv))
str r1, [r0]
ldr r0,=EPLLCON ; Set EPLL
ldr r1,=((<<)+(Startup_EMdiv<<)+(Startup_EPdiv<<)+(Startup_ESdiv))
str r1,[r0]
ldr r0, =CLKSRC ; Select MPLL clock out for SYSCLK
ldr r1, [r0]
orr r1, r1, #0x50
str r1, [r0]
;----------------------------
; MMU set Asynchonous Bus Mode ;2.4、设置MMU为异步模式
bl MMU_SetAsyncBusMode
;----------------------------
; Memory Controller initialize ;2.5、初始化内存控制器
bl InitMEM
;----------------------------
; SMC initialize ;2.6、初始化CPU的SD控制器
bl InitSSMC
;----------------------------
; Reset Case handling ;2.7.1、判断复位状态,如果不是唤醒则跳到下面的标号2中运行
ldr r1, =RSTSTAT
ldr r0, [r1]
tst r0, #0x8
beq %F2 ; if not wakeup from PowerOffmode case, Jump to normal booting seauence
;------------------------------ ;2.7.2、判断唤醒状态,如果不是RTC唤醒则跳到下面的标号6中运行
; Wakeup from PowerOff Mode case
ldr r1, =WKUPSTAT
ldr r0, [r1]
tst r0, #(<<)
beq %f6 ; if not wakeup from PowerOffmode Skip
;2.7.3、直接跳入内存中运行
ldr r2, =0x200000 ; offset into the RAM
add r2, r2, #0x30000000 ; add physical base
mov pc, r2 ; & jump to StartUp address
nop
nop
nop
b .
ldr r1, =RSTSTAT ;2.7.4、判断唤醒状态,如果不是深度休眠唤醒则跳到下面的标号BringUpWinCE中运行
ldr r0, [r1]
tst r0, #(<<)
beq BringUpWinCE ; if not wakeup from PowerOffmode Skip
JumpToRAM ;2.7.5、直接跳入内存中运行
ldr r2, =0x200000 ; offset into the RAM
add r2, r2, #0x30000000 ; add physical base
mov pc, r2 ; & jump to StartUp address
nop
nop
nop
b .
BringUpWinCE ;2.8、执行冷启动流程
;--------------------
; Clear RAM ;2.8.1、清空内存
ldr r0, =0x30000000 ; Start address (physical 0x3000.0000).
ldr r9, =0x04000000 ; 64MB of RAM.
stmia r0!, {r1-r8}
subs r9, r9, #
bne %B20
;---------------------
; Initialize stacks. ;2.8.2、初始化堆栈,为进入C语言的代码作环境准备
mrs r0, cpsr
bic r0, r0, #MODEMASK
; orr r1, r0, #UNDEFMODE | NOINT
; msr cpsr_cxsf, r1 ; UndefMode
; ldr sp, =UndefStack ; UndefStack=0x33FF_5C00
; orr r1, r0, #ABORTMODE | NOINT
; msr cpsr_cxsf, r1 ; AbortMode
; ldr sp, =AbortStack ; AbortStack=0x33FF_6000
orr r1, r0, #IRQMODE | NOINT
msr cpsr_cxsf, r1 ; IRQMode
ldr sp, =IRQStack ; IRQStack=0x33FF_7000
; orr r1, r0, #FIQMODE | NOINT
; msr cpsr_cxsf, r1 ; FIQMode
; ldr sp, =FIQStack ; FIQStack=0x33FF_8000
bic r0, r0, #MODEMASK | NOINT
orr r1, r0, #SVCMODE
msr cpsr_cxsf, r1 ; SVCMode
ldr sp, =SVCStack ; SVCStack=0x33FF_5800
;----------------------
; Jump to main C routine. ;2.8.3、跳入C语言代码编写的main函数里面继续执行
bl main
b .
ENTRY_END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;------------------------------
; Sub Routines for Boot Loader
;-------------------------------
LTORG
;------------------------
; Memory Controller initialize
IF :DEF: mSDR ;2.5、如果定义了mSDR则内存初始化函数为下面所示
InitMEM
;Set GPK port when using x32 bus width.
ldr r0,=GPKCON
ldr r1,=0xaaaaaaaa ; set Sdata[31:16]
str r1, [r0]
;Set SDR Memory parameter control registers
ldr r0,=BANKCFG
ldr r1,=BANKCFGVAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON1
ldr r1,=BANKCON1VAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON2
ldr r1,=BANKCON2VAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON3
ldr r1,=BANKCON3VAL ; set Sdata[31:16]
str r1, [r0]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x1<<) ;4nd:Issue a PALL command
str r1,[r2]
ldr r4,=REFRESH ;5fh : refresh cycle every 255-clock cycles
ldr r0,=0xff
str r0,[r4]
mov r0, #0x100 ;6th : wait 2 auto - clk
subs r0, r0,#;
bne %B02
bic r1,r1,#(0x3<<) ;7th:Issue a MRS command
orr r1,r1,#(0x2<<)
str r1,[r2]
ldr r4,=REFRESH ;8fh : refresh normal
ldr r0,=REFCYC
str r0,[r4]
orr r1,r1,#(0x3<<) ;9th: Issue a EMRS command
str r1,[r2]
bic r1,r1,#(0x3<<) ;10th:Issue a Normal mode
str r1,[r2]
mov pc, lr
ENDIF
IF :DEF: mDDR ;2.5、如果定义了mDDR则内存初始化函数为下面所示
InitMEM
;Set GPK port when using x32 bus width.
ldr r0,=GPKCON
ldr r1,=0xaaaaaaaa ; set Sdata[31:16]
str r1, [r0]
;Set DDR Memory parameter control registers
ldr r0,=BANKCFG
ldr r1,=BANKCFGVAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON1
ldr r1,=BANKCON1VAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON2
ldr r1,=BANKCON2VAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON3
ldr r1,=BANKCON3VAL ; set Sdata[31:16]
str r1, [r0]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x1<<) ; 4nd:Issue a PALL command
str r1,[r2]
ldr r4,=REFRESH ; 5fh : refresh cycle every 255-clock cycles
ldr r0,=0xff
str r0,[r4]
mov r0, #0x100 ; 6th : wait 2 auto - clk
subs r0, r0,#;
bne %B02
bic r1,r1,#(0x3<<) ; 7th : Issue a MRS command
orr r1,r1,#(0x2<<)
str r1,[r2]
ldr r4,=REFRESH ; 8fh : refresh normal
ldr r0,=REFCYC
str r0,[r4]
orr r1,r1,#(0x3<<) ; 9th : Issue a EMRS command
str r1,[r2]
bic r1,r1,#(0x3<<) ; 10th : Issue a Normal mode
str r1,[r2]
mov pc, lr
ENDIF
IF :DEF: DDR2 ;2.5、如果定义了DDR2则内存初始化函数为下面所示,此定义在SRC\Inc\s3c2416.inc里面有定义 GBLL DDR2
InitMEM
;Set GPK port when using x32 bus width.
ldr r0,=GPKCON
ldr r1,=0xaaaaaaaa ; set Sdata[31:16]
str r1, [r0]
;Set DDR2 Memory parameter control registers
ldr r0,=BANKCFG
ldr r1,=BANKCFGVAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON1
ldr r1,=BANKCON1VAL ; set Sdata[31:16]
str r1, [r0]
ldr r0,=BANKCON2
ldr r1,=BANKCON2VAL ; set Sdata[31:16]
str r1, [r0]
ldr r2,=BANKCON1 ; 4nd : Issue a PALL command
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x1<<)
str r1,[r2]
ldr r2,=BANKCON3 ; 5th : Issue a EMRS2 command
ldr r3,=0xffff0000
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,#(BA_EMRS2<<)
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x3<<)
str r1,[r2]
ldr r2,=BANKCON3 ; 6th : Issue a EMRS3 command
ldr r3,=0xffff0000
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,#(BA_EMRS3<<)
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x3<<)
str r1,[r2]
ldr r2,=BANKCON3 ; 7th : Issue a EMRS1 command
ldr r3,=0xffff0000
ldr r4,=((BA_EMRS1<<)+(RDQS_DIS<<)+(nDQS_DIS<<)+(OCD_MODE_EXIT<<)+(DLL_EN<<))
; (0x1<<30)|(0x0<<27)|(0x1<<26)|(0x0<<23)|(0x0<<16)
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,r4
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x3<<)
str r1,[r2]
ldr r2,=BANKCON3 ; 8th : Issue a MRS command
ldr r3,=0xffff
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,#((BA_MRS<<)+(DLL_RESET_HIGH<<)+(TM<<)+(CL_MRS<<))
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x2<<)
str r1,[r2]
ldr r2,=BANKCON1 ; 9nd : Issue a PALL command
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x1<<)
str r1,[r2]
ldr r4,=REFRESH ; 10th : wait 2 auto - clk
ldr r0,=0x20
str r0,[r4]
ldr r2,=BANKCON3 ; 11th : Issue a MRS command
ldr r3,=0xffff
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,#((BA_MRS<<)+(DLL_RESET_LOW<<)+(TM<<)+(CL_MRS<<))
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x2<<)
str r1,[r2]
mov r0, #0x100 ; Wait 200 clock
subs r0, r0,#;
bne %B2
ldr r2,=BANKCON3 ; 12th : Issue a EMRS1 command For OCD Mode Set to default
ldr r3,=0xffff0000
ldr r4,=((BA_EMRS1<<)+(RDQS_DIS<<)+(nDQS_DIS<<)+(OCD_MODE_DEFAULT<<)+(DLL_EN<<))
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,r4
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x3<<)
str r1,[r2]
ldr r2,=BANKCON3
ldr r3,=0xffff0000
ldr r4,=((BA_EMRS1<<)+(RDQS_DIS<<)+(nDQS_DIS<<)+(OCD_MODE_EXIT<<)+(DLL_EN<<))
ldr r1,[r2]
bic r1,r1,r3
orr r1,r1,r4
str r1,[r2]
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<)
orr r1,r1,#(0x3<<)
str r1,[r2]
ldr r4,=REFRESH ; 13fh : refresh normal
ldr r0,=REFCYC
str r0,[r4]
ldr r2,=BANKCON1 ; 14th : Issue a Normal mode
ldr r1,[r2]
bic r1,r1,#(0x3<<)
str r1,[r2]
ENDIF
;-----------------------------
; Static Memory Controller Initialize ;2.6、初始化CPU的SD控制器
InitSSMC
; Set SMC Memory parameter control registers : AMD Flash
ldr r0, =SMBIDCYR0
ldr r1, =IDCY0
str r1, [r0]
ldr r0, =SMBWSTRDR0
ldr r1, =WSTRD0
str r1, [r0]
ldr r0, =SMBWSTWRR0
ldr r1, =WSTWR0
str r1, [r0]
ldr r0, =SMBWSTOENR0
ldr r1, =WSTOEN0
str r1, [r0]
ldr r0, =SMBWSTWENR0
ldr r1, =WSTWEN0
str r1, [r0]
ldr r0, =SMBCR0
ldr r1, =(SMBCR0_2+SMBCR0_1+SMBCR0_0)
str r1, [r0]
ldr r0,=SMBWSTBRDR0
ldr r1,=WSTBRD0
str r1,[r0]
ldr r0, =SMBWSTBRDR0
ldr r1, =WSTBRD0
str r1, [r0]
ldr r0, =SSMCCR
ldr r1, =((MemClkRatio<<)+(SMClockEn<<))
str r1, [r0]
ldr r0, =SMBWSTRDR5
ldr r1, =0xe
str r1, [r0]
mov pc, lr
LTORG
;------------------------------------
; MMU Cache/TLB/etc on/off functions
R1_I EQU (<<)
R1_C EQU (<<)
R1_A EQU (<<)
R1_M EQU ()
;R1_iA EQU (1<<31)
;R1_nF EQU (1<<30)
;------------------------------------
; void MMU_EnableICache(void);
LEAF_ENTRY MMU_EnableICache
mrc p15, , r0, c1, c0,
orr r0, r0, #R1_I
mcr p15, , r0, c1, c0,
mov pc, lr
; void MMU_SetAsyncBusMode(void);
; FCLK:HCLK= 1:2
;------------------------------------
LEAF_ENTRY MMU_SetAsyncBusMode
mrc p15, , r0, c1, c0,
orr r0, r0, #R1_nF:OR:R1_iA
mcr p15, , r0, c1, c0,
mov pc, lr
; NAND code... ;3.0、Nand操作相关
;
A410_BASE_ADDR EQU 0x2000000
;;; MACRO
;;; LDR4STR1 $src,$tmp1,$tmp2
;;; ldrb $tmp1,[$src]
;;; ldrb $tmp2,[$src]
;;; orr $tmp1,$tmp1,$tmp2,LSL #8
;;; ldrb $tmp2,[$src]
;;; orr $tmp1,$tmp1,$tmp2,LSL #16
;;; ldrb $tmp2,[$src]
;;; orr $tmp1,$tmp1,$tmp2,LSL #24
;;; MEND
EXPORT __RdPage512
__RdPage512
;input:a1(r0)=pPage
stmfd sp!,{r1-r11}
ldr r1,=0x4e000010 ;NFDATA
mov r2,#0x200
ldr r4,[r1]
ldr r5,[r1]
ldr r6,[r1]
ldr r7,[r1]
ldr r8,[r1]
ldr r9,[r1]
ldr r10,[r1]
ldr r11,[r1]
stmia r0!,{r4-r11}
subs r2,r2,#
bne %B10
ldmfd sp!,{r1-r11}
mov pc,lr
END
程序跳转:main.c
#include <windows.h>
#include <pehdr.h>
#include <romldr.h>
#include "option.h"
#include "s2416ADDR.h"
// Constants.
//
#define MESSAGE_ON FALSE //TRUE
#define LED_ON 0xa
#define LED_OFF 0x0
#define NAND_SB_PAGE_SIZE_BYTES (0x200) // 1 Page = 0x200 (512 Bytes)
#define NAND_SB_BLOCK_SIZE_BYTES (0x4000) // 1 Block = 16 KB
#define NAND_SB_PAGES_PER_BLOCK (NAND_SB_BLOCK_SIZE_BYTES / NAND_SB_PAGE_SIZE_BYTES) // 32-pages
#define NAND_LB_PAGE_SIZE_BYTES (0x800) // 1 Page = 0x800 (2048 Bytes)
#define NAND_LB_BLOCK_SIZE_BYTES (0x20000) // 1 Block = 128 KB
#define NAND_LB_PAGES_PER_BLOCK (NAND_LB_BLOCK_SIZE_BYTES / NAND_LB_PAGE_SIZE_BYTES) // 64-pages
// NOTE: we assume that this Steppingstone loader occupies *part* the first (good) NAND flash block. More
// specifically, the loader takes up 4096 bytes (or 8 NAND pages) of the first block. We'll start our image
// copy on the very next page.
#define NAND_COPY_PAGE_OFFSET (2*((bLARGEBLOCK==TRUE)?NAND_LB_PAGES_PER_BLOCK:NAND_SB_PAGES_PER_BLOCK))
#define LOAD_ADDRESS_PHYSICAL 0x30038000
#define LOAD_SIZE_BYTES 0x00040000
#define LOAD_SIZE_PAGES (LOAD_SIZE_BYTES / ((bLARGEBLOCK==TRUE)?NAND_LB_PAGE_SIZE_BYTES:NAND_SB_PAGE_SIZE_BYTES))
// Globals variables.
//
ROMHDR * ;
// Function prototypes.
//
void MMU_EnableICache(void);
void Led_Display(int);
void Port_Init(void);
void NF_Init(void);
DWORD ReadFlashID(void);
int NF_ReadPage(UINT32 block, UINT32 page, volatile BYTE *buffer);
extern BOOL bLARGEBLOCK;
//
typedef void (*PFN_IMAGE_LAUNCH)();
/*
@func BOOLEAN | SetupCopySection | Copies the IPL image's copy section data (initialized globals) to the correct fix-up location. Once completed, the IPLs initialized globals are valid.
@rdesc TRUE == Success and FALSE == Failure.
@comm
@xref
*/
static BOOLEAN SetupCopySection(ROMHDR *const pTOC)
{
// This code doesn't make use of global variables so there are no copy sections. To reduce code size, this is a stub function...
//
return(TRUE);
}
/*
@func void | main | C entrypoint function for the Steppingstone loader.
@rdesc None.
@comm
@xref
*/
void main(void)
{
register nBlock;
register nPage;
register nBadBlocks;
volatile BYTE *pCopyPtr;
#if MESSAGE_ON==1
volatile DWORD boot_code;
#endif
// Set up copy section (initialized globals).
//
// NOTE: after this call, globals become valid.
//
//SetupCopySection(pTOC);
// Enable the ICache.
//
MMU_EnableICache();
// Set up all GPIO ports.
//
// TBD - DonGo
Port_Init(); //1、初始化IO口
Uart_Init(); //2、初始化打印信息的串口
Uart_SendString("\rMicrosoft Windows CE 5.0 Stepldr for DMA2416\r\n");
// Initialize the NAND flash interface.
//
//Uart_SendString("NF_Init...");
NF_Init(); //3、初始化Flash
// Turn the LEDs off.
Led_Display(LED_OFF);
//---------------------------------
// Copy image from NAND flash to RAM.//4、准备复制Flash文件到内存中运行
//
pCopyPtr = (BYTE *)LOAD_ADDRESS_PHYSICAL;
#if MESSAGE_ON==1
Uart_SendString("Image copy NAND block from ");
Uart_SendDWORD(NAND_COPY_PAGE_OFFSET/NAND_PAGES_PER_BLOCK,);
Uart_SendString(" to ");
Uart_SendDWORD((LOAD_SIZE_PAGES + NAND_COPY_PAGE_OFFSET)/NAND_PAGES_PER_BLOCK,);
Uart_SendString("Download memory address at ");
Uart_SendDWORD(LOAD_ADDRESS_PHYSICAL,);
#endif
if (ReadFlashID() != TRUE)
{
//Uart_SendString("NAND Flash is not supported!!\r\n");
);
}
nBadBlocks = ;
for (nPage = NAND_COPY_PAGE_OFFSET ; nPage < (LOAD_SIZE_PAGES + NAND_COPY_PAGE_OFFSET) ; nPage++) //5、执行拷贝操作
{
nBlock = ((nPage / ((bLARGEBLOCK==TRUE)?NAND_LB_PAGES_PER_BLOCK:NAND_SB_PAGES_PER_BLOCK)) + nBadBlocks);
//Uart_SendDWORD(nPage,1);
//Uart_SendString(" ");
if (!NF_ReadPage(nBlock, (nPage % ((bLARGEBLOCK==TRUE)?NAND_LB_PAGES_PER_BLOCK:NAND_SB_PAGES_PER_BLOCK)), pCopyPtr))//6、读取Flash写入内存
{
//Uart_SendString(hex2char(nBlock));
)
{
//Led_Display(0x9); // real ECC Error.
//Uart_SendString("ECC Error.\r\n");
// Spin forever...
)
{
}
}
// ECC error on a block boundary is (likely) a bad block - retry the page 0 read on the next block.
nBadBlocks++;
nPage--;
continue;
}
//Uart_SendDWORD(*pCopyPtr,0);
//Uart_SendString("\n");
pCopyPtr += ((bLARGEBLOCK==TRUE)?NAND_LB_PAGE_SIZE_BYTES:NAND_SB_PAGE_SIZE_BYTES);
}
// Turn the LEDs on.
//
//Led_Display(0x5);
#if MESSAGE_ON==1
boot_code = *(volatile DWORD *)LOAD_ADDRESS_PHYSICAL;
Uart_SendString("Bboot code : ");
Uart_SendDWORD(boot_code,);
//-----------------------------
// Jump to the image...
//
Uart_SendString("Now Jump to ");
Uart_SendDWORD(LOAD_ADDRESS_PHYSICAL,);
#endif
((PFN_IMAGE_LAUNCH)(LOAD_ADDRESS_PHYSICAL))(); //7、跳入内存指定地址运行
}
程序编译配置文件:stepldr.bib
MEMORY
; Name Start Size Type
; ------- -------- -------- ----
STEPLDR RAMIMAGE ;此处地址是CPU内置的RAM的地址文章最上面的图所示,大小为8K,即2416所支持的最大的自动复制大小
STACK 33ff5800 RESERVED ;程序运行时的栈指针
RAM 33ff0000 RAM ;程序运行内存
CONFIG
COMPRESSION=ON
PROFILE=OFF
KERNELFIXUPS=ON
ROMSTART=
ROMWIDTH=
ROMSIZE=00001000 ;实际大小只用了4K
MODULES
; Name Path Memory Type
; ---------- -------------------------------------------------------------- -----------
nk.exe $(_TARGETPLATROOT)\target\$(_TGTCPU)\$(WINCEDEBUG)\stepldr.exe STEPLDR
CE STEPLDR的更多相关文章
- CE修改器修改DNF 测试视频 阿修罗提升智力增加攻击力
使用CE修改器来修改网络游戏,如DNF 测试视频: CE修改器:指的是Cheat Engine,字面上的意思指的是作弊引擎的意思,是一款内存修改编辑工具.通过修改游戏的内存数据来得到一些原本无法实现的 ...
- PreEmptive Dotfuscator and Analytics CE
PreEmptive Dotfuscator and Analytics CE Dotfuscator 是领先的 .NET 模糊处理程序和压缩程序,有助于防止程序遭到反向工程,同时使程序更小更高效.D ...
- Visual Studio 2005 搭建Windows CE 6.0环境之准备
Microsoft Visual Studio 2005 Visual Studio 2005 Professional 官方90天试用版英文版:http://download.microsoft.c ...
- 游戏外挂四之利用CE和OD查找被选中怪物和怪物列表
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q Q:408365330 E-Mail:egojit@qq.com 这一节我们利 ...
- CE 进程间通信
WINCE下进程间通信常用的方式有:剪贴板(Clipboard),网络套接字(Socket),WM_COPYDATA消息,共享内存,管道(消息队列),注册表等 剪贴板 //////////////// ...
- CE 进程同步-事件
事件(event)分为有名的和无名的,使用有名事件的时候,在不同进程中创建的同名事件,其实就是同一个,这样就可以在不同的进程中使用了.两个进程里面都要创建事件,事件名要一致. //进程1 HANDLE ...
- CE搜索内存数据的原理
最近发现有朋友在玩游戏时, 使用一款工具来修改游戏的部分数据,作弊的效果, 也就是CE(Cheat Engine),这款工具是 delphi 编写的, 于是好奇, 然后瞬间想到API OpenPr ...
- ce游戏内存修改器(Cheat Engine)
ce修改器(Cheat Engine)一款专门修改内存修改编辑的游戏工具它包括16进制编辑,反汇编程序,内存查找工具新版6.1 版的CE与6.0 最大的区别就是添加了修改器制作工具,比之前 5.6.1 ...
- CE 文件读写操作
写入字符到文件中: // TODO: 写字符到文件 // 参数: CString类型的文件名FileName;char *类型的数据内容;unsigned int类型内容长度 // 返回: 成功返回T ...
随机推荐
- oracle_空值判断
Oracle空值测试 比较项目 is null is not null nvl 说明 NULL true false true null true false true 'NULL' fals ...
- angularjs ng-click
在angularjs的controller中一段代码,展示如下: var sortList = new SortList(); sortList.setSorts([$scope.year_inves ...
- c语言-四阶龙格-库塔法
#include<stdio.h> #include<math.h> #define n 14 //double func1(double x, double y); doub ...
- Windows Server 2003 IIS6.0+PHP5(FastCGI)+MySQL5环境搭建教程
准备篇 一.环境说明: 操作系统:Windows Server 2003 SP2 32位 PHP版本:php 5.3.14(我用的php 5.3.10安装版) MySQL版本:MySQL5.5.25 ...
- Codeforces Round #323 (Div. 1) A. GCD Table
A. GCD Table time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- Pegasos: Primal Estimated sub-GrAdient Solver for SVM
Abstract We describe and analyze a simple and effective iterative algorithm for solving the optimiza ...
- Python开发入门与实战15-IIS部署
15. IIS部署 前面的章节我们完成了基本的业务功能的开发,本章节我们来说说python django项目如何部署到实际的运行环境,完成开发系统的发布工作. Python Django 项目部署发布 ...
- VS.net中快捷键收缩和展开代码段 (转)
i. Ctrl-M-O 折叠所有方法 ii. Ctrl-M-P 展开所有方法并停止大纲显示(不可以再折叠了) iii. Ctrl-M-M 折叠或展开当前方法 iv. Ctrl-M-L展开所 ...
- mybatis学习2
解决字段名与实体类属性名不相同的冲突 1. 准备表和数据:CREATE TABLE orders(order_id INT PRIMARY KEY AUTO_INCREMENT,order_no VA ...
- 开始学习Dojo
学习:Dojo入门简易教程 Dojo Toolkit 简介 Dojo 于 2004 年创建,使开发 DHTML 和 JavaScript web 应用程序开发流程更为容易,隐藏了很多现代 web 浏览 ...