context_gcc.S 4.2 KB
Newer Older
1 2 3
/*
 * File      : context_gcc.S
 * This file is part of RT-Thread RTOS
B
bernard.xiong 已提交
4
 * COPYRIGHT (C) 2009, RT-Thread Development Team
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
 *
 * 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
35
.type rt_hw_interrupt_disable, %function
36 37
rt_hw_interrupt_disable:
	MRS		r0, PRIMASK
38
	CPSID	I
39 40 41 42 43 44
	BX		LR

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
.global rt_hw_interrupt_enable
45
.type rt_hw_interrupt_enable, %function
46 47 48 49 50 51 52 53 54 55
rt_hw_interrupt_enable:
	MSR		PRIMASK, r0
	BX		LR

/*
 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
 * r0 --> from
 * r1 --> to
 */
.global rt_hw_context_switch_interrupt
56
.type rt_hw_context_switch_interrupt, %function
57
.global rt_hw_context_switch
58
.type rt_hw_context_switch, %function
59 60 61 62

rt_hw_context_switch_interrupt:
rt_hw_context_switch:
	/* set rt_thread_switch_interrput_flag to 1 */
63 64 65 66 67 68
	LDR 	r2, =rt_thread_switch_interrput_flag
	LDR 	r3, [r2]
	CMP 	r3, #1
	BEQ 	_reswitch
	MOV 	r3, #1
	STR 	r3, [r2]
69

70 71
	LDR 	r2, =rt_interrupt_from_thread	/* set rt_interrupt_from_thread */
	STR 	r0, [r2]
72 73

_reswitch:
74 75
	LDR 	r2, =rt_interrupt_to_thread		/* set rt_interrupt_to_thread */
	STR 	r1, [r2]
76

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

/* 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
87
.type rt_hw_pend_sv, %function
88 89 90
rt_hw_pend_sv:
	/* disable interrupt to protect context switch */
	MRS		r2, PRIMASK
91
	CPSID	I
92

93
	/* get rt_thread_switch_interrupt_flag */
94
	LDR		r0, =rt_thread_switch_interrput_flag
95 96 97 98
	LDR		r1, [r0]
	CBZ		r1, pendsv_exit			/* pendsv already handled */

	/* clear rt_thread_switch_interrput_flag to 0 */
99 100 101 102 103 104 105
	MOV		r1, #0x00
	STR		r1, [r0]

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

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

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

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

119
pendsv_exit:
120 121 122 123 124 125 126 127 128 129 130
	/* restore interrupt */
	MSR		PRIMASK, r2

	ORR		lr, lr, #0x04
	BX		lr

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

	/* set from thread to 0 */
	LDR		r1, =rt_interrupt_from_thread
	MOV		r0, #0x0
	STR		r0, [r1]

141 142 143 144 145
	/* set interrupt flag to 1 */
	LDR 	r1, =rt_thread_switch_interrput_flag
	MOV 	r0, #1
	STR 	r0, [r1]

146 147 148
	/* set the PendSV exception priority */
	LDR		r0, =NVIC_SYSPRI2
	LDR		r1, =NVIC_PENDSV_PRI
wuyangyong's avatar
wuyangyong 已提交
149 150 151
  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]
B
bernard.xiong 已提交
156

157
	CPSIE	I                       /* enable interrupts at processor level */
B
bernard.xiong 已提交
158

159 160 161 162
	/* never reach here! */

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