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#ifdef TX_INCLUDE_USER_DEFINE_FILE
23#include "tx_user.h"
24#endif
25
26    .arm
27
28#ifdef TX_ENABLE_FIQ_SUPPORT
29SVC_MODE        =     0xD3               @ Disable IRQ/FIQ, SVC mode
30IRQ_MODE        =     0xD2               @ Disable IRQ/FIQ, IRQ mode
31#else
32SVC_MODE        =     0x93               @ Disable IRQ, SVC mode
33IRQ_MODE        =     0x92               @ Disable IRQ, IRQ mode
34#endif
35@
36    .global     _tx_thread_system_state
37    .global     _tx_thread_current_ptr
38    .global     _tx_thread_execute_ptr
39    .global     _tx_timer_time_slice
40    .global     _tx_thread_schedule
41    .global     _tx_thread_preempt_disable
42    .global     _tx_execution_isr_exit
43@
44@
45@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_restore
46@   since it will never be called 16-bit mode.  */
47@
48    .arm
49    .text
50    .align 2
51@/**************************************************************************/
52@/*                                                                        */
53@/*  FUNCTION                                               RELEASE        */
54@/*                                                                        */
55@/*    _tx_thread_context_restore                           ARM9/GNU       */
56@/*                                                           6.2.1        */
57@/*  AUTHOR                                                                */
58@/*                                                                        */
59@/*    William E. Lamie, Microsoft Corporation                             */
60@/*                                                                        */
61@/*  DESCRIPTION                                                           */
62@/*                                                                        */
63@/*    This function restores the interrupt context if it is processing a  */
64@/*    nested interrupt.  If not, it returns to the interrupt thread if no */
65@/*    preemption is necessary.  Otherwise, if preemption is necessary or  */
66@/*    if no thread was running, the function returns to the scheduler.    */
67@/*                                                                        */
68@/*  INPUT                                                                 */
69@/*                                                                        */
70@/*    None                                                                */
71@/*                                                                        */
72@/*  OUTPUT                                                                */
73@/*                                                                        */
74@/*    None                                                                */
75@/*                                                                        */
76@/*  CALLS                                                                 */
77@/*                                                                        */
78@/*    _tx_thread_schedule                   Thread scheduling routine     */
79@/*                                                                        */
80@/*  CALLED BY                                                             */
81@/*                                                                        */
82@/*    ISRs                                  Interrupt Service Routines    */
83@/*                                                                        */
84@/*  RELEASE HISTORY                                                       */
85@/*                                                                        */
86@/*    DATE              NAME                      DESCRIPTION             */
87@/*                                                                        */
88@/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
89@/*  03-08-2023     Cindy Deng               Modified comment(s), added    */
90@/*                                            #include tx_user.h,         */
91@/*                                            resulting in version 6.2.1  */
92@/*                                                                        */
93@/**************************************************************************/
94@VOID   _tx_thread_context_restore(VOID)
95@{
96    .global _tx_thread_context_restore
97    .type   _tx_thread_context_restore,function
98_tx_thread_context_restore:
99@
100@    /* Lockout interrupts.  */
101@
102    MOV     r0, #IRQ_MODE                   @ Build disable interrupts CPSR
103    MSR     CPSR, r0                        @ Lockout interrupts
104
105#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
106@
107@    /* Call the ISR exit function to indicate an ISR is complete.  */
108@
109    BL      _tx_execution_isr_exit          @ Call the ISR exit function
110#endif
111@
112@    /* Determine if interrupts are nested.  */
113@    if (--_tx_thread_system_state)
114@    {
115@
116    LDR     r3, =_tx_thread_system_state    @ Pickup address of system state variable
117    LDR     r2, [r3]                        @ Pickup system state
118    SUB     r2, r2, #1                      @ Decrement the counter
119    STR     r2, [r3]                        @ Store the counter
120    CMP     r2, #0                          @ Was this the first interrupt?
121    BEQ     __tx_thread_not_nested_restore  @ If so, not a nested restore
122@
123@    /* Interrupts are nested.  */
124@
125@    /* Just recover the saved registers and return to the point of
126@       interrupt.  */
127@
128    LDMIA   sp!, {r0, r10, r12, lr}         @ Recover SPSR, POI, and scratch regs
129    MSR     SPSR, r0                        @ Put SPSR back
130    LDMIA   sp!, {r0-r3}                    @ Recover r0-r3
131    MOVS    pc, lr                          @ Return to point of interrupt
132@
133@    }
134__tx_thread_not_nested_restore:
135@
136@    /* Determine if a thread was interrupted and no preemption is required.  */
137@    else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr))
138@               || (_tx_thread_preempt_disable))
139@    {
140@
141    LDR     r1, =_tx_thread_current_ptr     @ Pickup address of current thread ptr
142    LDR     r0, [r1]                        @ Pickup actual current thread pointer
143    CMP     r0, #0                          @ Is it NULL?
144    BEQ     __tx_thread_idle_system_restore @ Yes, idle system was interrupted
145@
146    LDR     r3, =_tx_thread_preempt_disable @ Pickup preempt disable address
147    LDR     r2, [r3]                        @ Pickup actual preempt disable flag
148    CMP     r2, #0                          @ Is it set?
149    BNE     __tx_thread_no_preempt_restore  @ Yes, don't preempt this thread
150    LDR     r3, =_tx_thread_execute_ptr     @ Pickup address of execute thread ptr
151    LDR     r2, [r3]                        @ Pickup actual execute thread pointer
152    CMP     r0, r2                          @ Is the same thread highest priority?
153    BNE     __tx_thread_preempt_restore     @ No, preemption needs to happen
154@
155@
156__tx_thread_no_preempt_restore:
157@
158@    /* Restore interrupted thread or ISR.  */
159@
160@    /* Pickup the saved stack pointer.  */
161@    tmp_ptr =  _tx_thread_current_ptr -> tx_thread_stack_ptr;
162@
163@   /* Recover the saved context and return to the point of interrupt.  */
164@
165    LDMIA   sp!, {r0, r10, r12, lr}         @ Recover SPSR, POI, and scratch regs
166    MSR     SPSR, r0                        @ Put SPSR back
167    LDMIA   sp!, {r0-r3}                    @ Recover r0-r3
168    MOVS    pc, lr                          @ Return to point of interrupt
169@
170@    }
171@    else
172@    {
173__tx_thread_preempt_restore:
174@
175    LDMIA   sp!, {r3, r10, r12, lr}         @ Recover temporarily saved registers
176    MOV     r1, lr                          @ Save lr (point of interrupt)
177    MOV     r2, #SVC_MODE                   @ Build SVC mode CPSR
178    MSR     CPSR, r2                        @ Enter SVC mode
179    STR     r1, [sp, #-4]!                  @ Save point of interrupt
180    STMDB   sp!, {r4-r12, lr}               @ Save upper half of registers
181    MOV     r4, r3                          @ Save SPSR in r4
182    MOV     r2, #IRQ_MODE                   @ Build IRQ mode CPSR
183    MSR     CPSR, r2                        @ Enter IRQ mode
184    LDMIA   sp!, {r0-r3}                    @ Recover r0-r3
185    MOV     r5, #SVC_MODE                   @ Build SVC mode CPSR
186    MSR     CPSR, r5                        @ Enter SVC mode
187    STMDB   sp!, {r0-r3}                    @ Save r0-r3 on thread's stack
188    MOV     r3, #1                          @ Build interrupt stack type
189    STMDB   sp!, {r3, r4}                   @ Save interrupt stack type and SPSR
190    LDR     r1, =_tx_thread_current_ptr     @ Pickup address of current thread ptr
191    LDR     r0, [r1]                        @ Pickup current thread pointer
192    STR     sp, [r0, #8]                    @ Save stack pointer in thread control
193                                            @   block
194@
195@    /* Save the remaining time-slice and disable it.  */
196@    if (_tx_timer_time_slice)
197@    {
198@
199    LDR     r3, =_tx_timer_time_slice       @ Pickup time-slice variable address
200    LDR     r2, [r3]                        @ Pickup time-slice
201    CMP     r2, #0                          @ Is it active?
202    BEQ     __tx_thread_dont_save_ts        @ No, don't save it
203@
204@        _tx_thread_current_ptr -> tx_thread_time_slice =  _tx_timer_time_slice;
205@        _tx_timer_time_slice =  0;
206@
207    STR     r2, [r0, #24]                   @ Save thread's time-slice
208    MOV     r2, #0                          @ Clear value
209    STR     r2, [r3]                        @ Disable global time-slice flag
210@
211@    }
212__tx_thread_dont_save_ts:
213@
214@
215@    /* Clear the current task pointer.  */
216@    _tx_thread_current_ptr =  TX_NULL;
217@
218    MOV     r0, #0                          @ NULL value
219    STR     r0, [r1]                        @ Clear current thread pointer
220@
221@    /* Return to the scheduler.  */
222@    _tx_thread_schedule();
223@
224    B       _tx_thread_schedule             @ Return to scheduler
225@    }
226@
227__tx_thread_idle_system_restore:
228@
229@    /* Just return back to the scheduler!  */
230@
231    MOV     r0, #SVC_MODE                   @ Build SVC mode CPSR
232    MSR     CPSR, r0                        @ Enter SVC mode
233    B       _tx_thread_schedule             @ Return to scheduler
234@}
235
236
237
238