1/**************************************************************************/
2/*                                                                        */
3/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4/*                                                                        */
5/*       This software is licensed under the Microsoft Software License   */
6/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8/*       and in the root directory of this software.                      */
9/*                                                                        */
10/**************************************************************************/
11
12
13/**************************************************************************/
14/**************************************************************************/
15/**                                                                       */
16/** ThreadX Component                                                     */
17/**                                                                       */
18/**   Initialize                                                          */
19/**                                                                       */
20/**************************************************************************/
21/**************************************************************************/
22
23
24#define GIC_SH_WEDGE    0xbbdc0280          /* For Inter-processor interrupts on MALTA board.  */
25
26    INITIAL_SR          =   0xFF00          # All IM bits set
27    SW_INTERRUPT_0      =   0x0100          # Software interrupt 0
28    SW_INTERRUPT_1      =   0x0200          # Software interrupt 1
29    INTERRUPT_0         =   0x0400          # Interrupt 0
30    INTERRUPT_1         =   0x0800          # Interrupt 1
31    INTERRUPT_2         =   0x1000          # Interrupt 2
32    INTERRUPT_3         =   0x2000          # Interrupt 3
33    INTERRUPT_4         =   0x4000          # Interrupt 4
34    INTERRUPT_5         =   0x8000          # Interrupt 5
35    EXCEPTION_VECTOR    =   0x00000180      # General exception vector
36    TEN_MS_COUNT        =   120000          # 10 ms clock rate
37
38    .text
39    .set        noreorder
40/**************************************************************************/
41/*                                                                        */
42/*  FUNCTION                                               RELEASE        */
43/*                                                                        */
44/*    _tx_initialize_low_level              MIPS32_interAptiv/Green Hills */
45/*                                                           6.2.1        */
46/*  AUTHOR                                                                */
47/*                                                                        */
48/*    Scott Larson, Microsoft Corporation                                 */
49/*                                                                        */
50/*  DESCRIPTION                                                           */
51/*                                                                        */
52/*    This function is responsible for any low-level processor            */
53/*    initialization, including setting up interrupt vectors, setting     */
54/*    up a periodic timer interrupt source, saving the system stack       */
55/*    pointer for use in ISR processing later, and finding the first      */
56/*    available RAM memory address for tx_application_define.             */
57/*                                                                        */
58/*  INPUT                                                                 */
59/*                                                                        */
60/*    None                                                                */
61/*                                                                        */
62/*  OUTPUT                                                                */
63/*                                                                        */
64/*    None                                                                */
65/*                                                                        */
66/*  CALLS                                                                 */
67/*                                                                        */
68/*    None                                                                */
69/*                                                                        */
70/*  CALLED BY                                                             */
71/*                                                                        */
72/*    _tx_initialize_kernel_enter           ThreadX entry function        */
73/*                                                                        */
74/*  RELEASE HISTORY                                                       */
75/*                                                                        */
76/*    DATE              NAME                      DESCRIPTION             */
77/*                                                                        */
78/*  03-08-2023      Scott Larson            Initial Version 6.2.1         */
79/*                                                                        */
80/**************************************************************************/
81/* VOID   _tx_initialize_low_level(VOID)
82{  */
83    .globl  _tx_initialize_low_level
84_tx_initialize_low_level:
85
86    di                                          # Ensure interrupts are disabled
87    ehb                                         #
88    mfc0    $8, $12                             # Pickup current SR
89    ori     $8, $8, INITIAL_SR                  # Build initial SR
90    mtc0    $8, $12                             # Setup SR
91
92    /* Save the system stack pointer.  */
93    /* _tx_thread_system_stack_ptr = (VOID_PTR) (SP);  */
94
95    la      $8, _tx_thread_system_stack_ptr     # Pickup address of system
96                                        /*      #   stack pointer  */
97    sw      $29, ($8)                           # Save system stack pointer
98
99
100    /* Save the first available memory address.  */
101    /* _tx_initialize_unused_memory =  (VOID_PTR) __ghsbegin_free_mem;  */
102
103    la      $9, __ghsbegin_free_mem             # Pickup first free address
104    la      $10, _tx_initialize_unused_memory   # Pickup address of unused
105                                        /*      #   memory  */
106    sw      $9, ($10)                           # Save unused memory address
107
108
109    /*  Set up the counter/compare registers to generate a periodic interrupt.  */
110
111    mtc0    $0, $9                              # Initialize CP0 timer count register to zero
112    ehb                                         #
113    li      $9,TEN_MS_COUNT                     # Default value
114    mtc0    $9, $11                             # Set timer compare register
115    ehb                                         #
116
117
118    /* Done, return to caller.  */
119
120    j       $31                                 # Return to caller
121    nop                                         # Delay slot
122/* }  */
123
124
125    /* Define the interrupt/exception handler trampoline code.  This needs to
126       be copied to address 0x80000180 cached or 0xA0000180 non-cache.  */
127
128    .globl  _tx_exception_trampoline
129_tx_exception_trampoline:
130    la      $26,_tx_exception_handler           # Pickup exception handler address
131    j       $26                                 # Jump to exception handler
132    nop                                         # Delay slot
133    nop                                         # Fill with nops....
134    nop                                         #
135    nop                                         #
136    nop                                         #
137    nop                                         #
138_tx_exception_trampoline_end:
139
140
141
142    /* Define the actual interrupt/exception handler.  Since this routine must handle
143       multiple exceptions, the context save/restore functions are called automatically.
144       Application specific ISR processing added to this routine must be inserted into
145       the proper place and use registers in accordance with the MIPS compiler, i.e.
146       $16-$23 (s0-s7) and $30 (s8) must be saved if they are used.  C functions called
147       from this area will automatically save/restore these registers if they are used.  */
148
149    .globl  _tx_exception_handler
150_tx_exception_handler:
151    mfc0    $26, $13                            # Pickup the cause register
152    ehb                                         #
153    andi    $26, $26, 0x3C                      # Isolate the exception code
154    bne     $26, $0, _tx_error_exceptions       # If non-zero, an error exception is present
155    nop                                         # Delay slot
156
157    la      $27, _tx_thread_smp_system_error    # Build address to system error flag
158    lw      $27, ($27)                          # Pickup system error flag
159_system_error_loop:
160    bne     $27, $0, _system_error_loop         # If error, just sit here!
161    nop
162
163    /* Otherwise, an interrupt exception is present.  Call context save before we
164       process normal interrupts.  */
165
166    la      $26, _tx_thread_context_save        # Pickup address of context save function
167    jalr    $27,$26                             # Call context save
168    nop                                         # Delay slot
169
170    /* Perform interrupt processing here!  When context save returns, interrupts are
171       disabled and all compiler scratch registers are available.  Also, s0 is saved and
172       is used in this function to hold the contents of the CAUSE register.  */
173
174    mfc0    $16, $13                            # Pickup the cause register
175
176
177    /* Interrupts may be re-enabled after this point.  */
178
179    /* Check for Interrupt 0.  */
180
181    andi    $8, $16, INTERRUPT_0                # Isolate interrupt 0 flag
182    beqz    $8, _tx_not_interrupt_0             # If not set, skip interrupt 0 processing
183    nop                                         # Delay slot
184
185    /* Interrupt 0 processing goes here!  */
186
187#ifdef TX_ENABLE_EVENT_TRACE
188    li      $4,1                                # Build interrupt type
189    la      $9, _tx_trace_isr_enter_insert      # Build interrupt enter logging address
190    jal     $9                                  # Call interrupt enter event logging
191    nop                                         #
192#endif
193
194    /* Clear inter-processor interrupt (and increment counter).  */
195
196    mfc0    $8, $4,2                            # Pickup UserLocal (VPE number)
197    la      $9, _tx_thread_smp_inter_core_interrupts # Address of inter-processor interrupt
198    sll     $8, $8, 2                           # Build offset to proper counter index
199    addu    $9, $9, $8                          # Build address of this VPE's counter
200    lw      $8, 0($9)                           # Pickup current value
201    addiu   $8, $8, 1                           # Increment current value
202    sw      $8, 0($9)                           # Store value back
203
204    li      $8, GIC_SH_WEDGE                    #
205    mfc0    $9, $15, 1                          # Get cp0 EBase
206    ext     $9, $9, 0, 10                       # Extract CPUNum
207    addiu   $9, 0x20                            # Offset to base of IPI interrupts.
208    sw      $9, 0($8)                           # Clear this IPI.
209
210#ifdef TX_ENABLE_EVENT_TRACE
211    li      $4,1                                # Build interrupt type
212    la      $9, _tx_trace_isr_exit_insert       # Build interrupt exit logging address
213    jal     $9                                  # Call interrupt exit event logging
214    nop                                         #
215#endif
216
217_tx_not_interrupt_0:
218
219    /* Check for Interrupt 1.  */
220
221    andi    $8, $16, INTERRUPT_1                # Isolate interrupt 1 flag
222    beqz    $8, _tx_not_interrupt_1             # If not set, skip interrupt 1 processing
223    nop                                         # Delay slot
224
225    /* Interrupt 1 processing goes here!  */
226
227_tx_not_interrupt_1:
228
229    /* Check for Interrupt 2.  */
230
231    andi    $8, $16, INTERRUPT_2                # Isolate interrupt 2 flag
232    beqz    $8, _tx_not_interrupt_2             # If not set, skip interrupt 2 processing
233    nop                                         # Delay slot
234
235    /* Interrupt 2 processing goes here!  */
236
237_tx_not_interrupt_2:
238
239    /* Check for Interrupt 3.  */
240
241    andi    $8, $16, INTERRUPT_3                # Isolate interrupt 3 flag
242    beqz    $8, _tx_not_interrupt_3             # If not set, skip interrupt 3 processing
243    nop                                         # Delay slot
244
245    /* Interrupt 3 processing goes here!  */
246
247_tx_not_interrupt_3:
248
249    /* Check for Interrupt 4.  */
250
251    andi    $8, $16, INTERRUPT_4                # Isolate interrupt 4 flag
252    beqz    $8, _tx_not_interrupt_4             # If not set, skip interrupt 4 processing
253    nop                                         # Delay slot
254
255    /* Interrupt 4 processing goes here!  */
256
257_tx_not_interrupt_4:
258
259    /* Check for Interrupt 5.  */
260
261    andi    $8, $16, INTERRUPT_5                # Isolate interrupt 5 flag
262    beqz    $8, _tx_not_interrupt_5             # If not set, skip interrupt 5 processing
263    nop                                         # Delay slot
264
265    /* Interrupt 5 processing goes here!  */
266
267#ifdef TX_ENABLE_EVENT_LOGGING
268    li      $4,0                                # Build interrupt type
269    la      $9, _tx_el_interrupt                # Build interrupt start logging address
270    jal     $9                                  # Call interrupt start event logging
271    nop                                         #
272#endif
273
274#ifdef TX_ENABLE_EVENT_TRACE
275    li      $4,0                                # Build interrupt type
276    la      $9, _tx_trace_isr_enter_insert      # Build interrupt enter logging address
277    jal     $9                                  # Call interrupt enter event logging
278    nop                                         #
279#endif
280
281
282    /* Interrupt 5 is the count/compare timer interrupt.  */
283
284    mtc0    $0, $9                              # Initialize CP0 count register to zero
285    ehb                                         #
286    li      $9, TEN_MS_COUNT                    # 10 ms @ 66 MHz
287    mtc0    $9, $11                             # Set compare register, reset count reg.
288    ehb                                         #
289
290    /* Call the ThreadX timer routine.  */
291
292    la      $8, _tx_timer_interrupt             # Build timer interrupt address
293    jal     $8                                  # Call timer interrupt handler
294    nop                                         #
295
296#ifdef TX_ENABLE_EVENT_LOGGING
297    li      $4,0                                # Build interrupt type
298    la      $9, _tx_el_interrupt_end            # Build interrupt end logging address
299    jal     $9                                  # Call interrupt end event logging
300    nop                                         #
301#endif
302
303#ifdef TX_ENABLE_EVENT_TRACE
304    li      $4,0                                # Build interrupt type
305    la      $9, _tx_trace_isr_exit_insert       # Build interrupt exit logging address
306    jal     $9                                  # Call interrupt exit event logging
307    nop                                         #
308#endif
309
310_tx_not_interrupt_5:
311
312    /* Check for Software Interrupt 0.  */
313
314    andi    $8, $16, SW_INTERRUPT_0             # Isolate software interrupt 0 flag
315    beqz    $8, _tx_not_interrupt_sw_0          # If not set, skip sw interrupt 0 processing
316    nop                                         # Delay slot
317
318    /* Software interrupt 0 processing goes here!  */
319
320_tx_not_interrupt_sw_0:
321
322    /* Check for Software Interrupt 1.  */
323
324    andi    $8, $16, SW_INTERRUPT_1             # Isolate software interrupt 1 flag
325    beqz    $8, _tx_not_interrupt_sw_1          # If not set, skip sw interrupt 1 processing
326    nop                                         # Delay slot
327
328    /* Software interrupt 1 processing goes here!  */
329
330_tx_not_interrupt_sw_1:
331
332    la      $8, _tx_thread_context_restore      # Pickup address of context restore function
333    j       $8                                  # Jump to context restore - does not return!
334    nop                                         # Delay slot
335
336    /* Error Exception processing goes here!  */
337
338    .globl  _tx_error_exceptions
339_tx_error_exceptions:
340
341    la      $26, _tx_thread_smp_system_error    # Build address of system error flag
342    li      $27, 1                              # Build error flag
343    sw      $27, ($26)                          # Set error flag
344
345_tx_error_exception_loop:
346    b       _tx_error_exception_loop            # Default error exception processing - just spin!
347    nop                                         # Delay slot
348
349
350    /* Reference the build options and the version ID to ensure they are part of the image.  */
351    la      $8, _tx_build_options
352    la      $9, _tx_version_id
353