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