283 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2006-2018, RT-Thread Development Team
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  *
 | |
|  * Change Logs:
 | |
|  * Date           Author       Notes
 | |
|  * 2008-12-11     XuXinming    first version
 | |
|  * 2011-03-17     Bernard      update to 0.4.x
 | |
|  */
 | |
| 
 | |
| #define WDMOD          (0xE0000000 + 0x00)
 | |
| #define VICIntEnClr    (0xFFFFF000 + 0x014)
 | |
| #define VICVectAddr    (0xFFFFF000 + 0xF00)
 | |
| #define VICIntSelect   (0xFFFFF000 + 0x00C)
 | |
| #define PLLCFG         (0xE01FC000 + 0x084)
 | |
| #define PLLCON         (0xE01FC000 + 0x080)
 | |
| #define PLLFEED        (0xE01FC000 + 0x08C)
 | |
| #define PLLSTAT        (0xE01FC000 + 0x088)
 | |
| #define CCLKCFG        (0xE01FC000 + 0x104)
 | |
| #define MEMMAP         (0xE01FC000 + 0x040)     
 | |
| #define SCS            (0xE01FC000 + 0x1A0)     
 | |
| #define CLKSRCSEL      (0xE01FC000 + 0x10C)
 | |
| #define MAMCR          (0xE01FC000 + 0x000)
 | |
| #define MAMTIM         (0xE01FC000 + 0x004)
 | |
| 
 | |
| /* stack memory */
 | |
| .section .bss.noinit
 | |
| .equ    IRQ_STACK_SIZE, 0x00000200
 | |
| .equ    FIQ_STACK_SIZE, 0x00000100
 | |
| .equ    UDF_STACK_SIZE, 0x00000004
 | |
| .equ    ABT_STACK_SIZE, 0x00000004
 | |
| .equ    SVC_STACK_SIZE, 0x00000200
 | |
| 
 | |
| .space  IRQ_STACK_SIZE
 | |
| IRQ_STACK:
 | |
| 
 | |
| .space  FIQ_STACK_SIZE
 | |
| FIQ_STACK:
 | |
| 
 | |
| .space  UDF_STACK_SIZE
 | |
| UDF_STACK:
 | |
| 
 | |
| .space  ABT_STACK_SIZE
 | |
| ABT_STACK:
 | |
| 
 | |
| .space  SVC_STACK_SIZE
 | |
| SVC_STACK:
 | |
| 
 | |
| .section .init, "ax"
 | |
| .code 32
 | |
| .globl _start
 | |
| _start:
 | |
|         b reset
 | |
|         ldr     pc, _vector_undef
 | |
|         ldr     pc, _vector_swi
 | |
|         ldr     pc, _vector_pabt
 | |
|         ldr     pc, _vector_dabt
 | |
|         ldr     pc, _vector_resv
 | |
|         ldr     pc, _vector_irq
 | |
|         ldr     pc, _vector_fiq
 | |
| 
 | |
| _vector_undef:  .word vector_undef
 | |
| _vector_swi:    .word vector_swi
 | |
| _vector_pabt:   .word vector_pabt
 | |
| _vector_dabt:   .word vector_dabt
 | |
| _vector_resv:   .word vector_resv
 | |
| _vector_irq:    .word vector_irq
 | |
| _vector_fiq:    .word vector_fiq
 | |
| 
 | |
| .balignl        16,0xdeadbeef
 | |
| 
 | |
| /*
 | |
|  * rtthread kernel start and end
 | |
|  * which are defined in linker script
 | |
|  */
 | |
| .globl _rtthread_start
 | |
| _rtthread_start:
 | |
|         .word _start
 | |
|         
 | |
| .globl _rtthread_end
 | |
| _rtthread_end:
 | |
|         .word  _end
 | |
| 
 | |
| /*
 | |
|  * rtthread bss start and end which are defined in linker script
 | |
|  */
 | |
| .globl _bss_start
 | |
| _bss_start:     
 | |
|         .word __bss_start
 | |
|         
 | |
| .globl _bss_end
 | |
| _bss_end:
 | |
|         .word __bss_end
 | |
| 
 | |
| .text
 | |
| .code 32
 | |
| 
 | |
| /* the system entry */
 | |
| reset:
 | |
|         /* enter svc mode */
 | |
|         msr cpsr_c, #SVCMODE|NOINT
 | |
|         
 | |
|         /*watch dog disable */
 | |
|         ldr r0,=WDMOD
 | |
|         ldr r1,=0x0             
 | |
|         str r1,[r0]
 | |
|         
 | |
|         /* all interrupt disable */
 | |
|         ldr r0,=VICIntEnClr
 | |
|         ldr r1,=0xffffffff
 | |
|         str r1,[r0]
 | |
|         
 | |
|         ldr     r1, =VICVectAddr
 | |
|         ldr     r0, =0x00
 | |
|         str     r0, [r1]
 | |
|         
 | |
|         ldr     r1, =VICIntSelect
 | |
|         ldr     r0, =0x00
 | |
|         str     r0, [r1]        
 | |
|         
 | |
|         /* setup stack */
 | |
|         bl              stack_setup
 | |
| 
 | |
|         /* copy .data to SRAM */
 | |
|         ldr     r1, =_sidata            /* .data start in image */
 | |
|         ldr     r2, =_edata             /* .data end in image   */
 | |
|         ldr     r3, =_sdata             /* sram data start      */
 | |
| data_loop:
 | |
|         ldr     r0, [r1, #0]
 | |
|         str     r0, [r3]
 | |
| 
 | |
|         add     r1, r1, #4
 | |
|         add     r3, r3, #4
 | |
| 
 | |
|         cmp     r3, r2                   /* check if data to clear */
 | |
|         blo     data_loop                /* loop until done        */
 | |
| 
 | |
|         /* clear .bss */
 | |
|         mov     r0,#0                   /* get a zero */
 | |
|         ldr     r1,=__bss_start         /* bss start  */
 | |
|         ldr     r2,=__bss_end           /* bss end    */
 | |
|         
 | |
| bss_loop:
 | |
|         cmp     r1,r2                   /* check if data to clear */
 | |
|         strlo   r0,[r1],#4              /* clear 4 bytes          */
 | |
|         blo     bss_loop                /* loop until done        */
 | |
| 
 | |
|         /* call C++ constructors of global objects */
 | |
|         ldr     r0, =__ctors_start__
 | |
|         ldr     r1, =__ctors_end__
 | |
| 
 | |
| ctor_loop:
 | |
|         cmp     r0, r1
 | |
|         beq     ctor_end
 | |
|         ldr     r2, [r0], #4
 | |
|         stmfd   sp!, {r0-r1}
 | |
|         mov     lr, pc
 | |
|         bx      r2
 | |
|         ldmfd   sp!, {r0-r1}
 | |
|         b       ctor_loop       
 | |
| ctor_end:
 | |
| 
 | |
|         /* start RT-Thread Kernel               */
 | |
|         ldr     pc, _rtthread_startup
 | |
| 
 | |
| _rtthread_startup: 
 | |
|         .word rtthread_startup
 | |
| 
 | |
|         .equ USERMODE,  0x10
 | |
|         .equ FIQMODE,   0x11
 | |
|         .equ IRQMODE,   0x12
 | |
|         .equ SVCMODE,   0x13
 | |
|         .equ ABORTMODE, 0x17
 | |
|         .equ UNDEFMODE, 0x1b
 | |
|         .equ MODEMASK,  0x1f
 | |
|         .equ NOINT,             0xc0
 | |
| 
 | |
| /* exception handlers */
 | |
| vector_undef:   bl rt_hw_trap_udef
 | |
| vector_swi:     bl rt_hw_trap_swi
 | |
| vector_pabt:    bl rt_hw_trap_pabt
 | |
| vector_dabt:    bl rt_hw_trap_dabt
 | |
| vector_resv:    bl rt_hw_trap_resv
 | |
| 
 | |
| .globl rt_interrupt_enter
 | |
| .globl rt_interrupt_leave
 | |
| .globl rt_thread_switch_interrupt_flag
 | |
| .globl rt_interrupt_from_thread
 | |
| .globl rt_interrupt_to_thread
 | |
| vector_irq:     
 | |
|         stmfd   sp!, {r0-r12,lr}
 | |
|         bl      rt_interrupt_enter
 | |
|         bl      rt_hw_trap_irq
 | |
|         bl      rt_interrupt_leave
 | |
| 
 | |
|         /* if rt_thread_switch_interrupt_flag set,
 | |
|          * jump to _interrupt_thread_switch and don't return
 | |
|          */
 | |
|         ldr     r0, =rt_thread_switch_interrupt_flag
 | |
|         ldr     r1, [r0]
 | |
|         cmp     r1, #1
 | |
|         beq     _interrupt_thread_switch
 | |
| 
 | |
|         ldmfd   sp!, {r0-r12,lr}
 | |
|         subs    pc, lr, #4
 | |
| 
 | |
|         .align  5
 | |
| vector_fiq:
 | |
|         stmfd   sp!,{r0-r7,lr}
 | |
|         bl      rt_hw_trap_fiq
 | |
|         ldmfd   sp!,{r0-r7,lr}
 | |
|         subs    pc,lr,#4
 | |
| 
 | |
| _interrupt_thread_switch:
 | |
|         mov     r1, #0          /* clear rt_thread_switch_interrupt_flag */
 | |
|         str     r1, [r0]
 | |
| 
 | |
|         ldmfd   sp!, {r0-r12,lr} /* reload saved registers */
 | |
|         stmfd   sp!, {r0-r3}    /* save r0-r3 */
 | |
|         mov     r1, sp
 | |
|         add     sp, sp, #16     /*  restore sp */
 | |
|         sub     r2, lr, #4      /* save old task's pc to r2 */
 | |
| 
 | |
|         mrs     r3, spsr        /* disable interrupt */
 | |
|         orr     r0, r3, #NOINT
 | |
|         msr     spsr_c, r0
 | |
| 
 | |
|         ldr     r0,  =.+8       /* switch to interrupted task's stack */
 | |
|         movs    pc, r0
 | |
| 
 | |
|         stmfd   sp!, {r2}       /* push old task's pc */
 | |
|         stmfd   sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */
 | |
|         mov     r4, r1          /* Special optimised code below */
 | |
|         mov     r5, r3
 | |
|         ldmfd   r4!, {r0-r3}
 | |
|         stmfd   sp!, {r0-r3}    /* push old task's r3-r0 */
 | |
|         stmfd   sp!, {r5}       /* push old task's psr */
 | |
|         mrs     r4, spsr
 | |
|         stmfd   sp!, {r4}       /* push old task's spsr */
 | |
| 
 | |
|         ldr     r4, =rt_interrupt_from_thread
 | |
|         ldr     r5, [r4]
 | |
|         str     sp, [r5]        /* store sp in preempted tasks's TCB */
 | |
| 
 | |
|         ldr     r6, =rt_interrupt_to_thread
 | |
|         ldr     r6, [r6]
 | |
|         ldr     sp, [r6]        /* get new task's stack pointer */
 | |
| 
 | |
|         ldmfd   sp!, {r4}       /* pop new task's spsr */
 | |
|         msr     SPSR_cxsf, r4
 | |
|         ldmfd   sp!, {r4}       /* pop new task's psr */
 | |
|         msr     CPSR_cxsf, r4
 | |
| 
 | |
|         ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
 | |
| 
 | |
| stack_setup:
 | |
|         mrs     r0, cpsr
 | |
|         bic     r0, r0, #MODEMASK
 | |
|         orr     r1, r0, #UNDEFMODE|NOINT
 | |
|         msr     cpsr_cxsf, r1                   /* undef mode */
 | |
|         ldr     sp, =UDF_STACK
 | |
| 
 | |
|         orr     r1,r0,#ABORTMODE|NOINT
 | |
|         msr     cpsr_cxsf,r1                    /* abort mode */
 | |
|         ldr     sp, =ABT_STACK
 | |
| 
 | |
|         orr     r1,r0,#IRQMODE|NOINT
 | |
|         msr     cpsr_cxsf,r1                    /* IRQ mode */
 | |
|         ldr     sp, =IRQ_STACK
 | |
| 
 | |
|         orr     r1,r0,#FIQMODE|NOINT
 | |
|         msr     cpsr_cxsf,r1                    /* FIQ mode */
 | |
|         ldr     sp, =FIQ_STACK
 | |
| 
 | |
|         bic     r0,r0,#MODEMASK
 | |
|         orr     r1,r0,#SVCMODE|NOINT
 | |
|         msr     cpsr_cxsf,r1                    /* SVC mode */
 | |
|         ldr     sp, =SVC_STACK
 | |
| 
 | |
|         /* USER mode is not initialized. */
 | |
|         mov     pc,lr                           /* The LR register may be not valid for the mode changes.*/
 |