summaryrefslogtreecommitdiff
path: root/libcpu/arm/s3c44b0/start_gcc.S
blob: 17a3d0da7f597836ff80f06f537ccc2d9c232b70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
 * File      : start.S
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://openlab.rt-thread.com/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-09-06     XuXinming    first version
 * 2006-09-20     Bernard      clean the code
 */

/**
 * @addtogroup S3C44B0
 */
/*@{*/

.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

.text
.code 32

/*
 * 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

#if defined(__FLASH_BUILD__)
/*
 * TEXT_BASE, 
 * which is defined in macro of make
 */
_TEXT_BASE: .word	TEXT_BASE
#endif

	.equ WTCON,		0x1d30000
	.equ INTCON,	0x1e00000
	.equ INTMSK, 	0x1e0000c

/* the system entry */
reset:
	/* enter svc mode */
	msr cpsr_c, #SVCMODE|NOINT

	/*watch dog disable */
	ldr r0,=WTCON
    ldr r1,=0x0 		
    str r1,[r0]
	
	/* all interrupt disable */
	ldr r0,=INTMSK
	ldr r1,=0x07ffffff
	str r1,[r0]
	
	ldr	r1, =INTCON
	ldr	r0, =0x05
	str	r0, [r1]

#if defined(__FLASH_BUILD__)
	/* init lowlevel */
	bl lowlevel_init
#endif

	/* setup stack */
	bl stack_setup
	
#if defined(__FLASH_BUILD__)
	mov r0, #0x0			/* r0 <- flash base address         */
	ldr r1, _TEXT_BASE		/* r1 <- the taget address          */
	
	ldr	r2, _rtthread_start
	ldr	r3, _bss_start
	sub	r2, r3, r2			/* r2 <- size of rtthread kernel    */
	add	r2, r0, r2			/* r2 <- source end address         */
	
copy_loop:
	ldmia	r0!, {r3-r10}	/* copy from source address [r0]    */
	stmia	r1!, {r3-r10}	/* copy to   target address [r1]    */
	cmp	r0, r2				/* until source end addreee [r2]    */
	ble	copy_loop
#endif
	
	/* 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  led_off
	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

/* each mode stack memory */
UNDSTACK_START:	.word _undefined_stack_start + 128
ABTSTACK_START:	.word _abort_stack_start + 128
FIQSTACK_START:	.word _fiq_stack_start + 1024
IRQSTACK_START:	.word _irq_stack_start + 1024
SVCSTACK_START: .word _svc_stack_start + 4096

stack_setup:
	/* undefined instruction mode */
	msr cpsr_c, #UNDEFMODE|NOINT
	ldr sp, UNDSTACK_START

	/* abort mode */
	msr cpsr_c, #ABORTMODE|NOINT
	ldr sp, ABTSTACK_START

	/* FIQ mode */
	msr cpsr_c, #FIQMODE|NOINT
	ldr sp, FIQSTACK_START

	/* IRQ mode */
	msr cpsr_c, #IRQMODE|NOINT
	ldr sp, IRQSTACK_START

	/* supervisor mode */
	msr cpsr_c, #SVCMODE|NOINT
	ldr sp, SVCSTACK_START

	mov	pc,lr				@ The LR register may be not valid for the mode changes.

.globl led_on
led_on:
	ldr	r1,	=0x1d20014		@ r1<-PDATC
	ldr	r0,	[r1]			@ r0<-[r1]
	orr	r0,	r0, #0x0e		@ r0=r0 or 0x0e
	str	r0,	[r1]			@ r0->[r1]
	mov	pc, lr

.globl led_off
led_off:
	ldr	r1,	=0x1d20010		@ r1<-PCONC
	ldr	r0,	=0x5f555555		@ r0<-0x5f555555
	str	r0,	[r1]			@ r0->[r1]

	ldr	r1,	=0x1d20014		@ r1<-PDATC
	ldr	r0,	=0x0			@ r0<-00
	str	r0,	[r1]			@ r0->[r1]

	mov	pc, lr