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#ifdef TX_ENABLE_FIQ_SUPPORT
26DISABLE_INTS    =       0xC0                    @ IRQ & FIQ interrupts disabled
27#else
28DISABLE_INTS    =       0x80                    @ IRQ interrupts disabled
29#endif
30@
31    .global     _tx_thread_system_state
32    .global     _tx_thread_current_ptr
33    .global     _tx_irq_processing_return
34    .global     _tx_execution_isr_enter
35@
36@
37@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_save
38@   since it will never be called 16-bit mode.  */
39@
40    .arm
41    .text
42    .align 2
43@/**************************************************************************/
44@/*                                                                        */
45@/*  FUNCTION                                               RELEASE        */
46@/*                                                                        */
47@/*    _tx_thread_context_save                             ARM11/GNU       */
48@/*                                                            6.2.1       */
49@/*  AUTHOR                                                                */
50@/*                                                                        */
51@/*    William E. Lamie, Microsoft Corporation                             */
52@/*                                                                        */
53@/*  DESCRIPTION                                                           */
54@/*                                                                        */
55@/*    This function saves the context of an executing thread in the       */
56@/*    beginning of interrupt processing.  The function also ensures that  */
57@/*    the system stack is used upon return to the calling ISR.            */
58@/*                                                                        */
59@/*  INPUT                                                                 */
60@/*                                                                        */
61@/*    None                                                                */
62@/*                                                                        */
63@/*  OUTPUT                                                                */
64@/*                                                                        */
65@/*    None                                                                */
66@/*                                                                        */
67@/*  CALLS                                                                 */
68@/*                                                                        */
69@/*    None                                                                */
70@/*                                                                        */
71@/*  CALLED BY                                                             */
72@/*                                                                        */
73@/*    ISRs                                                                */
74@/*                                                                        */
75@/*  RELEASE HISTORY                                                       */
76@/*                                                                        */
77@/*    DATE              NAME                      DESCRIPTION             */
78@/*                                                                        */
79@/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
80@/*  03-08-2023     Cindy Deng               Modified comment(s), added    */
81@/*                                            #include tx_user.h,         */
82@/*                                            resulting in version 6.2.1  */
83@/*                                                                        */
84@/**************************************************************************/
85@VOID   _tx_thread_context_save(VOID)
86@{
87    .global _tx_thread_context_save
88    .type   _tx_thread_context_save,function
89_tx_thread_context_save:
90@
91@    /* Upon entry to this routine, it is assumed that IRQ interrupts are locked
92@       out, we are in IRQ mode, and all registers are intact.  */
93@
94@    /* Check for a nested interrupt condition.  */
95@    if (_tx_thread_system_state++)
96@    {
97@
98    STMDB   sp!, {r0-r3}                    @ Save some working registers
99#ifdef TX_ENABLE_FIQ_SUPPORT
100    MRS     r0, CPSR                        @ Pickup the CPSR
101    ORR     r0, r0, #DISABLE_INTS           @ Build disable interrupt CPSR
102    MSR     CPSR_cxsf, r0                   @ Disable interrupts
103#endif
104    LDR     r3, =_tx_thread_system_state    @ Pickup address of system state variable
105    LDR     r2, [r3]                        @ Pickup system state
106    CMP     r2, #0                          @ Is this the first interrupt?
107    BEQ     __tx_thread_not_nested_save     @ Yes, not a nested context save
108@
109@    /* Nested interrupt condition.  */
110@
111    ADD     r2, r2, #1                      @ Increment the interrupt counter
112    STR     r2, [r3]                        @ Store it back in the variable
113@
114@   /* Save the rest of the scratch registers on the stack and return to the
115@      calling ISR.  */
116@
117    MRS     r0, SPSR                        @ Pickup saved SPSR
118    SUB     lr, lr, #4                      @ Adjust point of interrupt
119    STMDB   sp!, {r0, r10, r12, lr}         @ Store other registers
120@
121@    /* Return to the ISR.  */
122@
123    MOV     r10, #0                         @ Clear stack limit
124
125#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
126@
127@    /* Call the ISR enter function to indicate an ISR is executing.  */
128@
129    PUSH    {lr}                            @ Save ISR lr
130    BL      _tx_execution_isr_enter         @ Call the ISR enter function
131    POP     {lr}                            @ Recover ISR lr
132#endif
133
134    B       __tx_irq_processing_return      @ Continue IRQ processing
135@
136__tx_thread_not_nested_save:
137@    }
138@
139@    /* Otherwise, not nested, check to see if a thread was running.  */
140@    else if (_tx_thread_current_ptr)
141@    {
142@
143    ADD     r2, r2, #1                      @ Increment the interrupt counter
144    STR     r2, [r3]                        @ Store it back in the variable
145    LDR     r1, =_tx_thread_current_ptr     @ Pickup address of current thread ptr
146    LDR     r0, [r1]                        @ Pickup current thread pointer
147    CMP     r0, #0                          @ Is it NULL?
148    BEQ     __tx_thread_idle_system_save    @ If so, interrupt occurred in
149                                            @   scheduling loop - nothing needs saving!
150@
151@    /* Save minimal context of interrupted thread.  */
152@
153    MRS     r2, SPSR                        @ Pickup saved SPSR
154    SUB     lr, lr, #4                      @ Adjust point of interrupt
155    STMDB   sp!, {r2, r10, r12, lr}         @ Store other registers
156@
157@    /* Save the current stack pointer in the thread's control block.  */
158@    _tx_thread_current_ptr -> tx_thread_stack_ptr =  sp;
159@
160@    /* Switch to the system stack.  */
161@    sp =  _tx_thread_system_stack_ptr@
162@
163    MOV     r10, #0                         @ Clear stack limit
164
165#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
166@
167@    /* Call the ISR enter function to indicate an ISR is executing.  */
168@
169    PUSH    {lr}                            @ Save ISR lr
170    BL      _tx_execution_isr_enter         @ Call the ISR enter function
171    POP     {lr}                            @ Recover ISR lr
172#endif
173
174    B       __tx_irq_processing_return      @ Continue IRQ processing
175@
176@    }
177@    else
178@    {
179@
180__tx_thread_idle_system_save:
181@
182@    /* Interrupt occurred in the scheduling loop.  */
183@
184@    /* Not much to do here, just adjust the stack pointer, and return to IRQ
185@       processing.  */
186@
187    MOV     r10, #0                         @ Clear stack limit
188
189#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
190@
191@    /* Call the ISR enter function to indicate an ISR is executing.  */
192@
193    PUSH    {lr}                            @ Save ISR lr
194    BL      _tx_execution_isr_enter         @ Call the ISR enter function
195    POP     {lr}                            @ Recover ISR lr
196#endif
197
198    ADD     sp, sp, #16                     @ Recover saved registers
199    B       __tx_irq_processing_return      @ Continue IRQ processing
200@
201@    }
202@}
203
204
205
206