context_gcc.S 6.2 KB
Newer Older
wuyangyong's avatar
wuyangyong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * File      : context_gcc.S
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2009 - 2013, 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
 * 2010-01-25   Bernard      first version
 * 2012-06-01   aozima       set pendsv priority to 0xFF.
 * 2012-08-17   aozima       fixed bug: store r8 - r11.
 * 2013-02-20   aozima       port to gcc.
16
 * 2013-06-18   aozima       add restore MSP feature.
B
Bright Pan 已提交
17
 * 2013-11-04   bright       fixed hardfault bug for gcc.
wuyangyong's avatar
wuyangyong 已提交
18 19
 */
 
B
Bright Pan 已提交
20
    .cpu    cortex-m0
wuyangyong's avatar
wuyangyong 已提交
21 22 23 24
    .fpu    softvfp
    .syntax unified
    .thumb
    .text
wuyangyong's avatar
wuyangyong 已提交
25

B
Bright Pan 已提交
26 27 28 29 30
	.equ 	SCB_VTOR, 0xE000ED08            /* Vector Table Offset Register */
	.equ 	NVIC_INT_CTRL, 0xE000ED04       /* interrupt control state register */
	.equ 	NVIC_SHPR3, 0xE000ED20          /* system priority register (3) */
	.equ 	NVIC_PENDSV_PRI, 0x00FF0000     /* PendSV priority value (lowest) */
	.equ 	NVIC_PENDSVSET, 0x10000000      /* value to trigger PendSV exception */
wuyangyong's avatar
wuyangyong 已提交
31 32 33 34

/*
 * rt_base_t rt_hw_interrupt_disable();
 */
wuyangyong's avatar
wuyangyong 已提交
35 36
    .global rt_hw_interrupt_disable
    .type rt_hw_interrupt_disable, %function
wuyangyong's avatar
wuyangyong 已提交
37
rt_hw_interrupt_disable:
wuyangyong's avatar
wuyangyong 已提交
38 39 40
    MRS     R0, PRIMASK
    CPSID   I
    BX      LR
wuyangyong's avatar
wuyangyong 已提交
41 42 43 44

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
wuyangyong's avatar
wuyangyong 已提交
45 46
    .global rt_hw_interrupt_enable
    .type rt_hw_interrupt_enable, %function
wuyangyong's avatar
wuyangyong 已提交
47
rt_hw_interrupt_enable:
wuyangyong's avatar
wuyangyong 已提交
48 49
    MSR     PRIMASK, R0
    BX      LR
wuyangyong's avatar
wuyangyong 已提交
50 51 52 53 54 55

/*
 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
 * R0 --> from
 * R1 --> to
 */
wuyangyong's avatar
wuyangyong 已提交
56 57 58 59
    .global rt_hw_context_switch_interrupt
    .type rt_hw_context_switch_interrupt, %function
    .global rt_hw_context_switch
    .type rt_hw_context_switch, %function
wuyangyong's avatar
wuyangyong 已提交
60 61
rt_hw_context_switch_interrupt:
rt_hw_context_switch:
wuyangyong's avatar
wuyangyong 已提交
62 63 64 65 66
    /* set rt_thread_switch_interrupt_flag to 1 */
    LDR     R2, =rt_thread_switch_interrupt_flag
    LDR     R3, [R2]
    CMP     R3, #1
    BEQ     _reswitch
B
Bright Pan 已提交
67
    MOVS    R3, #1
wuyangyong's avatar
wuyangyong 已提交
68
    STR     R3, [R2]
wuyangyong's avatar
wuyangyong 已提交
69

wuyangyong's avatar
wuyangyong 已提交
70 71
    LDR     R2, =rt_interrupt_from_thread   /* set rt_interrupt_from_thread */
    STR     R0, [R2]
wuyangyong's avatar
wuyangyong 已提交
72 73

_reswitch:
wuyangyong's avatar
wuyangyong 已提交
74 75
    LDR     R2, =rt_interrupt_to_thread     /* set rt_interrupt_to_thread */
    STR     R1, [R2]
wuyangyong's avatar
wuyangyong 已提交
76

B
Bright Pan 已提交
77 78
    LDR     R0, =NVIC_INT_CTRL           /* trigger the PendSV exception (causes context switch) */
    LDR     R1, =NVIC_PENDSVSET
wuyangyong's avatar
wuyangyong 已提交
79 80
    STR     R1, [R0]
    BX      LR
wuyangyong's avatar
wuyangyong 已提交
81

B
bernard 已提交
82 83
/* R0 --> switch from thread stack
 * R1 --> switch to thread stack
wuyangyong's avatar
wuyangyong 已提交
84 85
 * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack
 */
wuyangyong's avatar
wuyangyong 已提交
86 87
    .global PendSV_Handler
    .type PendSV_Handler, %function
wuyangyong's avatar
wuyangyong 已提交
88
PendSV_Handler:
wuyangyong's avatar
wuyangyong 已提交
89 90 91
    /* disable interrupt to protect context switch */
    MRS     R2, PRIMASK
    CPSID   I
wuyangyong's avatar
wuyangyong 已提交
92

wuyangyong's avatar
wuyangyong 已提交
93 94 95
    /* get rt_thread_switch_interrupt_flag */
    LDR     R0, =rt_thread_switch_interrupt_flag
    LDR     R1, [R0]
B
Bright Pan 已提交
96 97
    CMP     R1, #0x00
    BEQ     pendsv_exit		/* pendsv aLReady handled */
wuyangyong's avatar
wuyangyong 已提交
98

wuyangyong's avatar
wuyangyong 已提交
99
    /* clear rt_thread_switch_interrupt_flag to 0 */
B
Bright Pan 已提交
100
    MOVS    R1, #0
wuyangyong's avatar
wuyangyong 已提交
101
    STR     R1, [R0]
wuyangyong's avatar
wuyangyong 已提交
102

wuyangyong's avatar
wuyangyong 已提交
103 104
    LDR     R0, =rt_interrupt_from_thread
    LDR     R1, [R0]
B
Bright Pan 已提交
105
    CMP     R1, #0x00
B
bernard 已提交
106
    BEQ     switch_to_thread    /* skip register save at the first time */
wuyangyong's avatar
wuyangyong 已提交
107

B
Bright Pan 已提交
108 109 110
	MRS     R1, PSP                 /* get from thread stack pointer */

    SUBS    R1, R1, #0x20           /* space for {R4 - R7} and {R8 - R11} */
wuyangyong's avatar
wuyangyong 已提交
111 112
    LDR     R0, [R0]
    STR     R1, [R0]                /* update from thread stack pointer */
wuyangyong's avatar
wuyangyong 已提交
113

B
Bright Pan 已提交
114 115 116 117 118 119 120
    STMIA   R1!, {R4 - R7}          /* push thread {R4 - R7} register to thread stack */

    MOV     R4, R8                  /* mov thread {R8 - R11} to {R4 - R7} */
    MOV     R5, R9
    MOV     R6, R10
    MOV     R7, R11
    STMIA   R1!, {R4 - R7}          /* push thread {R8 - R11} high register to thread stack */
B
bernard 已提交
121
switch_to_thread:
wuyangyong's avatar
wuyangyong 已提交
122 123 124
    LDR     R1, =rt_interrupt_to_thread
    LDR     R1, [R1]
    LDR     R1, [R1]                /* load thread stack pointer */
wuyangyong's avatar
wuyangyong 已提交
125

B
Bright Pan 已提交
126 127 128 129 130 131 132 133 134 135 136
	LDMIA   R1!, {R4 - R7}          /* pop thread {R4 - R7} register from thread stack */
    PUSH    {R4 - R7}               /* push {R4 - R7} to MSP for copy {R8 - R11} */

    LDMIA   R1!, {R4 - R7}          /* pop thread {R8 - R11} high register from thread stack to {R4 - R7} */
    MOV     R8,  R4                 /* mov {R4 - R7} to {R8 - R11} */
    MOV     R9,  R5
    MOV     R10, R6
    MOV     R11, R7

    POP     {R4 - R7}               /* pop {R4 - R7} from MSP */

wuyangyong's avatar
wuyangyong 已提交
137
    MSR     PSP, R1                 /* update stack pointer */
wuyangyong's avatar
wuyangyong 已提交
138 139

pendsv_exit:
wuyangyong's avatar
wuyangyong 已提交
140 141
    /* restore interrupt */
    MSR     PRIMASK, R2
wuyangyong's avatar
wuyangyong 已提交
142

B
Bright Pan 已提交
143 144 145
    MOVS    R0, #0x04
    RSBS    R0, R0, #0x00
    BX      R0
wuyangyong's avatar
wuyangyong 已提交
146 147 148 149
/*
 * void rt_hw_context_switch_to(rt_uint32 to);
 * R0 --> to
 */
wuyangyong's avatar
wuyangyong 已提交
150 151
    .global rt_hw_context_switch_to
    .type rt_hw_context_switch_to, %function
wuyangyong's avatar
wuyangyong 已提交
152
rt_hw_context_switch_to:
wuyangyong's avatar
wuyangyong 已提交
153 154 155 156 157
    LDR     R1, =rt_interrupt_to_thread
    STR     R0, [R1]

    /* set from thread to 0 */
    LDR     R1, =rt_interrupt_from_thread
B
Bright Pan 已提交
158
    MOVS    R0, #0
wuyangyong's avatar
wuyangyong 已提交
159 160 161 162
    STR     R0, [R1]

    /* set interrupt flag to 1 */
    LDR     R1, =rt_thread_switch_interrupt_flag
B
Bright Pan 已提交
163
    MOVS    R0, #1
wuyangyong's avatar
wuyangyong 已提交
164 165 166
    STR     R0, [R1]

    /* set the PendSV exception priority */
B
Bright Pan 已提交
167 168 169 170 171 172 173 174
    LDR     R0, =NVIC_SHPR3
    LDR     R1, =NVIC_PENDSV_PRI
    LDR     R2, [R0,#0x00]       /* read */
    ORRS    R1, R1, R2             /* modify */
    STR     R1, [R0]             /* write-back */

    LDR     R0, =NVIC_INT_CTRL               /* trigger the PendSV exception (causes context switch) */
    LDR     R1, =NVIC_PENDSVSET
wuyangyong's avatar
wuyangyong 已提交
175
    STR     R1, [R0]
B
Bright Pan 已提交
176
    NOP
177
    /* restore MSP */
B
Bright Pan 已提交
178 179 180
    LDR     R0, =SCB_VTOR
    LDR     R0, [R0]
    LDR     R0, [R0]
181
    NOP
B
Bright Pan 已提交
182
    MSR     MSP, R0
183

wuyangyong's avatar
wuyangyong 已提交
184
    CPSIE   I                       /* enable interrupts at processor level */
wuyangyong's avatar
wuyangyong 已提交
185

wuyangyong's avatar
wuyangyong 已提交
186
    /* never reach here! */
wuyangyong's avatar
wuyangyong 已提交
187 188

/* compatible with old version */
wuyangyong's avatar
wuyangyong 已提交
189 190
    .global rt_hw_interrupt_thread_switch
    .type rt_hw_interrupt_thread_switch, %function
wuyangyong's avatar
wuyangyong 已提交
191
rt_hw_interrupt_thread_switch:
wuyangyong's avatar
wuyangyong 已提交
192 193
    BX      LR
    NOP
wuyangyong's avatar
wuyangyong 已提交
194

wuyangyong's avatar
wuyangyong 已提交
195 196
    .global HardFault_Handler
    .type HardFault_Handler, %function
wuyangyong's avatar
wuyangyong 已提交
197 198 199 200 201
HardFault_Handler:
    /* get current context */
    MRS     R0, PSP                 /* get fault thread stack pointer */
    PUSH    {LR}
    BL      rt_hw_hard_fault_exception
B
Bright Pan 已提交
202
    POP     {PC}
wuyangyong's avatar
wuyangyong 已提交
203 204 205 206 207 208


/*
 * rt_uint32_t rt_hw_interrupt_check(void);
 * R0 --> state
 */
wuyangyong's avatar
wuyangyong 已提交
209 210
    .global rt_hw_interrupt_check
    .type rt_hw_interrupt_check, %function
wuyangyong's avatar
wuyangyong 已提交
211
rt_hw_interrupt_check:
wuyangyong's avatar
wuyangyong 已提交
212 213
    MRS     R0, IPSR
    BX      LR