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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
; * https://opensource.org/licenses/MIT.
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
;#define TX_SOURCE_CODE
;
;
;/* Include necessary system files. */
;
;#include "tx_api.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
extern __tx_thread_system_state
extern __tx_thread_current_ptr
section .text:CODE:ROOT
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_context_save RXv2/IAR */
;/* 6.1.11 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function saves the context of an executing thread in the */
;/* beginning of interrupt processing. The function also ensures that */
;/* the system stack is used upon return to the calling ISR. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* ISRs */
;/* */
;/**************************************************************************/
;VOID _tx_thread_context_save(VOID)
;{
public __tx_thread_context_save
__tx_thread_context_save:
;
; /* Upon entry to this routine, it is assumed that interrupts are locked
; out and the (interrupt) stack frame looks like the following:
;
; (lower address) SP -> [return address of this call]
; SP+4 -> Saved R1
; SP+8 -> Saved R2
; SP+12-> Interrupted PC
; SP+16-> Interrupted PSW
;
; /* Check for a nested interrupt condition. */
; if (_tx_thread_system_state++)
; {
;
MOV.L #__tx_thread_system_state, R1 ; Pick up address of system state
MOV.L [R1], R2 ; Pick up system state
CMP #0, R2 ; 0 -> no nesting
BEQ __tx_thread_not_nested_save
;
; /* Nested interrupt condition. */
;
ADD #1, r2 ; _tx_thread_system_state++
MOV.L r2, [r1]
;
; /* Save the rest of the scratch registers on the interrupt stack and return to the
; calling ISR. */
POP R1 ; Recuperate return address from stack
PUSHM R3-R5
PUSHM R14-R15
PUSHC FPSW ; (top) FPSW, R14, R15, R3, R4, R5, R1, R2, PC, PSW (bottom)
JMP R1 ; Return address was preserved in R1
;
__tx_thread_not_nested_save:
; }
;
; /* Otherwise, not nested, check to see if a thread was running. */
; else if (_tx_thread_current_ptr)
; {
;
ADD #1, R2 ; _tx_thread_system_state++
MOV.L R2, [R1]
MOV.L #__tx_thread_current_ptr, R2 ; Pickup current thread pointer
MOV.L [R2], R2
CMP #0,R2 ; Is it NULL?
BEQ __tx_thread_idle_system_save ; Yes, idle system is running - idle restore
;
; /* Move stack frame over to the current threads stack. */
; /* complete stack frame with registers not saved yet (R3-R5, R14-R15, FPSW) */
;
MVFC USP, R1 ; Pick up user stack pointer
MOV.L 16[R0], R2
MOV.L R2, [-R1] ; Save PSW on thread stack
MOV.L 12[R0], R2
MOV.L R2, [-R1] ; Save PC on thread stack
MOV.L 8[R0], R2
MOV.L R2, [-R1] ; Save R2 on thread stack
MOV.L 4[R0], R2
MOV.L R2, [-R1] ; Save R1 on thread stack
MOV.L R5, [-R1] ; Save R5 on thread stack
MOV.L R4, [-R1] ; Save R4 on thread stack
MOV.L R3, [-R1] ; Save R3 on thread stack
MOV.L R15, [-R1] ; Save R15 on thread stack
MOV.L R14, [-R1] ; Save R14 on thread stack
MVFC FPSW, R3
MOV.L R3, [-R1] ; Save FPSW on thread stack
POP R2 ; Pick up return address from interrupt stack
ADD #16, R0, R0 ; Correct interrupt stack pointer back to the bottom
MVTC R1, USP ; Set user/thread stack pointer
JMP R2 ; Return to ISR
; }
; else
; {
;
__tx_thread_idle_system_save:
;
; /* Interrupt occurred in the scheduling loop. */
;
POP R1 ; Pick up return address
ADD #16, R0, R0 ; Correct interrupt stack pointer back to the bottom (PC), don't care about saved registers
JMP R1 ; Return to caller
;
; }
;}
END
|