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