context_gcc.S 4.2 KB
Newer Older
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
/*
 * File      : context_gcc.S
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2009, 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://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2009-10-11     Bernard      first version
 */

/**
 * @addtogroup STM32
 */
/*@{*/

.cpu cortex-m3
.fpu softvfp
.syntax unified
.thumb
.text

.equ	NVIC_INT_CTRL,       0xE000ED04               /* interrupt control state register */
.equ	NVIC_SYSPRI2,        0xE000ED20               /* system priority register (2) */
.equ	NVIC_PENDSV_PRI,     0x00FF0000               /* PendSV priority value (lowest) */
.equ	NVIC_PENDSVSET,      0x10000000               /* value to trigger PendSV exception */

/*
 * rt_base_t rt_hw_interrupt_disable();
 */
.global rt_hw_interrupt_disable
.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
37
	MRS	r0, PRIMASK
38
	CPSID	I
39
	BX	LR
40 41 42 43 44 45 46

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
.global rt_hw_interrupt_enable
.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
47 48
	MSR	PRIMASK, r0
	BX	LR
49 50 51 52 53 54 55 56 57 58 59 60 61

/*
 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
 * r0 --> from
 * r1 --> to
 */
.global rt_hw_context_switch_interrupt
.type rt_hw_context_switch_interrupt, %function
.global rt_hw_context_switch
.type rt_hw_context_switch, %function

rt_hw_context_switch_interrupt:
rt_hw_context_switch:
D
dzzxzz 已提交
62 63
	/* set rt_thread_switch_interrupt_flag to 1 */
	LDR 	r2, =rt_thread_switch_interrupt_flag
64 65 66 67 68 69 70 71 72 73 74 75 76
	LDR 	r3, [r2]
	CMP 	r3, #1
	BEQ 	_reswitch
	MOV 	r3, #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]

77 78 79 80
	LDR	r0, =NVIC_INT_CTRL      		/* trigger the PendSV exception (causes context switch) */
	LDR	r1, =NVIC_PENDSVSET
	STR	r1, [r0]
	BX	LR
81 82 83 84 85 86 87 88 89

/* r0 --> swith from thread stack
 * r1 --> swith to thread stack
 * psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
 */
.global rt_hw_pend_sv
.type rt_hw_pend_sv, %function
rt_hw_pend_sv:
	/* disable interrupt to protect context switch */
90
	MRS	r2, PRIMASK
91 92 93
	CPSID	I

	/* get rt_thread_switch_interrupt_flag */
D
dzzxzz 已提交
94
	LDR	r0, =rt_thread_switch_interrupt_flag
95 96
	LDR	r1, [r0]
	CBZ	r1, pendsv_exit			/* pendsv already handled */
97

D
dzzxzz 已提交
98
	/* clear rt_thread_switch_interrupt_flag to 0 */
99 100
	MOV	r1, #0x00
	STR	r1, [r0]
101

102 103 104
	LDR	r0, =rt_interrupt_from_thread
	LDR	r1, [r0]
	CBZ	r1, swtich_to_thread    /* skip register save at the first time */
105

106
	MRS	r1, psp					/* get from thread stack pointer */
107
	STMFD	r1!, {r4 - r11}			/* push r4 - r11 register */
108 109
	LDR	r0, [r0]
	STR	r1, [r0]				/* update from thread stack pointer */
110 111

swtich_to_thread:
112 113 114
	LDR	r1, =rt_interrupt_to_thread
	LDR	r1, [r1]
	LDR	r1, [r1]				/* load thread stack pointer */
115 116

	LDMFD	r1!, {r4 - r11}			/* pop r4 - r11 register */
117
	MSR	psp, r1					/* update stack pointer */
118 119 120

pendsv_exit:
	/* restore interrupt */
121
	MSR	PRIMASK, r2
122

123 124
	ORR	lr, lr, #0x04
	BX	lr
125 126 127 128 129 130 131 132

/*
 * void rt_hw_context_switch_to(rt_uint32 to);
 * r0 --> to
 */
.global rt_hw_context_switch_to
.type rt_hw_context_switch_to, %function
rt_hw_context_switch_to:
133 134
	LDR	r1, =rt_interrupt_to_thread
	STR	r0, [r1]
135 136

	/* set from thread to 0 */
137 138 139
	LDR	r1, =rt_interrupt_from_thread
	MOV	r0, #0x0
	STR	r0, [r1]
140 141

	/* set interrupt flag to 1 */
D
dzzxzz 已提交
142
	LDR 	r1, =rt_thread_switch_interrupt_flag
143 144 145 146
	MOV 	r0, #1
	STR 	r0, [r1]

	/* set the PendSV exception priority */
147 148 149 150 151
	LDR	r0, =NVIC_SYSPRI2
	LDR	r1, =NVIC_PENDSV_PRI
	LDR.W   R2, [r0,#0x00]          /* read */
	ORR     r1,r1,r2                /* modify */
    	STR     r1, [r0]                /* write-back */
152

153 154 155
	LDR	r0, =NVIC_INT_CTRL      /* trigger the PendSV exception (causes context switch) */
	LDR	r1, =NVIC_PENDSVSET
	STR	r1, [r0]
156 157 158 159 160 161 162 163 164

	CPSIE	I                       /* enable interrupts at processor level */

	/* never reach here! */

/* compatible with old version */
.global rt_hw_interrupt_thread_switch
.type rt_hw_interrupt_thread_switch, %function
rt_hw_interrupt_thread_switch:
165
	BX	lr
166
	NOP