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