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 TX_SOURCE_CODE 25@ 26@ 27@/* Include necessary system files. */ 28@ 29@#include "tx_api.h" 30@#include "tx_initialize.h" 31@#include "tx_thread.h" 32@#include "tx_timer.h" 33 34 .arm 35 36SVC_MODE = 0xD3 @ Disable IRQ/FIQ SVC mode 37IRQ_MODE = 0xD2 @ Disable IRQ/FIQ IRQ mode 38FIQ_MODE = 0xD1 @ Disable IRQ/FIQ FIQ mode 39SYS_MODE = 0xDF @ Disable IRQ/FIQ SYS mode 40FIQ_STACK_SIZE = 512 @ FIQ stack size 41IRQ_STACK_SIZE = 1024 @ IRQ stack size 42SYS_STACK_SIZE = 1024 @ System stack size 43@ 44@ 45 .global _tx_thread_system_stack_ptr 46 .global _tx_initialize_unused_memory 47 .global _tx_thread_context_save 48 .global _tx_thread_context_restore 49 .global _tx_timer_interrupt 50 .global _end 51 .global _sp 52 .global _stack_bottom 53 54@ 55@ 56@/* Define the 16-bit Thumb mode veneer for _tx_initialize_low_level for 57@ applications calling this function from to 16-bit Thumb mode. */ 58@ 59 .text 60 .align 2 61 .thumb 62 .global $_tx_initialize_low_level 63 .type $_tx_initialize_low_level,function 64$_tx_initialize_low_level: 65 BX pc @ Switch to 32-bit mode 66 NOP @ 67 .arm 68 STMFD sp!, {lr} @ Save return address 69 BL _tx_initialize_low_level @ Call _tx_initialize_low_level function 70 LDMFD sp!, {lr} @ Recover saved return address 71 BX lr @ Return to 16-bit caller 72@ 73@ 74 .text 75 .align 2 76@/**************************************************************************/ 77@/* */ 78@/* FUNCTION RELEASE */ 79@/* */ 80@/* _tx_initialize_low_level ARM11/GNU */ 81@/* 6.1 */ 82@/* AUTHOR */ 83@/* */ 84@/* William E. Lamie, Microsoft Corporation */ 85@/* */ 86@/* DESCRIPTION */ 87@/* */ 88@/* This function is responsible for any low-level processor */ 89@/* initialization, including setting up interrupt vectors, setting */ 90@/* up a periodic timer interrupt source, saving the system stack */ 91@/* pointer for use in ISR processing later, and finding the first */ 92@/* available RAM memory address for tx_application_define. */ 93@/* */ 94@/* INPUT */ 95@/* */ 96@/* None */ 97@/* */ 98@/* OUTPUT */ 99@/* */ 100@/* None */ 101@/* */ 102@/* CALLS */ 103@/* */ 104@/* None */ 105@/* */ 106@/* CALLED BY */ 107@/* */ 108@/* _tx_initialize_kernel_enter ThreadX entry function */ 109@/* */ 110@/* RELEASE HISTORY */ 111@/* */ 112@/* DATE NAME DESCRIPTION */ 113@/* */ 114@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 115@/* */ 116@/**************************************************************************/ 117@VOID _tx_initialize_low_level(VOID) 118@{ 119 .global _tx_initialize_low_level 120 .type _tx_initialize_low_level,function 121_tx_initialize_low_level: 122@ 123@ /* We must be in SVC mode at this point! */ 124@ 125@ /* Setup various stack pointers. */ 126@ 127 LDR r1, =_sp @ Get pointer to stack area 128 129#ifdef TX_ENABLE_IRQ_NESTING 130@ 131@ /* Setup the system mode stack for nested interrupt support */ 132@ 133 LDR r2, =SYS_STACK_SIZE @ Pickup stack size 134 MOV r3, #SYS_MODE @ Build SYS mode CPSR 135 MSR CPSR_cxsf, r3 @ Enter SYS mode 136 SUB r1, r1, #1 @ Backup 1 byte 137 BIC r1, r1, #7 @ Ensure 8-byte alignment 138 MOV sp, r1 @ Setup SYS stack pointer 139 SUB r1, r1, r2 @ Calculate start of next stack 140#endif 141 142 LDR r2, =FIQ_STACK_SIZE @ Pickup stack size 143 MOV r0, #FIQ_MODE @ Build FIQ mode CPSR 144 MSR CPSR, r0 @ Enter FIQ mode 145 SUB r1, r1, #1 @ Backup 1 byte 146 BIC r1, r1, #7 @ Ensure 8-byte alignment 147 MOV sp, r1 @ Setup FIQ stack pointer 148 SUB r1, r1, r2 @ Calculate start of next stack 149 LDR r2, =IRQ_STACK_SIZE @ Pickup IRQ stack size 150 MOV r0, #IRQ_MODE @ Build IRQ mode CPSR 151 MSR CPSR, r0 @ Enter IRQ mode 152 SUB r1, r1, #1 @ Backup 1 byte 153 BIC r1, r1, #7 @ Ensure 8-byte alignment 154 MOV sp, r1 @ Setup IRQ stack pointer 155 SUB r3, r1, r2 @ Calculate end of IRQ stack 156 MOV r0, #SVC_MODE @ Build SVC mode CPSR 157 MSR CPSR, r0 @ Enter SVC mode 158 LDR r2, =_stack_bottom @ Pickup stack bottom 159 CMP r3, r2 @ Compare the current stack end with the bottom 160_stack_error_loop: 161 BLT _stack_error_loop @ If the IRQ stack exceeds the stack bottom, just sit here! 162@ 163@ /* Save the system stack pointer. */ 164@ _tx_thread_system_stack_ptr = (VOID_PTR) (sp); 165@ 166 LDR r2, =_tx_thread_system_stack_ptr @ Pickup stack pointer 167 STR r1, [r2] @ Save the system stack 168@ 169@ /* Save the first available memory address. */ 170@ _tx_initialize_unused_memory = (VOID_PTR) _end; 171@ 172 LDR r1, =_end @ Get end of non-initialized RAM area 173 LDR r2, =_tx_initialize_unused_memory @ Pickup unused memory ptr address 174 ADD r1, r1, #8 @ Increment to next free word 175 STR r1, [r2] @ Save first free memory address 176@ 177@ /* Setup Timer for periodic interrupts. */ 178@ 179@ /* Done, return to caller. */ 180@ 181#ifdef __THUMB_INTERWORK 182 BX lr @ Return to caller 183#else 184 MOV pc, lr @ Return to caller 185#endif 186@} 187@ 188@ 189@/* Define shells for each of the interrupt vectors. */ 190@ 191 .global __tx_undefined 192__tx_undefined: 193 B __tx_undefined @ Undefined handler 194@ 195 .global __tx_swi_interrupt 196__tx_swi_interrupt: 197 B __tx_swi_interrupt @ Software interrupt handler 198@ 199 .global __tx_prefetch_handler 200__tx_prefetch_handler: 201 B __tx_prefetch_handler @ Prefetch exception handler 202@ 203 .global __tx_abort_handler 204__tx_abort_handler: 205 B __tx_abort_handler @ Abort exception handler 206@ 207 .global __tx_reserved_handler 208__tx_reserved_handler: 209 B __tx_reserved_handler @ Reserved exception handler 210@ 211 .global __tx_irq_handler 212 .global __tx_irq_processing_return 213__tx_irq_handler: 214@ 215@ /* Jump to context save to save system context. */ 216 B _tx_thread_context_save 217__tx_irq_processing_return: 218@ 219@ /* At this point execution is still in the IRQ mode. The CPSR, point of 220@ interrupt, and all C scratch registers are available for use. In 221@ addition, IRQ interrupts may be re-enabled - with certain restrictions - 222@ if nested IRQ interrupts are desired. Interrupts may be re-enabled over 223@ small code sequences where lr is saved before enabling interrupts and 224@ restored after interrupts are again disabled. */ 225@ 226@ /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 227@ from IRQ mode with interrupts disabled. This routine switches to the 228@ system mode and returns with IRQ interrupts enabled. 229@ 230@ NOTE: It is very important to ensure all IRQ interrupts are cleared 231@ prior to enabling nested IRQ interrupts. */ 232#ifdef TX_ENABLE_IRQ_NESTING 233 BL _tx_thread_irq_nesting_start 234#endif 235@ 236@ /* For debug purpose, execute the timer interrupt processing here. In 237@ a real system, some kind of status indication would have to be checked 238@ before the timer interrupt handler could be called. */ 239@ 240 BL _tx_timer_interrupt @ Timer interrupt handler 241@ 242@ 243@ /* If interrupt nesting was started earlier, the end of interrupt nesting 244@ service must be called before returning to _tx_thread_context_restore. 245@ This routine returns in processing in IRQ mode with interrupts disabled. */ 246#ifdef TX_ENABLE_IRQ_NESTING 247 BL _tx_thread_irq_nesting_end 248#endif 249@ 250@ /* Jump to context restore to restore system context. */ 251 B _tx_thread_context_restore 252@ 253@ 254@ /* This is an example of a vectored IRQ handler. */ 255@ 256@ .global __tx_example_vectored_irq_handler 257@__tx_example_vectored_irq_handler: 258@ 259@ 260@ /* Save initial context and call context save to prepare for 261@ vectored ISR execution. */ 262@ 263@ STMDB sp!, {r0-r3} @ Save some scratch registers 264@ MRS r0, SPSR @ Pickup saved SPSR 265@ SUB lr, lr, #4 @ Adjust point of interrupt 266@ STMDB sp!, {r0, r10, r12, lr} @ Store other scratch registers 267@ BL _tx_thread_vectored_context_save @ Vectored context save 268@ 269@ /* At this point execution is still in the IRQ mode. The CPSR, point of 270@ interrupt, and all C scratch registers are available for use. In 271@ addition, IRQ interrupts may be re-enabled - with certain restrictions - 272@ if nested IRQ interrupts are desired. Interrupts may be re-enabled over 273@ small code sequences where lr is saved before enabling interrupts and 274@ restored after interrupts are again disabled. */ 275@ 276@ 277@ /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start 278@ from IRQ mode with interrupts disabled. This routine switches to the 279@ system mode and returns with IRQ interrupts enabled. 280@ 281@ NOTE: It is very important to ensure all IRQ interrupts are cleared 282@ prior to enabling nested IRQ interrupts. */ 283@#ifdef TX_ENABLE_IRQ_NESTING 284@ BL _tx_thread_irq_nesting_start 285@#endif 286@ 287@ /* Application IRQ handlers can be called here! */ 288@ 289@ /* If interrupt nesting was started earlier, the end of interrupt nesting 290@ service must be called before returning to _tx_thread_context_restore. 291@ This routine returns in processing in IRQ mode with interrupts disabled. */ 292@#ifdef TX_ENABLE_IRQ_NESTING 293@ BL _tx_thread_irq_nesting_end 294@#endif 295@ 296@ /* Jump to context restore to restore system context. */ 297@ B _tx_thread_context_restore 298@ 299@ 300#ifdef TX_ENABLE_FIQ_SUPPORT 301 .global __tx_fiq_handler 302 .global __tx_fiq_processing_return 303__tx_fiq_handler: 304@ 305@ /* Jump to fiq context save to save system context. */ 306 B _tx_thread_fiq_context_save 307__tx_fiq_processing_return: 308@ 309@ /* At this point execution is still in the FIQ mode. The CPSR, point of 310@ interrupt, and all C scratch registers are available for use. */ 311@ 312@ /* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start 313@ from FIQ mode with interrupts disabled. This routine switches to the 314@ system mode and returns with FIQ interrupts enabled. 315@ 316@ NOTE: It is very important to ensure all FIQ interrupts are cleared 317@ prior to enabling nested FIQ interrupts. */ 318#ifdef TX_ENABLE_FIQ_NESTING 319 BL _tx_thread_fiq_nesting_start 320#endif 321@ 322@ /* Application FIQ handlers can be called here! */ 323@ 324@ /* If interrupt nesting was started earlier, the end of interrupt nesting 325@ service must be called before returning to _tx_thread_fiq_context_restore. */ 326#ifdef TX_ENABLE_FIQ_NESTING 327 BL _tx_thread_fiq_nesting_end 328#endif 329@ 330@ /* Jump to fiq context restore to restore system context. */ 331 B _tx_thread_fiq_context_restore 332@ 333@ 334#else 335 .global __tx_fiq_handler 336__tx_fiq_handler: 337 B __tx_fiq_handler @ FIQ interrupt handler 338#endif 339@ 340@ 341BUILD_OPTIONS: 342 .word _tx_build_options @ Reference to bring in 343VERSION_ID: 344 .word _tx_version_id @ Reference to bring in 345 346 347 348