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