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