context_gcc.S 3.6 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
/*
 * File      : context_gcc.S
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006 - 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
rt_hw_interrupt_disable:
	MRS		r0, PRIMASK
	CPSID		I
	BX		LR

/*
 * void rt_hw_interrupt_enable(rt_base_t level);
 */
.global rt_hw_interrupt_enable
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
.global rt_hw_context_switch

rt_hw_context_switch_interrupt:
rt_hw_context_switch:
	/* set rt_thread_switch_interrput_flag to 1 */
	LDR 		r2, =rt_thread_switch_interrput_flag
	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]

	LDR		r0, =NVIC_INT_CTRL      	/* trigger the PendSV exception (causes context switch) */
	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
rt_hw_pend_sv:
	/* disable interrupt to protect context switch */
	MRS		r2, PRIMASK
	CPSID		I

	/* clear rt_thread_switch_interrput_flag to 0 */
	LDR		r0, =rt_thread_switch_interrput_flag
	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]
	LDR		r1, [r1]		/* load thread stack pointer */

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

	/* 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
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]

	/* set the PendSV exception priority */
	LDR		r0, =NVIC_SYSPRI2
	LDR		r1, =NVIC_PENDSV_PRI
	STR		r1, [r0]

	LDR		r0, =NVIC_INT_CTRL      /* trigger the PendSV exception (causes context switch) */
	LDR		r1, =NVIC_PENDSVSET
	STR		r1, [r0]
	
	CPSIE		I                       /* enable interrupts at processor level */
	
	/* never reach here! */

/* compatible with old version */
.global rt_hw_interrupt_thread_switch
rt_hw_interrupt_thread_switch:
	BX		lr
	NOP