1;/**************************************************************************/
2;/*                                                                        */
3;/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4;/*                                                                        */
5;/*       This software is licensed under the Microsoft Software License   */
6;/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7;/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8;/*       and in the root directory of this software.                      */
9;/*                                                                        */
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#ifdef TX_ENABLE_FIQ_SUPPORT
35DISABLE_INTS    DEFINE  0xC0                    ; IRQ & FIQ interrupts disabled
36#else
37DISABLE_INTS    DEFINE  0x80                    ; IRQ interrupts disabled
38#endif
39
40    EXTERN      _tx_thread_system_state
41    EXTERN      _tx_thread_current_ptr
42    EXTERN      _tx_execution_isr_enter
43;
44;
45;/**************************************************************************/
46;/*                                                                        */
47;/*  FUNCTION                                               RELEASE        */
48;/*                                                                        */
49;/*    _tx_thread_vectored_context_save                    ARM9/IAR        */
50;/*                                                           6.1          */
51;/*  AUTHOR                                                                */
52;/*                                                                        */
53;/*    William E. Lamie, Microsoft Corporation                             */
54;/*                                                                        */
55;/*  DESCRIPTION                                                           */
56;/*                                                                        */
57;/*    This function saves the context of an executing thread in the       */
58;/*    beginning of interrupt processing.  The function also ensures that  */
59;/*    the system stack is used upon return to the calling ISR.            */
60;/*                                                                        */
61;/*  INPUT                                                                 */
62;/*                                                                        */
63;/*    None                                                                */
64;/*                                                                        */
65;/*  OUTPUT                                                                */
66;/*                                                                        */
67;/*    None                                                                */
68;/*                                                                        */
69;/*  CALLS                                                                 */
70;/*                                                                        */
71;/*    None                                                                */
72;/*                                                                        */
73;/*  CALLED BY                                                             */
74;/*                                                                        */
75;/*    ISRs                                                                */
76;/*                                                                        */
77;/*  RELEASE HISTORY                                                       */
78;/*                                                                        */
79;/*    DATE              NAME                      DESCRIPTION             */
80;/*                                                                        */
81;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
82;/*                                                                        */
83;/**************************************************************************/
84;VOID   _tx_thread_vectored_context_save(VOID)
85;{
86    RSEG    .text:CODE:NOROOT(2)
87    PUBLIC  _tx_thread_vectored_context_save
88    CODE32
89_tx_thread_vectored_context_save
90;
91;    /* Upon entry to this routine, it is assumed that IRQ interrupts are locked
92;       out, we are in IRQ mode, the minimal context is already saved, and the
93;       lr register contains the return ISR address.  */
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 var
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 occured 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_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    END
195
196