⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.s

📁 EP7312的入门例子
💻 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 + -