1/*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2006-09-06     XuXinming    first version
9 * 2006-09-20     Bernard      clean the code
10 */
11
12/**
13 * @addtogroup S3C44B0
14 */
15/*@{*/
16
17.section .init, "ax"
18.code 32
19.globl _start
20_start:
21    b reset
22    ldr pc, _vector_undef
23    ldr pc, _vector_swi
24    ldr pc, _vector_pabt
25    ldr pc, _vector_dabt
26    ldr pc, _vector_resv
27    ldr pc, _vector_irq
28    ldr pc, _vector_fiq
29
30_vector_undef:  .word vector_undef
31_vector_swi:    .word vector_swi
32_vector_pabt:   .word vector_pabt
33_vector_dabt:   .word vector_dabt
34_vector_resv:   .word vector_resv
35_vector_irq:    .word vector_irq
36_vector_fiq:    .word vector_fiq
37
38.text
39.code 32
40
41/*
42 * rtthread kernel start and end
43 * which are defined in linker script
44 */
45.globl _rtthread_start
46_rtthread_start:.word _start
47.globl _rtthread_end
48_rtthread_end:  .word  _end
49
50/*
51 * rtthread bss start and end
52 * which are defined in linker script
53 */
54.globl _bss_start
55_bss_start: .word __bss_start
56.globl _bss_end
57_bss_end:   .word __bss_end
58
59#if defined(__FLASH_BUILD__)
60/*
61 * TEXT_BASE,
62 * which is defined in macro of make
63 */
64_TEXT_BASE: .word   TEXT_BASE
65#endif
66
67    .equ WTCON,     0x1d30000
68    .equ INTCON,    0x1e00000
69    .equ INTMSK,    0x1e0000c
70
71/* the system entry */
72reset:
73    /* enter svc mode */
74    msr cpsr_c, #SVCMODE|NOINT
75
76    /*watch dog disable */
77    ldr r0,=WTCON
78    ldr r1,=0x0
79    str r1,[r0]
80
81    /* all interrupt disable */
82    ldr r0,=INTMSK
83    ldr r1,=0x07ffffff
84    str r1,[r0]
85
86    ldr r1, =INTCON
87    ldr r0, =0x05
88    str r0, [r1]
89
90#if defined(__FLASH_BUILD__)
91    /* init lowlevel */
92    bl lowlevel_init
93#endif
94
95    /* setup stack */
96    bl stack_setup
97
98#if defined(__FLASH_BUILD__)
99    mov r0, #0x0            /* r0 <- flash base address         */
100    ldr r1, _TEXT_BASE      /* r1 <- the taget address          */
101
102    ldr r2, _rtthread_start
103    ldr r3, _bss_start
104    sub r2, r3, r2          /* r2 <- size of rtthread kernel    */
105    add r2, r0, r2          /* r2 <- source end address         */
106
107copy_loop:
108    ldmia   r0!, {r3-r10}   /* copy from source address [r0]    */
109    stmia   r1!, {r3-r10}   /* copy to   target address [r1]    */
110    cmp r0, r2      /* until source end address [r2]    */
111    ble copy_loop
112#endif
113
114    /* start RT-Thread Kernel */
115    ldr pc, _rtthread_startup
116
117_rtthread_startup: .word rtthread_startup
118
119    .equ USERMODE,  0x10
120    .equ FIQMODE,   0x11
121    .equ IRQMODE,   0x12
122    .equ SVCMODE,   0x13
123    .equ ABORTMODE, 0x17
124    .equ UNDEFMODE, 0x1b
125    .equ MODEMASK,  0x1f
126    .equ NOINT,     0xc0
127
128/* exception handlers */
129vector_undef:   bl rt_hw_trap_udef
130vector_swi:     bl rt_hw_trap_swi
131vector_pabt:    bl rt_hw_trap_pabt
132vector_dabt:    bl rt_hw_trap_dabt
133vector_resv:    bl rt_hw_trap_resv
134
135.globl rt_interrupt_enter
136.globl rt_interrupt_leave
137.globl rt_thread_switch_interrupt_flag
138.globl rt_interrupt_from_thread
139.globl rt_interrupt_to_thread
140vector_irq:
141    stmfd   sp!, {r0-r12,lr}
142    bl  led_off
143    bl  rt_interrupt_enter
144    bl  rt_hw_trap_irq
145    bl  rt_interrupt_leave
146
147    /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
148    ldr r0, =rt_thread_switch_interrupt_flag
149    ldr r1, [r0]
150    cmp r1, #1
151    beq _interrupt_thread_switch
152
153    ldmfd   sp!, {r0-r12,lr}
154    subs    pc, lr, #4
155
156    .align  5
157vector_fiq:
158    stmfd sp!,{r0-r7,lr}
159    bl rt_hw_trap_fiq
160    ldmfd sp!,{r0-r7,lr}
161    subs pc,lr,#4
162
163_interrupt_thread_switch:
164    mov r1, #0              @ clear rt_thread_switch_interrupt_flag
165    str r1, [r0]
166
167    ldmfd sp!, {r0-r12,lr}  @ reload saved registers
168    stmfd sp!, {r0-r3}      @ save r0-r3
169    mov r1, sp
170    add sp, sp, #16         @ restore sp
171    sub r2, lr, #4          @ save old task's pc to r2
172
173    mrs r3, spsr            @ disable interrupt
174    orr r0, r3, #NOINT
175    msr spsr_c, r0
176
177    ldr r0,  =.+8           @ switch to interrupted task's stack
178    movs pc, r0
179
180    stmfd sp!, {r2}         @ push old task's pc
181    stmfd sp!, {r4-r12,lr}  @ push old task's lr,r12-r4
182    mov r4, r1              @ Special optimised code below
183    mov r5, r3
184    ldmfd r4!, {r0-r3}
185    stmfd sp!, {r0-r3}      @ push old task's r3-r0
186    stmfd sp!, {r5}         @ push old task's psr
187    mrs r4, spsr
188    stmfd sp!, {r4}         @ push old task's spsr
189
190    ldr r4, =rt_interrupt_from_thread
191    ldr r5, [r4]
192    str sp, [r5]            @ store sp in preempted tasks's TCB
193
194    ldr r6, =rt_interrupt_to_thread
195    ldr r6, [r6]
196    ldr sp, [r6]            @ get new task's stack pointer
197
198    ldmfd sp!, {r4}         @ pop new task's spsr
199    msr SPSR_cxsf, r4
200    ldmfd sp!, {r4}         @ pop new task's psr
201    msr CPSR_cxsf, r4
202
203    ldmfd sp!, {r0-r12,lr,pc}   @ pop new task's r0-r12,lr & pc
204
205/* each mode stack memory */
206UNDSTACK_START: .word _undefined_stack_start + 128
207ABTSTACK_START: .word _abort_stack_start + 128
208FIQSTACK_START: .word _fiq_stack_start + 1024
209IRQSTACK_START: .word _irq_stack_start + 1024
210SVCSTACK_START: .word _svc_stack_start + 4096
211
212stack_setup:
213    /* undefined instruction mode */
214    msr cpsr_c, #UNDEFMODE|NOINT
215    ldr sp, UNDSTACK_START
216
217    /* abort mode */
218    msr cpsr_c, #ABORTMODE|NOINT
219    ldr sp, ABTSTACK_START
220
221    /* FIQ mode */
222    msr cpsr_c, #FIQMODE|NOINT
223    ldr sp, FIQSTACK_START
224
225    /* IRQ mode */
226    msr cpsr_c, #IRQMODE|NOINT
227    ldr sp, IRQSTACK_START
228
229    /* supervisor mode */
230    msr cpsr_c, #SVCMODE|NOINT
231    ldr sp, SVCSTACK_START
232
233    mov pc,lr               @ The LR register may be not valid for the mode changes.
234
235.globl led_on
236led_on:
237    ldr r1, =0x1d20014      @ r1<-PDATC
238    ldr r0, [r1]            @ r0<-[r1]
239    orr r0, r0, #0x0e       @ r0=r0 or 0x0e
240    str r0, [r1]            @ r0->[r1]
241    mov pc, lr
242
243.globl led_off
244led_off:
245    ldr r1, =0x1d20010      @ r1<-PCONC
246    ldr r0, =0x5f555555     @ r0<-0x5f555555
247    str r0, [r1]            @ r0->[r1]
248
249    ldr r1, =0x1d20014      @ r1<-PDATC
250    ldr r0, =0x0            @ r0<-00
251    str r0, [r1]            @ r0->[r1]
252
253    mov pc, lr
254