summaryrefslogtreecommitdiff
path: root/bsp/gkipc/armv6/context_gcc.s
blob: 2980654f3fbde903bf3b968b1d782642f9eb0ad7 (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
/*
 * File      : context.S
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006, RT-Thread Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2011-01-13     weety    copy from mini2440
 */

#define NOINT			0xc0

.globl __delay
__delay:
		subs	r0, r0, #1
#if 1
		movls	pc, lr
		subs	r0, r0, #1
		movls	pc, lr
		subs	r0, r0, #1
		movls	pc, lr
		subs	r0, r0, #1
		movls	pc, lr
		subs	r0, r0, #1
		movls	pc, lr
		subs	r0, r0, #1
		movls	pc, lr
		subs	r0, r0, #1
		movls	pc, lr
		subs	r0, r0, #1
#endif
		bhi	__delay
		mov	pc, lr


/*
 * rt_base_t rt_hw_interrupt_disable();
 */
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable:
	mrs r0, cpsr
	orr r1, r0, #NOINT
	msr cpsr_c, r1
	mov pc, lr

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
	msr cpsr, r0
	mov pc, lr


    .globl  restore_context
    @.func   restore_context
    
    .globl  save_context
    @.func   save_context

save_context:
    stmfd	sp!, {lr}		@ push pc (lr should be pushed in place of PC)
	stmfd	sp!, {r0-r12, lr}	@ push lr & register file

	mrs	r4, cpsr
	stmfd	sp!, {r4}		@ push cpsr
	mrs	r4, spsr
	stmfd	sp!, {r4}		@ push spsr

	str	sp, [r0]			@ store sp in preempted tasks TCB
	mov pc, lr
    bx lr                 @ branch back to caller


restore_context:
    ldr	sp, [r0]			@ get new task stack pointer

	ldmfd	sp!, {r4}		@ pop new task spsr
	msr	spsr_cxsf, r4
	ldmfd	sp!, {r4}		@ pop new task cpsr
	msr	spsr_cxsf, r4

	ldmfd	sp!, {r0-r12, lr, pc}^	@ pop new task r0-r12, lr & pc

    
    
/*
 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
 * r0 --> from
 * r1 --> to
 */
.globl rt_hw_context_switch
rt_hw_context_switch:
	stmfd	sp!, {lr}		@ push pc (lr should be pushed in place of PC)
	stmfd	sp!, {r0-r12, lr}	@ push lr & register file

	mrs	r4, cpsr
	stmfd	sp!, {r4}		@ push cpsr
	mrs	r4, spsr
	stmfd	sp!, {r4}		@ push spsr

	str	sp, [r0]			@ store sp in preempted tasks TCB
	ldr	sp, [r1]			@ get new task stack pointer

	ldmfd	sp!, {r4}		@ pop new task spsr
	msr	spsr_cxsf, r4
	ldmfd	sp!, {r4}		@ pop new task cpsr
	msr	spsr_cxsf, r4

	ldmfd	sp!, {r0-r12, lr, pc}^	@ pop new task r0-r12, lr & pc

/*
 * void rt_hw_context_switch_to(rt_uint32 to);
 * r0 --> to
 */
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
	ldr	sp, [r0]		@ get new task stack pointer

	ldmfd	sp!, {r4}		@ pop new task spsr
	msr	spsr_cxsf, r4
	ldmfd	sp!, {r4}		@ pop new task cpsr
	msr	cpsr_cxsf, r4

	ldmfd	sp!, {r0-r12, lr, pc}	@ pop new task r0-r12, lr & pc

/*
 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
 */
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
	ldr r2, =rt_thread_switch_interrupt_flag
	ldr r3, [r2]
	cmp r3, #1
	beq _reswitch
	mov r3, #1				@ set rt_thread_switch_interrupt_flag to 1
	str r3, [r2]
	ldr r2, =rt_interrupt_from_thread	@ set rt_interrupt_from_thread
	str r0, [r2]
_reswitch:
	ldr r2, =rt_interrupt_to_thread		@ set rt_interrupt_to_thread
	str r1, [r2]
	mov pc, lr