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

📄 crt0.s

📁 开源的BIOS启动软件
💻 S
字号:
#include "bios/linkage.h"#define CSR_BASE	0x42000000#define SDRAM_TIMING	0x10c#define SDRAM_ADDR_SZ0	0x110#define SDRAM_ADDR_SZ1	0x114#define SDRAM_ADDR_SZ2	0x118#define SDRAM_ADDR_SZ3	0x11c#define SDRAM_BASE	0x40000000#define SDRAM_NRARRAYS	4#define SDRAM_ARRAYOFF	0x00004000#define UARTDR           0x160#define BAUD_RATE_DIVISOR_300     2603#define BAUD_RATE_DIVISOR_2400    325#define BAUD_RATE_DIVISOR_9600    80#define BAUD_RATE_DIVISOR_19200   40#define BAUD_RATE_DIVISOR_38400   19#define BAUD_RATE_DIVISOR_56000   13#define BAUD_RATE_DIVISOR_115200  6#define BAUD_RATE_DIVISOR_128000  5#define BAUD_RATE_DIVISOR        BAUD_RATE_DIVISOR_38400#define DEBUG_RAM/* * The CAS latency *	Valid: 2 or 3 cycles */#define Tcas	2/* * The RAS cycle time in cycles (Tas + Trp) *	Valid: 4 to 10 cycles */#define Trc	5/* * The RAS to CAS delay in cycles *	Valid: 2 or 3 cycles */#define Trcd	2/* * Last data in to activate or refresh in cycles *	Valid: 2 to 5 cycles */#define Tdal	3/* * Row precharge time *	Valid: 1 to 4 cycles */#define Trp	2/* * Refresh time (in us) */#define Tref	64000/* * Add an extra cycle to the command drive time? */#define CmdDrv	0	.text@ Entry	.globl	_entry_entry:	mrs	r0, cpsr	bic	r0, r0, #0x1f	orr	r0, r0, #0xd3	msr	cpsr, r0/* * switch the ROM memory map * so that we can access the SDRAM */	ldr	pc, 1f1:	.word	switchswitch:	mov	r0, #0	mcr	p15, 0, r0, c7, c7, 0	@ flush all caches                             /* * We need all caches off for the SDRAM initialisation - * we have s/w timing loops to time the SDRAM refresh * cycles in here, which must be synchronised to the bus * clock. */	mrc	p15, 0, r0, c1, c0	@ Control reg	bic	r0, r0, #0x0d		@ D-cache, wback & MMU off	bic	r0, r0, #1 << 12	@ I-cache off	mcr	p15, 0, r0, c1, c0	@ Control reg	bl	ser_init/* * Initialise SDRAM.  This copes with the SDRAM in any state - * it does a complete initialisation and allocation of all * banks.  We basically follow the sequence given in the * EBSA285 manual. * * Turn off SDRAM refresh */init_ram:	mov	r0, #0	mov	ip, #CSR_BASE	str	r0, [ip, #SDRAM_TIMING]	mov	r4, #Tcas	mov	r5,     #(CmdDrv & 1) << 1	orr	r5, r5, #((Trc - 3) & 7) << 8	orr	r5, r5, #(Trcd & 3) << 4	orr	r5, r5, #((Tdal - 2) & 3) << 2	orr	r5, r5, #(Trp - 1) & 3	orr	r5, r5, r4, lsl #6	@ add in Tcas/*  * Wait for any refresh cycles to complete */	mov	r0, #641:	subs	r0, r0, #1	bgt	1b/* * All-banks precharge SDRAM arrays */	mov	r0, #SDRAM_BASE	mov	r1, #SDRAM_NRARRAYS1:	ldr	r2, [r0]	ldr	r2, [r0]	add	r0, r0, #SDRAM_ARRAYOFF	subs	r1, r1, #1	bgt	1b/* * Write mode registers */	mov	r0, #0x02		@ burst (4 words)	orr	r0, r0, r4, lsl #4	@ Tcas	mov	r0, r0, lsl #2		@ shift up two places	orr	r0, r0, #SDRAM_BASE	mov	r1, #SDRAM_NRARRAYS1:	str	r0, [r0]	add	r0, r0, #SDRAM_ARRAYOFF	subs	r1, r1, #1	bgt	1b/* * Turn on minimum SDRAM refresh */	orr	r0, r5, #0x00010000	@ 640us refresh time	str	r0, [ip, #SDRAM_TIMING]/* * Set size to 64MB, space banks at 64MB intervals, with multiplexer mode 4 */	mov	r1, #SDRAM_NRARRAYS	add	r2, ip, #SDRAM_ADDR_SZ0	mov	r0, #0x4f1:	str	r0, [r2], #4	add	r0, r0, #64*1024*1024	subs	r1, r1, #1	bgt	1b/* * Wait for banks to be refreshed.  We actually wait 2560 cycles (80 refreshes) */	mov	r0, #10	mov	r1, #01:	subs	r1, r1, #2	bgt	1b	subs	r0, r0, #1	bgt	1b/* * Set SDRAM refresh to normal */	orr	r0, r5, #(Tref / 2621) << 16	str	r0, [ip, #SDRAM_TIMING]	mov	r4, #0x000000001:	mov	r5, #0/* * Detect RAM multiplexer settings. * * Theory of operation: *  There are 6 distinct multiplexer settings.  It is possible to detect *  which multiplexer settings are correct for the SDRAM array by testing *  just four bits with the multiplexer set to mode 4: *   row address 9 *   row address 10 *   row address 11 *   bank address 1 *  we test to see if toggling these address lines are used by the SDRAM, *  and select the multiplexer setting from the result. * * Multiplexer 	BA1	RA11	RA10	RA9	code	Max array size *  000 1 (08)	-	-	-	-	0	1MB *  000 0 (00)	-	-	-	used	1	2MB *  001 x (10)	-	-	used	used	3	16MB *  010 x (20)	-	used	used	used	7	64MB *  011 x (30)	used	-	used	used	b	8MB	 *  100 x (40)	used	used	used	used	f	64MB */#ifdef DEBUG_RAM	bl	debug_bank		@ corrupts r2#endif	mov	r0, r4			@ check for presence	add	r1, r4, #64	bl	testram#ifdef DEBUG_RAM	bl	debug_testres		@ corrupts r1-r3,r6,r7#endif	bne	next_bank		@ array not present - disable	mov	r0, r4			@ check bit 20 (BA1)	orr	r1, r0, #1 << 20	bl	testram#ifdef DEBUG_RAM	bl	debug_testres		@ corrupts r1-r3,r6,r7#endif	orreq	r5, r5, #8		@ bit 20 (BA1) has an effect	mov	r0, r4			@ check bit 22 (row 11)	orr	r1, r0, #1 << 22	bl	testram#ifdef DEBUG_RAM	bl	debug_testres		@ corrupts r1-r3,r6,r7#endif	orreq	r5, r5, #4		@ bit 22 (row 11) has an effect	mov	r0, r4			@ check bit 21 (row 10)	orr	r1, r0, #1 << 21	bl	testram#ifdef DEBUG_RAM	bl	debug_testres		@ corrupts r1-r3,r6,r7#endif	orreq	r5, r5, #2		@ bit 21 (row 10) has an effect	mov	r0, r4			@ check bit 18 (row 9)	orr	r1, r0, #1 << 18	bl	testram#ifdef DEBUG_RAM	bl	debug_testres		@ corrupts r1-r3,r6,r7#endif	orreq	r5, r5, #1		@ bit 18 (row 9) has an effect#ifdef DEBUG_RAM	bl	debug_result#endif	adr	r1, ram_modes		@ convert test result to mux setting	ldrb	r6, [r1, r5]	teq	r6, #0xff		@ was the test result illegal?	moveq	r5, #0			@ if it was, disable the array	beq	next_bank	orr	r6, r6, r4		@ incorporate address	add	r0, ip, #SDRAM_ADDR_SZ0	@ set mux correctly	orr	r5, r6, #7		@ leave array size at 64MB	str	r5, [r0, r4, lsr #24]/* * Detect RAM array size */	mov	r5, #1 << 20		@ start at 1MB	mov	r7, #12:	mov	r0, r4			@ check bit (r7 + 19)	add	r1, r4, r5	bl	testram	bne	3f			@ if bit (r7 + 19) doesnt work	mov	r5, r5, lsl #1	cmp	r7, #7	addne	r7, r7, #1	bne	2b3:	orr	r5, r6, r7next_bank:	add	r0, ip, #SDRAM_ADDR_SZ0	str	r5, [r0, r4, lsr #24]	@ set array size#ifdef DEBUG_RAM	bl	debug_size#endif	add	r4, r4, #0x04000000	@ next bank address	teq	r4, #0x10000000	bne	1b/* * Now that we know the size of each SDRAM array, allocate * their addresses, starting at the largest size and working * progressively smaller. *  r4 is our "top of memory" */	mov	r3, #7			@ start at largest size	mov	r4, #0x000000001:	mov	r5, #SDRAM_NRARRAYS	add	r2, ip, #SDRAM_ADDR_SZ02:	ldr	r0, [r2], #4		@ Read SDRAM size & addr	and	r1, r0, #7	teq	r1, r3	bne	3f	and	r0, r0, #127		@ Preserve size etc	orr	r0, r0, r4		@ Add base address	str	r0, [r2, #-4]		@ Write SDRAM size & addr	mov	r0, #524288	add	r4, r4, r0, lsl r1	@ Next address3:	subs	r5, r5, #1		@ Next bank	bgt	2b	subs	r3, r3, #1		@ Next size	bgt	1b#ifdef DEBUG_RAM	bl	debug_totalsize#endif	teq	r4, #0	beq	init_ram/* * Now setup caches */	mrc	p15, 0, r0, c1, c0	@ read control reg	bic	r0, r0, #0x0d		@ D-cache, wback & MMU off	orr	r0, r0, #1 << 12	@ I-cache on	mcr	p15, 0, r0, c1, c0	@ Control reg	mov	r0, #0	mcr	p15, 0, r0, c15, c1, 2	@ clock switching on/* * Copy the data segment to the SDRAM */	ldr	r1, =SYMBOL_NAME(_data)	ldr	r2, =SYMBOL_NAME(_etext)	ldr	r3, =SYMBOL_NAME(_data_sz)1:	ldr	r0, [r2], #4	str	r0, [r1], #4	subs	r3, r3, #4	bgt	1b/* * and zero the BSS */	mov	r0, #0	ldr	r1, =SYMBOL_NAME(_bss_start)	ldr	r2, =SYMBOL_NAME(_end)1:	str	r0, [r1], #4	cmp	r1, r2	blt	1b/* * Allocate the stack 1MB below the very top of memory. * Memory above this is reserved for malloc() */	sub	sp, r4, #1048576/* * initialise the vectors */	bl	vec_init/* * Don't forget to update ram_size */	ldr	r0, =SYMBOL_NAME(ram_size)	str	r4, [r0]/* * Now jump into the C code */	bl	SYMBOL_NAME(start_main)l:	b	lram_modes:				@ BA1  RA11 RA10 RA9	.byte	0x08			@  -    -    -    -	.byte	0x00			@  -    -    -    x	.byte	0xff			@  -    -    x    - (illegal)	.byte	0x10			@  -    -    x    x	.byte	0xff			@  -    x    -    - (illegal)	.byte	0xff			@  -    x    -    x (illegal)	.byte	0xff			@  -    x    x    - (illegal)	.byte	0x20			@  -    x    x    x	.byte	0xff			@  x    -    -    - (illegal)	.byte	0xff			@  x    -    -    x (illegal)	.byte	0xff			@  x    -    x    - (illegal)	.byte	0x30			@  x    -    x    x	.byte	0xff			@  x    x    -    - (illegal)	.byte	0xff			@  x    x    -    x (illegal)	.byte	0xff			@  x    x    x    - (illegal)	.byte	0x40			@  x    x    x    x/* * Test to see if two RAM locations are aliases. *  r0 = location 1 *  r1 = location 2 */testram:	mov	r10, #0x55	orr	r10, r10, #0xaa00	orr	r10, r10, r10, lsl #16	@ r10 = 0xaa55aa55	str	r10, [r0]		@ store 0xaa55aa55 to [r0]	mvn	r10, r10	str	r10, [r1]		@ store 0x55aa55aa to [r1]	mvn	r10, r10	ldr	r11, [r0]	teq	r10, r11		@ is [r0] 0xaa55aa55?	bne	1f			@ no - this means r1 is an alias of r0	mvn	r10, r10	str	r10, [r0]		@ store 0x55aa55aa to [r0]	mvn	r10, r10	str	r10, [r1]		@ store 0xaa55aa55 to [r1]	mvn	r10, r10	ldr	r11, [r0]	teq	r10, r11		@ is [r0] 0x55aa55aa?1:	mov	pc, lr#ifdef DEBUG_RAMdebug_bank:	mov	r2, lr	adr	r0, bankmsg	bl	ser_prints	mov	r0, r4	bl	ser_printhex	mov	r0, #'\n'	mov	lr, r2	b	ser_printcdebug_result:	mov	r2, lr	adr	r0, result	bl	ser_prints	mov	r0, r5	bl	ser_printhexbyte	mov	r0, #'\n'	mov	lr, r2	b	ser_printcdebug_size:	mov	r2, lr	adr	r0, size	bl	ser_prints	mov	r0, r5	bl	ser_printhex	mov	r0, #'\n'	mov	lr, r2	b	ser_printcdebug_totalsize:	mov	r2, lr	adr	r0, totalsize	bl	ser_prints	mov	r0, r4	bl	ser_printhex	mov	r0, #'\n'	mov	lr, r2	b	ser_printcdebug_testres:	mrs	r2, cpsr		@ Save CPSR	msr	spsr, r2	mov	r2, lr	mov	r3, r0	mov	r6, r10	mov	r7, r11	adr	r0, testres1	bl	ser_prints	mov	r0, r3	bl	ser_printhex	adr	r0, testres2	bl	ser_prints	mov	r0, r1	bl	ser_printhex	adr	r0, testres3	bl	ser_prints	mov	r0, r6	bl	ser_printhex	adr	r0, testres4	bl	ser_prints	mov	r0, r7	bl	ser_printhex	mov	r0, #'\n'	bl	ser_printc	movs	pc, r2			@ restore CPSRbankmsg:	.asciz	"Bank address   : 0x"result:	.asciz	"  Detect result: 0x"size:	.asciz	"  Bank size reg: 0x"totalsize:	.asciz	"Total RAM size : 0x"testres1:	.asciz	"    Test result: 0x"testres2:	.asciz	" : 0x"testres3:	.asciz	", wrote 0x"testres4:	.asciz	", read 0x"	.align#endifser_init:	mov	r0, #0x42000000	orr	r0, r0, #0x160	mov	r1, #0	str	r1, [r0, #20]	mov	r2, #161:	str	r1, [r0, #0]		@ write data	ldr	r3, [r0, #0]		@ read data	ldr	r3, [r0, #4]		@ read status	subs	r2, r2, #1	bne	1b	mov	r1, #1	str	r1, [r0, #20]	mov	r1, #BAUD_RATE_DIVISOR	str	r1, [r0, #16]	mov	r1, #0	str	r1, [r0, #12]	mov	r1, #3 << 5	str	r1, [r0, #8]	mov	r2, #161:	ldr	r1, [r0, #4]	subs	r2, r2, #1	bne	1b	mov	pc, lrser_prints:	mov	r11, #0x42000000	orr	r11, r11, #0x1601:	ldrb	r10, [r0], #1	teq	r10, #0	moveq	pc, lr2:	str	r10, [r11]3:	ldr	r9, [r11, #24]	tst	r9, #1 << 5	bne	3b	teq	r10, #'\n'	moveq	r10, #'\r'	beq	2b	b	1bser_printc:	mov	r11, #0x42000000	orr	r11, r11, #0x1601:	str	r0, [r11]2:	ldr	r9, [r11, #24]	tst	r9, #1 << 5	bne	2b	teq	r0, #'\n'	moveq	r0, #'\r'	beq	1b	mov	pc, lrser_printhexbyte:	mov	r11, #0x42000000	orr	r11, r11, #0x160	mov	r9, #2	mov	r0, r0, lsl #24	b	1fser_printhex:	mov	r11, #0x42000000	orr	r11, r11, #0x160	mov	r9, #81:	and	r10, r0, #0xf0000000	mov	r10, r10, lsr #28	cmp	r10, #10	adccs	r10, r10, #6	add	r10, r10, #'0'	str	r10, [r11]2:	ldr	r10, [r11, #24]	tst	r10, #1 << 3	bne	2b	mov	r0, r0, lsl #4	subs	r9, r9, #1	bne	1b	mov	pc, lr/* * void ser_write(const char *buffer, int nr) */ENTRY(ser_write)	stmfd	sp!, {r9 - r11, lr}	bl	ser_prints	ldmfd	sp!, {r9 - r11, pc}ENTRY(ser_stat)	mov	r3, #0x42000000	ldr	r0, [r3, #0x160 + 24]	and	r0, r0, #1 << 4	mov	pc, lr/* * extern struct timer { *  unsigned int to; *  unsigned int status; *  void (*fn)(int); * } timers[]; *//* * int ser_read(char *buffer, int nr) */ENTRY(ser_read)	mov	ip, r0	mov	r3, #0x42000000	orr	r3, r3, #0x160		@ base address of UART1:	ldr	r2, [r3, #24]		@ check status	tst	r2, #1 << 4	beq	2f	ldr	r2, =SYMBOL_NAME(timers) @ check timer	ldr	r2, [r2, #4]	teq	r2, #0	bne	3f	b	1b2:	ldr	r2, [r3, #0]		@ read character	strb	r2, [r0], #1	ldr	r2, [r3, #4]		@ read status	subs	r1, r1, #1	bne	1b	sub	r0, r0, ip	mov	pc, lr3:	mov	r0, #0			@ timed out	mov	pc, lr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -