context_rvds.S 4.1 KB
Newer Older
1
;/*
B
bernard.xiong 已提交
2
; * File      : context_rvds.S
3
; * 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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
; *
; * 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-01-17     Bernard      first version
; */

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

NVIC_INT_CTRL   EQU     0xE000ED04               ; interrupt control state register
NVIC_SYSPRI2    EQU     0xE000ED20               ; system priority register (2)
NVIC_PENDSV_PRI EQU     0x00FF0000               ; PendSV priority value (lowest)
NVIC_PENDSVSET  EQU     0x10000000               ; value to trigger PendSV exception

	AREA |.text|, CODE, READONLY, ALIGN=2
	THUMB
	REQUIRE8
	PRESERVE8

	IMPORT rt_thread_switch_interrput_flag
	IMPORT rt_interrupt_from_thread
	IMPORT rt_interrupt_to_thread

;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable    PROC
	EXPORT  rt_hw_interrupt_disable
	MRS		r0, PRIMASK
	CPSID   I
	BX		LR
	ENDP

;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable    PROC
	EXPORT  rt_hw_interrupt_enable
	MSR		PRIMASK, r0
	BX      LR
	ENDP

;/*
; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; * r0 --> from
; * r1 --> to
; */
58 59
rt_hw_context_switch_interrupt
	EXPORT rt_hw_context_switch_interrupt
60 61 62 63 64 65
rt_hw_context_switch    PROC
	EXPORT rt_hw_context_switch

	; set rt_thread_switch_interrput_flag to 1
	LDR 	r2, =rt_thread_switch_interrput_flag
	LDR 	r3, [r2]
66 67
	CMP 	r3, #1
	BEQ 	_reswitch
68 69 70 71 72
	MOV 	r3, #1
	STR 	r3, [r2]

	LDR 	r2, =rt_interrupt_from_thread	; set rt_interrupt_from_thread
	STR 	r0, [r2]
73 74

_reswitch
75 76 77
	LDR 	r2, =rt_interrupt_to_thread		; set rt_interrupt_to_thread
	STR 	r1, [r2]

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

; r0 --> swith from thread stack
; r1 --> swith to thread stack
; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
rt_hw_pend_sv	PROC
	EXPORT rt_hw_pend_sv
89 90 91 92 93

	; disable interrupt to protect context switch
	MRS		r2, PRIMASK
	CPSID   I

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

	; clear rt_thread_switch_interrput_flag to 0
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
	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

	MRS     r1, psp                 ; get from thread stack pointer
	STMFD	r1!, {r4 - r11}			; push r4 - r11 register
	LDR		r0, [r0]
	STR		r1, [r0]				; update from thread stack pointer

swtich_to_thread
	LDR		r1, =rt_interrupt_to_thread
	LDR		r1, [r1]
B
bernard.xiong 已提交
115
	LDR		r1, [r1]				; load thread stack pointer
116 117 118 119

	LDMFD	r1!, {r4 - r11}			; pop r4 - r11 register
	MSR		psp, r1					; update stack pointer

120
pendsv_exit
121 122 123
	; restore interrupt
	MSR		PRIMASK, r2

124 125 126 127 128 129 130
	ORR     lr, lr, #0x04
	BX		lr
	ENDP

;/*
; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to
131
; * this fucntion is used to perform the first thread switch
132 133 134
; */
rt_hw_context_switch_to    PROC
	EXPORT rt_hw_context_switch_to
135
	; set to thread
136 137 138 139 140 141 142 143
	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]

144 145 146 147 148
	; set interrupt flag to 1
	LDR 	r1, =rt_thread_switch_interrput_flag
	MOV 	r0, #1
	STR 	r0, [r1]

149 150 151 152 153
	; set the PendSV exception priority
    LDR     r0, =NVIC_SYSPRI2
    LDR     r1, =NVIC_PENDSV_PRI
    STR     r1, [r0]

154 155
	; trigger the PendSV exception (causes context switch)
    LDR     r0, =NVIC_INT_CTRL
156 157
    LDR     r1, =NVIC_PENDSVSET
    STR     r1, [r0]
B
bernard.xiong 已提交
158

159 160
	; enable interrupts at processor level
    CPSIE   I
B
bernard.xiong 已提交
161

162 163 164
	; never reach here!
	ENDP

165 166
; compatible with old version
rt_hw_interrupt_thread_switch PROC
167 168
	EXPORT rt_hw_interrupt_thread_switch
	BX		lr
169
	NOP
170 171
	ENDP

172
	END