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/**   Thread                                                              */
18/**                                                                       */
19/**************************************************************************/
20/**************************************************************************/
21#ifdef TX_INCLUDE_USER_DEFINE_FILE
22#include "tx_user.h"
23#endif
24
25    .syntax unified
26#if defined(THUMB_MODE)
27    .thumb
28#else
29    .arm
30#endif
31
32SVC_MODE        =       0x13                    // SVC mode
33
34THUMB_MASK      =       0x20                    // Thumb bit mask
35
36#ifdef TX_ENABLE_FIQ_SUPPORT
37CPSR_MASK       =       0xFF                    // Mask initial CPSR, T, IRQ & FIQ interrupts enabled
38#else
39CPSR_MASK       =       0xBF                    // Mask initial CPSR, T, IRQ interrupts enabled
40#endif
41
42    .text
43    .align 2
44/**************************************************************************/
45/*                                                                        */
46/*  FUNCTION                                               RELEASE        */
47/*                                                                        */
48/*    _tx_thread_stack_build                               ARMv7-A        */
49/*                                                           6.4.0        */
50/*  AUTHOR                                                                */
51/*                                                                        */
52/*    William E. Lamie, Microsoft Corporation                             */
53/*                                                                        */
54/*  DESCRIPTION                                                           */
55/*                                                                        */
56/*    This function builds a stack frame on the supplied thread's stack.  */
57/*    The stack frame results in a fake interrupt return to the supplied  */
58/*    function pointer.                                                   */
59/*                                                                        */
60/*  INPUT                                                                 */
61/*                                                                        */
62/*    thread_ptr                            Pointer to thread control blk */
63/*    function_ptr                          Pointer to return function    */
64/*                                                                        */
65/*  OUTPUT                                                                */
66/*                                                                        */
67/*    None                                                                */
68/*                                                                        */
69/*  CALLS                                                                 */
70/*                                                                        */
71/*    None                                                                */
72/*                                                                        */
73/*  CALLED BY                                                             */
74/*                                                                        */
75/*    _tx_thread_create                     Create thread service         */
76/*                                                                        */
77/*  RELEASE HISTORY                                                       */
78/*                                                                        */
79/*    DATE              NAME                      DESCRIPTION             */
80/*                                                                        */
81/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
82/*  04-25-2022     Zhen Kong                Updated comments,             */
83/*                                            resulting in version 6.1.11 */
84/*  10-31-2023     Tiejun Zhou              Modified comment(s), added    */
85/*                                            #include tx_user.h,         */
86/*                                            resulting in version 6.3.0  */
87/*  12-31-2023     Yajun Xia                Modified comment(s),          */
88/*                                            Added thumb mode support,   */
89/*                                            resulting in version 6.4.0  */
90/*                                                                        */
91/**************************************************************************/
92#if defined(THUMB_MODE)
93    .thumb_func
94#endif
95    .global  _tx_thread_stack_build
96    .type    _tx_thread_stack_build,function
97_tx_thread_stack_build:
98
99
100    /* Build a fake interrupt frame.  The form of the fake interrupt stack
101       on the ARMv7-A should look like the following after it is built:
102
103       Stack Top:      1           Interrupt stack frame type
104                       CPSR        Initial value for CPSR
105                       a1 (r0)     Initial value for a1
106                       a2 (r1)     Initial value for a2
107                       a3 (r2)     Initial value for a3
108                       a4 (r3)     Initial value for a4
109                       v1 (r4)     Initial value for v1
110                       v2 (r5)     Initial value for v2
111                       v3 (r6)     Initial value for v3
112                       v4 (r7)     Initial value for v4
113                       v5 (r8)     Initial value for v5
114                       sb (r9)     Initial value for sb
115                       sl (r10)    Initial value for sl
116                       fp (r11)    Initial value for fp
117                       ip (r12)    Initial value for ip
118                       lr (r14)    Initial value for lr
119                       pc (r15)    Initial value for
120                       0       For stack backtracing
121
122    Stack Bottom: (higher memory address)  */
123
124    LDR     r2, [r0, #16]                   // Pickup end of stack area
125    BIC     r2, r2, #7                      // Ensure 8-byte alignment
126    SUB     r2, r2, #76                     // Allocate space for the stack frame
127
128    /* Actually build the stack frame.  */
129
130    MOV     r3, #1                          // Build interrupt stack type
131    STR     r3, [r2, #0]                    // Store stack type
132
133    MRS     r3, CPSR                        // Pickup CPSR
134    BIC     r3, #CPSR_MASK                  // Mask mode bits of CPSR
135    ORR     r3, #SVC_MODE                   // Build CPSR, SYS mode, interrupts enabled
136    TST     r1, #1                          // Check if the initial PC is a Thumb function
137    IT      NE
138    ORRNE   r3, #THUMB_MASK                 // If the initial PC is a thumb function, CPSR must reflect this
139    STR     r3, [r2, #4]                    // Store initial CPSR
140
141    MOV     r3, #0                          // Build initial register value
142    STR     r3, [r2, #8]                    // Store initial r0
143    STR     r3, [r2, #12]                   // Store initial r1
144    STR     r3, [r2, #16]                   // Store initial r2
145    STR     r3, [r2, #20]                   // Store initial r3
146    STR     r3, [r2, #24]                   // Store initial r4
147    STR     r3, [r2, #28]                   // Store initial r5
148    STR     r3, [r2, #32]                   // Store initial r6
149    STR     r3, [r2, #36]                   // Store initial r7
150    STR     r3, [r2, #40]                   // Store initial r8
151    STR     r3, [r2, #44]                   // Store initial r9
152    STR     r3, [r2, #52]                   // Store initial r11
153    STR     r3, [r2, #56]                   // Store initial r12
154    STR     r3, [r2, #68]                   // 0 for back-trace
155
156    LDR     r3, [r0, #12]                   // Pickup stack starting address
157    STR     r3, [r2, #48]                   // Store initial r10 (sl)
158
159    LDR     r3,=_tx_thread_schedule         // Pickup address of _tx_thread_schedule for GDB backtrace
160    STR     r3, [r2, #60]                   // Store initial r14 (lr)
161
162    STR     r1, [r2, #64]                   // Store initial pc
163
164    /* Setup stack pointer.  */
165
166    STR     r2, [r0, #8]                    // Save stack pointer in thread's
167                                            //   control block
168    BX      lr                              // Return to caller
169