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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
|
;/***************************************************************************
; * 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 */
;/** */
;/**************************************************************************/
;/**************************************************************************/
#ifdef TX_INCLUDE_USER_DEFINE_FILE
#include "tx_user.h"
#endif
.equ BTA, 0x412
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_context_fast_restore ARC_HS/MetaWare */
;/* 6.2.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function restores the fast interrupt context, which can be a */
;/* nesting condition on a non-fast ISR, an idle system restore, a */
;/* restore of an interrupted thread, and a preemption of an interrupted*/
;/* thread. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* _tx_thread_schedule Thread scheduling routine */
;/* */
;/* CALLED BY */
;/* */
;/* ISRs Interrupt Service Routines */
;/* */
;/**************************************************************************/
;VOID _tx_thread_context_fast_restore(VOID)
;{
.global _tx_thread_context_fast_restore
.type _tx_thread_context_fast_restore, @function
_tx_thread_context_fast_restore:
;
; /* Note: it is assumed that the stack pointer is in the same position now as
; it was after the last context fast save call. */
;
.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the ISR exit function to indicate an ISR is complete. */
;
bl.d _tx_execution_isr_exit ; Call the ISR exit function
sub sp, sp, 16 ; ..allocating some space on the stack
add sp, sp, 16 ; Recover the stack space
.endif
;
; /* Determine if interrupts are nested. */
; if (--_tx_thread_system_state)
; {
;
ld r0, [gp, _tx_thread_system_state@sda] ; Pickup system state contents
sub r0, r0, 1 ; Decrement the system state
st r0, [gp, _tx_thread_system_state@sda] ; Store the new system state
breq r0, 0, __tx_thread_not_nested_restore ; If zero, not a nested interrupt
;
; /* Interrupts are nested. */
;
; /* Just recover the saved registers and return to the point of
; interrupt. */
;
__tx_thread_nested_restore:
rtie ; Return from interrupt
;
;
; }
__tx_thread_not_nested_restore:
;
; /* Determine if a thread was interrupted and no preemption is required. */
; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr))
; || (_tx_thread_preempt_disable))
; {
;
ld r0, [gp, _tx_thread_current_ptr@sda] ; Pickup current thread pointer
ld r2, [gp, _tx_thread_preempt_disable@sda] ; Pickup preempt disable flag
sub.f 0, r0, 0 ; Set condition codes
beq.d __tx_thread_idle_system_restore ; If NULL, idle system was interrupted
lr r4, [AUX_IRQ_ACT] ; Pickup the interrupt active register
neg r5, r4 ; Negate
and r5, r4, r5 ; See if there are any other interrupts present
brne.d r4, r5, __tx_thread_no_preempt_restore ; If more interrupts, just return to the point of interrupt
ld r4, [gp, _tx_thread_execute_ptr@sda] ; Pickup next thread to execute
brne r2, 0, __tx_thread_no_preempt_restore ; If set, don't preempt executing thread
brne r0, r4, __tx_thread_preempt_restore ; Not equal, preempt executing thread
;
;
__tx_thread_no_preempt_restore:
;
; /* Restore interrupted thread or ISR. */
;
; /* Pickup the saved stack pointer. */
; sp = _tx_thread_current_ptr -> tx_thread_stack_ptr;
;
; /* Return to the point of interrupt. */
;
rtie ; Return from interrupt
;
; }
; else
; {
__tx_thread_preempt_restore:
;
lr r3, [status32_p0] ; Pickup the interrupted status32.p0 register
lsr r4, r3, 16 ; Move the register bank bits down
and r4, r4, 7 ; Isolate the register bank
breq r4, 0, __tx_software_interrupt_context ; If register bank 0, software interrupt context is present
st ilink, [sp, 0] ; Save ilink (point of interrupt)
st r3, [sp, 4] ; Save actual status32.p0
bclr r4, r3, 16 ; Build register bank 0 value
bclr r4, r4, 17 ;
bclr r4, r4, 18 ;
sr r4, [status32_p0] ; Setup status32.p0 to return to bank 0 when fast ISR is finishe
mov ilink, sp ; Pass the information back to the other register bank via ilink
bclr r3, r3, 31 ; Make sure interrupts are not enabled
kflag r3 ; Switch back to the interrupted thread's hardware register bank
sub sp, sp, 168 ; Allocate an hardware interrupt stack frame
st r0, [sp, 132] ; Temporarily save r0
mov r0, 3 ; Build hardware interrupt stack type
st r0, [sp, 0] ; Setup interrupt stack type
.ifndef TX_DISABLE_LP
lr r0, [LP_START] ; Pickup LP_START
st r0, [sp, 4] ; Save LP_START
lr r0, [LP_END] ; Pickup LP_END
st r0, [sp, 8] ; Save LP_END
st LP_COUNT, [sp, 12] ; Save LP_COUNT
.endif
lr r0, [BTA] ; Pickup BTA
st r0, [sp, 156] ; Save BTA
ld r0, [ilink, 0] ; Pickup the point of interrupt
st r0, [sp, 160] ; Setup the point of interrupt
st r0, [sp, 20] ; Save ilink
ld r0, [ilink, 4] ; Pickup the status32
st r0, [sp, 164] ; Setup the status32
ld r0, [gp, _tx_thread_current_ptr@sda] ; Pickup current thread pointer
st sp, [r0, 8] ; Save stack pointer in thread control block
ld r0, [sp, 132] ; Restore r0
lr ilink, [status32] ; Pickup status32 register
bset ilink, ilink, 16 ; Build register bank 1 value
bclr ilink, ilink, 17 ;
bclr ilink, ilink, 18 ;
kflag ilink ; Move back to register bank 0
b __tx_preempt_save_done ; Done, finished with preemption save
__tx_software_interrupt_context:
st ilink, [sp, 0] ; Save ilink (point of interrupt)
st r3, [sp, 4] ; Save status32
mov ilink, sp ; Pass the information back to the other register bank via ilink
bclr r3, r3, 31 ; Make sure interrupts are not enabled
kflag r3 ; Switch back to the interrupted thread's hardware register bank
sub sp, sp, 168 ; Allocate an hardware interrupt stack frame
st blink, [sp, 16] ; Save blink
st fp, [sp, 24] ; Save fp
st gp, [sp, 28] ; Save gp
st r25, [sp, 32] ; Save r25
st r24, [sp, 36] ; Save r24
st r23, [sp, 40] ; Save r23
st r22, [sp, 44] ; Save r22
st r21, [sp, 48] ; Save r21
st r20, [sp, 52] ; Save r20
st r19, [sp, 56] ; Save r19
st r18, [sp, 60] ; Save r18
st r17, [sp, 64] ; Save r17
st r16, [sp, 68] ; Save r16
st r15, [sp, 72] ; Save r15
st r14, [sp, 76] ; Save r14
st r13, [sp, 80] ; Save r13
st r12, [sp, 84] ; Save r12
st r11, [sp, 88] ; Save r11
st r10, [sp, 92] ; Save r10
st r9, [sp, 96] ; Save r9
st r8, [sp, 100] ; Save r8
st r7, [sp, 104] ; Save r7
st r6, [sp, 108] ; Save r6
st r5, [sp, 112] ; Save r5
st r4, [sp, 116] ; Save r6
st r3, [sp, 120] ; Save r3
st r2, [sp, 124] ; Save r2
st r1, [sp, 128] ; Save r1
st r0, [sp, 132] ; Save r0
st r30, [sp, 136] ; Save r30
.ifndef TX_DISABLE_LP
lr r10, [LP_START] ; Pickup LP_START
lr r9, [LP_END] ; Pickup LP_END
st LP_COUNT, [sp, 12] ; Save LP_COUNT
st r10, [sp, 4] ; Save LP_START
st r9, [sp, 8] ; Save LP_END
.endif
lr r0, [BTA] ; Pickup BTA
st r0, [sp, 156] ; Save BTA
mov r6, 1 ; Build interrupt stack type
st r6, [sp, 0] ; Setup interrupt stack type
ld r0, [ilink, 0] ; Pickup the point of interrupt
st r0, [sp, 160] ; Setup the point of interrupt
st r0, [sp, 20] ; Save ilink
ld r0, [ilink, 4] ; Pickup the status32
st r0, [sp, 164] ; Setup the status32
ld r0, [gp, _tx_thread_current_ptr@sda] ; Pickup current thread pointer
st sp, [r0, 8] ; Save stack pointer in thread control block
lr ilink, [status32] ; Pickup status32 register
bset ilink, ilink, 16 ; Build register bank 1 value
bclr ilink, ilink, 17 ;
bclr ilink, ilink, 18 ;
kflag ilink ; Move back to register bank 1
__tx_preempt_save_done:
;
ld r0, [gp, _tx_thread_current_ptr@sda] ; Pickup current thread ptr
;
; /* Save the remaining time-slice and disable it. */
; if (_tx_timer_time_slice)
; {
;
ld r2, [gp, _tx_timer_time_slice@sda] ; Pickup time-slice contents
mov r7, 0 ; Build clear/NULL value
breq r2, 0, __tx_thread_dont_save_ts ; No time-slice, don't need to save it
;
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
; _tx_timer_time_slice = 0;
;
st r2, [r0, 24] ; If set, save remaining time-slice
st r7, [gp, _tx_timer_time_slice@sda] ; If set, clear time slice
;
; }
__tx_thread_dont_save_ts:
;
;
; /* Clear the current thread pointer. */
; _tx_thread_current_ptr = TX_NULL;
;
st r7, [gp, _tx_thread_current_ptr@sda] ; Set current thread ptr to NULL
mov ilink, _tx_thread_schedule ; Build address of scheduler
rtie ; Return from interrupt to scheduler
;
; }
;
; /* Return to the scheduler. */
; _tx_thread_schedule();
;
__tx_thread_idle_system_restore:
lr r4, [AUX_IRQ_ACT] ; Pickup the interrupt active register
neg r5, r4 ; Negate
and r5, r4, r5 ; See if there are any other interrupts present
sub.f 0, r4, r5 ; Set condition codes
bne __tx_thread_nested_restore ; If more interrupts, just return to the point of interrupt
mov ilink, _tx_thread_schedule ; Build address of scheduler
rtie ; Return from interrupt to scheduler
;
;}
.end
|