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 .arm 24 25SVC_MODE = 0xD3 // Disable IRQ/FIQ SVC mode 26IRQ_MODE = 0xD2 // Disable IRQ/FIQ IRQ mode 27FIQ_MODE = 0xD1 // Disable IRQ/FIQ FIQ mode 28SYS_MODE = 0xDF // Disable IRQ/FIQ SYS mode 29FIQ_STACK_SIZE = 512 // FIQ stack size 30IRQ_STACK_SIZE = 1024 // IRQ stack size 31SYS_STACK_SIZE = 1024 // System stack size 32THUMB_MASK = 0x20 // THUMB mode bit 33 34 .global _tx_thread_system_stack_ptr 35 .global _tx_initialize_unused_memory 36 .global _tx_thread_context_save 37 .global _tx_thread_context_restore 38 .global _tx_timer_interrupt 39 .global _end 40 .global _sp 41 .global _stack_bottom 42 43 44/* Define the 16-bit Thumb mode veneer for _tx_initialize_low_level for 45 applications calling this function from to 16-bit Thumb mode. */ 46 47 .text 48 .align 2 49 .thumb 50 .global $_tx_initialize_low_level 51 .type $_tx_initialize_low_level,function 52$_tx_initialize_low_level: 53 BX pc // Switch to 32-bit mode 54 NOP // 55 .arm 56 STMFD sp!, {lr} // Save return address 57 BL _tx_initialize_low_level // Call _tx_initialize_low_level function 58 LDMFD sp!, {lr} // Recover saved return address 59 BX lr // Return to 16-bit caller 60 61 .text 62 .align 2 63/**************************************************************************/ 64/* */ 65/* FUNCTION RELEASE */ 66/* */ 67/* _tx_initialize_low_level ARMv7-A */ 68/* 6.1.11 */ 69/* AUTHOR */ 70/* */ 71/* William E. Lamie, Microsoft Corporation */ 72/* */ 73/* DESCRIPTION */ 74/* */ 75/* This function is responsible for any low-level processor */ 76/* initialization, including setting up interrupt vectors, setting */ 77/* up a periodic timer interrupt source, saving the system stack */ 78/* pointer for use in ISR processing later, and finding the first */ 79/* available RAM memory address for tx_application_define. */ 80/* */ 81/* INPUT */ 82/* */ 83/* None */ 84/* */ 85/* OUTPUT */ 86/* */ 87/* None */ 88/* */ 89/* CALLS */ 90/* */ 91/* None */ 92/* */ 93/* CALLED BY */ 94/* */ 95/* _tx_initialize_kernel_enter ThreadX entry function */ 96/* */ 97/* RELEASE HISTORY */ 98/* */ 99/* DATE NAME DESCRIPTION */ 100/* */ 101/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 102/* 04-25-2022 Zhen Kong Updated comments, */ 103/* resulting in version 6.1.11 */ 104/* */ 105/**************************************************************************/ 106 .global _tx_initialize_low_level 107 .type _tx_initialize_low_level,function 108_tx_initialize_low_level: 109 110 /* We must be in SVC mode at this point! */ 111 112 /* Setup various stack pointers. */ 113 114 LDR r1, =_sp // Get pointer to stack area 115 116#ifdef TX_ENABLE_IRQ_NESTING 117 118 /* Setup the system mode stack for nested interrupt support */ 119 120 LDR r2, =SYS_STACK_SIZE // Pickup stack size 121 MOV r3, #SYS_MODE // Build SYS mode CPSR 122 MSR CPSR_c, r3 // Enter SYS mode 123 SUB r1, r1, #1 // Backup 1 byte 124 BIC r1, r1, #7 // Ensure 8-byte alignment 125 MOV sp, r1 // Setup SYS stack pointer 126 SUB r1, r1, r2 // Calculate start of next stack 127#endif 128 129 LDR r2, =FIQ_STACK_SIZE // Pickup stack size 130 MOV r0, #FIQ_MODE // Build FIQ mode CPSR 131 MSR CPSR, r0 // Enter FIQ mode 132 SUB r1, r1, #1 // Backup 1 byte 133 BIC r1, r1, #7 // Ensure 8-byte alignment 134 MOV sp, r1 // Setup FIQ stack pointer 135 SUB r1, r1, r2 // Calculate start of next stack 136 LDR r2, =IRQ_STACK_SIZE // Pickup IRQ stack size 137 MOV r0, #IRQ_MODE // Build IRQ mode CPSR 138 MSR CPSR, r0 // Enter IRQ mode 139 SUB r1, r1, #1 // Backup 1 byte 140 BIC r1, r1, #7 // Ensure 8-byte alignment 141 MOV sp, r1 // Setup IRQ stack pointer 142 SUB r3, r1, r2 // Calculate end of IRQ stack 143 MOV r0, #SVC_MODE // Build SVC mode CPSR 144 MSR CPSR, r0 // Enter SVC mode 145 LDR r2, =_stack_bottom // Pickup stack bottom 146 CMP r3, r2 // Compare the current stack end with the bottom 147_stack_error_loop: 148 BLT _stack_error_loop // If the IRQ stack exceeds the stack bottom, just sit here! 149 150 LDR r2, =_tx_thread_system_stack_ptr // Pickup stack pointer 151 STR r1, [r2] // Save the system stack 152 153 LDR r1, =_end // Get end of non-initialized RAM area 154 LDR r2, =_tx_initialize_unused_memory // Pickup unused memory ptr address 155 ADD r1, r1, #8 // Increment to next free word 156 STR r1, [r2] // Save first free memory address 157 158#ifdef __THUMB_INTERWORK 159 BX lr // Return to caller 160#else 161 MOV pc, lr // Return to caller 162#endif 163 164/* Define shells for each of the interrupt vectors. */ 165 166 .global __tx_undefined 167__tx_undefined: 168 B __tx_undefined // Undefined handler 169 170 .global __tx_reserved_handler 171__tx_reserved_handler: 172 B __tx_reserved_handler // Reserved exception handler 173 174 .global __tx_irq_handler 175 .global __tx_irq_processing_return 176__tx_irq_handler: 177 178 /* Jump to context save to save system context. */ 179 B _tx_thread_context_save 180__tx_irq_processing_return: 181// 182 /* At this point execution is still in the IRQ mode. The CPSR, point of 183 interrupt, and all C scratch registers are available for use. In 184 addition, IRQ interrupts may be re-enabled - with certain restrictions - 185 if nested IRQ interrupts are desired. Interrupts may be re-enabled over 186 small code sequences where lr is saved before enabling interrupts and 187 restored after interrupts are again disabled. */ 188 189 /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 190 from IRQ mode with interrupts disabled. This routine switches to the 191 system mode and returns with IRQ interrupts enabled. 192 193 NOTE: It is very important to ensure all IRQ interrupts are cleared 194 prior to enabling nested IRQ interrupts. */ 195#ifdef TX_ENABLE_IRQ_NESTING 196 BL _tx_thread_irq_nesting_start 197#endif 198 199 /* For debug purpose, execute the timer interrupt processing here. In 200 a real system, some kind of status indication would have to be checked 201 before the timer interrupt handler could be called. */ 202 203 BL _tx_timer_interrupt // Timer interrupt handler 204 205 206 /* If interrupt nesting was started earlier, the end of interrupt nesting 207 service must be called before returning to _tx_thread_context_restore. 208 This routine returns in processing in IRQ mode with interrupts disabled. */ 209#ifdef TX_ENABLE_IRQ_NESTING 210 BL _tx_thread_irq_nesting_end 211#endif 212 213 /* Jump to context restore to restore system context. */ 214 B _tx_thread_context_restore 215 216 217 /* This is an example of a vectored IRQ handler. */ 218 219 220 221 /* Save initial context and call context save to prepare for 222 vectored ISR execution. */ 223 224 /* At this point execution is still in the IRQ mode. The CPSR, point of 225 interrupt, and all C scratch registers are available for use. In 226 addition, IRQ interrupts may be re-enabled - with certain restrictions - 227 if nested IRQ interrupts are desired. Interrupts may be re-enabled over 228 small code sequences where lr is saved before enabling interrupts and 229 restored after interrupts are again disabled. */ 230 231 232 /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 233 from IRQ mode with interrupts disabled. This routine switches to the 234 system mode and returns with IRQ interrupts enabled. 235 236 NOTE: It is very important to ensure all IRQ interrupts are cleared 237 prior to enabling nested IRQ interrupts. */ 238 239 /* Application IRQ handlers can be called here! */ 240 241 /* If interrupt nesting was started earlier, the end of interrupt nesting 242 service must be called before returning to _tx_thread_context_restore. 243 This routine returns in processing in IRQ mode with interrupts disabled. */ 244 245 246 247#ifdef TX_ENABLE_FIQ_SUPPORT 248 .global __tx_fiq_handler 249 .global __tx_fiq_processing_return 250__tx_fiq_handler: 251asdf 252 /* Jump to fiq context save to save system context. */ 253 B _tx_thread_fiq_context_save 254__tx_fiq_processing_return: 255 256 /* At this point execution is still in the FIQ mode. The CPSR, point of 257 interrupt, and all C scratch registers are available for use. */ 258 259 /* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start 260 from FIQ mode with interrupts disabled. This routine switches to the 261 system mode and returns with FIQ interrupts enabled. 262 263 NOTE: It is very important to ensure all FIQ interrupts are cleared 264 prior to enabling nested FIQ interrupts. */ 265#ifdef TX_ENABLE_FIQ_NESTING 266 BL _tx_thread_fiq_nesting_start 267#endif 268 269 /* Application FIQ handlers can be called here! */ 270 271 /* If interrupt nesting was started earlier, the end of interrupt nesting 272 service must be called before returning to _tx_thread_fiq_context_restore. */ 273#ifdef TX_ENABLE_FIQ_NESTING 274 BL _tx_thread_fiq_nesting_end 275#endif 276 277 /* Jump to fiq context restore to restore system context. */ 278 B _tx_thread_fiq_context_restore 279 280 281#else 282 .global __tx_fiq_handler 283__tx_fiq_handler: 284 B __tx_fiq_handler // FIQ interrupt handler 285#endif 286 287 288/**************************************************************************/ 289/* */ 290/* FUNCTION RELEASE */ 291/* */ 292/* __tx_prefetch_handler & __tx_abort_handler Cortex-A7/MMU/GNU */ 293/* 6.2.1 */ 294/* AUTHOR */ 295/* */ 296/* Scott Larson, Microsoft Corporation */ 297/* */ 298/* DESCRIPTION */ 299/* */ 300/* This function handles MMU exceptions and fills the */ 301/* _txm_module_manager_memory_fault_info struct. */ 302/* */ 303/* INPUT */ 304/* */ 305/* None */ 306/* */ 307/* OUTPUT */ 308/* */ 309/* None */ 310/* */ 311/* CALLS */ 312/* */ 313/* _txm_module_manager_memory_fault_handler */ 314/* _tx_execution_thread_exit */ 315/* _tx_thread_schedule */ 316/* */ 317/* CALLED BY */ 318/* */ 319/* MMU exceptions */ 320/* */ 321/* RELEASE HISTORY */ 322/* */ 323/* DATE NAME DESCRIPTION */ 324/* */ 325/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ 326/* */ 327/**************************************************************************/ 328 329// ******************************************************************* 330// MMU Exception Handling 331// ******************************************************************* 332 // EXTERN _tx_thread_system_state 333 // EXTERN _txm_module_manager_memory_fault_info 334 // EXTERN _tx_thread_current_ptr 335 // EXTERN _txm_module_manager_memory_fault_handler 336 // EXTERN _tx_execution_thread_exit 337 // EXTERN _tx_thread_schedule 338 339 .global __tx_prefetch_handler 340 .global __tx_abort_handler 341__tx_prefetch_handler: 342__tx_abort_handler: 343 STMDB sp!, {r0-r3} // Save some working registers 344 LDR r3, =_tx_thread_system_state // Pickup address of system state var 345 LDR r2, [r3, #0] // Pickup system state 346 ADD r2, r2, #1 // Increment the interrupt counter 347 STR r2, [r3, #0] // Store it back in the variable 348 SUB lr, lr, #4 // Adjust point of exception 349 350 /* Now pickup and store all the fault related information. */ 351 352 // Pickup the memory fault info struct 353 LDR r3, =_txm_module_manager_memory_fault_info 354 LDR r0, =_tx_thread_current_ptr // Build current thread pointer address 355 LDR r1, [r0] // Pickup the current thread pointer 356 STR r1, [r3, #0] // Save current thread pointer 357 STR lr, [r3, #4] // Save point of fault 358 MRC p15, 0, r0, c6, c0, 0 // Read DFAR 359 STR r0, [r3, #8] // Save DFAR 360 MRC p15, 0, r0, c5, c0, 0 // Read DFSR 361 STR r0, [r3, #12] // Save DFSR 362 MRC p15, 0, r0, c6, c0, 2 // Read IFAR 363 STR r0, [r3, #16] // Save IFAR 364 MRC p15, 0, r0, c5, c0, 1 // Read IFSR 365 STR r0, [r3, #20] // Save IFSR 366 367 // Save registers r0-r12 368 POP {r0-r2} 369 STR r0, [r3, #28] // Save r0 370 STR r1, [r3, #32] // Save r1 371 STR r2, [r3, #36] // Save r2 372 POP {r0} 373 STR r0, [r3, #40] // Save r3 374 STR r4, [r3, #44] // Save r4 375 STR r5, [r3, #48] // Save r5 376 STR r6, [r3, #52] // Save r6 377 STR r7, [r3, #56] // Save r7 378 STR r8, [r3, #60] // Save r8 379 STR r9, [r3, #64] // Save r9 380 STR r10,[r3, #68] // Save r10 381 STR r11,[r3, #72] // Save r11 382 STR r12,[r3, #76] // Save r12 383 384 CPSID if, #0x1F // Enter SYS mode 385 MOV r0, lr // Pickup lr 386 MOV r1, sp // Pickup sp 387 CPSID if, #0x17 // Back to ABT mode 388 STR r0, [r3, #80] // Save lr 389 STR r1, [r3, #24] // Save sp 390 MRS r0, SPSR // Pickup SPSR 391 STR r0, [r3, #84] // Save SPSR 392 ORR r0, r0, #SYS_MODE // Return into SYS mode 393 BIC r0, r0, #THUMB_MASK // Clear THUMB mode 394 MSR SPSR_c, r0 // Save SPSR 395 396 // Call memory manager fault handler 397 BL _txm_module_manager_memory_fault_handler 398 399#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 400 401 /* Call the thread exit function to indicate the thread is no longer executing. */ 402 403 BL _tx_execution_thread_exit // Call the thread exit function 404#endif 405 406 LDR r0, =_tx_thread_system_state // Pickup address of system state 407 LDR r1, [r0] // Pickup system state 408 SUB r1, r1, #1 // Decrement 409 STR r1, [r0] // Store new system state 410 411 MOV r1, #0 // Build NULL value 412 LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer 413 STR r1, [r0] // Clear current thread pointer 414 415 // Return from exception 416 LDR lr, =_tx_thread_schedule // Load scheduler address 417 MOVS pc, lr // Return to scheduler 418// ******************************************************************* 419// End of MMU exception handling. 420// ******************************************************************* 421 422 423 /* Reference build options and version ID to ensure they come in. */ 424 425BUILD_OPTIONS: 426 .word _tx_build_options // Reference to bring in 427VERSION_ID: 428 .word _tx_version_id // Reference to bring in 429