/* ex4_start.s */

	.global main
	.global _start
	
	/* Symbols defined by the linker script */
	.global _etext
	.global _data
	.global _edata
	.global __bss_start__
	.global __bss_end__

	.text
	.arm
_start:
	/* Vectors (8 total)  */
	b reset   /* reset */
	b loop   /* undefined instruction  */
	b loop   /* software interrupt */
	b loop   /* prefetch abort */
	b loop   /* data abort */
	nop      /* reserved for the bootloader checksum */
	ldr pc, [pc, #-0x0FF0] /* VicVectAddr */


/* Setup C runtime:
 - copy .data section to SRAM
 - clear .bss
 - setup stack pointer
 - jump to main
*/


reset:
/* ----------------------------------------------------------------
 * LPC21xx PLL setup
 * ----------------------------------------------------------------
 */
reset:
    /* Use r0 for indirect addressing */
    ldr	r0, PLLBASE

    /* PLLCFG = PLLCFG_VALUE */
    mov	r3, #PLLCFG_VALUE
    str r3, [r0, #PLLCFG_OFFSET]

    /* PLLCON = PLLCON_PLLE */
    mov	r3, #PLLCON_PLLE
    str r3, [r0, #PLLCON_OFFSET]

    /* PLLFEED = PLLFEED1, PLLFEED2 */
    mov	r1, #PLLFEED1
    mov	r2, #PLLFEED2
    str r1, [r0, #PLLFEED_OFFSET]
    str r2, [r0, #PLLFEED_OFFSET]

    /* 	while ((PLLSTAT & PLLSTAT_PLOCK) == 0); */
	

pll_loop:
    ldr r3, [r0, #PLLSTAT_OFFSET]
    tst	r3, #PLLSTAT_PLOCK
    beq	pll_loop

    /* PLLCON = PLLCON_PLLC|PLLCON_PLLE */
    mov	r3, #PLLCON_PLLC|PLLCON_PLLE
    str r3, [r0, #PLLCON_OFFSET]

    /* PLLFEED = PLLFEED1, PLLFEED2 */
    str r1, [r0, #PLLFEED_OFFSET]
    str r2, [r0, #PLLFEED_OFFSET]
	
stacks_init:
	ldr r0, STACK_START
	/* FIQ mode stack */
	msr CPSR_c, #FIQ_MODE|IRQ_DISABLE|FIQ_DISABLE
	mov sp,r0
	sub r0,r0,#FIQ_STACK_SIZE
	/* IRQ mode stack */
	msr CPSR_c, #IRQ_MODE|IRQ_DISABLE|FIQ_DISABLE
	mov sp, r0
	sub r0, r0, #IRQ_STACK_SIZE
	msr CPSR_c, #SYS_MODE
	mov sp,r0
	
/* copiar valores iniciales de variables 	*/
	ldr r0, data_source
	ldr r1, data_start
	ldr r2, data_end
copy_data:
	cmp   r1, r2
	ldrne r3, [r0], #4
	strne r3, [r1], #4
	bne   copy_data
	
	/* Clear .bss */
	ldr r0, =0
	ldr r1, bss_start
	ldr r2, bss_end
/* inicializar con 0 variables sin valor inicial */
clear_bss:
	cmp   r1, r2
	strne r0, [r1], #4
	bne   clear_bss
	
seguir:	
	/* Stack pointer */
#	ldr sp, stack_addr
	bl  main

/* Catch return from main */

loop:   b   loop

/* Constants 

	LPC SRAM starts at 0x40000000, and there is 16Kb = 4000h */
stack_addr:		.word   0x40004000

PLLBASE:        .word   0xE01FC080
MAMBASE:        .word   0xE01FC000
STACK_START:		.word	0x40004000

/* LED control registers  */
IOSET0:			.word 	0xE0028004
IODIR0:			.word	0xE0028008
IOCLR0:			.word	0xE002800C
IODIR0_VALUE:	.word	0x00000020
IOSET0_VALUE:	.word	0x00000020
IOCLR0_VALUE:	.word	0x00000020
/* Linker symbols */
data_source:    .word   _etext
data_start:     .word   _data
data_end:       .word   _edata
bss_start:      .word   __bss_start__
bss_end:        .word   __bss_end__

/* IRQ configuration */
VICVECTADDR0:	.word	0xFFFFF100
VICVECTADDR1:	.word	0xFFFFF104
VICVECTADDR2:	.word	0xFFFFF108
VICVECTADDR3:	.word	0xFFFFF10C
VICVECTADDR4:	.word	0xFFFFF110


/* ----------------------------------------------------------------
 * 8-bit constants
 * ----------------------------------------------------------------
 *
 * These 8-bit constants are used as immediate values and offsets.
 */

/* PLL configuration */
    .equ PLLCON_OFFSET,   0x0
    .equ PLLCFG_OFFSET,   0x4
    .equ PLLSTAT_OFFSET,  0x8
    .equ PLLFEED_OFFSET,  0xC

    .equ PLLCON_PLLE,    (1 << 0)
    .equ PLLCON_PLLC,    (1 << 1)
    .equ PLLSTAT_PLOCK,  (1 << 10)
    .equ PLLFEED1,        0xAA
    .equ PLLFEED2,        0x55

    .equ PLLCFG_VALUE,    0x23

/* MAM configuration */
    .equ MAMCR_OFFSET,   0x0
    .equ MAMTIM_OFFSET,  0x4

    .equ MAMCR_VALUE,    0x2  /* fully enabled */
    .equ MAMTIM_VALUE,   0x4  /* fetch cycles  */
	
/* stack configuration */
	.equ FIQ_MODE,	0x11
	.equ FIQ_STACK_SIZE, 0x8
	.equ FIQ_DISABLE, (1 << 6)
	.equ IRQ_DISABLE, (1 << 7)
	.equ IRQ_STACK_SIZE, 0x100
	.equ IRQ_MODE, 0x12
	.equ SYS_MODE, 0x1F

	.end
