context_gcc.S 6.1 KB
Newer Older
B
Bernard Xiong 已提交
1 2 3
/*
 * File      : context_gcc.S
 * This file is part of RT-Thread RTOS
4
 * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
B
Bernard Xiong 已提交
5 6 7 8 9 10 11 12
 *
 * 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
13 14 15 16
 * 2010-12-29   onelife   Modify for EFM32
 * 2011-06-17   onelife   Merge all of the assembly source code into context_gcc.S
 * 2011-07-12   onelife   Add interrupt context check function
 * 2013-06-18   aozima    add restore MSP feature.
17
 * 2013-07-09   aozima    enhancement hard fault exception handler.
B
Bernard Xiong 已提交
18 19
 */
 
20 21 22 23 24 25
    .cpu    cortex-m3
    .fpu    softvfp
    .syntax unified
    .thumb
    .text

26
    .equ    SCB_VTOR, 0xE000ED08            /* Vector Table Offset Register */
27 28 29 30 31
    .equ    ICSR, 0xE000ED04                /* interrupt control state register */
    .equ    PENDSVSET_BIT, 0x10000000       /* value to trigger PendSV exception */
    
    .equ    SHPR3, 0xE000ED20               /* system priority register (3) */
    .equ    PENDSV_PRI_LOWEST, 0x00FF0000   /* PendSV priority value (lowest) */
B
Bernard Xiong 已提交
32 33 34 35

/*
 * rt_base_t rt_hw_interrupt_disable();
 */
36 37
    .global rt_hw_interrupt_disable
    .type rt_hw_interrupt_disable, %function
B
Bernard Xiong 已提交
38
rt_hw_interrupt_disable:
39 40 41
    MRS     R0, PRIMASK
    CPSID   I
    BX      LR
B
Bernard Xiong 已提交
42 43 44 45

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
46 47
    .global rt_hw_interrupt_enable
    .type rt_hw_interrupt_enable, %function
B
Bernard Xiong 已提交
48
rt_hw_interrupt_enable:
49 50
    MSR     PRIMASK, R0
    BX      LR
B
Bernard Xiong 已提交
51 52 53 54 55 56

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

71 72
    LDR     R2, =rt_interrupt_from_thread   /* set rt_interrupt_from_thread */
    STR     R0, [R2]
B
Bernard Xiong 已提交
73 74

_reswitch:
75 76
    LDR     R2, =rt_interrupt_to_thread     /* set rt_interrupt_to_thread */
    STR     R1, [R2]
B
Bernard Xiong 已提交
77

78 79 80 81
    LDR     R0, =ICSR           /* trigger the PendSV exception (causes context switch) */
    LDR     R1, =PENDSVSET_BIT
    STR     R1, [R0]
    BX      LR
B
Bernard Xiong 已提交
82 83 84 85 86

/* R0 --> swith from thread stack
 * R1 --> swith to thread stack
 * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack
 */
87 88
    .global PendSV_Handler
    .type PendSV_Handler, %function
B
Bernard Xiong 已提交
89
PendSV_Handler:
90 91 92
    /* disable interrupt to protect context switch */
    MRS     R2, PRIMASK
    CPSID   I
B
Bernard Xiong 已提交
93

94 95 96 97
    /* get rt_thread_switch_interrupt_flag */
    LDR     R0, =rt_thread_switch_interrupt_flag
    LDR     R1, [R0]
    CBZ     R1, pendsv_exit         /* pendsv aLReady handled */
B
Bernard Xiong 已提交
98

99 100 101
    /* clear rt_thread_switch_interrupt_flag to 0 */
    MOV     R1, #0
    STR     R1, [R0]
B
Bernard Xiong 已提交
102

103 104 105
    LDR     R0, =rt_interrupt_from_thread
    LDR     R1, [R0]
    CBZ     R1, swtich_to_thread    /* skip register save at the first time */
B
Bernard Xiong 已提交
106

107 108 109 110
    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 */
B
Bernard Xiong 已提交
111 112

swtich_to_thread:
113 114 115
    LDR     R1, =rt_interrupt_to_thread
    LDR     R1, [R1]
    LDR     R1, [R1]                /* load thread stack pointer */
B
Bernard Xiong 已提交
116

117 118
    LDMFD   R1!, {R4 - R11}         /* pop R4 - R11 register */
    MSR     PSP, R1                 /* update stack pointer */
B
Bernard Xiong 已提交
119 120

pendsv_exit:
121 122
    /* restore interrupt */
    MSR     PRIMASK, R2
B
Bernard Xiong 已提交
123

124 125
    ORR     LR, LR, #0x04
    BX      LR
B
Bernard Xiong 已提交
126 127 128 129 130

/*
 * void rt_hw_context_switch_to(rt_uint32 to);
 * R0 --> to
 */
131 132
    .global rt_hw_context_switch_to
    .type rt_hw_context_switch_to, %function
B
Bernard Xiong 已提交
133
rt_hw_context_switch_to:
134 135 136 137 138 139 140
    LDR     R1, =rt_interrupt_to_thread
    STR     R0, [R1]

    /* set from thread to 0 */
    LDR     R1, =rt_interrupt_from_thread
    MOV     R0, #0
    STR     R0, [R1]
B
Bernard Xiong 已提交
141

142 143 144 145
    /* set interrupt flag to 1 */
    LDR     R1, =rt_thread_switch_interrupt_flag
    MOV     R0, #1
    STR     R0, [R1]
B
Bernard Xiong 已提交
146

147 148 149 150 151 152
    /* set the PendSV exception priority */
    LDR     R0, =SHPR3
    LDR     R1, =PENDSV_PRI_LOWEST
    LDR.W   R2, [R0,#0]             /* read */
    ORR     R1, R1, R2              /* modify */
    STR     R1, [R0]                /* write-back */
B
Bernard Xiong 已提交
153

154 155 156
    LDR     R0, =ICSR               /* trigger the PendSV exception (causes context switch) */
    LDR     R1, =PENDSVSET_BIT
    STR     R1, [R0]
B
Bernard Xiong 已提交
157

158 159 160 161 162 163
    /* restore MSP */
    LDR     r0, =SCB_VTOR
    LDR     r0, [r0]
    LDR     r0, [r0]
    NOP
    MSR     msp, r0
B
Bernard Xiong 已提交
164

165
    CPSIE   I                       /* enable interrupts at processor level */
B
Bernard Xiong 已提交
166

167
    /* never reach here! */
B
Bernard Xiong 已提交
168 169

/* compatible with old version */
170 171
    .global rt_hw_interrupt_thread_switch
    .type rt_hw_interrupt_thread_switch, %function
B
Bernard Xiong 已提交
172
rt_hw_interrupt_thread_switch:
173 174
    BX      LR
    NOP
B
Bernard Xiong 已提交
175

176 177
    .global HardFault_Handler
    .type HardFault_Handler, %function
B
Bernard Xiong 已提交
178 179
HardFault_Handler:
    /* get current context */
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    MRS     r0, msp                 /* get fault context from handler. */
    TST     lr, #0x04               /* if(!EXC_RETURN[2]) */
    BEQ     _get_sp_done
    MRS     r0, psp                 /* get fault context from thread. */
_get_sp_done:

    STMFD   r0!, {r4 - r11}         /* push r4 - r11 register */
    STMFD   r0!, {lr}               /* push exec_return register */

    TST     lr, #0x04               /* if(!EXC_RETURN[2])
    BEQ     _update_msp
    MSR     psp, r0                 /* update stack pointer to PSP. */
    B       _update_done
_update_msp:
    MSR     msp, r0                 /* update stack pointer to MSP. */
_update_done:

B
Bernard Xiong 已提交
197 198 199 200 201 202 203 204 205 206 207
    PUSH    {LR}
    BL      rt_hw_hard_fault_exception
    POP     {LR}

    ORR     LR, LR, #0x04
    BX      LR

/*
 * rt_uint32_t rt_hw_interrupt_check(void);
 * R0 --> state
 */
208 209
    .global rt_hw_interrupt_check
    .type rt_hw_interrupt_check, %function
B
Bernard Xiong 已提交
210
rt_hw_interrupt_check:
211 212
    MRS     R0, IPSR
    BX      LR