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