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