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