/* Sample initialization file */ .extern main .extern exit .extern AT91F_LowLevelInit .extern pio_irq_isr_value .text .code 32 .align 0 .extern __stack_end__ .extern __bss_beg__ .extern __bss_end__ .extern __data_beg__ .extern __data_end__ .extern __data+beg_src__ .global start .global endless_loop /* Stack Sizes */ .set UND_STACK_SIZE, 0x00000004 .set ABT_STACK_SIZE, 0x00000004 .set FIQ_STACK_SIZE, 0x00000400 .set IRQ_STACK_SIZE, 0X00000400 .set SVC_STACK_SIZE, 0x00000400 /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */ .set MODE_USR, 0x10 /* User Mode */ .set MODE_FIQ, 0x11 /* FIQ Mode */ .set MODE_IRQ, 0x12 /* IRQ Mode */ .set MODE_SVC, 0x13 /* Supervisor Mode */ .set MODE_ABT, 0x17 /* Abort Mode */ .set MODE_UND, 0x1B /* Undefined Mode */ .set MODE_SYS, 0x1F /* System Mode */ .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */ .equ AT91C_BASE_AIC, (0xFFFFF000) .equ AT91C_BASE_MC, (0xFFFFFF00) .equ AT91C_BASE_PIOA, 0xFFFFF400 .equ AT91C_BASE_TC0, 0xFFFA0000 .equ AT91C_BASE_SSC, 0xFFFD4000 .equ SSC_RCMR, 0x10 .equ AT91C_TC_SWTRG, (1 << 2) .equ AT91C_TC_CLKEN, (1 << 0) .equ PIO_DATA, (1 << 27) .equ PIOA_SODR, 0x30 .equ PIOA_CODR, 0x34 .equ PIOA_PDSR, 0x3c .equ PIOA_IDR, 0x44 .equ PIOA_ISR, 0x4c .equ TC_CCR, 0x00 .equ AIC_EOICR, (304) .equ PIO_LED1, (1 << 25) .equ PIO_LED2, (1 << 12) .equ MC_RCR, 0xFFFFFF00 .equ AIC_ISCR, (0x12C) .equ PIO_SECONDARY_IRQ, 31 .equ PIO_SECONDARY_IRQ_BIT, (1 << PIO_SECONDARY_IRQ) /* FIQ latency is approx 1us. At 13.56 MHz carrier frequency this means that * 13.56 cycles of the carrier have passed when the FIQ kicks in and this is * the amount that CV0 should be loaded to. (Round up) */ .equ TC0_FRAME_OFFSET, 9 start: _start: _mainCRTStartup: /* Setup a stack for each mode - note that this only sets up a usable stack for system/user, SWI and IRQ modes. Also each mode is setup with interrupts initially disabled. */ ldr r0, .LC6 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 */ /* Preload registers for FIQ handler */ ldr r10, =AT91C_BASE_PIOA ldr r12, =AT91C_BASE_TC0 ldr r8, =AT91C_BASE_AIC mov r9, #AT91C_TC_SWTRG /*ldr r9, =AT91C_BASE_SSC*/ 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 /* System Mode */ mov sp, r0 /* We want to start in supervisor mode. Operation will switch to system mode when the first task starts. */ msr CPSR_c, #MODE_SVC|I_BIT|F_BIT bl AT91F_LowLevelInit /* Clear BSS. */ mov a2, #0 /* Fill value */ mov fp, a2 /* Null frame pointer */ mov r7, a2 /* Null frame pointer for Thumb */ ldr r1, .LC1 /* Start of memory block */ ldr r3, .LC2 /* End of memory block */ subs r3, r3, r1 /* Length of block */ beq .end_clear_loop mov r2, #0 .clear_loop: strb r2, [r1], #1 subs r3, r3, #1 bgt .clear_loop .end_clear_loop: /* Initialise data. */ ldr r1, .LC3 /* Start of memory block */ ldr r2, .LC4 /* End of memory block */ ldr r3, .LC5 subs r3, r3, r1 /* Length of block */ beq .end_set_loop .set_loop: ldrb r4, [r2], #1 strb r4, [r1], #1 subs r3, r3, #1 bgt .set_loop .end_set_loop: /* call main */ mov r0, #0 /* no arguments */ mov r1, #0 /* no argv either */ ldr lr, =main bx lr endless_loop: b endless_loop .align 0 .LC1: .word __bss_beg__ .LC2: .word __bss_end__ .LC3: .word __data_beg__ .LC4: .word __data_beg_src__ .LC5: .word __data_end__ .LC6: .word __stack_end__ /* Setup vector table. Note that undf, pabt, dabt, fiq just execute a null loop. */ .section .startup,"ax" .code 32 .align 0 b _start /* reset - _start */ ldr pc, _undf /* undefined - _undf */ ldr pc, _swi /* SWI - _swi */ ldr pc, _pabt /* program abort - _pabt */ ldr pc, _dabt /* data abort - _dabt */ nop /* reserved */ ldr pc, [pc,#-0xF20] /* IRQ - read the AIC */ /* ldr pc, [pc,#-0xF20] /* FIQ - fall through to fiq_handler */ /* Following is modified from openpcd/firmware/src/start/Cstartup_app.S */ #define LED_TRIGGER .global fiq_handler .func fiq_handler my_fiq_handler: /* code that uses pre-initialized FIQ reg */ /* r8 tmp r9 AT91C_TC_SWTRG r10 AT91C_BASE_PIOA r11 tmp r12 AT91C_BASE_TC0 r13 stack r14 lr */ #ifdef LED_TRIGGER mov r11, #PIO_LED1 str r11, [r10, #PIOA_CODR] /* enable LED */ #endif ldr r8, [r10, #PIOA_ISR] /* Store the retrieved PIO ISR value into pio_irq_isr_value */ ldr r11, =pio_irq_isr_value str r8, [r11] tst r8, #PIO_DATA /* check for PIO_DATA change */ ldrne r11, [r10, #PIOA_PDSR] tstne r11, #PIO_DATA /* check for PIO_DATA == 1 */ strne r9, [r12, #TC_CCR] /* software trigger */ movne r11, #PIO_DATA strne r11, [r10, #PIOA_IDR] /* disable further PIO_DATA FIQ */ /* Trigger PIO_SECONDARY_IRQ */ mov r11, #PIO_SECONDARY_IRQ_BIT ldr r8, =AT91C_BASE_AIC str r11, [r8, #AIC_ISCR] #ifdef LED_TRIGGER mov r11, #PIO_LED1 str r11, [r10, #PIOA_SODR] /* disable LED */ #endif /*- Mark the End of Interrupt on the AIC */ ldr r11, =AT91C_BASE_AIC str r11, [r11, #AIC_EOICR] /*- Restore the Program Counter using the LR_fiq directly in the PC */ subs pc, lr, #4 .size my_fiq_handler, . - my_fiq_handler .endfunc _undf: .word __undf /* undefined */ _swi: .word swi_handler /* SWI */ _pabt: .word __pabt /* program abort */ _dabt: .word __dabt /* data abort */ _fiq: .word __fiq /* FIQ */ __undf: b . /* undefined */ __pabt: b . /* program abort */ __dabt: b . /* data abort */ __fiq: b . /* FIQ */ .end