📄 init.s
字号:
;--------------------------------------------------------------------------------------------------------------------------------
; INIT.S -
; Copyright (c) 1999 SUN Sirius, Inc.
;--------------------------------------------------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------------------------------------------------
; Define the code area. |C$$code| is area produced by C compiler or for code otherwise associated with the C library.
; NOTE:
; 1. The AREA must have the attribute READONLY, otherwise the linker will not place it in ROM.
; 2. The AREA must have the attribute CODE, otherwise the assembler will not let us put any code in this AREA.
;--------------------------------------------------------------------------------------------------------------------------------
AREA |C$$code|, CODE, READONLY
;--------------------------------------------------------------------------------------------------------------------------------
; The following are conditional assembly flags(条件汇编). Leave commented if you don't want to assemble the corresponding code block.
; MMU_enabled EQU 0x1 ;
; DRAM_enabled EQU 0x1 ;
; FIQ_enabled EQR 0x1 ;
; NOTE :
; These can be defined in the project file. If commented, then not defined by default.
;--------------------------------------------------------------------------------------------------------------------------------
ENTRY
;--------------------------------------------------------------------------------------------------------------------------------
; The ARM vector table(向量表).
; This must reside(居住) at location 0x00000000 in the ARM's address space. When the ARM takes an execption, it changes the program
; counter to one of the first eight addresses in memory. Each vector has only one instruction(指令), so we use that instruction to load
; the program counter with the address of the handler rountine, which is stored in a table following the vector table.
;
; Now, starting to set interrupt/exception vectors.
;--------------------------------------------------------------------------------------------------------------------------------
B Reset_Handler ;
B Undefined_Handler ;
B SWI_Handler ;
B Prefetch_Handler ;
B Abort_Handler ;
NOP ;Reserved vector -- do not use.
B IRQ_Handler ;
B FIQ_Handler ;
;--------------------------------------------------------------------------------------------------------------------------------
; The fast interrupt vector is handled specially. Instead of branching (分支) to the rountine for handling the FIQ, we simply place the
; FIQ code after the vector table. This avoids an additionaly branch(and the associated cost(成本))when we are trying to handle a
; FAST interrupt.
;
; For now, we do nothing if we received a FIQ.
;--------------------------------------------------------------------------------------------------------------------------------
FIQ_Handler
B FIQ_Handler
;--------------------------------------------------------------------------------------------------------------------------------
; The undefined instruction handler. This is called when an instruction reaches the execute stage(执行阶段) of the ARM pipeline(管道),
; but is not an instruction which is recognized by the ARM processor. We don't do anything special to try and recover.
;--------------------------------------------------------------------------------------------------------------------------------
Undefined_Handler
B Undefined_Handler
;--------------------------------------------------------------------------------------------------------------------------------
; The software interrupt handler. We don't support any SWIs, so simply return to the caller.
;--------------------------------------------------------------------------------------------------------------------------------
SWI_Handler
B SWI_Handler
;--------------------------------------------------------------------------------------------------------------------------------
; The instruction pre-fetch(指令预取) abort handler. This is called when an instruction reaches the execute stage(执行阶段) of the
; ARM pipeline(管道), but the pre-fetch of the instruction failed due to(由于) a MMU error. This doesn't need to do a whole lot unless
; we are implementing virtual memory.
; NOTE:
; a whole lot : 非常多,多得不能再多了
;--------------------------------------------------------------------------------------------------------------------------------
Prefetch_Handler
B Prefetch_Handler
;--------------------------------------------------------------------------------------------------------------------------------
; The data abort handler. This is called when a load or store instruction is executed and the memory access failed due to a MMU error.
; This doesn't need to do a whole lot unless we are implementing virtual memory.
;--------------------------------------------------------------------------------------------------------------------------------
Abort_Handler
B Abort_Handler
;--------------------------------------------------------------------------------------------------------------------------------
; The IRQ interrupt handler. This is called when the IRQ line(IRQ编号) going into the ARM processor goes high, indicating an external
; device is requesting the attention(关注) of the processor.
;--------------------------------------------------------------------------------------------------------------------------------
IRQ_Handler
;
; If we don't need interrupts, simply use the next instruction. For now, simply comment it.
B IRQ_Handler
; Call the actual interrupt handler which can be in C or assemnly.
; IMPORT InterruptHandler
;bl InterruptHandler
;--------------------------------------------------------------------------------------------------------------------------------
; NOTE: There are teo ways to call an IRQ in C.
; 1. The first way is to simply define the function in C as int or void. In this case, you must save the stack in this rountine and
; restore it when finished.
; 2. The second method is to cast() the function with the __irq keyword (two underkines). The __irq keyword ensures that
; r0-r3 and r12 are preserved(保留), and the function exits with SUBS pc, lr, #4.
;
; For this example, we will use the __irq keyword. The code that saves the stack is commented out. The following is steps:
;
; Save any register which might get clobbered by the actual interrupt handler rountine (which is in C). This register set is the one define
; APCS as being destroyable by the callee.
; stmdb r13!, {r0-r3, r12} ;needed if not using __irq keyword.
; Call the actual interrupt handler which can be in C or assemnly.
; IMPORT InterruptHandler
; bl InterruptHandler
;
; Restore the registers which we saved.
; ldmia r13!, {r0-r3, r12} ;thie step only needed, if not using __irq keyword
;
; Return to the interrupt code.
; subs pc, r14, #4 ;this step needed if not using __irq keyword in C program.
;--------------------------------------------------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------------------------------------------------
; ResetHandler is the startup code to be used
;--------------------------------------------------------------------------------------------------------------------------------
Reset_Handler
;
; Setup the MMU for 32 bit code and data.
ldr r0, =0x0000007d
mcr p15, 0, r0, c1, c0
;Disable all interrupts (this should be disabled on reset, but just in case...)
ldr r0, =0x00000000
str r0, [r12, #0x0280] ;INTMR1 = 0x8000.0280
add r11, r12, #0x1000
str r0, [r11, #0x280] ;INTMR2 = 0x8000.1280
;--------------------------------------------------------------------------------------------------------------------------------
; Do this section only if DRAM is required.
IF (:DEF: DRAM_enabled)
; Enabled DRAM Bank 0 and Bank 1, each is 8 megabytes(兆字节) ×32.
; By default, Bank 0 is at address 0xC000.0000, and Bank 1 is at address 0xD000.0000
;
ldr r0, =0x81; ; Enable dram refresh ar maximum rate (64KHz)
str r0, [r12, #0x200] ; Store result in DRFPR register 0x8000.0200
;
; Stub for memory test
;
; Set SYSCON2 to zero (default value, step not necessary). Bit 2 sets x32 DRAM
;
ldr r1, =0x0
add r11, r12, #0x1000
str r1, [r11, #0x1000] ; Init syscon2 register at 0x8000.1100
ENDIF
; End of DRAM intialization
;--------------------------------------------------------------------------------------------------------------------------------
; Set bits 1:2 in SYSCON3 for 74 MHz clock speed (default is 18MHz on reset)
ldr r1, =0x06
add r11, r12, #0x2000
str r1, [r11, #0x200] ; Init syscon3 register at 0x8000.2200
;--------------------------------------------------------------------------------------------------------------------------------
; Now configure the MemConfig register to get the following:
; nCS0 = NOR FLASH, 32-bit, 3 wait states
; nCS1 = NAND FLASH, 32-bit, 2 wait states
; nCS2 = Ethernet, 16-BIT, 8 wait states(was 32-bit = 0x00)
; nCS3 = Parallel/Keyboard/GPIOs, 32-bit, 1 wait state
; nCS4 = USB, 8-bit, 1 wait state, 2 w/s radom (was 32-bit, 0x3c)
; nCS5 = Unused/general purpose, 32-bit, 8 wait states;
;--------------------------------------------------------------------------------------------------------------------------------
MemConfig1Value EQU 0x3c011814
MemConfig2Value EQU 0x0000001e ; Boot rom and internal SRAM are ignored.
; Configure nCS0-nCS3
ldr r1, =MemConfig1Value
str r1, [r12, #0x0180]; ; MEMCFG1 = 0x8000.0180
; Configure nCS4 & nCS5
ldr r1, = MemConfig2Value
str r1, [r12, #0x01c0]; ;MEMCFG2 = 0x8000.01c0
;--------------------------------------------------------------------------------------------------------------------------------
; Define Stacks
; The follow section defines the stack pointer for IRQ and SVC modes. This is optional as the debugger will assgin iu's own stack area
; with the $top_of_mempry variable in "debugger internals".
; However, this code is necessary if this program is used to launch an embedded application in C or assembly.
;--------------------------------------------------------------------------------------------------------------------------------
; Put the ARM processor into IRQ mode.
mrs r0, cpsr ;
bic r0, r0, #0x0000001F ;
orr r0, r0, #0x00000012 ;
msr cpsr_cf, r0 ;
; Set up the stack pointer for IRQ mode. We use the on-board SRAM for the stack for simplicity's sake(出于简单的原因)
ldr r13, =IRQStackEnd ; Stack goes downwards from end.
; go downward(upward, forward, backword): 到下面(上面,前面,后面)
; Put the ARM processor into SVC mode and enable the IRQ interrupt.
mrs r0, cpsr
bic r0, r0, #0x0000009F ;
orr r0, r0, #0x00000013 ;
msr cpsr_cf, r0 ;
; Set up the stack pointer. We use the on-board SRAM for the stack for simplicity's sake.
ldr r13, =SVCStackEnd ;
IF (:DEF: FIQ_enabled)
; Put the ARM processor into FIQ mode
ldr r0, =0x000000D1 ;
msr cpsr_cf, r0
; Initialize the values of the FIQ mode banked registers.
ldr r8, =0x00000000 ;
ldr r9, =0x00000000
ldr r10, =0x00000000
ldr r11, =0x00000000
ldr r12, =0x00000000
; Set up the stack pointer for FIQ mode
ldr r13, =FIQStackEnd
ENDIF
; End of Stack Setup
;--------------------------------------------------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------------------------------------------------
; Set up the MMU.
; Start by flushing the cache and TLB. This section may be eliminated(消除,排除) if MMU is not desired(想得到的).
;--------------------------------------------------------------------------------------------------------------------------------
IF (:DEF: MMU_enabled)
ldr r0, =0x00000000
mcr p15, 0, r0, c5, c0
mcr p15, 0, r0,c7, c0
; Set user mode access for all 16 domains.
ldr r0, 0x55555555
mcr p15, 0, r0, c3, c0
; Tell the MMU where to find the page table.
IMPORT PageTable
ldr r0, =PageTable
mcr p15, 0, r0, c2, c0
; Enable the MMU.
ldr r0, =0x0000007d
mcr p15, 0, r0, c1, c0
; There should always be two NOP instructions following the enable or disable of the MMU.
mov r0, r0
mov r0, r0
ENDIF
; End of MMU intialization
;--------------------------------------------------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------------------------------------------------
; The following are copy data.
; Copy the read-write data block from ROM to RAM.
;--------------------------------------------------------------------------------------------------------------------------------
IMPORT |Image$$RO$$Limit|
IMPORT |Image$$RW$$Base|
IMPORT |Image$$ZI$$Base|
ldr r0, =|Image$$RO$$Limit|
ldr r1, =|Image$$RW$$Base|
ldr r2, =|Image$$ZI$$Base|
cpoy_rw
cmp r1, r2
ldrne r3, [r0], #+4
strne r3, [r1], #+4
bne cpoy_rw
; Fill the zero initialized data block in RAM with zeros.
IMPORT |Image$$RW$$Limit|
ldr r2, =|Image$$RW$$Limit|
ldr r3, = 0x0000000
zero
cmp r1, r2
strne r3, [r1], #+4
bne zero
program
;
; Call the actual C program program.
IMPORT C_vMain
bl C_vMain
; Normal, the program should not return, but just in case, branch to the reset vector and start over.
b Reset_Handler
;--------------------------------------------------------------------------------------------------------------------------------
; Zero-initialized read/write data area for stacks.
; This area determined by the RW value in the linker under "entry and base"
;--------------------------------------------------------------------------------------------------------------------------------
AREA |CStack##zidata|, DATA, READWRITE, NOINIT
;--------------------------------------------------------------------------------------------------------------------------------
; Memory buffers to contain the stacks for the various processor modes which we will be using.
;--------------------------------------------------------------------------------------------------------------------------------
SVCStack
% 0x400
SVCStackEnd
IRQStack
% 0x100
IRQStackEnd
FIQStack
% 0xc
FIQStackEnd
;--------------------------------------------------------------------------------------------------------------------------------
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -