1/***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12/**************************************************************************/
13/**************************************************************************/
14/**                                                                       */
15/** ThreadX Component                                                     */
16/**                                                                       */
17/**   Thread                                                              */
18/**                                                                       */
19/**************************************************************************/
20/**************************************************************************/
21
22
23/* #define TX_SOURCE_CODE  */
24
25
26/* Include necessary system files.  */
27
28/*  #include "tx_api.h"
29    #include "tx_thread.h"
30    #include "tx_timer.h"  */
31
32    EXTERN      _tx_thread_current_ptr
33    EXTERN      _tx_thread_system_state
34    EXTERN      _tx_thread_system_stack_ptr
35#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
36    EXTERN      _tx_execution_isr_enter
37#endif
38
39
40    SECTION `.text`:CODE:REORDER:NOROOT(2)
41    CODE
42/**************************************************************************/
43/*                                                                        */
44/*  FUNCTION                                               RELEASE        */
45/*                                                                        */
46/*    _tx_thread_context_save                            RISC-V32/IAR     */
47/*                                                           6.1          */
48/*  AUTHOR                                                                */
49/*                                                                        */
50/*    William E. Lamie, Microsoft Corporation                             */
51/*    Tom van Leeuwen, Technolution B.V.                                  */
52/*                                                                        */
53/*  DESCRIPTION                                                           */
54/*                                                                        */
55/*    This function saves the context of an executing thread in the       */
56/*    beginning of interrupt processing.  The function also ensures that  */
57/*    the system stack is used upon return to the calling ISR.            */
58/*                                                                        */
59/*  INPUT                                                                 */
60/*                                                                        */
61/*    None                                                                */
62/*                                                                        */
63/*  OUTPUT                                                                */
64/*                                                                        */
65/*    None                                                                */
66/*                                                                        */
67/*  CALLS                                                                 */
68/*                                                                        */
69/*    None                                                                */
70/*                                                                        */
71/*  CALLED BY                                                             */
72/*                                                                        */
73/*    ISRs                                                                */
74/*                                                                        */
75/*  RELEASE HISTORY                                                       */
76/*                                                                        */
77/*    DATE              NAME                      DESCRIPTION             */
78/*                                                                        */
79/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
80/*                                                                        */
81/**************************************************************************/
82/* VOID   _tx_thread_context_save(VOID)
83{  */
84    PUBLIC      _tx_thread_context_save
85_tx_thread_context_save:
86
87    /* Upon entry to this routine, it is assumed that interrupts are locked
88       out and the interrupt stack fame has been allocated and x1 (ra) has
89       been saved on the stack. */
90
91    sw      x5, 0x4C(sp)                                ; First store t0 and t1
92    sw      x6, 0x48(sp)
93
94    la      x5, _tx_thread_system_state                 ; Pickup address of system state
95    lw      x6, 0(x5)                                   ; Pickup system state
96
97    /* Check for a nested interrupt condition.  */
98    /* if (_tx_thread_system_state++)
99    {  */
100    beqz    x6, _tx_thread_not_nested_save              ; If 0, first interrupt condition
101    addi    x6, x6, 1                                   ; Increment the interrupt counter
102    sw      x6, 0(x5)                                   ; Store the interrupt counter
103
104    /* Nested interrupt condition.
105       Save the reset of the scratch registers on the stack and return to the
106       calling ISR.  */
107
108    sw      x7, 0x44(sp)                                ; Store t2
109    sw      x8, 0x30(sp)                                ; Store s0
110    sw      x10, 0x6C(sp)                               ; Store a0
111    sw      x11, 0x68(sp)                               ; Store a1
112    sw      x12, 0x64(sp)                               ; Store a2
113    sw      x13, 0x60(sp)                               ; Store a3
114    sw      x14, 0x5C(sp)                               ; Store a4
115    sw      x15, 0x58(sp)                               ; Store a5
116    sw      x16, 0x54(sp)                               ; Store a6
117    sw      x17, 0x50(sp)                               ; Store a7
118    sw      x28, 0x40(sp)                               ; Store t3
119    sw      x29, 0x3C(sp)                               ; Store t4
120    sw      x30, 0x38(sp)                               ; Store t5
121    sw      x31, 0x34(sp)                               ; Store t6
122    csrr    t0, mepc                                    ; Load exception program counter
123    sw      t0, 0x78(sp)                                ; Save it on the stack
124
125#if __iar_riscv_base_isa == rv32e
126
127    /* Save floating point scratch registers.  */
128
129    fsw     f0, 0x7C(sp)                                ; Store ft0
130    fsw     f1, 0x80(sp)                                ; Store ft1
131    fsw     f2, 0x84(sp)                                ; Store ft2
132    fsw     f3, 0x88(sp)                                ; Store ft3
133    fsw     f4, 0x8C(sp)                                ; Store ft4
134    fsw     f5, 0x90(sp)                                ; Store ft5
135    fsw     f6, 0x94(sp)                                ; Store ft6
136    fsw     f7, 0x98(sp)                                ; Store ft7
137    fsw     f10,0xA4(sp)                                ; Store fa0
138    fsw     f11,0xA8(sp)                                ; Store fa1
139    fsw     f12,0xAC(sp)                                ; Store fa2
140    fsw     f13,0xB0(sp)                                ; Store fa3
141    fsw     f14,0xB4(sp)                                ; Store fa4
142    fsw     f15,0xB8(sp)                                ; Store fa5
143    fsw     f16,0xBC(sp)                                ; Store fa6
144    fsw     f17,0xC0(sp)                                ; Store fa7
145    fsw     f28,0xEC(sp)                                ; Store ft8
146    fsw     f29,0xF0(sp)                                ; Store ft9
147    fsw     f30,0xF4(sp)                                ; Store ft10
148    fsw     f31,0xF8(sp)                                ; Store ft11
149    csrr    t0, fcsr
150    sw      t0, 0xFC(sp)                                ; Store fcsr
151#endif
152
153#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
154    call    _tx_execution_isr_enter                     ; Call the ISR execution enter function
155#endif
156
157    ret                                                 ; Return to calling ISR
158
159_tx_thread_not_nested_save:
160    /* }  */
161
162    /* Otherwise, not nested, check to see if a thread was running.  */
163    /* else if (_tx_thread_current_ptr)
164    {  */
165    addi    x6, x6, 1                                   ; Increment the interrupt counter
166    sw      x6, 0(x5)                                   ; Store the interrupt counter
167
168    /* Not nested: Find the user thread that was running and load our SP */
169
170    lw      x5, _tx_thread_current_ptr                  ; Pickup current thread pointer
171    beqz    x5, _tx_thread_idle_system_save             ; If NULL, idle system was interrupted
172
173    /* Save the standard scratch registers.  */
174
175    sw      x7, 0x44(sp)                                ; Store t2
176    sw      x8, 0x30(sp)                                ; Store s0
177    sw      x10, 0x6C(sp)                               ; Store a0
178    sw      x11, 0x68(sp)                               ; Store a1
179    sw      x12, 0x64(sp)                               ; Store a2
180    sw      x13, 0x60(sp)                               ; Store a3
181    sw      x14, 0x5C(sp)                               ; Store a4
182    sw      x15, 0x58(sp)                               ; Store a5
183    sw      x16, 0x54(sp)                               ; Store a6
184    sw      x17, 0x50(sp)                               ; Store a7
185    sw      x28, 0x40(sp)                               ; Store t3
186    sw      x29, 0x3C(sp)                               ; Store t4
187    sw      x30, 0x38(sp)                               ; Store t5
188    sw      x31, 0x34(sp)                               ; Store t6
189
190    csrr    t0, mepc                                    ; Load exception program counter
191    sw      t0, 0x78(sp)                                ; Save it on the stack
192
193#if __iar_riscv_base_isa == rv32e
194
195    /* Save floating point scratch registers.  */
196
197    fsw     f0, 0x7C(sp)                                ; Store ft0
198    fsw     f1, 0x80(sp)                                ; Store ft1
199    fsw     f2, 0x84(sp)                                ; Store ft2
200    fsw     f3, 0x88(sp)                                ; Store ft3
201    fsw     f4, 0x8C(sp)                                ; Store ft4
202    fsw     f5, 0x90(sp)                                ; Store ft5
203    fsw     f6, 0x94(sp)                                ; Store ft6
204    fsw     f7, 0x98(sp)                                ; Store ft7
205    fsw     f10,0xA4(sp)                                ; Store fa0
206    fsw     f11,0xA8(sp)                                ; Store fa1
207    fsw     f12,0xAC(sp)                                ; Store fa2
208    fsw     f13,0xB0(sp)                                ; Store fa3
209    fsw     f14,0xB4(sp)                                ; Store fa4
210    fsw     f15,0xB8(sp)                                ; Store fa5
211    fsw     f16,0xBC(sp)                                ; Store fa6
212    fsw     f17,0xC0(sp)                                ; Store fa7
213    fsw     f28,0xEC(sp)                                ; Store ft8
214    fsw     f29,0xF0(sp)                                ; Store ft9
215    fsw     f30,0xF4(sp)                                ; Store ft10
216    fsw     f31,0xF8(sp)                                ; Store ft11
217    csrr    t0, fcsr
218    sw      t0, 0xFC(sp)                                ; Store fcsr
219#endif
220
221    /* Save the current stack pointer in the thread's control block.  */
222    /* _tx_thread_current_ptr -> tx_thread_stack_ptr =  sp;  */
223
224    /* Switch to the system stack.  */
225    /* sp =  _tx_thread_system_stack_ptr;  */
226
227    lw      t1, _tx_thread_current_ptr                  ; Pickup current thread pointer
228    sw      sp, 8(t1)                                   ; Save stack pointer*/
229
230#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
231    /* _tx_execution_isr_enter is called with thread stack pointer */
232    call    _tx_execution_isr_enter                     ; Call the ISR execution enter function
233#endif
234
235
236    lw      sp, _tx_thread_system_stack_ptr             ; Switch to system stack
237    ret                                                 ; Return to calling ISR
238
239    /* }
240    else
241    {  */
242
243_tx_thread_idle_system_save:
244
245
246#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
247    call    _tx_execution_isr_enter                     ; Call the ISR execution enter function
248#endif
249
250    /* Interrupt occurred in the scheduling loop.  */
251
252    /* }
253}  */
254#if __iar_riscv_base_isa == rv32e
255    addi    sp, sp, 260                                 ; Recover stack frame - with floating point enabled
256#else
257    addi    sp, sp, 128                                 ; Recover the reserved stack space
258#endif
259    ret                                                 ; Return to calling ISR
260
261    END
262