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    EXTERN  __tx_thread_execute_ptr
24    EXTERN  __tx_thread_current_ptr
25    EXTERN  __tx_timer_time_slice
26    IMPORT  __txm_module_manager_kernel_dispatch
27    IMPORT  __tx_thread_system_state
28    EXTERN  __txm_module_manager_memory_fault_info
29    EXTERN  __txm_module_manager_memory_fault_handler
30
31    section .text:CODE:ROOT
32
33/**************************************************************************/
34/*                                                                        */
35/*  FUNCTION                                               RELEASE        */
36/*                                                                        */
37/*    _tx_thread_schedule                                  RXv2/IAR       */
38/*                                                           6.1.10       */
39/*  AUTHOR                                                                */
40/*                                                                        */
41/*    Scott Larson, Microsoft Corporation                                 */
42/*                                                                        */
43/*  DESCRIPTION                                                           */
44/*                                                                        */
45/*    This function waits for a thread control block pointer to appear in */
46/*    the _tx_thread_execute_ptr variable.  Once a thread pointer appears */
47/*    in the variable, the corresponding thread is resumed.               */
48/*                                                                        */
49/*  INPUT                                                                 */
50/*                                                                        */
51/*    None                                                                */
52/*                                                                        */
53/*  OUTPUT                                                                */
54/*                                                                        */
55/*    None                                                                */
56/*                                                                        */
57/*  CALLS                                                                 */
58/*                                                                        */
59/*    None                                                                */
60/*                                                                        */
61/*  CALLED BY                                                             */
62/*                                                                        */
63/*    _tx_initialize_kernel_enter          ThreadX entry function         */
64/*    _tx_thread_system_return             Return to system from thread   */
65/*    _tx_thread_context_restore           Restore thread's context       */
66/*                                                                        */
67/*  RELEASE HISTORY                                                       */
68/*                                                                        */
69/*    DATE              NAME                      DESCRIPTION             */
70/*                                                                        */
71/*  12-30-2020     William E. Lamie         Initial Version 6.1.3         */
72/*  10-15-2021     William E. Lamie         Modified comment(s), and      */
73/*                                            removed unnecessary stack   */
74/*                                            type checking,              */
75/*                                            resulting in version 6.1.9  */
76/*                                                                        */
77/**************************************************************************/
78// VOID   _tx_thread_schedule(VOID)
79// {
80    public __tx_thread_schedule
81__tx_thread_schedule:
82
83    /* Enable interrupts.  */
84
85    SETPSW  I
86
87    /* Wait for a thread to execute.  */
88    // do
89    // {
90    MOV.L   #__tx_thread_execute_ptr, R1        // Address of thread to executer ptr
91__tx_thread_schedule_loop:
92    MOV.L   [R1],R2                             // Pickup next thread to execute
93    CMP     #0,R2                               // Is it NULL?
94    BEQ     __tx_thread_schedule_loop           // Yes, idle system, keep checking
95
96    // }
97    // while(_tx_thread_execute_ptr == TX_NULL);
98
99    /* Yes! We have a thread to execute.  Lockout interrupts and transfer control to it.  */
100
101    CLRPSW  I                                   // Disable interrupts
102
103    /* Setup the current thread pointer.  */
104    // _tx_thread_current_ptr =  _tx_thread_execute_ptr;
105
106    MOV.L   #__tx_thread_current_ptr, R3
107    MOV.L   R2,[R3]                             // Setup current thread pointer
108
109    /* Increment the run count for this thread.  */
110    // _tx_thread_current_ptr -> tx_thread_run_count++;
111
112    MOV.L   4[R2],R3                            // Pickup run count
113    ADD     #1,R3                               // Increment run counter
114    MOV.L   R3,4[R2]                            // Store it back in control block
115
116    /* Setup time-slice, if present.  */
117    // _tx_timer_time_slice =  _tx_thread_current_ptr -> tx_thread_time_slice;
118
119    MOV.L   24[R2],R3                           // Pickup thread time-slice
120    MOV.L   #__tx_timer_time_slice,R4           // Pickup pointer to time-slice
121    MOV.L   R3, [R4]                            // Setup time-slice
122
123    /* Switch to the thread's stack.  */
124    // SP =  _tx_thread_execute_ptr -> tx_thread_stack_ptr;
125    SETPSW  U                                   // User stack mode
126    MOV.L   8[R2],SP                            // Pickup stack pointer
127
128
129    /* Set up MPU. */
130    // Disable MPU
131    MOV.L   #0x00086500,R1                      // Pickup MPEN
132    MOV     #0,R3                               // Build disable value
133    MOV.L   R3,[R1]                             // Disable MPU
134    // Determine if protection for this thread is required
135    MOV.L   156[R2],R1                          // Pickup user_mode
136    CMP     #0,R1                               // Is protection required for this thread?
137    BEQ     skip_mpu_setup                      // No, skip MPU setup
138
139    MOV.L   #0x00086408,R1                      // Region 1 Start Page Register address
140    MOV.L   144[R2],R2                          // Address of module instance ptr at offset 144 in TCB
141    ADD     #100,R2,R2                          // Get address of MPU table in module struct, starting at region 1
142
143    // Region 0 (Trampoline from User mode to ThreadX) set up in txm_module_manager_setup_mpu_registers.c
144
145    // Build region 1 (User code)
146    MOV.L   [R2+],R4                            // Pickup region 1 start page, increment to region 1 end page
147    MOV.L   R4,[R1+]                            // Setup region 1 start page reg, increment to region 1 end page reg.
148    MOV.L   [R2+],R4                            // Pickup region 1 end page, increment to region 2 start page
149    MOV.L   R4,[R1+]                            // Setup region 1 end page reg, increment to region 2 start page reg.
150
151    // Build region 2 (User data)
152    MOV.L   [R2+],R4                            // Pickup region 2 start page, increment to region 2 end page
153    MOV.L   R4,[R1+]                            // Setup region 2 start page reg, increment to region 2 end page reg.
154    MOV.L   [R2+],R4                            // Pickup region 2 end page, increment to region 3 start page
155    MOV.L   R4,[R1+]                            // Setup region 2 end page reg, increment to region 3 start page reg.
156
157    // Build region 3 (Shared memory)
158    MOV.L   [R2+],R4                            // Pickup region 3 start page, increment to region 3 end page
159    MOV.L   R4,[R1+]                            // Setup region 3 start page reg, increment to region 3 end page reg.
160    MOV.L   [R2+],R4                            // Pickup region 3 end page, increment to region 4 start page
161    MOV.L   R4,[R1+]                            // Setup region 3 end page reg, increment to region 4 start page reg.
162
163    // Region 4-7 unused
164
165    // Setup background region
166    MOV.L   #0x00086504,R1                      // Pickup MPBAC
167    MOV     #0,[R1]                             // Read/Write/Execute prohibited.
168    // Enable MPU
169    MOV.L   #0x00086500,R1                      // Pickup MPEN
170    MOV     #1,[R1]                             // Enable MPU
171
172skip_mpu_setup
173
174    POPM    R1-R3                               // Restore accumulators.
175    MVTACLO R3, A0
176    MVTACHI R2, A0
177    MVTACGU R1, A0
178    POPM    R1-R3
179    MVTACLO R3, A1
180    MVTACHI R2, A1
181    MVTACGU R1, A1
182
183    POPM    R6-R13                              // Recover interrupt stack frame
184    POPC    FPSW
185    POPM    R14-R15
186    POPM    R3-R5
187    POPM    R1-R2
188    RTE                                         // Return to point of interrupt, this restores PC and PSW
189
190// }
191
192    extern __tx_thread_context_save
193    extern __tx_thread_context_restore
194
195/*  Software triggered interrupt used to perform context switches.
196    The priority of this interrupt is set to the lowest priority within
197    tx_initialize_low_level() and triggered by ThreadX when calling
198    _tx_thread_system_return(). */
199
200    public ___interrupt_27
201___interrupt_27:
202
203    PUSHM R1-R2
204
205    BSR __tx_thread_context_save
206
207    BRA __tx_thread_context_restore
208
209
210/* You may have to modify BSP to use this handler.
211    // MPU Memory access violation
212    PUBLIC ___excep_access_inst
213    PUBLIC ___violation_handler
214___excep_access_inst
215___violation_handler
216    // Disable interrupts
217    CLRPSW  I                                   // disable interrupts
218    // Save contents of R1 and R2
219    PUSH    R1
220    PUSH    R2
221    // Increment and save system state
222    MOV.L   #__tx_thread_system_state, R1       // Pickup address of system state
223    MOV.L   [R1], R2                            // Pickup system state
224    ADD     #1, R2                              // Increment
225    MOV.L   R2, [R1]                            // Store new system state
226
227    // Now pickup and store all the fault related information.
228
229    MOV.L   #__txm_module_manager_memory_fault_info, R1
230    MOV.L   #__tx_thread_current_ptr, R2        // Build current thread pointer address
231    MOV.L   [R2], R2                            // Pickup the current thread pointer
232    MOV.L   R2, 0[R1]                           // Save current thread pointer in fault info structure
233    MOV.L   8[SP], R2                           // Pickup instruction address at point of fault
234    MOV.L   R2, 4[R1]                           // Save point of fault
235    MOV.L   #0x0008650C, R2                     // Pickup Memory-Protection Error Status Register
236    MOV.L   [R2], 8[R1]                         // Save MPESTS
237    MOV.L   #0x00086514, R2                     // Pickup Data Memory-Protection Error Address Register
238    MOV.L   [R2], 12[R1]                        // Save MPDEA
239    MOV.L   #0x00086528, R2                     // Pickup Instruction Hit Region Register
240    MOV.L   [R2], 16[R1]                        // Save MHITI
241    MOV.L   #0x0008652C, R2                     // Pickup Data Hit Region Register
242    MOV.L   [R2], 20[R1]                        // Save MHITD
243    MOV.L   12[SP], R2                          // Pickup PSW
244    MOV.L   R2, 24[R1]                          // Save PSW
245    MVFC    USP, R2                             // Pickup user stack pointer
246    MOV.L   R2, 28[R1]                          // Save user stack pointer
247    MOV.L   R3, 40[R1]                          // Save R3
248    MOV.L   R4, 44[R1]                          // Save R4
249    MOV.L   R5, 48[R1]                          // Save R5
250    MOV.L   R6, 52[R1]                          // Save R6
251    MOV.L   R7, 56[R1]                          // Save R7
252    MOV.L   R8, 60[R1]                          // Save R8
253    MOV.L   R9, 64[R1]                          // Save R9
254    MOV.L   R10, 68[R1]                         // Save R10
255    MOV.L   R11, 72[R1]                         // Save R11
256    MOV.L   R12, 76[R1]                         // Save R12
257    MOV.L   R13, 80[R1]                         // Save R13
258    MOV.L   R14, 84[R1]                         // Save R14
259    MOV.L   R15, 84[R1]                         // Save R15
260    POP     R3                                  // Recall R1
261    MOV.L   R3, 32[R1]                          // Save R1
262    POP     R3                                  // Recall R2
263    MOV.L   R3, 36[R1]                          // Save R2
264
265    BSR     __txm_module_manager_memory_fault_handler    // Call memory manager fault handler
266
267    // Decrement and save system state
268    MOV.L   #__tx_thread_system_state, R1       // Pickup address of system state
269    MOV.L   [R1], R2                            // Pickup system state
270    SUB     #1, R2                              // Decrement
271    MOV.L   R2, [R1]                            // Store new system state
272
273    MOV.L   #__tx_thread_current_ptr, R2        // Pickup address of current thread pointer
274    MOV.L   #0, [R2]                            // Clear current thread pointer
275    BRA     __tx_thread_schedule                // Attempt to schedule the next thread
276*/
277
278
279    public ___interrupt_26
280___interrupt_26:
281    PUBLIC __txm_module_manager_kernel
282__txm_module_manager_kernel
283
284    MOV.L   [SP], R5                            // Get return address
285    CMP     #__txm_module_manager_user_mode_entry+3, R5   // Did we come from user_mode_entry?
286    BEQ     __txm_module_manager_entry          // If so, continue.
287    RTE                                         // If not, then return from where we came.
288
289__txm_module_manager_entry
290    // We are entering the kernel from a module thread with user mode selected.
291    // At this point, we are out of user mode!
292    // Clear current user mode.
293    MOV.L   #__tx_thread_current_ptr, R5
294    MOV     [R5],R5
295    MOV     #0,152[R5]
296
297    // Switch to kernel stack
298    PUSHM   R1-R2
299    MVFC    USP, R1                             // Pickup module thread stack pointer
300    MOV.L   R1, 172[R5]                         // Save module thread stack pointer
301    MOV.L   164[R5], R1                         // Pickup kernel stack end
302#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
303    MOV.L   R1, 16[R5]                          // Set stack end
304    MOV.L   160[R5], R2                         // Pickup kernel stack start
305    MOV.L   R2, 12[R5]                          // Set stack start
306    MOV.L   168[R5], R2                         // Pickup kernel stack size
307    MOV.L   R2, 20[R5]                          // Set stack size
308#endif
309    MVTC    R1, USP                             // Set stack pointer
310    POPM    R1-R2
311
312    // Modify PSW in ISP to return in supervisor mode and user stack
313    MOV.L   4[SP], R5
314    BCLR    #20, R5
315    MOV.L   R5, 4[SP]
316
317    // Return to user_mode_entry where kernel_dispatch will be called.
318    RTE
319
320
321
322    SECTION CODE:CODE (4)   // Align 4, smallest page size for MPU is 16 bytes.
323    ALIGN   4
324    PUBLIC __txm_module_manager_user_mode_entry
325__txm_module_manager_user_mode_entry
326
327    INT #26     // Enter ThreadX kernel (exit User mode).
328
329    // At this point, we are out of user mode.
330    // Simply call the kernel dispatch function.
331    MOV.L #__txm_module_manager_kernel_dispatch,R5
332    JSR R5
333
334    // Restore user mode while inside of ThreadX.
335    MOV.L   #__tx_thread_current_ptr, R5
336    MOV     [R5],R5
337    MOV     #1,152[R5]
338
339    // Switch to module thread stack
340#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
341    PUSH    R1
342    MOV.L   176[R5], R1                         // Pickup module thread stack start
343    MOV.L   R1, 12[R5]                          // Set stack start
344    MOV.L   180[R5], R1                         // Pickup module thread stack end
345    MOV.L   R1, 16[R5]                          // Set stack end
346    MOV.L   184[R5], R1                         // Pickup kernel stack size
347    MOV.L   R1, 20[R5]                          // Set stack size
348    POP     R1
349#endif
350    MOV.L   172[R5], R5                         // Pickup module thread stack pointer
351    MVTC    R5, USP                             // Set stack pointer
352
353
354    // USP is set for an RTS, need to set for RTE to set User mode in PSW.
355    // Push return address on SP
356    MOV.L  [SP],R5
357    PUSH   R5
358    // Set user mode and place PSW in prev position in SP
359    MVFC   PSW,R5
360    BSET   #20,R5
361    MOV.L  R5,4[SP]
362    RTE
363
364    // Fill rest of page with NOPs.
365    NOP
366    NOP
367    NOP
368    NOP
369
370    NOP
371    NOP
372    NOP
373    NOP
374
375    NOP
376    NOP
377    NOP
378    NOP
379
380    END
381