1;/***************************************************************************
2; * Copyright (c) 2024 Microsoft Corporation
3; *
4; * This program and the accompanying materials are made available under the
5; * terms of the MIT License which is available at
6; * https://opensource.org/licenses/MIT.
7; *
8; * SPDX-License-Identifier: MIT
9; **************************************************************************/
10;
11;
12;/**************************************************************************/
13;/**************************************************************************/
14;/**                                                                       */
15;/** ThreadX Component                                                     */
16;/**                                                                       */
17;/**   Initialize                                                          */
18;/**                                                                       */
19;/**************************************************************************/
20;/**************************************************************************/
21;
22;
23;#define TX_SOURCE_CODE
24;
25;
26;/* Include necessary system files.  */
27;
28;#include "tx_api.h"
29;#include "tx_initialize.h"
30;#include "tx_thread.h"
31;#include "tx_timer.h"
32;
33;
34SVC_MODE        DEFINE  0xD3                    ; Disable irq,fiq SVC mode
35IRQ_MODE        DEFINE  0xD2                    ; Disable irq,fiq IRQ mode
36FIQ_MODE        DEFINE  0xD1                    ; Disable irq,fiq FIQ mode
37SYS_MODE        DEFINE  0xDF                    ; Disable irq,fiq SYS mode
38;
39;
40
41    EXTERN      _tx_thread_system_stack_ptr
42    EXTERN      _tx_initialize_unused_memory
43    EXTERN      _tx_thread_context_save
44;    EXTERN      _tx_thread_vectored_context_save
45    EXTERN      _tx_thread_context_restore
46#ifdef TX_ENABLE_FIQ_SUPPORT
47    EXTERN      _tx_thread_fiq_context_save
48    EXTERN      _tx_thread_fiq_context_restore
49#endif
50#ifdef TX_ENABLE_IRQ_NESTING
51    EXTERN      _tx_thread_irq_nesting_start
52    EXTERN      _tx_thread_irq_nesting_end
53#endif
54#ifdef TX_ENABLE_FIQ_NESTING
55    EXTERN      _tx_thread_fiq_nesting_start
56    EXTERN      _tx_thread_fiq_nesting_end
57#endif
58    EXTERN      _tx_timer_interrupt
59    EXTERN      ?cstartup
60    EXTERN      _tx_build_options
61    EXTERN      _tx_version_id
62;
63;
64;
65;/* Define the FREE_MEM segment that will specify where free memory is
66;   defined.  This must also be located in at the end of other RAM segments
67;   in the linker control file.  The value of this segment is what is passed
68;   to tx_application_define.  */
69;
70    RSEG    FREE_MEM:DATA
71    PUBLIC  __tx_free_memory_start
72__tx_free_memory_start
73    DS32    4
74;
75;
76;
77;
78;/**************************************************************************/
79;/*                                                                        */
80;/*  FUNCTION                                               RELEASE        */
81;/*                                                                        */
82;/*    _tx_initialize_low_level                            ARM11/IAR       */
83;/*                                                            6.1         */
84;/*  AUTHOR                                                                */
85;/*                                                                        */
86;/*    William E. Lamie, Microsoft Corporation                             */
87;/*                                                                        */
88;/*  DESCRIPTION                                                           */
89;/*                                                                        */
90;/*    This function is responsible for any low-level processor            */
91;/*    initialization, including setting up interrupt vectors, setting     */
92;/*    up a periodic timer interrupt source, saving the system stack       */
93;/*    pointer for use in ISR processing later, and finding the first      */
94;/*    available RAM memory address for tx_application_define.             */
95;/*                                                                        */
96;/*  INPUT                                                                 */
97;/*                                                                        */
98;/*    None                                                                */
99;/*                                                                        */
100;/*  OUTPUT                                                                */
101;/*                                                                        */
102;/*    None                                                                */
103;/*                                                                        */
104;/*  CALLS                                                                 */
105;/*                                                                        */
106;/*    None                                                                */
107;/*                                                                        */
108;/*  CALLED BY                                                             */
109;/*                                                                        */
110;/*    _tx_initialize_kernel_enter           ThreadX entry function        */
111;/*                                                                        */
112;/*  RELEASE HISTORY                                                       */
113;/*                                                                        */
114;/*    DATE              NAME                      DESCRIPTION             */
115;/*                                                                        */
116;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
117;/*                                                                        */
118;/**************************************************************************/
119;VOID   _tx_initialize_low_level(VOID)
120;{
121    RSEG    .text:CODE:NOROOT(2)
122    CODE32
123    PUBLIC  _tx_initialize_low_level
124_tx_initialize_low_level
125;
126;    /****** NOTE ****** The IAR 4.11a and above releases call main in SYS mode.  */
127;
128;    /* Remember the stack pointer, link register, and switch to SVC mode.  */
129;
130    MOV     r0, sp                              ; Remember the SP
131    MOV     r1, lr                              ; Remember the LR
132    MOV     r3, #SVC_MODE                       ; Build SVC mode CPSR
133    MSR     CPSR_cxsf, r3                       ; Switch to SVC mode
134    MOV     sp, r0                              ; Inherit the stack pointer setup by cstartup
135    MOV     lr, r1                              ; Inherit the link register
136;
137;    /* Pickup the start of free memory.  */
138;
139    LDR     r0, =__tx_free_memory_start         ; Get end of non-initialized RAM area
140;
141;    /* Save the system stack pointer.  */
142;    _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
143;
144;    /* Save the first available memory address.  */
145;    _tx_initialize_unused_memory =  (VOID_PTR) FREE_MEM;
146;
147    LDR     r2, =_tx_initialize_unused_memory   ; Pickup unused memory ptr address
148    STR     r0, [r2, #0]                        ; Save first free memory address
149;
150;    /* Setup Timer for periodic interrupts.  */
151;
152;    /* Done, return to caller.  */
153;
154#ifdef TX_THUMB
155    BX      lr                                  ; Return to caller
156#else
157    MOV     pc, lr                              ; Return to caller
158#endif
159;}
160;
161;/* Define shells for each of the interrupt vectors.  */
162;
163    RSEG    .text:CODE:NOROOT(2)
164    PUBLIC  __tx_undefined
165__tx_undefined
166    B       __tx_undefined                      ; Undefined handler
167;
168    RSEG    .text:CODE:NOROOT(2)
169    PUBLIC  __tx_swi_interrupt
170__tx_swi_interrupt
171    B       __tx_swi_interrupt                  ; Software interrupt handler
172;
173    RSEG    .text:CODE:NOROOT(2)
174    PUBLIC  __tx_prefetch_handler
175__tx_prefetch_handler
176    B       __tx_prefetch_handler               ; Prefetch exception handler
177;
178    RSEG    .text:CODE:NOROOT(2)
179    PUBLIC  __tx_abort_handler
180__tx_abort_handler
181    B       __tx_abort_handler                  ; Abort exception handler
182;
183    RSEG    .text:CODE:NOROOT(2)
184    PUBLIC  __tx_reserved_handler
185__tx_reserved_handler
186    B       __tx_reserved_handler               ; Reserved exception handler
187;
188    RSEG    .text:CODE:NOROOT(2)
189    PUBLIC  __tx_irq_handler
190    RSEG    .text:CODE:NOROOT(2)
191    PUBLIC  __tx_irq_processing_return
192__tx_irq_handler
193;
194;    /* Jump to context save to save system context.  */
195    B       _tx_thread_context_save
196__tx_irq_processing_return
197;
198;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
199;       interrupt, and all C scratch registers are available for use.  In
200;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
201;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
202;       small code sequences where lr is saved before enabling interrupts and
203;       restored after interrupts are again disabled.  */
204;
205;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
206;       from IRQ mode with interrupts disabled.  This routine switches to the
207;       system mode and returns with IRQ interrupts enabled.
208;
209;       NOTE:  It is very important to ensure all IRQ interrupts are cleared
210;       prior to enabling nested IRQ interrupts.  */
211#ifdef TX_ENABLE_IRQ_NESTING
212    BL      _tx_thread_irq_nesting_start
213#endif
214;
215;    /* For debug purpose, execute the timer interrupt processing here.  In
216;       a real system, some kind of status indication would have to be checked
217;       before the timer interrupt handler could be called.  */
218;
219    BL      _tx_timer_interrupt                 ; Timer interrupt handler
220;
221;    /* Application IRQ handlers can be called here!  */
222;
223;    /* If interrupt nesting was started earlier, the end of interrupt nesting
224;       service must be called before returning to _tx_thread_context_restore.
225;       This routine returns in processing in IRQ mode with interrupts disabled.  */
226#ifdef TX_ENABLE_IRQ_NESTING
227    BL      _tx_thread_irq_nesting_end
228#endif
229;
230;    /* Jump to context restore to restore system context.  */
231    B       _tx_thread_context_restore
232;
233;
234;    /* This is an example of a vectored IRQ handler.  */
235;
236;    RSEG    .text:CODE:NOROOT(2)
237;    PUBLIC  __tx_example_vectored_irq_handler
238;__tx_example_vectored_irq_handler
239;
240;    /* Jump to context save to save system context.  */
241;    STMDB   sp!, {r0-r3}                    ; Save some scratch registers
242;    MRS     r0, SPSR                        ; Pickup saved SPSR
243;    SUB     lr, lr, #4                      ; Adjust point of interrupt
244;    STMDB   sp!, {r0, r10, r12, lr}         ; Store other registers
245;    BL      _tx_thread_vectored_context_save
246;
247;    /* At this point execution is still in the IRQ mode.  The CPSR, point of
248;       interrupt, and all C scratch registers are available for use.  In
249;       addition, IRQ interrupts may be re-enabled - with certain restrictions -
250;       if nested IRQ interrupts are desired.  Interrupts may be re-enabled over
251;       small code sequences where lr is saved before enabling interrupts and
252;       restored after interrupts are again disabled.  */
253;
254;    /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
255;       from IRQ mode with interrupts disabled.  This routine switches to the
256;       system mode and returns with IRQ interrupts enabled.
257;
258;       NOTE:  It is very important to ensure all IRQ interrupts are cleared
259;       prior to enabling nested IRQ interrupts.  */
260;#ifdef TX_ENABLE_IRQ_NESTING
261;    BL      _tx_thread_irq_nesting_start
262;#endif
263;
264;    /* Application IRQ handler is called here!  */
265;
266;    /* If interrupt nesting was started earlier, the end of interrupt nesting
267;       service must be called before returning to _tx_thread_context_restore.
268;       This routine returns in processing in IRQ mode with interrupts disabled.  */
269;#ifdef TX_ENABLE_IRQ_NESTING
270;    BL      _tx_thread_irq_nesting_end
271;#endif
272;
273;    /* Jump to context restore to restore system context.  */
274;    B       _tx_thread_context_restore
275;
276;
277#ifdef TX_ENABLE_FIQ_SUPPORT
278    RSEG    .text:CODE:NOROOT(2)
279    PUBLIC  __tx_fiq_handler
280    RSEG    .text:CODE:NOROOT(2)
281    PUBLIC  __tx_fiq_processing_return
282__tx_fiq_handler
283;
284;    /* Jump to fiq context save to save system context.  */
285    B       _tx_thread_fiq_context_save
286__tx_fiq_processing_return
287;
288;    /* At this point execution is still in the FIQ mode.  The CPSR, point of
289;       interrupt, and all C scratch registers are available for use.  */
290;
291;    /* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start
292;       from FIQ mode with interrupts disabled.  This routine switches to the
293;       system mode and returns with FIQ interrupts enabled.
294;
295;       NOTE:  It is very important to ensure all FIQ interrupts are cleared
296;       prior to enabling nested FIQ interrupts.  */
297#ifdef TX_ENABLE_FIQ_NESTING
298    BL      _tx_thread_fiq_nesting_start
299#endif
300;
301;    /* Application FIQ handlers can be called here!  */
302;
303;    /* If interrupt nesting was started earlier, the end of interrupt nesting
304;       service must be called before returning to _tx_thread_fiq_context_restore.  */
305#ifdef TX_ENABLE_FIQ_NESTING
306    BL      _tx_thread_fiq_nesting_end
307#endif
308;
309;    /* Jump to fiq context restore to restore system context.  */
310    B       _tx_thread_fiq_context_restore
311;
312;
313#else
314    RSEG    .text:CODE:NOROOT(2)
315    PUBLIC  __tx_fiq_handler
316__tx_fiq_handler
317    B       __tx_fiq_handler                    ; FIQ interrupt handler
318#endif
319;
320;
321BUILD_OPTIONS
322    DC32    _tx_build_options                   ; Reference to ensure it comes in
323VERSION_ID
324    DC32    _tx_version_id                      ; Reference to ensure it comes in
325    END
326
327