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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2026-present Eclipse ThreadX contributors
*
* 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 */
/** */
/** Initialize */
/** */
/**************************************************************************/
/**************************************************************************/
#define GIC_SH_WEDGE 0xbbdc0280 /* For Inter-processor interrupts on MALTA board. */
INITIAL_SR = 0xFF00 # All IM bits set
SW_INTERRUPT_0 = 0x0100 # Software interrupt 0
SW_INTERRUPT_1 = 0x0200 # Software interrupt 1
INTERRUPT_0 = 0x0400 # Interrupt 0
INTERRUPT_1 = 0x0800 # Interrupt 1
INTERRUPT_2 = 0x1000 # Interrupt 2
INTERRUPT_3 = 0x2000 # Interrupt 3
INTERRUPT_4 = 0x4000 # Interrupt 4
INTERRUPT_5 = 0x8000 # Interrupt 5
EXCEPTION_VECTOR = 0x00000180 # General exception vector
TEN_MS_COUNT = 120000 # 10 ms clock rate
.text
.set noreorder
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_initialize_low_level MIPS32_interAptiv/GNU */
/* 6.2.1 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for any low-level processor */
/* initialization, including setting up interrupt vectors, setting */
/* up a periodic timer interrupt source, saving the system stack */
/* pointer for use in ISR processing later, and finding the first */
/* available RAM memory address for tx_application_define. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* */
/**************************************************************************/
/* VOID _tx_initialize_low_level(VOID)
{ */
.globl _tx_initialize_low_level
_tx_initialize_low_level:
di # Ensure interrupts are disabled
ehb #
mfc0 $8, $12 # Pickup current SR
ori $8, $8, INITIAL_SR # Build initial SR
mtc0 $8, $12 # Setup SR
/* Save the system stack pointer. */
/* _tx_thread_system_stack_ptr = (VOID_PTR) (SP); */
la $8, _tx_thread_system_stack_ptr # Pickup address of system
/* # stack pointer */
sw $29, ($8) # Save system stack pointer
/* Save the first available memory address. */
/* _tx_initialize_unused_memory = (VOID_PTR) _free_memory; */
la $9, _free_memory # Pickup first free address
la $10, _tx_initialize_unused_memory # Pickup address of unused
/* # memory */
sw $9, ($10) # Save unused memory address
/* Set up the counter/compare registers to generate a periodic interrupt. */
mtc0 $0, $9 # Initialize CP0 timer count register to zero
ehb #
li $9,TEN_MS_COUNT # Default value
mtc0 $9, $11 # Set timer compare register
ehb #
/* Done, return to caller. */
j $31 # Return to caller
nop # Delay slot
/* } */
/* Define the interrupt/exception handler trampoline code. This needs to
be copied to address 0x80000180 cached or 0xA0000180 non-cache. */
.globl _tx_exception_trampoline
_tx_exception_trampoline:
la $26,_tx_exception_handler # Pickup exception handler address
j $26 # Jump to exception handler
nop # Delay slot
nop # Fill with nops....
nop #
nop #
nop #
nop #
_tx_exception_trampoline_end:
/* Define the actual interrupt/exception handler. Since this routine must handle
multiple exceptions, the context save/restore functions are called automatically.
Application specific ISR processing added to this routine must be inserted into
the proper place and use registers in accordance with the MIPS compiler, i.e.
$16-$23 (s0-s7) and $30 (s8) must be saved if they are used. C functions called
from this area will automatically save/restore these registers if they are used. */
.globl _tx_exception_handler
_tx_exception_handler:
mfc0 $26, $13 # Pickup the cause register
ehb #
andi $26, $26, 0x3C # Isolate the exception code
bne $26, $0, _tx_error_exceptions # If non-zero, an error exception is present
nop # Delay slot
la $27, _tx_thread_smp_system_error # Build address to system error flag
lw $27, ($27) # Pickup system error flag
_system_error_loop:
bne $27, $0, _system_error_loop # If error, just sit here!
nop
/* Otherwise, an interrupt exception is present. Call context save before we
process normal interrupts. */
la $26, _tx_thread_context_save # Pickup address of context save function
jalr $27,$26 # Call context save
nop # Delay slot
/* Perform interrupt processing here! When context save returns, interrupts are
disabled and all compiler scratch registers are available. Also, s0 is saved and
is used in this function to hold the contents of the CAUSE register. */
mfc0 $16, $13 # Pickup the cause register
/* Interrupts may be re-enabled after this point. */
/* Check for Interrupt 0. */
andi $8, $16, INTERRUPT_0 # Isolate interrupt 0 flag
beqz $8, _tx_not_interrupt_0 # If not set, skip interrupt 0 processing
nop # Delay slot
/* Interrupt 0 processing goes here! */
#ifdef TX_ENABLE_EVENT_TRACE
li $4,1 # Build interrupt type
la $9, _tx_trace_isr_enter_insert # Build interrupt enter logging address
jal $9 # Call interrupt enter event logging
nop #
#endif
/* Clear inter-processor interrupt (and increment counter). */
mfc0 $8, $4,2 # Pickup UserLocal (VPE number)
la $9, _tx_thread_smp_inter_core_interrupts # Address of inter-processor interrupt
sll $8, $8, 2 # Build offset to proper counter index
addu $9, $9, $8 # Build address of this VPE's counter
lw $8, 0($9) # Pickup current value
addiu $8, $8, 1 # Increment current value
sw $8, 0($9) # Store value back
li $8, GIC_SH_WEDGE #
mfc0 $9, $15, 1 # Get cp0 EBase
ext $9, $9, 0, 10 # Extract CPUNum
addiu $9, 0x20 # Offset to base of IPI interrupts.
sw $9, 0($8) # Clear this IPI.
#ifdef TX_ENABLE_EVENT_TRACE
li $4,1 # Build interrupt type
la $9, _tx_trace_isr_exit_insert # Build interrupt exit logging address
jal $9 # Call interrupt exit event logging
nop #
#endif
_tx_not_interrupt_0:
/* Check for Interrupt 1. */
andi $8, $16, INTERRUPT_1 # Isolate interrupt 1 flag
beqz $8, _tx_not_interrupt_1 # If not set, skip interrupt 1 processing
nop # Delay slot
/* Interrupt 1 processing goes here! */
_tx_not_interrupt_1:
/* Check for Interrupt 2. */
andi $8, $16, INTERRUPT_2 # Isolate interrupt 2 flag
beqz $8, _tx_not_interrupt_2 # If not set, skip interrupt 2 processing
nop # Delay slot
/* Interrupt 2 processing goes here! */
_tx_not_interrupt_2:
/* Check for Interrupt 3. */
andi $8, $16, INTERRUPT_3 # Isolate interrupt 3 flag
beqz $8, _tx_not_interrupt_3 # If not set, skip interrupt 3 processing
nop # Delay slot
/* Interrupt 3 processing goes here! */
_tx_not_interrupt_3:
/* Check for Interrupt 4. */
andi $8, $16, INTERRUPT_4 # Isolate interrupt 4 flag
beqz $8, _tx_not_interrupt_4 # If not set, skip interrupt 4 processing
nop # Delay slot
/* Interrupt 4 processing goes here! */
_tx_not_interrupt_4:
/* Check for Interrupt 5. */
andi $8, $16, INTERRUPT_5 # Isolate interrupt 5 flag
beqz $8, _tx_not_interrupt_5 # If not set, skip interrupt 5 processing
nop # Delay slot
/* Interrupt 5 processing goes here! */
/* Interrupt 5 is the count/compare timer interrupt. */
#ifdef TX_ENABLE_EVENT_TRACE
li $4,0 # Build interrupt type
la $9, _tx_trace_isr_enter_insert # Build interrupt enter logging address
jal $9 # Call interrupt enter event logging
nop #
#endif
/* Interrupt 5 is the count/compare timer interrupt. */
mtc0 $0, $9 # Initialize CP0 count register to zero
ehb #
li $9, TEN_MS_COUNT # 10 ms @ 66 MHz
mtc0 $9, $11 # Set compare register, reset count reg.
ehb #
/* Call the ThreadX timer routine. */
la $8, _tx_timer_interrupt # Build timer interrupt address
jal $8 # Call timer interrupt handler
nop #
#ifdef TX_ENABLE_EVENT_TRACE
li $4,0 # Build interrupt type
la $9, _tx_trace_isr_exit_insert # Build interrupt exit logging address
jal $9 # Call interrupt exit event logging
nop #
#endif
_tx_not_interrupt_5:
/* Check for Software Interrupt 0. */
andi $8, $16, SW_INTERRUPT_0 # Isolate software interrupt 0 flag
beqz $8, _tx_not_interrupt_sw_0 # If not set, skip sw interrupt 0 processing
nop # Delay slot
/* Software interrupt 0 processing goes here! */
_tx_not_interrupt_sw_0:
/* Check for Software Interrupt 1. */
andi $8, $16, SW_INTERRUPT_1 # Isolate software interrupt 1 flag
beqz $8, _tx_not_interrupt_sw_1 # If not set, skip sw interrupt 1 processing
nop # Delay slot
/* Software interrupt 1 processing goes here! */
_tx_not_interrupt_sw_1:
la $8, _tx_thread_context_restore # Pickup address of context restore function
j $8 # Jump to context restore - does not return!
nop # Delay slot
/* Error Exception processing goes here! */
.globl _tx_error_exceptions
_tx_error_exceptions:
b _tx_error_exceptions # Default error exception processing
nop # Delay slot
/* Reference the build options and the version ID to ensure they are part of the image. */
la $8, _tx_build_options
la $9, _tx_version_id
|