
/******************************************************
crt.s
Este modulo em assembly tem os vetores de interrupcao
e os procedimentos de inicializacao
***************************************************** */
/* Tamanhos das pilhas */
.set  UND_STACK_SIZE, 0x00000004	/* 4 bytes para Undefined Instruction */
.set  ABT_STACK_SIZE, 0x00000004	/* 4 bytes para "abort"	*/
.set  FIQ_STACK_SIZE, 0x00000040	/* 64 bytes de pilha para "FIQ" */
.set  IRQ_STACK_SIZE, 0X00000040	/* 64 bytes de pilha para "IRQ" */
.set  SVC_STACK_SIZE, 0x00000040	/* 64 bytes de pilha no modo supervisor	*/

/* Padroes de bits de Modo e Interrupcao (I & F) nos CPSRs
 (program status registers) */
.set  MODE_USR,	0x10	/* Normal User Mode				*/
.set  MODE_FIQ,	0x11	/* FIQ Processing Fast Interrupts Mode		*/
.set  MODE_IRQ,	0x12	/* IRQ Processing Standard Interrupts Mode	*/
.set  MODE_SVC,	0x13	/* Supervisor Processing Software Interrupts Mode */
.set  MODE_ABT,	0x17	/* Abort Processing memory Faults Mode	*/
.set  MODE_UND,	0x1B	/* Undefined Processing	Undefined Instructions Mode	*/
.set  MODE_SYS,	0x1F	/* System Running Priviledged Operating	System Tasks  Mode	*/

.set  I_BIT, 0x80	/* Bit que habilita IRQ no CPSR */
.set  F_BIT, 0x40	/* Bit que habilita FIQ no CPSR */
.set  SORP, 0x40000200

.text
.arm

.global	Reset_Handler
.global	_startup
.func	_startup

_startup:

# Exception Vectors

_vectors:	ldr	PC, Reset_Addr
		ldr	PC, Undef_Addr
		ldr	PC, SWI_Addr
		ldr	PC, PAbt_Addr
		ldr	PC, DAbt_Addr
		nop	/* Reservado para a soma (checksum) dos vetores	*/
		ldr	PC, [PC,#-0x0120]	
/* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor	Martin	*/
		ldr	PC, FIQ_Addr

Reset_Addr:	.word	Reset_Handler	/* definido neste modulo */
Undef_Addr:	.word	UNDEF_Routine	/* definido no main.c  */
SWI_Addr:	.word	SWI_Routine	/* definido no main.c  */
PAbt_Addr:	.word	UNDEF_Routine	/* definido no main.c  */
DAbt_Addr:	.word	UNDEF_Routine	/* definido no main.c  */
FIQ_Addr:	.word	FIQ_Routine	/* definido no main.c  */
		.word	0	/* Arredonda para um total de 16 vetores  */

Reset_Handler:
/* MEMMAP = 1 Vetores na Flash a partir de 0x00000000		*/
/* MEMMAP = 2 Vetores remapeados para a RAM em 0x40000000	*/
		mov	r0, #1		/*Vetores na Flash */
		ldr	r1, = 0xE01FC040	/* MEMMAP	*/
		str	r0, [r1]

/* Configura a pilha para cada modo de operacao. */
		ldr	r0, =_stack_end
		msr	CPSR_c,	#MODE_UND|I_BIT|F_BIT	/* Undefined Instruction Mode  */
		mov	sp, r0
		sub	r0, r0,	#UND_STACK_SIZE
		msr	CPSR_c,	#MODE_ABT|I_BIT|F_BIT	/* Abort Mode */
		mov	sp, r0
		sub	r0, r0,	#ABT_STACK_SIZE
		msr	CPSR_c,	#MODE_FIQ|I_BIT|F_BIT	/* FIQ Mode */
		mov	sp, r0	
		sub	r0, r0,	#FIQ_STACK_SIZE
		msr	CPSR_c,	#MODE_IRQ|I_BIT|F_BIT	/* IRQ Mode */
		mov	sp, r0
		sub	r0, r0,	#IRQ_STACK_SIZE
		msr	CPSR_c,	#MODE_SVC|I_BIT|F_BIT	/* Supervisor Mode */
		mov	sp, r0
		sub	r0, r0,	#SVC_STACK_SIZE
		msr	CPSR_c,	#MODE_SYS|I_BIT|F_BIT	/* User	Mode */
		mov	sp, r0
/* copy .kex section (Copy from ROM to RAM) */
		ldr	R1, =_etext
		ldr	R2, =_kex
		ldr	R3, =_ekex
7:		cmp	R2, R3
		ldrlo	R0, [R1], #4
		strlo	R0, [R2], #4
		blo	7b

/* copy .data section (Copy from ROM to RAM) */
		ldr	R1, =_ekex
		ldr	R2, =_data
		ldr	R3, =_edata
1:		cmp	R2, R3
		ldrlo	R0, [R1], #4
		strlo	R0, [R2], #4
		blo	1b

/* Clear .bss section (Zero init)  */
		mov	R0, #0
		ldr	R1, =_bss_start
		ldr	R2, =_bss_end
2:		cmp	R1, R2
		strlo	R0, [R1], #4
		blo	2b

/******** Configura clock (Acrescentado por Marcos Stemmer)*/
		ldr	r3, = 0xE01FC100
		mov	r2, #0x21	/* Liga clock 12M */
		str	r2, [r3, #0xa0]	/* SCS = 0x21	GPIO em modo Fast */
Lp2:
		ldr	r2, [r3, #0xa0]	/* Espera estabilizar		*/
		tst	r2, #0x40	/* while(SCS & 0x40);		*/
		beq	Lp2
		mov	r2, #1		/* Usa clock 12M para a CPU	*/
		str	r2, [r3, #0x0c]	/* CLKSRCSEL = 1;		*/
		mov	r2, #0		/* Divisor por 1 na CPU 	*/
		str	r2, [r3, #0x04]	/* CCLKCFG=0;			*/
/* Divisor por 1 nos perifericos */
		ldr	r2, = 0x55555555
		str	r2, [r3, #0xA8]	/* PCLKSEL0 = 0x55555555;	*/
		str	r2, [r3, #0xAC] /* PCLKSEL1 = 0x55555555;	*/
/* Configura o MAM */
		mov	r2, #0		/*Deve fazer PINSEL10=0 para que */
		ldr	r3, = 0xE002C028	/* GPIO da P0 e P2 funcionem */
		str	r2, [r3, #0]
		ldr	r3, = 0xE01FC000
		str	r2, [r3, #0]	/* MAMCR=0 */
		mov	r2, #3
		str	r2, [r3, #4]	/* MAMTIM=3 */
		mov	r2, #2
		str	r2, [r3, #0]	/* MAMCR=2 */
/****** Fim da configuracao do clock *******/

/* Entra na funcao main() do programa em C  */

		mov	r0, #0          /* argc = 0  */
		mov	r1, #0          /* argv = NULL */
		ldr	r14, = Reset_Handler	/* Se retornar vai para Reset_Handler */
		ldr	pc, = main
.endfunc
.end
