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