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