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/GNU */ 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) _free_memory; */ 102 103 la $9, _free_memory # 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 268 /* Interrupt 5 is the count/compare timer interrupt. */ 269 270#ifdef TX_ENABLE_EVENT_TRACE 271 li $4,0 # Build interrupt type 272 la $9, _tx_trace_isr_enter_insert # Build interrupt enter logging address 273 jal $9 # Call interrupt enter event logging 274 nop # 275#endif 276 277 278 /* Interrupt 5 is the count/compare timer interrupt. */ 279 280 mtc0 $0, $9 # Initialize CP0 count register to zero 281 ehb # 282 li $9, TEN_MS_COUNT # 10 ms @ 66 MHz 283 mtc0 $9, $11 # Set compare register, reset count reg. 284 ehb # 285 286 /* Call the ThreadX timer routine. */ 287 288 la $8, _tx_timer_interrupt # Build timer interrupt address 289 jal $8 # Call timer interrupt handler 290 nop # 291 292#ifdef TX_ENABLE_EVENT_TRACE 293 li $4,0 # Build interrupt type 294 la $9, _tx_trace_isr_exit_insert # Build interrupt exit logging address 295 jal $9 # Call interrupt exit event logging 296 nop # 297#endif 298 299_tx_not_interrupt_5: 300 301 /* Check for Software Interrupt 0. */ 302 303 andi $8, $16, SW_INTERRUPT_0 # Isolate software interrupt 0 flag 304 beqz $8, _tx_not_interrupt_sw_0 # If not set, skip sw interrupt 0 processing 305 nop # Delay slot 306 307 /* Software interrupt 0 processing goes here! */ 308 309_tx_not_interrupt_sw_0: 310 311 /* Check for Software Interrupt 1. */ 312 313 andi $8, $16, SW_INTERRUPT_1 # Isolate software interrupt 1 flag 314 beqz $8, _tx_not_interrupt_sw_1 # If not set, skip sw interrupt 1 processing 315 nop # Delay slot 316 317 /* Software interrupt 1 processing goes here! */ 318 319_tx_not_interrupt_sw_1: 320 321 la $8, _tx_thread_context_restore # Pickup address of context restore function 322 j $8 # Jump to context restore - does not return! 323 nop # Delay slot 324 325 /* Error Exception processing goes here! */ 326 327 .globl _tx_error_exceptions 328_tx_error_exceptions: 329 b _tx_error_exceptions # Default error exception processing 330 nop # Delay slot 331 332 333 /* Reference the build options and the version ID to ensure they are part of the image. */ 334 la $8, _tx_build_options 335 la $9, _tx_version_id 336