comparison src/nucleus/gcc/tct.S @ 74:d076885a0669

src/nucleus/gcc: initial import from Citrine
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 20 Jul 2018 05:40:33 +0000
parents
children 6738273be0b3
comparison
equal deleted inserted replaced
73:0f466af1eaf0 74:d076885a0669
1 /*
2 ************************************************************************
3 *
4 * Copyright Mentor Graphics Corporation 2002
5 * All Rights Reserved.
6 *
7 * THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS
8 * THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS
9 * SUBJECT TO LICENSE TERMS.
10 *
11 ************************************************************************
12 ************************************************************************
13 *
14 * FILE NAME VERSION
15 *
16 * tct.s Nucleus PLUS\ARM925\Code Composer 1.14.1
17 *
18 * COMPONENT
19 *
20 * TC - Thread Control
21 *
22 * DESCRIPTION
23 *
24 * This file contains the target processor dependent routines for
25 * performing target-dependent scheduling functions.
26 *
27 * FUNCTIONS
28 *
29 * TCT_Control_Interrupts Enable / disable interrupts
30 * by changing
31 * TCD_Interrupt_Level
32 * TCT_Local_Control_Interrupts Enable/disable interrupts
33 * by not changing
34 * TCD_Interrupt_Level
35 * TCT_Restore_Interrupts Restores interrupts to the
36 * level in TCD_Interrupt_Level
37 * TCT_Build_Task_Stack Build initial task stack
38 * TCT_Build_HISR_Stack Build initial HISR stack
39 * TCT_Build_Signal_Frame Build signal handler frame
40 * TCT_Check_Stack Check current stack
41 * TCT_Schedule Schedule the next thread
42 * TCT_Control_To_Thread Transfer control to a thread
43 * TCT_Control_To_System Transfer control from thread
44 * TCT_Signal_Exit Exit from signal handler
45 * TCT_Current_Thread Returns a pointer to current
46 * thread
47 * TCT_Set_Execute_Task Sets TCD_Execute_Task under
48 * protection from interrupts
49 * TCT_Protect Protect critical section
50 * TCT_Unprotect Unprotect critical section
51 * TCT_Unprotect_Specific Release specific protection
52 * TCT_Set_Current_Protect Set the thread's current
53 * protection field
54 * TCT_Protect_Switch Switch to protected thread
55 * TCT_Schedule_Protected Schedule the protected thread
56 * TCT_Interrupt_Context_Save Save interrupted context
57 * TCT_Interrupt_Context_Restore Restore interrupted context
58 * TCT_Activate_HISR Activate a HISR
59 * TCT_HISR_Shell HISR execution shell
60 *
61 * DEPENDENCIES
62 *
63 * cs_extr.h Common Service functions
64 * tc_extr.h Thread Control functions
65 *
66 * HISTORY
67 *
68 * NAME DATE REMARKS
69 *
70 * B. Ronquillo 08-28-2002 Released version 1.14.1
71 *
72 ************************************************************************
73 */
74
75 #define NU_SOURCE_FILE
76
77 /*
78 ******************************
79 * INCLUDE ASSEMBLY CONSTANTS *
80 ******************************
81 * Define constants used in low-level initialization.
82 */
83
84 #include "asm_defs.h"
85 #include "../include/config.h"
86
87 .code 32
88
89 /* TCT_System_Limit is a global variable defined in this module */
90
91 .comm TCT_System_Limit,4,4
92
93 .text
94
95 /*
96 **********************************
97 * LOCAL VARIABLE DECLARATIONS *
98 **********************************
99 * Define pointers to system variables so their addresses may be obtained in a
100 * pc-relative manner.
101 */
102
103 System_Limit:
104 .word TCT_System_Limit
105
106 Int_Level:
107 .word TCD_Interrupt_Level
108
109 Task_Shell:
110 .word TCC_Task_Shell
111
112 HISR_Shell:
113 .word TCT_HISR_Shell
114
115 Signal_Shell:
116 .word TCC_Signal_Shell
117
118 Current_Thread:
119 .word TCD_Current_Thread
120
121 Execute_HISR:
122 .word TCD_Execute_HISR
123
124 Execute_Task:
125 .word TCD_Execute_Task
126
127 Time_Slice:
128 .word TMD_Time_Slice
129
130 Slice_State:
131 .word TMD_Time_Slice_State
132
133 System_Stack:
134 .word TCD_System_Stack
135
136 Int_Count:
137 .word TCD_Interrupt_Count
138
139 HISR_Tails:
140 .word TCD_Active_HISR_Tails
141
142 HISR_Heads:
143 .word TCD_Active_HISR_Heads
144
145 /*
146 ************************************************************************
147 *
148 * FUNCTION
149 *
150 * TCT_Control_Interrupts
151 *
152 * DESCRIPTION
153 *
154 * This function enables and disables interrupts as specified by
155 * the caller. Interrupts disabled by this call are left disabled
156 * until the another call is made to enable them.
157 *
158 * CALLED BY
159 *
160 * Application
161 *
162 * CALLS
163 *
164 * None
165 *
166 * INPUTS
167 *
168 * new_level New interrupt enable level
169 *
170 * OUTPUTS
171 *
172 * old_level Previous interrupt enable
173 * level
174 *
175 * HISTORY
176 *
177 * NAME DATE REMARKS
178 *
179 * W. Lamie 02-15-1994 Created initial version 1.0
180 * D. Lamie 02-15-1994 Verified version 1.0
181 * C. Meredith 03-01-1994 Lockout interrupts while setting
182 * up the new level, resutling in
183 * version 1.1
184 * D. Lamie 03-18-1994 Verified version 1.1
185 * M. Trippi 02-03-1997 Masked the return value to only
186 * return the interrupt bits.
187 * (SPR0252)
188 *
189 ************************************************************************
190 */
191
192 @INT TCT_Control_Interrupts (INT new_level)
193 @{
194
195 .globl TCT_Control_Interrupts
196 TCT_Control_Interrupts:
197
198 @INT old_level; Old interrupt level
199
200 @ lock out all interrupts before any checking or changing
201
202 @ Obtain the current interrupt lockout posture.
203 @ old_level = TCD_Interrupt_Level;
204
205 @ Setup new interrupt lockout posture.
206 @ TCD_Interrupt_Level = new_level;
207
208 @ renable interrupts for the specified lockout
209
210 @ Return old interrupt lockout level.
211 @ return(old_level);
212
213 MRS r2,CPSR @ Pickup current CPSR
214 ORR r2,r2,#LOCKOUT @ Build lockout CPSR
215 MSR CPSR,r2 @ Lockout interrupts temporarily
216 LDR r1, Int_Level @ Pickup interrupt level
217 LDR r3,[r1, #0] @ Pickup current interrupt lockout
218 BIC r2,r2,#LOCK_MSK @ Clear lockout mask
219 ORR r2,r2,r0 @ Build new CPSR with appropriate
220 @ interrupts locked out
221 STR r0,[r1,#0] @ Save current lockout
222 MSR CPSR,r2 @ Setup new CPSR lockout bits
223 AND r0,r3,#LOCK_MSK @ Return previous lockout (SPR0252)
224
225 BX r14 @ Return to caller
226
227 @}
228
229 /*
230 ************************************************************************
231 *
232 * FUNCTION
233 *
234 * TCT_Local_Control_Interrupts
235 *
236 * DESCRIPTION
237 *
238 * This function enables and disables interrupts as specified by
239 * the caller.
240 *
241 * CALLED BY
242 *
243 * Application
244 *
245 * CALLS
246 *
247 * None
248 *
249 * INPUTS
250 *
251 * new_level New interrupt enable level
252 *
253 * OUTPUTS
254 *
255 * old_level Previous interrupt enable
256 * level
257 *
258 * HISTORY
259 *
260 * NAME DATE REMARKS
261 *
262 * C. Meredith 03-01-1994 Created initial version 1.1
263 * D. Lamie 03-18-1994 Verified version 1.1
264 * M. Trippi 02-03-1997 Masked the return value to only
265 * return the interrupt bits.
266 * (SPR0252)
267 *
268 ************************************************************************
269 */
270
271 @INT TCT_Local_Control_Interrupts (INT new_level)
272 @{
273
274 .globl TCT_Local_Control_Interrupts
275 TCT_Local_Control_Interrupts:
276
277 @INT old_level; Old interrupt level
278
279 @ read in the old level
280 @ old_level = current interrupt level of processor;
281
282 MRS r2,CPSR @ Pickup current CPSR
283 MOV r3,r2 @ save the old level
284
285 @ clear out the old level and set the new level
286 @ current interrupt level of processor &= ~LOCKOUT;
287 @ current interrupt level of processor |= new_level;
288
289 BIC r2,r2,#LOCK_MSK @ Clear all current interrupts
290 ORR r2,r2,r0 @ Build new CPSR with new
291 @ interrupt level
292 MSR CPSR,r2 @ Setup new CPSR interrupt bits
293
294 @ Return old interrupt lockout level.
295 @ return(old_level);
296
297 AND r0,r3,#LOCK_MSK @ Return previous lockout (SPR0252)
298
299 BX r14 @ Return to caller
300
301 @}
302
303 /*
304 ************************************************************************
305 *
306 * FUNCTION
307 *
308 * TCT_Restore_Interrupts
309 *
310 * DESCRIPTION
311 *
312 * This function restores interrupts to that specified in the global
313 * TCD_Interrupt_Level variable.
314 *
315 * CALLED BY
316 *
317 * Application
318 *
319 * CALLS
320 *
321 * None
322 *
323 * INPUTS
324 *
325 * None.
326 *
327 * OUTPUTS
328 *
329 * None.
330 *
331 * HISTORY
332 *
333 * NAME DATE REMARKS
334 *
335 * C. Meredith 03-01-1994 Created initial version 1.1
336 * D. Lamie 03-18-1994 Verified version 1.1
337 *
338 ************************************************************************
339 */
340
341 @VOID TCT_Restore_Interrupts (VOID)
342 @{
343
344 .globl TCT_Restore_Interrupts
345 TCT_Restore_Interrupts:
346
347 @ Lock out all interrupts before any checking or changing
348 @ Obtain the current interrupt lockout posture.
349 @ Reload the level base on the TCD_Interrupt_Level variable
350
351 MRS r1,CPSR @ Pickup current CPSR
352 MOV r2,r1 @ save the CPSR value
353 ORR r1,r1,#LOCKOUT @ Build lockout CPSR
354 MSR CPSR,r1 @ Lockout interrupts temporarily
355 BIC r2,r2,#LOCK_MSK @ Clear current interrupt levels
356 LDR r1,Int_Level @ Load address of TCD_Interrupt_Level
357 LDR r0,[r1, #0] @ Pickup current interrupt lockout
358 ORR r2,r2,r0 @ Build new CPSR with appropriate
359 @ interrupts locked out
360 MSR CPSR,r2 @ Setup new CPSR lockout bits
361
362 BX r14 @ Return to caller
363
364 @}
365
366 /*
367 ************************************************************************
368 *
369 * FUNCTION
370 *
371 * TCT_Build_Task_Stack
372 *
373 * DESCRIPTION
374 *
375 * This function builds an initial stack frame for a task. The
376 * initial stack contains information concerning initial values of
377 * registers and the task's point of entry. Furthermore, the
378 * initial stack frame is in the same form as an interrupt stack
379 * frame.
380 *
381 * CALLED BY
382 *
383 * TCC_Create_Task Create a new task
384 * TCC_Reset_Task Reset the specified task
385 *
386 * CALLS
387 *
388 * None
389 *
390 * INPUTS
391 *
392 * task Task control block pointer
393 *
394 * OUTPUTS
395 *
396 * None
397 *
398 * HISTORY
399 *
400 * NAME DATE REMARKS
401 *
402 * W. Lamie 02-15-1994 Created initial version 1.0
403 * D. Lamie 02-15-1994 Verified version 1.0
404 *
405 ************************************************************************
406 */
407
408 @VOID TCT_Build_Task_Stack(TC_TCB *task)
409 @{
410
411 .globl TCT_Build_Task_Stack
412 TCT_Build_Task_Stack:
413
414 @ Pickup the stack base.
415 @ REG_Stack_Base = (BYTE_PTR) task -> tc_stack_start;
416
417 LDR r2,[r0,#0x24] @ Pickup the stack starting address
418
419 @ Pickup the stack size.
420 @ REG_Stack_Size = task -> tc_stack_size;
421
422 LDR r1,[r0,#0x30] @ Pickup the stack size in bytes
423
424 @ Calculate the stack ending address.
425 @ REG_Stack_End = REG_Stack_Base + REG_Stack_Size - 1;
426
427 ADD r3,r1,r2 @ Compute the beginning of stack
428 BIC r3,r3,#3 @ Insure word alignment
429 SUB r3,r3,#4 @ Reserve a word
430
431 @ Save the stack ending address.
432 @ task -> tc_stack_end = REG_Stack_End;
433
434 STR r3,[r0,#0x28] @ Save the stack ending address
435
436 @ Reference the task shell.
437 @ REG_Function_Ptr = (VOID *) TCC_Task_Shell;
438
439 @ Build an initial stack. This initial stack frame facilitates an
440 @ interrupt return to the TCC_Task_Shell function, which in turn
441 @ invokes the application task. The initial stack frame has the
442 @ following format:
443
444 @ (Lower Address) Stack Top -> 1 (Interrupt stack type)
445 @ CPSR Saved CPSR
446 @ r0 Saved r0
447 @ r1 Saved r1
448 @ r2 Saved r2
449 @ r3 Saved r3
450 @ r4 Saved r4
451 @ r5 Saved r5
452 @ r6 Saved r6
453 @ r7 Saved r7
454 @ r8 Saved r8
455 @ r9/sb Saved r9/sl
456 @ r10/sl Saved r10/sl
457 @ fp Saved fp
458 @ r12 Saved r12
459 @ r13 Saved r13
460 @ r14 Saved r14
461 @ (Higher Address) Stack Bottom-> r15 Saved r15
462
463
464 LDR r2, Task_Shell @ Pickup address of shell entry
465 STR r2,[r3], #-4 @ Store entry address on stack
466 MOV r2,#0 @ Clear value for initial registers
467 STR r2,[r3], #-4 @ Store initial r14
468 ADD r2,r3,#8 @ Compute initial r13
469 STR r2,[r3], #-4 @ Store initial r13 (Stack Bottom)
470 STR r2,[r3], #-4 @ Store initial r12
471 STR r2,[r3], #-4 @ Store initial fp
472 LDR r2,[r0,#0x24] @ Pickup the stack starting address
473 STR r2,[r3], #-4 @ Store initial r10/sl
474 MOV r2,#0 @ Clear value for initial registers
475 STR r2,[r3], #-4 @ Store initial r9/sb
476 STR r2,[r3], #-4 @ Store initial r8
477 STR r2,[r3], #-4 @ Store initial r7
478 STR r2,[r3], #-4 @ Store initial r6
479 STR r2,[r3], #-4 @ Store initial r5
480 STR r2,[r3], #-4 @ Store initial r4
481 STR r2,[r3], #-4 @ Store initial r3
482 STR r2,[r3], #-4 @ Store initial r2
483 STR r2,[r3], #-4 @ Store initial r1
484 STR r2,[r3], #-4 @ Store initial r0
485 MSR CPSR_f,r2 @ Clear the flags
486 MRS r2,CPSR @ Pickup the CPSR
487 BIC r2,r2,#LOCK_MSK @ Clear initial interrupt lockout
488 STR r2,[r3], #-4 @ Store CPSR on the initial stack
489 MOV r2,#1 @ Build interrupt stack type (1)
490 STR r2,[r3, #0] @ Store stack type on the top
491
492 @ Save the minimum amount of remaining stack memory.
493 @ task -> tc_stack_minimum = REG_Stack_Size - 72;
494
495 MOV r2,#72 @ Size of interrupt stack frame
496 SUB r1,r1,r2 @ Compute minimum available bytes
497 STR r1,[r0, #0x34] @ Save in minimum stack area
498
499 @ Save the new stack pointer into the task's control block.
500 @ task -> tc_stack_pointer = (VOID *) Stack_Top;
501
502 STR r3,[r0, #0x2C] @ Save stack pointer
503
504 BX r14 @ Return to caller
505
506 @}
507
508 /*
509 ************************************************************************
510 *
511 * FUNCTION
512 *
513 * TCT_Build_HISR_Stack
514 *
515 * DESCRIPTION
516 *
517 * This function builds an HISR stack frame that allows quick
518 * scheduling of the HISR.
519 *
520 * CALLED BY
521 *
522 * TCC_Create_HISR Create HISR function
523 *
524 * CALLS
525 *
526 * None
527 *
528 * INPUTS
529 *
530 * hisr HISR control block pointer
531 *
532 * OUTPUTS
533 *
534 * None
535 *
536 * HISTORY
537 *
538 * NAME DATE REMARKS
539 *
540 * W. Lamie 02-15-1994 Created initial version 1.0
541 * D. Lamie 02-15-1994 Verified version 1.0
542 *
543 ************************************************************************
544 */
545
546 @VOID TCT_Build_HISR_Stack(TC_HCB *hisr)
547 @{
548
549 .globl TCT_Build_HISR_Stack
550 TCT_Build_HISR_Stack:
551
552 @ Pickup the stack base.
553 @ REG_Stack_Base = (BYTE_PTR) hisr -> tc_stack_start;
554
555 LDR r2,[r0,#0x24] @ Pickup the stack starting address
556
557 @ Pickup the stack size.
558 @ REG_Stack_Size = hisr -> tc_stack_size;
559
560 LDR r1,[r0,#0x30] @ Pickup the stack size in bytes
561
562 @ Calculate the stack ending address.
563 @ REG_Stack_End = REG_Stack_Base + REG_Stack_Size;
564
565 ADD r3,r1,r2 @ Compute the beginning of stack
566 BIC r3,r3,#3 @ Insure word alignment
567 SUB r3,r3,#4 @ Reserve a word
568
569 @ Save the stack ending address.
570 @ hisr -> tc_stack_end = REG_Stack_End;
571
572 STR r3,[r0,#0x28] @ Save the stack ending address
573
574 @ Reference the HISR shell.
575 @ REG_Function_Ptr = (VOID *) TCT_HISR_Shell;
576
577 @ Build an initial stack. This initial stack frame facilitates an
578 @ solicited return to the TCT_HISR_Shell function, which in turn
579 @ invokes the appropriate HISR. The initial HISR stack frame has the
580 @ following format:
581
582 @ (Lower Address) Stack Top -> 0 (Solicited stack type)
583 @ !!FOR THUMB ONLY!! 0/0x20 Saved state mask
584 @ r4 Saved r4
585 @ r5 Saved r5
586 @ r6 Saved r6
587 @ r7 Saved r7
588 @ r8 Saved r8
589 @ r9/sb Saved r9/sl
590 @ r10/sl Saved r10/sl
591 @ fp Saved fp
592 @ r12 Saved r12
593 @ (Higher Address) Stack Bottom-> r15 Saved r15
594
595
596 LDR r2,HISR_Shell @ Pickup address of shell entry
597 STR r2,[r3], #-4 @ Store entry address on stack
598 ADD r2,r3,#4 @ Compute initial r13
599 STR r2,[r3], #-4 @ Store initial r12
600 STR r2,[r3], #-4 @ Store initial fp
601 LDR r2,[r0,#0x24] @ Pickup the stack starting address
602 STR r2,[r3], #-4 @ Store initial r10/sl
603 MOV r2,#0 @ Clear value for initial registers
604 STR r2,[r3], #-4 @ Store initial r9/sb
605 STR r2,[r3], #-4 @ Store initial r8
606 STR r2,[r3], #-4 @ Store initial r7
607 STR r2,[r3], #-4 @ Store initial r6
608 STR r2,[r3], #-4 @ Store initial r5
609 STR r2,[r3], #-4 @ Store initial r4
610 #if 1 /* was .if THUMB */
611 STR r2,[r3], #-4 @ Store initial state mask
612 #endif
613 STR r2,[r3, #0] @ Store solicited stack type on the
614 @ top of the stack
615
616 @ Save the minimum amount of remaining stack memory.
617 @ hisr -> tc_stack_minimum = REG_Stack_Size - (ARM)44 or (THUMB)48;
618
619 #if 1 /* was .if THUMB */
620 MOV r2,#48 @ Size of solicited stack frame
621 #else
622 MOV r2,#44 @ Size of solicited stack frame
623 #endif
624
625 SUB r1,r1,r2 @ Compute minimum available bytes
626 STR r1,[r0, #0x34] @ Save in minimum stack area
627
628 @ Save the new stack pointer into the task's control block.
629 @ hisr -> tc_stack_pointer = (VOID *) Stack_Top;
630
631 STR r3,[r0, #0x2C] @ Save stack pointer
632
633 BX r14 @ Return to caller
634
635 @}
636
637 /*
638 ************************************************************************
639 *
640 * FUNCTION
641 *
642 * TCT_Build_Signal_Frame
643 *
644 * DESCRIPTION
645 *
646 * This function builds a frame on top of the task's stack to
647 * cause the task's signal handler to execute the next time
648 * the task is executed.
649 *
650 * CALLED BY
651 *
652 * TCC_Send_Signals Send signals to a task
653 *
654 * CALLS
655 *
656 * None
657 *
658 * INPUTS
659 *
660 * task Task control block pointer
661 *
662 * OUTPUTS
663 *
664 * None
665 *
666 * HISTORY
667 *
668 * NAME DATE REMARKS
669 *
670 * W. Lamie 02-15-1994 Created initial version 1.0
671 * D. Lamie 02-15-1994 Verified version 1.0
672 *
673 ************************************************************************
674 */
675
676 @VOID TCT_Build_Signal_Frame(TC_TCB *task)
677 @{
678
679 .globl TCT_Build_Signal_Frame
680 TCT_Build_Signal_Frame:
681
682 @ Pickup the stack pointer.
683 @ REG_Stack_Ptr = (BYTE_PTR) task -> tc_stack_pointer;
684
685 LDR r3,[r0,#0x2c] @ Pickup the current stack pointer
686
687 @ Reference the Signal shell.
688 @ REG_Function_Ptr = (VOID *) TCC_Signal_Shell;
689
690 @ Build a signal stack. This signal stack frame facilitates an
691 @ solicited return to the TCC_Signal_Shell function, which in turn
692 @ invokes the appropriate signal handler. The initial HISR stack frame
693 @ has the following format:
694
695 @ (Lower Address) Stack Top -> 0 (Solicited stack type)
696 @ !!FOR THUMB ONLY!! 0/0x20 Saved state mask
697 @ r4 Saved r4
698 @ r5 Saved r5
699 @ r6 Saved r6
700 @ r7 Saved r7
701 @ r8 Saved r8
702 @ r9/sb Saved r9/sl
703 @ r10/sl Saved r10/sl
704 @ fp Saved fp
705 @ r12 Saved r12
706 @ (Higher Address) Stack Bottom-> r15 Saved r15
707
708
709 LDR r2,Signal_Shell @ Pickup address of shell entry
710 SUB r3,r3,#4
711 STR r2,[r3], #-4 @ Store entry address on stack
712 ADD r2,r3,#4 @ Compute initial r13
713 STR r2,[r3], #-4 @ Store initial r12
714 STR r2,[r3], #-4 @ Store initial fp
715 LDR r2,[r0,#0x24] @ Pickup the stack starting address
716 STR r2,[r3], #-4 @ Store initial r10/sl
717 MOV r2,#0 @ Clear value for initial registers
718 STR r2,[r3], #-4 @ Store initial r9/sb
719 STR r2,[r3], #-4 @ Store initial r8
720 STR r2,[r3], #-4 @ Store initial r7
721 STR r2,[r3], #-4 @ Store initial r6
722 STR r2,[r3], #-4 @ Store initial r5
723 STR r2,[r3], #-4 @ Store initial r4
724 #if 0
725 MOV r1,#0x20 @ Get initial state mask
726 STR r1,[r3], #-4 @ Store initial state mask
727 #else
728 STR r2,[r3], #-4 @ TCC_Signal_Shell is an ARM proc
729 #endif
730
731 STR r2,[r3, #0] @ Store solicited stack type on the
732 @ top of the stack
733
734 @ Save the new stack pointer into the task's control block.
735 @ task -> tc_stack_pointer = (VOID *) (REG_Stack_Ptr - REG_Stack_Size);
736
737 STR r3,[r0, #0x2C] @ Save stack pointer
738
739 BX r14 @ Return to caller
740
741 @}
742
743 /*
744 ************************************************************************
745 *
746 * FUNCTION
747 *
748 * TCT_Check_Stack
749 *
750 * DESCRIPTION
751 *
752 * This function checks the current stack for overflow conditions.
753 * Additionally, this function keeps track of the minimum amount
754 * of stack space for the calling thread and returns the current
755 * available stack space.
756 *
757 * CALLED BY
758 *
759 * TCC_Send_Signals Send signals to a task
760 *
761 * CALLS
762 *
763 * ERC_System_Error System error handler
764 *
765 * INPUTS
766 *
767 * None
768 *
769 * OUTPUTS
770 *
771 * available bytes in stack
772 *
773 * HISTORY
774 *
775 * NAME DATE REMARKS
776 *
777 * W. Lamie 02-15-1994 Created initial version 1.0
778 * D. Lamie 02-15-1994 Verified version 1.0
779 *
780 ************************************************************************
781 */
782
783 @UNSIGNED TCT_Check_Stack(void)
784 @{
785
786 .globl TCT_Check_Stack
787 TCT_Check_Stack:
788
789 @TC_TCB *thread;
790 @UNSIGNED remaining;
791
792 @ Pickup the current task/HISR pointer.
793 @ thread = (TC_TCB *) TCD_Current_Thread;
794
795 LDR r0,Current_Thread @ Pickup address of thread pointer
796 LDR r0,[r0,#0] @ Pickup thread pointer
797
798 @ Determine if there is a current thread.
799 @ if (thread)
800 @ {
801
802 CMP r0,#0 @ Determine if a thread is active
803 MOV r3,#0 @ Default remaining value
804 BEQ TCT_Skip_Stack_Check @ If NU_NULL, skip stack checking
805
806 @ Determine if the stack pointers are out of range.
807 @ if ((thread -> tc_stack_pointer < thread -> tc_stack_start) ||
808 @ (thread -> tc_stack_pointer > thread -> tc_stack_end))
809
810 LDR r2,[r0,#0x24] @ Pickup start of stack area
811 CMP r13,r2 @ Compare with current stack ptr
812 BLT TCT_Stack_Range_Error @ If less, stack is out of range
813 LDR r1,[r0,#0x28] @ Pickup end of stack area
814 CMP r13,r1 @ Compare with current stack ptr
815 BLE TCT_Stack_Range_Okay @ If less, stack range is okay
816
817 @ Stack overflow condition exits.
818 @ ERC_System_Error(NU_STACK_OVERFLOW);
819
820 TCT_Stack_Range_Error:
821
822 STR r14,[r13, #4]! @ Store r14 on the stack
823 MOV r0,#3 @ Build NU_STACK_OVERFLOW code
824 BL ERC_System_Error @ Call system error handler. Note:
825 @ control is not returned!
826 @ Examine stack to find return
827 @ address of this routine.
828
829 TCT_Stack_Range_Okay:
830
831 @ Calculate the amount of available space on the stack.
832 @ remaining = (BYTE_PTR) thread -> tc_stack_pointer -
833 @ (BYTE_PTR) thread -> tc_stack_start;
834
835 SUB r3,r13,r2 @ Calculate remaining stack size
836
837 @ Determine if there is enough memory on the stack to save all of the
838 @ registers.
839 @ if (remaining < 80)
840
841 CMP r3,#80 @ Is there enough room for an
842 @ interrupt frame?
843 BCS TCT_No_Stack_Error @ If so, no stack overflow yet
844
845 @ Stack overflow condition is about to happen.
846 @ ERC_System_Error(NU_STACK_OVERFLOW);
847
848 STR r14,[r13, #4]! @ Store r14 on the stack
849 MOV r0,#3 @ Build NU_STACK_OVERFLOW code
850 BL ERC_System_Error @ Call system error handler. Note:
851 @ control is not returned!
852 @ Examine stack to find return
853 @ address of this routine.
854
855 TCT_No_Stack_Error:
856
857 @ Determine if this is a new minimum amount of stack space.
858 @ if (remaining < thread -> tc_stack_minimum)
859
860 LDR r2,[r0,#0x34]
861 CMP r3,r2
862 STRCC r3,[r0,#0x34]
863
864 @ Save the new stack minimum.
865 @ thread -> tc_stack_minimum = remaining;
866 @ }
867 @ else
868
869 @ Set the remaining bytes to 0.
870 @ remaining = 0;
871
872 @ Return the remaining number of bytes on the stack.
873 @ return(remaining);
874
875 TCT_Skip_Stack_Check:
876 MOV r0,r3 @ Return remaining bytes
877
878 BX r14 @ Return to caller
879
880 @}
881
882 /*
883 ************************************************************************
884 *
885 * FUNCTION
886 *
887 * TCT_Schedule
888 *
889 * DESCRIPTION
890 *
891 * This function waits for a thread to become ready. Once a thread
892 * is ready, this function initiates a transfer of control to that
893 * thread.
894 *
895 * CALLED BY
896 *
897 * INC_Initialize Main initialization routine
898 *
899 * CALLS
900 *
901 * TCT_Control_To_Thread Transfer control to a thread
902 *
903 * INPUTS
904 *
905 * TCD_Execute_Task Pointer to task to execute
906 *
907 * OUTPUTS
908 *
909 * None
910 *
911 * HISTORY
912 *
913 * NAME DATE REMARKS
914 *
915 * W. Lamie 02-15-1994 Created initial version 1.0
916 * D. Lamie 02-15-1994 Verified version 1.0
917 *
918 ************************************************************************
919 */
920
921 @VOID TCT_Schedule(void)
922 @{
923
924 .globl TCT_Schedule
925 TCT_Schedule:
926
927 @ Restore interrupts according to the value contained in
928 @ TCD_Interrupt_Level.
929
930 LDR r1,Int_Level @ Build address of interrupt level
931 MRS r0,CPSR @ Pickup current CPSR
932 LDR r2,[r1, #0] @ Pickup current interrupt lockout
933 BIC r0,r0,#LOCK_MSK @ Clear the interrupt lockout bits
934 ORR r0,r0,r2 @ Build new interrupt lockout CPSR
935 MSR CPSR,r0 @ Setup new CPSR
936 LDR r2,Execute_HISR @ Pickup TCD_Execute_HISR address
937 LDR r3,Execute_Task @ Pickup TCD_Execute_Task address
938
939 #ifdef INCLUDE_PROVIEW
940 @ Nucleus ProView Hook
941 @ We check if upon entering TCT_Schedule we already have a task to excute.
942 @ if not, we start IDLE.
943 LDR r0,[r2, #0] @ Pickup highest priority HISR ptr
944 CMP r0,#0 @ Is there a HISR active?
945 BNE TCT_Schedule_Thread @ Found an HISR
946 LDR r0,[r3, #0] @ Pickup highest priority Task ptr
947 CMP r0,#0 @ Is there a task active?
948 BNE TCT_Schedule_Thread @ If not, start IDLE.
949 STR r2,[r13, #-4]! @ Save r2 on the stack
950 STR r3,[r13, #-4]! @ Save r3 on the stack
951 BL _NU_Idle_Hook
952 LDR r3,[r13], #4 @ Recover r2
953 LDR r2,[r13], #4 @ Recover r3
954 #endif
955
956
957 @ Wait until a thread (task or HISR) is available to execute.
958 @ do
959 @ {
960 .globl TCT_Schedule_Loop
961 TCT_Schedule_Loop:
962
963 @ } while ((!TCD_Execute_HISR) && (!TCD_Execute_Task));
964
965 LDR r0,[r2, #0] @ Pickup highest priority HISR ptr
966 CMP r0,#0 @ Is there a HISR active?
967 BNE TCT_Schedule_Thread @ Found an HISR
968 LDR r0,[r3, #0] @ Pickup highest priority Task ptr
969 CMP r0,#0 @ Is there a task active?
970 #if CONFIG_INCLUDE_L1
971 BEQ _GSM_Small_Sleep
972 #else
973 BEQ TCT_Schedule_Loop @ If not, continue the search
974 #endif
975
976 @ Yes, either a task or an HISR is ready to execute. Lockout
977 @ interrupts while the thread is transferred to.
978
979 TCT_Schedule_Thread:
980 MRS r1,CPSR @ Pickup CPSR again
981 ORR r1,r1,#LOCKOUT @ Build interrupt lockout value
982 MSR CPSR,r1 @ Lockout interrupts
983
984 @ Transfer control to the thread by falling through to the following
985 @ routine.
986 @}
987
988 /*
989 ************************************************************************
990 *
991 * FUNCTION
992 *
993 * TCT_Control_To_Thread
994 *
995 * DESCRIPTION
996 *
997 * This function transfers control to the specified thread. Each
998 * time control is transferred to a thread, its scheduled counter
999 * is incremented. Additionally, time-slicing for task threads is
1000 * enabled in this routine. The TCD_Current_Thread pointer is
1001 * setup by this function.
1002 *
1003 * CALLED BY
1004 *
1005 * TCT_Schedule Indirectly called
1006 * TCT_Protect Protection task switch
1007 *
1008 * CALLS
1009 *
1010 * None
1011 *
1012 * INPUTS
1013 *
1014 * thread Thread control block pointer
1015 *
1016 * OUTPUTS
1017 *
1018 * None
1019 *
1020 * HISTORY
1021 *
1022 * NAME DATE REMARKS
1023 *
1024 * W. Lamie 02-15-1994 Created initial version 1.0
1025 * D. Lamie 02-15-1994 Verified version 1.0
1026 *
1027 ************************************************************************
1028 */
1029
1030 @VOID TCT_Control_To_Thread(TC_TCB *thread)
1031 @{
1032 TCT_Control_To_Thread:
1033
1034 @ Setup the current thread pointer.
1035 @ TCD_Current_Thread = (VOID *) thread;
1036
1037 LDR r1,Current_Thread @ Pickup current thread ptr address
1038 LDR r2,[r0, #0x1c] @ Pickup scheduled count
1039 STR r0,[r1, #0] @ Setup current thread pointer
1040
1041 @ Increment the thread scheduled counter.
1042 @ thread -> tc_scheduled++;
1043
1044 LDR r3,[r0, #0x20] @ Pickup time slice value
1045 ADD r2,r2,#1 @ Increment the scheduled count
1046 STR r2,[r0, #0x1c] @ Store new scheduled count
1047
1048 @ Check for time slice option.
1049 @ if (thread -> tc_cur_time_slice)
1050 @ {
1051 CMP r3,#0 @ Is there a time slice?
1052 BEQ TCT_No_Start_TS_1 @ If 0, there is no time slice
1053
1054 @ Start a time slice.
1055 @ TMD_Time_Slice = thread -> tc_cur_time_slice;
1056 @ TMD_Time_Slice_State = 0;
1057
1058 LDR r2,Time_Slice @ Pickup address of TMD_Time_Slice
1059 LDR r1,Slice_State @ Pickup address of
1060 @ TMD_Time_Slice_State
1061 STR r3,[r2, #0] @ Setup the time slice
1062 MOV r2,#0 @ Build active state flag
1063 STR r2,[r1,#0] @ Set the active flag
1064 @ }
1065 TCT_No_Start_TS_1:
1066 #ifdef INCLUDE_PROVIEW
1067 @ Nucleus ProView Hook
1068
1069 STR r0,[r13, #-4]! @ Save r0 on the stack
1070 BL _NU_Schedule_Task_Hook @ Branch to RTView
1071 LDR r0,[r13], #4 @ Recover return address
1072 #endif
1073
1074
1075 @ Pickup the stack pointer and resume the thread.
1076 @ REG_Stack_Ptr = thread -> tc_stack_pointer;
1077
1078 LDR r13,[r0, #0x2c] @ Switch to thread's stack pointer
1079
1080 @ Pop off the saved information associated with the thread. After we
1081 @ determine which type of stack is present. A 1 on the top of the
1082 @ stack indicates an interrupt stack, while a 0 on the top of the
1083 @ stack indicates a solicited type of stack.
1084
1085 @ Remember that the interrupt level that is restored must represent
1086 @ the interrupt level in TCD_Interrupt_Level.
1087
1088 LDR r1,[r13], #4 @ Pop off the stack type
1089 CMP r1,#1 @ See if it is an interrupt stack
1090 BEQ TCT_Interrupt_Resume @ If so, an interrupt resume of
1091 @ thread is required
1092 LDR r1, Int_Level @ Pickup address of interrupt
1093 @ lockout
1094 MRS r0,CPSR @ Pickup current CPSR
1095 BIC r0,r0,#LOCK_MSK @ Clear lockout mask
1096
1097 BIC r0,r0,#0x80000000
1098
1099
1100 LDR r2,[r1, #0] @ Pickup interrupt lockout mask
1101 ORR r0,r0,r2 @ Build new interrupt lockout mask
1102 #if 1 /* was .if THUMB */
1103 LDR r2,[r13], #4 @ Pop off the state mask
1104 ORR r0,r0,r2 @ Set appropriate state
1105 #endif
1106 MSR SPSR,r0 @ Place it into the SPSR
1107 LDMIA r13!,{r4-r12,r15}^ @ A solicited return is required.
1108 @ This type of return only
1109 @ recovers r4-r13 & r15
1110 TCT_Interrupt_Resume:
1111 LDR r0,[r13], #4 @ Pop off the CPSR
1112 LDR r1,Int_Level @ Pickup address of interrupt
1113 @ lockout
1114 BIC r0,r0,#LOCK_MSK @ Clear lockout mask
1115 LDR r2,[r1, #0] @ Pickup interrupt lockout mask
1116 ORR r0,r0,r2 @ Build new interrupt lockout mask
1117 MSR SPSR,r0 @ Place it into the SPSR
1118 LDMIA r13,{r0-r15}^ @ Recover all registers and resume
1119 @ at point of interrupt
1120 @}
1121
1122 /*
1123 ************************************************************************
1124 *
1125 * FUNCTION
1126 *
1127 * TCT_Control_To_System
1128 *
1129 * DESCRIPTION
1130 *
1131 * This function returns control from a thread to the system. Note
1132 * that this service is called in a solicited manner, i.e. it is
1133 * not called from an interrupt thread. Registers required by the
1134 * compiler to be preserved across function boundaries are saved by
1135 * this routine. Note that this is usually a sub-set of the total
1136 * number of available registers.
1137 *
1138 * CALLED BY
1139 *
1140 * Other Components
1141 *
1142 * CALLS
1143 *
1144 * TCT_Schedule Schedule the next thread
1145 *
1146 * INPUTS
1147 *
1148 * None
1149 *
1150 * OUTPUTS
1151 *
1152 * None
1153 *
1154 * HISTORY
1155 *
1156 * NAME DATE REMARKS
1157 *
1158 * W. Lamie 02-15-1994 Created initial version 1.0
1159 * D. Lamie 02-15-1994 Verified version 1.0
1160 * C. Meredith 03-01-1994 Corrected problem in time-slice
1161 * reset logic, resulting in
1162 * version 1.1
1163 * D. Lamie 03-18-1994 Verified version 1.1
1164 *
1165 ************************************************************************
1166 */
1167
1168 @VOID TCT_Control_To_System(void)
1169 @{
1170
1171 .globl TCT_Control_To_System
1172 TCT_Control_To_System:
1173
1174 @ Lockout interrupts.
1175
1176 MRS r0,CPSR @ Pickup current CPSR
1177 ORR r0,r0,#LOCKOUT @ Build interrupt lockout value
1178 MSR CPSR,r0 @ Lockout interrupts
1179
1180 @ Save a minimal context of the thread.
1181
1182 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
1183 @ the current stack
1184 #if 1 /* was .if THUMB */
1185 MOV r2,r14 @ Determine what state the caller
1186 MOV r2,r2,LSL #31 @ was in and build an
1187 MOV r2,r2,LSR #26 @ appropriate state mask
1188 STR r2,[r13, #-4]! @ Place it on the stack
1189 #endif
1190
1191 MOV r2,#0 @ Build solicited stack type value
1192 @ and NU_NULL value
1193 STR r2,[r13, #-4]! @ Place it on the top of the stack
1194
1195 @ Setup a pointer to the thread control block.
1196 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1197
1198 LDR r1,Current_Thread @ Pickup current thread ptr address
1199 LDR r0,[r1, #0] @ Pickup current thread pointer
1200
1201 @ Clear the current thread control block pointer.
1202 @ TCD_Current_Thread = NU_NULL;
1203
1204 LDR r3,Slice_State @ Pickup time slice state address
1205 STR r2,[r1, #0] @ Set current thread pointer to
1206 @ NU_NULL
1207
1208 @ Check to see if a time slice is active. If so, copy the original time
1209 @ slice into the current time slice field of the task's control block.
1210 @ if (TMD_Time_Slice_State == 0)
1211 @ {
1212 LDR r1,[r3, #0] @ Pickup time slice state flag
1213 CMP r1,#0 @ Compare with active value
1214 BNE TCT_No_Stop_TS_1 @ If non-active, don't disable
1215
1216
1217 @ Insure that the next time the task runs it gets a fresh time
1218 @ slice.
1219 @ REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
1220
1221 LDR r1,[r0, #0x40] @ Pickup original time slice
1222
1223 @ Clear any active time slice by setting the state to NOT_ACTIVE.
1224 @ TMD_Time_Slice_State = 1;
1225
1226 MOV r2,#1 @ Build disable value
1227 STR r2,[r3, #0] @ Disable time slice
1228 STR r1,[r0, #0x20] @ Reset current time slice
1229 @ }
1230 TCT_No_Stop_TS_1:
1231
1232 @ Save off the current stack pointer in the control block.
1233 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
1234
1235 STR r13,[r0, #0x2c] @ Save the thread's stack pointer
1236
1237 @ Clear the task's current protection.
1238 @ (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
1239 @ REG_Thread_Ptr -> tc_current_protect = NU_NULL;
1240
1241 LDR r1,[r0, #0x38] @ Pickup current thread pointer
1242 MOV r2,#0 @ Build NU_NULL value
1243 STR r2,[r0, #0x38] @ Clear the protect pointer field
1244 STR r2,[r1, #0] @ Release the actual protection
1245
1246 @ Switch to the system stack.
1247 @ REG_Stack_Ptr = TCD_System_Stack;
1248
1249 LDR r1, System_Stack @ Pickup address of stack pointer
1250 LDR r2, System_Limit @ Pickup address of stack limit ptr
1251 LDR r13,[r1, #0] @ Switch to system stack
1252 LDR r10,[r2, #0] @ Setup system stack limit
1253
1254 @ Finished, return to the scheduling loop.
1255
1256 B TCT_Schedule @ Return to scheduling loop
1257 @}
1258
1259 /*
1260 ************************************************************************
1261 *
1262 * FUNCTION
1263 *
1264 * TCT_Signal_Exit
1265 *
1266 * DESCRIPTION
1267 *
1268 * This function exits from a signal handler. The primary purpose
1269 * of this function is to clear the scheduler protection and switch
1270 * the stack pointer back to the normal task's stack pointer.
1271 *
1272 * CALLED BY
1273 *
1274 * TCC_Signal_Shell Signal handling shell func
1275 *
1276 * CALLS
1277 *
1278 * TCT_Schedule Scheduler
1279 *
1280 * INPUTS
1281 *
1282 * None
1283 *
1284 * OUTPUTS
1285 *
1286 * None
1287 *
1288 * HISTORY
1289 *
1290 * NAME DATE REMARKS
1291 *
1292 * W. Lamie 02-15-1994 Created initial version 1.0
1293 * D. Lamie 02-15-1994 Verified version 1.0
1294 * C. Meredith 03-01-1994 Corrected problem in time-slice
1295 * reset logic, resulting in
1296 * version 1.1
1297 * D. Lamie 03-18-1994 Verified version 1.1
1298 *
1299 ************************************************************************
1300 */
1301
1302 @VOID TCT_Signal_Exit(void)
1303 @{
1304
1305 .globl TCT_Signal_Exit
1306 TCT_Signal_Exit:
1307
1308 @ Lockout interrupts.
1309
1310 MRS r3,CPSR @ Pickup current CPSR
1311 ORR r3,r3,#LOCKOUT @ Build lockout value
1312 MSR CPSR,r3 @ Lockout interrupts
1313
1314 @ Setup a pointer to the thread control block.
1315 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1316
1317 LDR r1,Current_Thread @ Pickup address of thread pointer
1318 MOV r2,#0 @ Build NU_NULL value
1319 LDR r0,[r1,#0] @ Pickup current thread pointer
1320
1321 @ Clear the current thread control block.
1322 @ TCD_Current_Thread = NU_NULL;
1323
1324 LDR r3,Slice_State @ Pickup time slice state address
1325 STR r2,[r1, #0] @ Clear current thread pointer
1326
1327 @ Check to see if a time slice is active. If so, copy the original time
1328 @ slice into the current time slice field of the task's control block.
1329 @ if (TMD_Time_Slice_State == 0)
1330 @ {
1331
1332 LDR r1,[r3, #0] @ Pickup time slice state flag
1333 CMP r1,#0 @ Compare with active value
1334 BNE TCT_No_Stop_TS_2 @ If non-active, don't disable
1335
1336 @ Insure that the next time the task runs it gets a fresh time
1337 @ slice.
1338 @ REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
1339
1340 LDR r1,[r0, #0x40] @ Pickup original time slice
1341
1342 @ Clear any active time slice by setting the state to NOT_ACTIVE.
1343 @ TMD_Time_Slice_State = 1;
1344
1345 MOV r2,#1 @ Build disable value
1346 STR r2,[r3, #0] @ Disable time slice
1347 STR r1,[r0, #0x20] @ Reset current time slice
1348 @ }
1349 TCT_No_Stop_TS_2:
1350
1351 @ Switch back to the saved stack. The saved stack pointer was saved
1352 @ before the signal frame was built.
1353 @ REG_Thread_Ptr -> tc_stack_pointer =
1354 @ REG_Thread_Ptr -> tc_saved_stack_ptr;
1355
1356 LDR r1,[r0, #0x3c] @ Pickup saved stack pointer
1357 STR r1,[r0, #0x2c] @ Place in current stack pointer
1358
1359 @ Clear the task's current protection.
1360 @ (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
1361 @ REG_Thread_Ptr -> tc_current_protect = NU_NULL;
1362
1363 LDR r1,[r0, #0x38] @ Pickup current thread pointer
1364 MOV r2,#0 @ Build NU_NULL value
1365 STR r2,[r0, #0x38] @ Clear the protect pointer field
1366 STR r2,[r1, #0] @ Release the actual protection
1367
1368 @ Switch to the system stack.
1369 @ REG_Stack_Ptr = (BYTE_PTR) TCD_System_Stack;
1370
1371 LDR r1, System_Stack @ Pickup address of stack pointer
1372 LDR r2, System_Limit @ Pickup address of stack limit ptr
1373 LDR r13,[r1, #0] @ Switch to system stack
1374 LDR r10,[r2, #0] @ Setup system stack limit
1375
1376 @ Finished, return to the scheduling loop.
1377
1378 B TCT_Schedule @ Return to scheduling loop
1379 @}
1380
1381 /*
1382 ************************************************************************
1383 *
1384 * FUNCTION
1385 *
1386 * TCT_Current_Thread
1387 *
1388 * DESCRIPTION
1389 *
1390 * This function returns the current thread pointer.
1391 *
1392 * CALLED BY
1393 *
1394 * Application
1395 * System Components
1396 *
1397 * CALLS
1398 *
1399 * None
1400 *
1401 * INPUTS
1402 *
1403 * None
1404 *
1405 * OUTPUTS
1406 *
1407 * Pointer to current thread
1408 *
1409 * HISTORY
1410 *
1411 * NAME DATE REMARKS
1412 *
1413 * W. Lamie 02-15-1994 Created initial version 1.0
1414 * D. Lamie 02-15-1994 Verified version 1.0
1415 *
1416 ************************************************************************
1417 */
1418
1419 @VOID *TCT_Current_Thread(void)
1420 @{
1421
1422 .globl TCT_Current_Thread
1423 TCT_Current_Thread:
1424
1425 @ Return the current thread pointer.
1426 @ return(TCD_Current_Thread);
1427
1428 LDR r0, Current_Thread @ Pickup address of thread pointer
1429 LDR r0,[r0, #0] @ Pickup current thread pointer
1430
1431 BX r14 @ Return to caller
1432
1433 @}
1434
1435 /*
1436 ************************************************************************
1437 *
1438 * FUNCTION
1439 *
1440 * TCT_Set_Execute_Task
1441 *
1442 * DESCRIPTION
1443 *
1444 * This function sets the current task to execute variable under
1445 * protection against interrupts.
1446 *
1447 * CALLED BY
1448 *
1449 * TCC Scheduling Routines
1450 *
1451 * CALLS
1452 *
1453 * None
1454 *
1455 * INPUTS
1456 *
1457 * task Pointer to task control block
1458 *
1459 * OUTPUTS
1460 *
1461 * TCD_Execute_Task Modified variable
1462 *
1463 * HISTORY
1464 *
1465 * NAME DATE REMARKS
1466 *
1467 * W. Lamie 02-15-1994 Created initial version 1.0
1468 * D. Lamie 02-15-1994 Verified version 1.0
1469 *
1470 ************************************************************************
1471 */
1472
1473 @VOID TCT_Set_Execute_Task(TC_TCB *task)
1474 @{
1475
1476 .globl TCT_Set_Execute_Task
1477 TCT_Set_Execute_Task:
1478
1479 @ Now setup the TCD_Execute_Task pointer.
1480 @ TCD_Execute_Task = task;
1481
1482 LDR r1, Execute_Task @ Pickup execute task ptr address
1483 STR r0,[r1,#0] @ Setup new task to execute
1484
1485 BX r14 @ Return to caller
1486
1487 @}
1488
1489 /*
1490 ************************************************************************
1491 *
1492 * FUNCTION
1493 *
1494 * TCT_Protect
1495 *
1496 * DESCRIPTION
1497 *
1498 * This function protects against multiple thread access.
1499 *
1500 * CALLED BY
1501 *
1502 * Application
1503 * System Components
1504 *
1505 * CALLS
1506 *
1507 * None
1508 *
1509 * INPUTS
1510 *
1511 * protect Pointer to protection block
1512 *
1513 * OUTPUTS
1514 *
1515 * None
1516 *
1517 * HISTORY
1518 *
1519 * NAME DATE REMARKS
1520 *
1521 * W. Lamie 02-15-1994 Created initial version 1.0
1522 * D. Lamie 02-15-1994 Verified version 1.0
1523 *
1524 ************************************************************************
1525 */
1526
1527 @VOID TCT_Protect(TC_PROTECT *protect)
1528 @{
1529
1530 .globl TCT_Protect
1531 TCT_Protect:
1532
1533 @ Determine if the caller is in a task or HISR thread.
1534 @ if (TCD_Current_Thread)
1535 @ {
1536
1537 LDR r1,Current_Thread @ Pickup current thread ptr address
1538 LDR r3,[r1, #0] @ Pickup current thread pointer
1539 CMP r3,#0 @ Check to see if it is non-NULL
1540 BEQ TCT_Skip_Protect @ If NULL, skip protection
1541
1542 @ Lockout interrupts.
1543
1544 MRS r1,CPSR @ Pickup current CPSR
1545 ORR r1,r1,#LOCKOUT @ Place lockout value in
1546 MSR CPSR,r1 @ Lockout interrupts
1547
1548 @ Wait until the protect structure is available.
1549 @ while (protect -> tc_tcb_pointer != NU_NULL)
1550 @ {
1551
1552 TCT_Protect_Loop:
1553 LDR r1,[r0, #0] @ Pickup protection owner field
1554 CMP r1,#0 @ Is there any protection?
1555 BEQ TCT_Protect_Available @ If NU_NULL, no current protection
1556
1557 @ Protection structure is not available.
1558
1559 @ Indicate that another thread is waiting.
1560 @ protect -> tc_thread_waiting = 1;
1561
1562 MOV r2,#1 @ Build thread waiting flag
1563 STR r2,[r0, #4] @ Set waiting field
1564
1565 @ Directly schedule the thread waiting.
1566 @ TCT_Schedule_Protected(protect -> tc_tcb_pointer);
1567
1568 STR r0,[r13, #-4]! @ Save r0 on the stack
1569 STR r14,[r13, #-4]! @ Save r14 on the stack
1570 MOV r0,r3 @ Place current thread into r0
1571 BL TCT_Schedule_Protected @ Call routine to schedule the
1572 @ owner of the thread
1573
1574 LDR r14,[r13], #4 @ Recover saved r14
1575 LDR r0,[r13], #4 @ Recover saved r0
1576
1577 @ Lockout interrupts.
1578
1579 LDR r1,Current_Thread @ Pickup current thread ptr address
1580 LDR r3,[r1, #0] @ Pickup current thread pointer
1581 MRS r1,CPSR @ Pickup current CPSR
1582 ORR r1,r1,#LOCKOUT @ Place lockout value in
1583 MSR CPSR,r1 @ Lockout interrupts
1584 B TCT_Protect_Loop @ Examine protect flags again
1585 @ }
1586 TCT_Protect_Available:
1587
1588 @ Protection structure is available.
1589
1590 @ Indicate that this thread owns the protection.
1591 @ protect -> tc_tcb_pointer = TCD_Current_Thread;
1592
1593 STR r3,[r0, #0] @ Indicate calling thread owns this
1594 @ protection
1595
1596 @ Clear the thread waiting flag.
1597 @ protect -> tc_thread_waiting = 0;
1598
1599 MOV r2,#0 @ Clear value
1600 STR r2,[r0, #4] @ Clear the thread waiting flag
1601
1602 @ Save the protection pointer in the thread's control block. Note
1603 @ that both task and HISR threads share the same control block
1604 @ format.
1605 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1606 @ REG_Thread_Ptr -> tc_current_protect = protect;
1607
1608 STR r0,[r3, #0x38] @ Setup current protection
1609
1610 @ Restore interrupts.
1611
1612 LDR r2,Int_Level @ Pickup address of interrupt level
1613 MRS r1,CPSR @ Pickup current CPSR
1614 LDR r3,[r2, #0] @ Pickup interrupt lockout level
1615 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
1616 ORR r1,r1,r3 @ Build new interrupt lockout
1617 MSR CPSR,r1 @ Setup CPSR appropriately
1618 @ }
1619
1620 TCT_Skip_Protect:
1621
1622 BX r14 @ Return to caller
1623
1624 @}
1625
1626 /*
1627 ************************************************************************
1628 *
1629 * FUNCTION
1630 *
1631 * TCT_Unprotect
1632 *
1633 * DESCRIPTION
1634 *
1635 * This function releases protection of the currently active
1636 * thread. If the caller is not an active thread, then this
1637 * request is ignored.
1638 *
1639 * CALLED BY
1640 *
1641 * Application
1642 * System Components
1643 *
1644 * CALLS
1645 *
1646 * None
1647 *
1648 * INPUTS
1649 *
1650 * None
1651 *
1652 * OUTPUTS
1653 *
1654 * None
1655 *
1656 * HISTORY
1657 *
1658 * NAME DATE REMARKS
1659 *
1660 * W. Lamie 02-15-1994 Created initial version 1.0
1661 * D. Lamie 02-15-1994 Verified version 1.0
1662 *
1663 ************************************************************************
1664 */
1665
1666 @VOID TCT_Unprotect(void)
1667 @{
1668
1669 .globl TCT_Unprotect
1670 TCT_Unprotect:
1671
1672
1673 @ Determine if the caller is in a task or HISR thread.
1674 @ if (TCD_Current_Thread)
1675 @ {
1676
1677 LDR r1,Current_Thread @ Pickup current thread ptr address
1678 LDR r3,[r1, #0] @ Pickup current thread pointer
1679 CMP r3,#0 @ Check to see if it is non-NULL
1680 BEQ TCT_Skip_Unprotect @ If NULL, skip unprotection
1681
1682 @ Setup a thread control block pointer.
1683 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1684
1685 @ Determine if there is a currently active protection.
1686 @ if (REG_Thread_Ptr -> tc_current_protect)
1687 @ {
1688
1689 LDR r0,[r3, #0x38] @ Pickup current protect field
1690 CMP r0,#0 @ Is there a protection in force?
1691 BEQ TCT_Skip_Unprotect @ If not, nothing is protected
1692
1693 @ Lockout interrupts.
1694
1695 MRS r1,CPSR @ Pickup current CPSR
1696 ORR r1,r1,#LOCKOUT @ Place lockout value in
1697 MSR CPSR,r1 @ Lockout interrupts
1698
1699 @ Yes, this thread still has this protection structure.
1700 @ REG_Protect_Ptr = REG_Thread_Ptr -> tc_current_protect;
1701
1702 @ Is there a higher priority thread waiting for the protection
1703 @ structure?
1704 @ if (REG_Protect_Ptr -> tc_thread_waiting)
1705
1706 LDR r2,[r0, #4] @ Pickup thread waiting flag
1707 CMP r2,#0 @ Are there any threads waiting?
1708 BEQ TCT_Not_Waiting_Unpr @ If not, just release protection
1709
1710 @ Transfer control to the system. Note that this
1711 @ automatically clears the current protection and it returns
1712 @ to the caller of this routine instead of this routine.
1713 @ TCT_Control_To_System();
1714
1715 B TCT_Control_To_System @ Return control to the system
1716
1717 @ else
1718 @ {
1719 TCT_Not_Waiting_Unpr:
1720
1721 @ Clear the protection.
1722 @ REG_Thread_Ptr -> tc_current_protect = NU_NULL;
1723 @ REG_Protect_Ptr -> tc_tcb_pointer = NU_NULL;
1724
1725 MOV r2,#0 @ Build NU_NULL value
1726 STR r2,[r0, #0] @ Release the protection
1727 STR r2,[r3, #0x38] @ Clear protection pointer in the
1728 @ control block
1729
1730 @ }
1731
1732 TCT_Not_Protected:
1733 @ Restore interrupts again.
1734
1735 LDR r2,Int_Level @ Pickup address of interrupt level
1736 MRS r1,CPSR @ Pickup current CPSR
1737 LDR r3,[r2, #0] @ Pickup interrupt lockout level
1738 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
1739 ORR r1,r1,r3 @ Build new interrupt lockout
1740 MSR CPSR,r1 @ Setup CPSR appropriately
1741
1742 @ }
1743 @ }
1744 TCT_Skip_Unprotect:
1745
1746 BX r14 @ Return to caller
1747
1748 @}
1749
1750 /*
1751 ************************************************************************
1752 *
1753 * FUNCTION
1754 *
1755 * TCT_Unprotect_Specific
1756 *
1757 * DESCRIPTION
1758 *
1759 * This function releases a specific protection structure.
1760 *
1761 * CALLED BY
1762 *
1763 * Application
1764 * System Components
1765 *
1766 * CALLS
1767 *
1768 * None
1769 *
1770 * INPUTS
1771 *
1772 * protect Pointer to protection block
1773 *
1774 * OUTPUTS
1775 *
1776 * None
1777 *
1778 * HISTORY
1779 *
1780 * NAME DATE REMARKS
1781 *
1782 * W. Lamie 02-15-1994 Created initial version 1.0
1783 * D. Lamie 02-15-1994 Verified version 1.0
1784 * C. Meredith 03-01-1994 Corrected problem in time-slice
1785 * reset logic, corrected bug
1786 * using protect ptr, resulting
1787 * in version 1.1
1788 * D. Lamie 03-18-1994 Verified version 1.1
1789 *
1790 ************************************************************************
1791 */
1792
1793 @VOID Specific(TC_PROTECT *protect)
1794 @{
1795
1796 .globl TCT_Unprotect_Specific
1797 TCT_Unprotect_Specific:
1798
1799 @ Determine if the caller is in a task or HISR thread.
1800 @ if (TCD_Current_Thread)
1801 @ {
1802
1803 LDR r1,Current_Thread @ Pickup current thread ptr address
1804 LDR r3,[r1, #0] @ Pickup current thread pointer
1805 CMP r3,#0 @ Check to see if it is non-NULL
1806 BEQ TCT_Skip_Unprot_Spec @ If NULL, skip unprotect specific
1807
1808 @ Lockout interrupts.
1809
1810 MRS r1,CPSR @ Pickup current CPSR
1811 ORR r1,r1,#LOCKOUT @ Place lockout value in
1812 MSR CPSR,r1 @ Lockout interrupts
1813
1814 @ Clear the protection pointer.
1815 @ protect -> tc_tcb_pointer = NU_NULL;
1816
1817 MOV r2,#0 @ Build NU_NULL value
1818 STR r2,[r0, #0] @ Clear protection ownership
1819
1820 @ Determine if a thread is waiting.
1821 @ if (protect -> tc_thread_waiting)
1822 @ {
1823
1824 LDR r1,[r0, #4] @ Pickup the waiting field
1825 CMP r1,#0 @ Is there another thread waiting?
1826 BEQ TCT_Not_Waiting_Unspec @ No, restore interrupts and return
1827
1828 @ A higher-priority thread is waiting.
1829
1830 @ Save a minimal context of the thread.
1831
1832 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
1833 @ the current stack
1834
1835 #if 1 /* was .if THUMB */
1836 MOV r2,r14 @ Determine what state the caller
1837 MOV r2,r2,LSL #31 @ was in and build an
1838 MOV r2,r2,LSR #26 @ appropriate state mask
1839 STR r2,[r13, #-4]! @ Place it on the stack
1840 #endif
1841
1842 MOV r2,#0 @ Build solicited stack type value
1843 @ and NU_NULL value
1844 STR r2,[r13, #-4]! @ Place it on the top of the stack
1845
1846 @ Setup a pointer to the thread control block.
1847 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1848
1849 LDR r1,Current_Thread @ Pickup current thread ptr address
1850 LDR r0,[r1, #0] @ Pickup current thread pointer
1851
1852 @ Clear the current thread control block pointer.
1853 @ TCD_Current_Thread = NU_NULL;
1854
1855 LDR r3,Slice_State @ Pickup time slice state address
1856 STR r2,[r1, #0] @ Set current thread pointer to
1857 @ NU_NULL
1858
1859 @ Check to see if a time slice is active. If so, copy the
1860 @ original time slice into the current time slice field of the
1861 @ thread's control block.
1862 @ if (TMD_Time_Slice_State == 0)
1863 @ {
1864
1865 LDR r1,[r3, #0] @ Pickup time slice state flag
1866 CMP r1,#0 @ Compare with active value
1867 BNE TCT_No_Stop_TS_3 @ If non-active, don't disable
1868
1869 @ Insure that the next time the task runs it gets a fresh time
1870 @ slice.
1871 @ REG_Thread_Ptr -> tc_cur_time_slice =
1872 @ REG_Thread_Ptr -> tc_time_slice;
1873
1874 LDR r1,[r0, #0x40] @ Pickup original time slice
1875
1876 @ Clear any active time slice by setting the state to
1877 @ NOT_ACTIVE.
1878 @ TMD_Time_Slice_State = 1;
1879
1880 MOV r2,#1 @ Build disable value
1881 STR r2,[r3, #0] @ Disable time slice
1882 STR r1,[r0, #0x20] @ Reset current time slice
1883 @ }
1884
1885 TCT_No_Stop_TS_3:
1886
1887 @ Save off the current stack pointer in the control block.
1888 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
1889
1890 STR r13,[r0, #0x2c] @ Save the thread's stack pointer
1891
1892 @ Switch to the system stack.
1893 @ REG_Stack_Ptr = TCD_System_Stack;
1894
1895 LDR r1,System_Stack @ Pickup address of stack pointer
1896 LDR r2,System_Limit @ Pickup address of stack limit ptr
1897 LDR r13,[r1, #0] @ Switch to system stack
1898 LDR r10,[r2, #0] @ Setup system stack limit
1899
1900 @ Finished, return to the scheduling loop.
1901
1902 B TCT_Schedule @ Return to scheduling loop
1903
1904 @ }
1905 @ else
1906 @ {
1907 TCT_Not_Waiting_Unspec:
1908
1909 @ No higher-priority thread is waiting.
1910
1911 @ Restore interrupts.
1912
1913 LDR r2,Int_Level @ Pickup address of interrupt level
1914 MRS r1,CPSR @ Pickup current CPSR
1915 LDR r3,[r2, #0] @ Pickup interrupt lockout level
1916 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
1917 ORR r1,r1,r3 @ Build new interrupt lockout
1918 MSR CPSR,r1 @ Setup CPSR appropriately
1919
1920 @ }
1921 @ }
1922
1923 TCT_Skip_Unprot_Spec:
1924
1925 BX r14 @ Return to caller
1926
1927 @}
1928
1929 /*
1930 ************************************************************************
1931 *
1932 * FUNCTION
1933 *
1934 * TCT_Set_Current_Protect
1935 *
1936 * DESCRIPTION
1937 *
1938 * This function sets the current protection field of the current
1939 * thread's control block to the specified protection pointer.
1940 *
1941 * CALLED BY
1942 *
1943 * TCC_Resume_Task Resume task function
1944 *
1945 * CALLS
1946 *
1947 * None
1948 *
1949 * INPUTS
1950 *
1951 * protect Pointer to protection block
1952 *
1953 * OUTPUTS
1954 *
1955 * None
1956 *
1957 * HISTORY
1958 *
1959 * NAME DATE REMARKS
1960 *
1961 * W. Lamie 02-15-1994 Created initial version 1.0
1962 * D. Lamie 02-15-1994 Verified version 1.0
1963 *
1964 ************************************************************************
1965 */
1966
1967 @VOID TCT_Set_Current_Protect(TC_PROTECT *protect)
1968 @{
1969
1970 .globl TCT_Set_Current_Protect
1971 TCT_Set_Current_Protect:
1972
1973 @ Determine if the caller is in a task or HISR thread.
1974 @ if (TCD_Current_Thread)
1975 @ {
1976
1977 LDR r1,Current_Thread @ Pickup current thread ptr address
1978 LDR r3,[r1, #0] @ Pickup current thread pointer
1979 CMP r3,#0 @ Check to see if a thread is
1980 @ active
1981
1982 @ Point at the current thread control block.
1983 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1984
1985 @ Modify the current protection.
1986 @ REG_Thread_Ptr -> tc_current_protect = protect;
1987
1988 STRNE r0,[r3, #0x38] @ Setup new protection
1989 @ }
1990
1991
1992 BX r14 @ Return to caller
1993
1994 @}
1995
1996 /*
1997 ************************************************************************
1998 *
1999 * FUNCTION
2000 *
2001 * TCT_Protect_Switch
2002 *
2003 * DESCRIPTION
2004 *
2005 * This function waits until a specific task no longer has any
2006 * protection associated with it. This is necessary since task's
2007 * cannot be suspended or terminated unless they have released all
2008 * of their protection.
2009 *
2010 * CALLED BY
2011 *
2012 * System Components
2013 *
2014 * CALLS
2015 *
2016 * None
2017 *
2018 * INPUTS
2019 *
2020 * thread Pointer to thread control blk
2021 *
2022 * OUTPUTS
2023 *
2024 * None
2025 *
2026 * HISTORY
2027 *
2028 * NAME DATE REMARKS
2029 *
2030 * W. Lamie 02-15-1994 Created initial version 1.0
2031 * D. Lamie 02-15-1994 Verified version 1.0
2032 *
2033 ************************************************************************
2034 */
2035
2036 @VOID TCT_Protect_Switch(VOID *thread)
2037 @{
2038
2039 .globl TCT_Protect_Switch
2040 TCT_Protect_Switch:
2041
2042 @ Lockout interrupts.
2043
2044 MRS r1,CPSR @ Pickup current CPSR
2045 ORR r1,r1,#LOCKOUT @ Place lockout value in
2046 MSR CPSR,r1 @ Lockout interrupts
2047
2048 @ REG_Thread_Ptr = (TC_TCB *) thread;
2049
2050 @ Wait until the specified task has no protection associated with it.
2051 @ while (REG_Thread_Ptr -> tc_current_protect)
2052 @ {
2053
2054 LDR r1,[r0, #0x38] @ Pickup protection of specified
2055 @ thread
2056 CMP r1,#0 @ Does the specified thread have
2057 @ an active protection?
2058 BEQ TCT_Switch_Done @ If not, protect switch is done
2059
2060 @ Let the task run again in an attempt to clear its protection.
2061
2062 @ Indicate that a higher priority thread is waiting.
2063 @ (REG_Thread_Ptr -> tc_current_protect) -> tc_thread_waiting = 1;
2064
2065 MOV r2,#1 @ Build waiting flag value
2066 STR r2,[r1, #4] @ Set waiting flag of the
2067 @ protection owned by the other
2068 @ thread
2069
2070 @ Directly schedule the thread waiting.
2071 @ TCT_Schedule_Protected((REG_Thread_Ptr -> tc_current_protect)
2072 @ -> tc_tcb_pointer);
2073
2074 LDR r2,Current_Thread @ Pickup current thread ptr address
2075 STR r0,[r13, #-4]! @ Save r0 on the stack
2076 STR r14,[r13, #-4]! @ Save r14 on the stack
2077 MOV r1,r0 @ Move new thread into r1
2078 LDR r0,[r2, #0] @ Pickup current thread pointer
2079 BL TCT_Schedule_Protected @ Call routine to schedule the
2080 @ owner of the thread
2081
2082 LDR r14,[r13], #4 @ Recover saved r14
2083 LDR r0,[r13], #4 @ Recover saved r0
2084
2085 @ Lockout interrupts.
2086
2087 B TCT_Protect_Switch @ Branch to top of routine and
2088 @ start over
2089 @ }
2090 TCT_Switch_Done:
2091
2092 @ Restore interrupts.
2093
2094 LDR r2,Int_Level @ Pickup address of interrupt level
2095 MRS r1,CPSR @ Pickup current CPSR
2096 LDR r3,[r2, #0] @ Pickup interrupt lockout level
2097 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
2098 ORR r1,r1,r3 @ Build new interrupt lockout
2099 MSR CPSR,r1 @ Setup CPSR appropriately
2100
2101
2102 BX r14 @ Return to caller
2103
2104 @}
2105
2106 /*
2107 ************************************************************************
2108 *
2109 * FUNCTION
2110 *
2111 * TCT_Schedule_Protected
2112 *
2113 * DESCRIPTION
2114 *
2115 * This function saves the minimal context of the thread and then
2116 * directly schedules the thread that has protection over the
2117 * the thread that called this routine.
2118 *
2119 * CALLED BY
2120 *
2121 * TCT_Protect
2122 * TCT_Protect_Switch
2123 *
2124 * CALLS
2125 *
2126 * TCT_Control_To_Thread Transfer control to protected
2127 * thread
2128 *
2129 * INPUTS
2130 *
2131 * None
2132 *
2133 * OUTPUTS
2134 *
2135 * None
2136 *
2137 * HISTORY
2138 *
2139 * NAME DATE REMARKS
2140 *
2141 * W. Lamie 02-15-1994 Created initial version 1.0
2142 * D. Lamie 02-15-1994 Verified version 1.0
2143 * C. Meredith 03-01-1994 Corrected problem in time-slice
2144 * reset logic, resulting in
2145 * version 1.1
2146 * D. Lamie 03-18-1994 Verified version 1.1
2147 *
2148 ************************************************************************
2149 */
2150
2151 @VOID TCT_Schedule_Protected(VOID *thread)
2152 @{
2153
2154 .globl TCT_Schedule_Protected
2155 TCT_Schedule_Protected:
2156
2157 @ Interrupts are already locked out by the caller.
2158
2159 @ Save minimal context required by the system.
2160
2161 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
2162 @ the current stack
2163
2164 #if 1 /* was .if THUMB */
2165 MOV r2,r14 @ Determine what state the caller
2166 MOV r2,r2,LSL #31 @ was in and build an
2167 MOV r2,r2,LSR #26 @ appropriate state mask
2168 STR r2,[r13, #-4]! @ Place it on the stack
2169 #endif
2170
2171 MOV r2,#0 @ Build solicited stack type value
2172 @ and NU_NULL value
2173 STR r2,[r13, #-4]! @ Place it on the top of the stack
2174 MOV r4,r1 @ Save thread to schedule
2175
2176 @ Setup a pointer to the thread control block.
2177 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
2178
2179 LDR r1,Current_Thread @ Pickup current thread ptr address
2180
2181 @ Clear the current thread control block.
2182 @ TCD_Current_Thread = NU_NULL;
2183
2184 LDR r3,Slice_State @ Pickup time slice state address
2185 STR r2,[r1, #0] @ Set current thread pointer to
2186 @ NU_NULL
2187
2188 @ Check to see if a time slice is active. If so, copy the original time
2189 @ slice into the current time slice field of the task's control block.
2190 @ if (TMD_Time_Slice_State == 0)
2191 @ {
2192
2193 LDR r1,[r3, #0] @ Pickup time slice state flag
2194 CMP r1,#0 @ Compare with active value
2195 BNE TCT_No_Stop_TS_4 @ If non-active, don't disable
2196
2197 @ Insure that the next time the task runs it gets a fresh time
2198 @ slice.
2199 @ REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
2200
2201 LDR r1,[r0, #0x40] @ Pickup original time slice
2202
2203 @ Clear any active time slice by setting the state to NOT_ACTIVE.
2204 @ TMD_Time_Slice_State = 1;
2205
2206 MOV r2,#1 @ Build disable value
2207 STR r2,[r3, #0] @ Disable time slice
2208 STR r1,[r0, #0x20] @ Reset current time slice
2209
2210 @ }
2211 TCT_No_Stop_TS_4:
2212
2213 @ Save off the current stack pointer in the control block.
2214 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
2215
2216 STR r13,[r0, #0x2c] @ Save the thread's stack pointer
2217
2218 @ Switch to the system stack.
2219 @ TCD_System_Stack = (VOID *) REG_Stack_Ptr;
2220
2221 LDR r1,System_Stack @ Pickup address of stack pointer
2222 LDR r2,System_Limit @ Pickup address of stack limit ptr
2223 LDR r13,[r1, #0] @ Switch to system stack
2224 LDR r10,[r2, #0] @ Setup system stack limit
2225
2226 @ Transfer control to the specified thread directly.
2227 @ TCT_Control_To_Thread(thread);
2228
2229 LDR r2,Int_Level @ Pickup address of interrupt level
2230 MRS r1,CPSR @ Pickup current CPSR
2231 LDR r3,[r2, #0] @ Pickup interrupt lockout level
2232 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
2233 ORR r1,r1,r3 @ Build new interrupt lockout
2234 MOV r0,r4 @ Indicate thread to schedule
2235 MSR CPSR,r1 @ Setup CPSR appropriately
2236 ORR r1,r1,#LOCKOUT @ Build lockout value again
2237 MSR CPSR,r1 @ Lockout interrupts again
2238 B TCT_Control_To_Thread @ Schedule the thread indirectly
2239 @}
2240
2241 /*
2242 ************************************************************************
2243 *
2244 * FUNCTION
2245 *
2246 * TCT_Interrupt_Context_Save
2247 *
2248 * DESCRIPTION
2249 *
2250 * This function saves the interrupted thread's context. Nested
2251 * interrupts are also supported. If a task or HISR thread was
2252 * interrupted, the stack pointer is switched to the system stack
2253 * after the context is saved.
2254 *
2255 * CALLED BY
2256 *
2257 * Application ISRs Assembly language ISRs
2258 * INT_Interrupt_Shell Interrupt handler shell
2259 *
2260 * CALLS
2261 *
2262 * None
2263 *
2264 * INPUTS
2265 *
2266 * vector Interrupt's vector number
2267 *
2268 * OUTPUTS
2269 *
2270 * None
2271 *
2272 * HISTORY
2273 *
2274 * NAME DATE REMARKS
2275 *
2276 * W. Lamie 02-15-1994 Created initial version 1.0
2277 * D. Lamie 02-15-1994 Verified version 1.0
2278 * D. Driscoll 01-04-2002 Released version 1.13.3.
2279 * Updated to handle nested /
2280 * prioritized IRQs
2281 ************************************************************************
2282 */
2283
2284 @VOID TCT_Interrupt_Context_Save(INT vector)
2285 @{
2286
2287 .globl TCT_Interrupt_Context_Save
2288 TCT_Interrupt_Context_Save:
2289 @ Determine if this is a nested interrupt.
2290 LDR r1,Int_Count @ Pickup address of interrupt count
2291 LDR r2,[r1, #0] @ Pickup interrupt counter
2292 ADD r2,r2,#1 @ Add 1 to interrupt counter
2293 STR r2,[r1, #0] @ Store new interrupt counter value
2294 CMP r2,#1 @ Is it nested?
2295 BEQ TCT_Not_Nested_Save @ No
2296
2297 @ Nested interrupt. Save complete context on the current stack.
2298 TCT_Nested_Save:
2299
2300 /* No longer needed in the FreeCalypso version, as we can use r0 instead. */
2301 #if 0
2302 @ 1. Save another register on the exception stack so we have enough to work with
2303 STMDB r13!,{r5}
2304 #endif
2305
2306 @ 2. Save the necessary exception registers into r1-r3
2307 MOV r1,r13 @ Put the exception r13 into r1
2308 MOV r2,r14 @ Move the return address for the caller
2309 @ of this function into r2
2310 MRS r3,spsr @ Put the exception spsr into r3
2311
2312 @ 3. Adjust the exception stack pointer for future exceptions
2313 ADD r13,r13,#20 @ r13 reset to pre-interrupt value
2314
2315 @ 4. Switch CPU modes to save context on system stack
2316 MRS r0,CPSR @ Pickup the current CPSR
2317 BIC r0,r0,#MODE_MASK @ Clear the mode bits
2318
2319 ORR r0,r0,#SUP_MODE @ Change to supervisor mode (SVD)
2320
2321 MSR CPSR,r0 @ Switch modes (IRQ->SVC)
2322
2323 @ 5. Store the SVC r13 into r5 so the r13 can be saved as is.
2324 @ FreeCalyspo: using r0 instead
2325 MOV r0,r13
2326
2327 @ 6. Save the exception return address on the stack (r15).
2328 STMDB r0!,{r4}
2329
2330 @ 7. Save r5-r14 on stack (used to be r6-r14)
2331 STMDB r0!,{r5-r14}
2332
2333 @ 8. Switch back to using r13 now that the original r13 has been saved.
2334 MOV r13,r0
2335
2336 /* no longer relevant */
2337 #if 0
2338 @ 9. Get r5 and exception enable registers off of exception stack and
2339 @ save r5 (stored in r4) back to the system stack.
2340 LDMIA r1!,{r4-r5}
2341 STMDB r13!,{r4}
2342 MOV r4,r5 @ Put exception enable value into r4
2343 #endif
2344
2345 @ 10. Get the rest of the registers off the exception stack and
2346 @ save them onto the system stack.
2347 LDMIA r1!,{r5-r8,r11} @ Get r0-r4 off exception stack
2348 STMDB r13!,{r5-r8,r11} @ Put r0-r4 on system stack
2349
2350 /* no longer relevant */
2351 #if 0
2352 @ 11. Store the exception enable value back on the exception stack.
2353 STMDB r1,{r4}
2354 #endif
2355
2356 @ 12. Save the SPSR on the system stack (CPSR)
2357 STMDB r13!,{r3}
2358
2359 /* TI's approach to interrupt handling does not support re-enabling here */
2360 #if 0
2361 @ 13. Re-enable interrupts
2362 MRS r1,CPSR
2363 BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT)
2364 MSR CPSR,r1
2365 #endif
2366
2367 BX r2 @ Return to calling ISR
2368 @ }
2369 @ else
2370 @ {
2371 TCT_Not_Nested_Save:
2372
2373 @ Determine if a thread was interrupted.
2374 @ if (TCD_Current_Thread)
2375 @ {
2376
2377 LDR r1,Current_Thread @ Pickup current thread ptr address
2378 LDR r1,[r1, #0] @ Pickup the current thread pointer
2379 CMP r1,#0 @ Is it NU_NULL?
2380 BEQ TCT_Idle_Context_Save @ If no, no real save is necessary
2381
2382
2383 @ Yes, a thread was interrupted. Save complete context on the
2384 @ thread's stack.
2385
2386 /* No longer needed in the FreeCalypso version, as we can use r0 instead. */
2387 #if 0
2388 @ 1. Save another register on the exception stack so we have enough to work with
2389 STMDB r13!,{r5}
2390 #endif
2391
2392 @ 2. Save the necessary exception registers into r1-r3
2393 MOV r1,r13 @ Put the exception r13 into r1
2394 MOV r2,r14 @ Move the return address for the caller
2395 @ of this function into r2
2396 MRS r3,spsr @ Put the exception spsr into r3
2397
2398 @ 3. Adjust the exception stack pointer for future exceptions
2399 ADD r13,r13,#20 @ r13 reset to pre-interrupt value
2400
2401 @ 4. Switch CPU modes to save context on system stack
2402 MRS r0,CPSR @ Pickup the current CPSR
2403 BIC r0,r0,#MODE_MASK @ Clear the mode bits
2404
2405 ORR r0,r0,#SUP_MODE @ Change to supervisor mode (SVD)
2406
2407 MSR CPSR,r0 @ Switch modes (IRQ->SVC)
2408
2409 @ 5. Store the SVC r13 into r5 so the r13 can be saved as is.
2410 @ FreeCalyspo: using r0 instead
2411 MOV r0,r13
2412
2413 @ 6. Save the exception return address on the stack (r15).
2414 STMDB r0!,{r4}
2415
2416 @ 7. Save r5-r14 on stack (used to be r6-r14)
2417 STMDB r0!,{r5-r14}
2418
2419 @ 8. Switch back to using r13 now that the original r13 has been saved.
2420 MOV r13,r0
2421
2422 /* no longer relevant */
2423 #if 0
2424 @ 9. Get r5 and exception enable registers off of exception stack and
2425 @ save r5 (stored in r4) back to the system stack.
2426 LDMIA r1!,{r4-r5}
2427 STMDB r13!,{r4}
2428 MOV r4,r5 @ Put exception enable value into r4
2429 #endif
2430
2431 @ 10. Get the rest of the registers off the exception stack and
2432 @ save them onto the system stack.
2433 LDMIA r1!,{r5-r8,r11} @ Get r0-r4 off exception stack
2434 STMDB r13!,{r5-r8,r11} @ Put r0-r4 on system stack
2435
2436 /* no longer relevant */
2437 #if 0
2438 @ 11. Store the exception enable value back on the exception stack.
2439 STMDB r1,{r4}
2440 #endif
2441
2442 @ 12. Save the SPSR on the system stack (CPSR)
2443 STMDB r13!,{r3}
2444
2445 @ 13. Save stack type to the task stack (1=interrupt stack)
2446 MOV r1,#1 @ Interrupt stack type
2447 STMDB r13!,{r1}
2448
2449 @ Save the thread's stack pointer in the control block.
2450 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread
2451 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr
2452
2453 LDR r1,Current_Thread @ Pickup current thread ptr address
2454 LDR r3,[r1, #0] @ Pickup current thread pointer
2455 STR r13,[r3, #TC_STACK_POINTER] @ Save stack pointer
2456
2457 @ Switch to the system stack.
2458 @ REG_Stack_Ptr = TCD_System_Stack
2459
2460 LDR r1,System_Stack @ Pickup address of stack pointer
2461 LDR r3,System_Limit @ Pickup address of stack limit ptr
2462 LDR r13,[r1, #0] @ Switch to system stack
2463 LDR r10,[r3, #0] @ Setup system stack limit
2464
2465 /* TI's approach to interrupt handling does not support re-enabling here */
2466 #if 0
2467 @ Re-enable interrupts
2468 MRS r1,CPSR
2469 BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT)
2470 MSR CPSR,r1
2471 #endif
2472
2473 @ Return to caller ISR.
2474
2475 BX r2 @ Return to caller ISR
2476
2477 @ }
2478
2479 TCT_Idle_Context_Save:
2480
2481 MOV r2,r14 @ Save r14 in r2
2482 @ LDR r3,[r13] @ Get exception enable value from stack
2483 ADD r13,r13,#20 @ Adjust exception r13 for future interrupts
2484 @ STR r3,[r13] @ Put exception enable value back on stack
2485
2486 MRS r1,CPSR @ Pickup current CPSR
2487 BIC r1,r1,#MODE_MASK @ Clear the current mode
2488 @ BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT) @ Re-enable interrupts
2489
2490 ORR r1,r1,#SUP_MODE @ Prepare to switch to supervisor
2491 @ mode (SVC)
2492 MSR CPSR,r1 @ Switch to supervisor mode (SVC)
2493
2494 BX r2 @ Return to caller ISR
2495
2496 @ }
2497 @}
2498
2499 /*
2500 ************************************************************************
2501 *
2502 * FUNCTION
2503 *
2504 * TCT_Interrupt_Context_Restore
2505 *
2506 * DESCRIPTION
2507 *
2508 * This function restores the interrupt context if a nested
2509 * interrupt condition is present. Otherwise, this routine
2510 * transfers control to the scheduling function.
2511 *
2512 * CALLED BY
2513 *
2514 * Application ISRs Assembly language ISRs
2515 * INT_Interrupt_Shell Interrupt handler shell
2516 *
2517 * CALLS
2518 *
2519 * TCT_Schedule Thread scheduling function
2520 *
2521 * INPUTS
2522 *
2523 * None
2524 *
2525 * OUTPUTS
2526 *
2527 * None
2528 *
2529 * HISTORY
2530 *
2531 * NAME DATE REMARKS
2532 *
2533 * W. Lamie 02-15-1994 Created initial version 1.0
2534 * D. Lamie 02-15-1994 Verified version 1.0
2535 * D. Driscoll 01-04-2002 Released version 1.13.3.
2536 * Updated to handle nested /
2537 * prioritized IRQs
2538 *
2539 ************************************************************************
2540 */
2541
2542 @VOID TCT_Interrupt_Context_Restore(void)
2543 @{
2544
2545 .globl TCT_Interrupt_Context_Restore
2546 TCT_Interrupt_Context_Restore:
2547 @ It is assumed that anything pushed on the stack by ISRs has been
2548 @ removed upon entry into this routine.
2549
2550 @ Decrement and check for nested interrupt conditions.
2551 @ if (--TCD_Interrupt_Count)
2552 @ {
2553
2554 LDR r1,Int_Count @ Pickup address of interrupt count
2555 LDR r2,[r1, #0] @ Pickup interrupt counter
2556 SUB r2,r2,#1 @ Decrement interrupt counter
2557 STR r2,[r1, #0] @ Store interrupt counter
2558 CMP r2,#0
2559 BEQ TCT_Not_Nested_Restore
2560
2561 @ Restore previous context.
2562
2563 LDR r1,[r13], #4 @ Pickup the saved CPSR
2564
2565 MSR SPSR,r1 @ Place into saved SPSR
2566 LDMIA r13,{r0-r15}^ @ Return to the point of interrupt
2567
2568 @ }
2569 @ else
2570 @ {
2571
2572 TCT_Not_Nested_Restore:
2573
2574 @ Determine if a thread is active.
2575 @ if (TCD_Current_Thread)
2576 @ {
2577
2578 LDR r1,Current_Thread @ Pickup current thread ptr address
2579 LDR r0,[r1, #0] @ Pickup current thread pointer
2580 CMP r0,#0 @ Determine if a thread is active
2581 BEQ TCT_Idle_Context_Restore @ If not, idle system restore
2582
2583 @ Clear the current thread pointer.
2584 @ TCD_Current_Thread = NU_NULL
2585
2586 MOV r2,#0 @ Build NU_NULL value
2587 STR r2,[r1, #0] @ Set current thread ptr to NU_NULL
2588
2589 @ Determine if a time slice is active. If so, the remaining
2590 @ time left on the time slice must be saved in the task's
2591 @ control block.
2592 @ if (TMD_Time_Slice_State == 0)
2593 @ {
2594
2595 LDR r3,Slice_State @ Pickup time slice state address
2596 LDR r1,[r3, #0] @ Pickup time slice state
2597 CMP r1,#0 @ Determine if time slice active
2598 BNE TCT_Idle_Context_Restore @ If not, skip time slice reset
2599
2600 @ Pickup the remaining portion of the time slice and save it
2601 @ in the task's control block.
2602 @ REG_Thread_Ptr -> tc_cur_time_slice = TMD_Time_Slice
2603 @ TMD_Time_Slice_State = 1
2604
2605 LDR r2,Time_Slice @ Pickup address of time slice left
2606 MOV r1,#1 @ Build disable time slice value
2607 LDR r2,[r2, #0] @ Pickup remaining time slice
2608 STR r1,[r3, #0] @ Disable time slice
2609 STR r2,[r0, #TC_CUR_TIME_SLICE] @ Store remaining time slice
2610
2611 @ }
2612 @ }
2613 TCT_Idle_Context_Restore:
2614
2615 @ Reset the system stack pointer.
2616 LDR r1,System_Stack @ Pickup address of stack pointer
2617 LDR r2,System_Limit @ Pickup address of stack limit ptr
2618 LDR r13,[r1, #0] @ Switch to system stack
2619 LDR r10,[r2, #0] @ Setup system stack limit
2620
2621 @ Return to scheduler.
2622
2623 B TCT_Schedule @ Return to scheduling loop
2624
2625 @ }
2626 @}
2627
2628 /*
2629 ************************************************************************
2630 *
2631 * FUNCTION
2632 *
2633 * TCT_Activate_HISR
2634 *
2635 * DESCRIPTION
2636 *
2637 * This function activates the specified HISR. If the HISR is
2638 * already activated, the HISR's activation count is simply
2639 * incremented. Otherwise, the HISR is placed on the appropriate
2640 * HISR priority list in preparation for execution.
2641 *
2642 * CALLED BY
2643 *
2644 * Application LISRs
2645 *
2646 * CALLS
2647 *
2648 * None
2649 *
2650 * INPUTS
2651 *
2652 * hisr Pointer to HISR to activate
2653 *
2654 * OUTPUTS
2655 *
2656 * NU_SUCCESS Successful completion
2657 *
2658 * HISTORY
2659 *
2660 * NAME DATE REMARKS
2661 *
2662 * W. Lamie 02-15-1994 Created initial version 1.0
2663 * D. Lamie 02-15-1994 Verified version 1.0
2664 *
2665 ************************************************************************
2666 */
2667
2668 @STATUS TCT_Activate_HISR(TC_HCB *hisr)
2669 @{
2670
2671 .globl TCT_Activate_HISR
2672 TCT_Activate_HISR:
2673
2674 @INT priority;
2675
2676
2677 @ Lockout interrupts.
2678
2679 STR r4,[r13, #-4]! @ Save r4
2680 MRS r4,CPSR @ Pickup current CPSR
2681 ORR r1,r4,#LOCKOUT @ Build interrupt lockout value
2682 MSR CPSR,r1 @ Lockout interrupts
2683
2684 @ Determine if the HISR is already active.
2685 @ if (hisr -> tc_activation_count)
2686 @ {
2687
2688 LDR r1,[r0,#0x40] @ Pickup current activation count
2689 CMP r1,#0 @ Is it the first activation?
2690 BEQ TCT_First_Activate @ Yes, place it on the correct list
2691
2692 @ Increment the activation count. Make sure that it does not go
2693 @ to zero.
2694 @ hisr -> tc_activation_count++;
2695
2696 ADDS r1,r1,#1 @ Increment the activation count
2697 STR r1,[r0,#0x40] @ Store new activation count
2698
2699 @ if (hisr -> tc_activation_count == 0)
2700
2701 @ hisr -> tc_activation_count = 0xFFFFFFFFUL;
2702
2703 MVNEQ r1,#0 @ If counter rolled-over reset
2704 STREQ r1,[r0,#0x40] @ Store all ones count
2705 B TCT_Activate_Done @ Finished with activation
2706 @ }
2707 @ else
2708 @ {
2709 TCT_First_Activate:
2710
2711
2712 @ Set the activation count to 1.
2713 @ hisr -> tc_activation_count = 1;
2714
2715 MOV r1,#1 @ Initial activation count
2716 STR r1,[r0,#0x40] @ Store initial activation count
2717
2718 @ Pickup the HISR's priority.
2719 @ priority = hisr -> tc_priority;
2720
2721 @ Determine if there is something in the given priority list.
2722 @ if (TCD_Active_HISR_Tails[priority])
2723 @ {
2724
2725 LDRB r1,[r0,#0x1a] @ Pickup priority of HISR
2726 LDR r2,HISR_Tails @ Pickup tail pointer base
2727 LDR r3,[r2,r1,LSL #2] @ Pickup tail pointer for priority
2728 CMP r3,#0 @ Is this first HISR at priority?
2729 BEQ TCT_First_HISR @ No, append to end of HISR list
2730
2731 @ Something is already on this list. Add after the tail.
2732 @ (TCD_Active_HISR_Tails[priority]) -> tc_active_next = hisr;
2733 @ TCD_Active_HISR_Tails[priority] = hisr;
2734
2735 STR r0,[r3,#0x3c] @ Setup the active next pointer
2736 STR r0,[r2,r1,LSL #2] @ Setup the tail pointer
2737 B TCT_Activate_Done @ Finished with activate processing
2738 @ }
2739 @ else
2740 @ {
2741 TCT_First_HISR:
2742
2743 @ Nothing is on this list.
2744 @ TCD_Active_HISR_Heads[priority] = hisr;
2745 @ TCD_Active_HISR_Tails[priority] = hisr;
2746
2747 LDR r3,HISR_Heads @ Pickup address of head pointers
2748 STR r0,[r2,r1,LSL #2] @ Set tail pointer to this HISR
2749 STR r0,[r3,r1,LSL #2] @ Set head pointer to this HISR
2750
2751 @ Determine the highest priority HISR.
2752 @ if (TCD_Active_HISR_Heads[0])
2753 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[0];
2754 @ else if (TCD_Active_HISR_Heads[1])
2755 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[1];
2756 @ else
2757 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[2];
2758
2759 LDR r1,[r3,#0] @ Pickup priority 0 head pointer
2760 LDR r0,Execute_HISR @ Build address to execute HISR ptr
2761 CMP r1,#0 @ Is priority 0 active?
2762 LDREQ r1,[r3,#4] @ If not, pickup priority 1 head
2763 CMPEQ r1,#0 @ Is priority 1 active?
2764 LDREQ r1,[r3,#8] @ Else, must be priority 2 active
2765 STR r1,[r0,#0] @ Store which ever priority is the
2766 @ active one
2767 @ }
2768 @ }
2769 TCT_Activate_Done:
2770
2771 MSR CPSR,r4 @ Restore interrupt lockout
2772 LDR r4,[r13], #4 @ Restore corrupted r4
2773
2774 @ return(NU_SUCCESS);
2775
2776 MOV r0,#0 @ Always return NU_SUCCESS
2777
2778 BX r14 @ Return to caller
2779
2780 @}
2781
2782 /*
2783 ************************************************************************
2784 *
2785 * FUNCTION
2786 *
2787 * TCT_HISR_Shell
2788 *
2789 * DESCRIPTION
2790 *
2791 * This function is the execution shell of each and every HISR. If
2792 * the HISR has completed its processing, this shell routine exits
2793 * back to the system. Otherwise, it sequentially calls the HISR
2794 * routine until the activation count goes to zero.
2795 *
2796 * CALLED BY
2797 *
2798 * HISR Scheduling
2799 *
2800 * CALLS
2801 *
2802 * hisr -> tc_entry Actual entry function of HISR
2803 *
2804 * INPUTS
2805 *
2806 * None
2807 *
2808 * OUTPUTS
2809 *
2810 * None
2811 *
2812 * HISTORY
2813 *
2814 * NAME DATE REMARKS
2815 *
2816 * W. Lamie 02-15-1994 Created initial version 1.0
2817 * D. Lamie 02-15-1994 Verified version 1.0
2818 *
2819 ************************************************************************
2820 */
2821
2822 @VOID TCT_HISR_Shell(void)
2823 @{
2824 .globl TCT_HISR_Shell
2825 TCT_HISR_Shell:
2826
2827 @ Point at the HISR.
2828 @ REG_HISR_Ptr = (TC_HCB *) TCD_Current_Thread;
2829
2830 LDR r0,Current_Thread @ Build address of thread pointer
2831 LDR r5,[r0, #0] @ Pickup control block pointer
2832
2833 @ do
2834 @ {
2835 TCT_HISR_Loop:
2836
2837 @ Call the HISR's entry routine.
2838 @ (*(REG_HISR_Ptr -> tc_entry)) ();
2839
2840 /* old TMS470 code:
2841
2842 .if THUMB = 0
2843
2844 MOV r14,r15 ; Setup return value
2845 LDR r15,[r5,#44h] ; Call HISR entry function
2846 .else
2847 LDR r4,[r5,#44h] ; Get HISR entry function
2848 TST r4,#1 ; See if calling Thumb or ARM
2849 BNE Thumbsec
2850 MOV r14,r15 ; Setup return value
2851 BX r4
2852 B ARMCODE
2853 Thumbsec:
2854 ADD r14, r15, #1
2855 BX r4
2856 .state16
2857 ThumbAfterHisr
2858 MOV r1, r15
2859 BX r1
2860 .state32
2861 .endif
2862 */
2863
2864 /* new code for the GNU style of ARM/Thumb interworking */
2865 ldr r4, [r5, #TC_HISR_ENTRY]
2866 mov lr, pc
2867 bx r4
2868
2869 @ Lockout interrupts.
2870
2871 MRS r1,CPSR @ Pickup current CPSR
2872 ORR r1,r1,#LOCKOUT @ Build interrupt lockout
2873 MSR CPSR,r1 @ Lockout interrupts
2874
2875 @ On return, decrement the activation count and check to see if
2876 @ it is 0. Once it reaches 0, the HISR should be made inactive.
2877 @ REG_HISR_Ptr -> tc_activation_count--;
2878
2879
2880 LDR r0,[r5, #0x40] @ Pickup current activation count
2881 SUBS r0,r0,#1 @ Subtract and set condition codes
2882 STR r0,[r5, #0x40] @ Store new activation count
2883 BEQ TCT_HISR_Finished @ Finished processing HISR
2884
2885 @ Restore interrupts.
2886
2887 LDR r2,Int_Level @ Pickup address of interrupt level
2888 MRS r1,CPSR @ Pickup current CPSR
2889 LDR r3,[r2, #0] @ Pickup interrupt lockout level
2890 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
2891 ORR r1,r1,r3 @ Build new interrupt lockout
2892 MSR CPSR,r1 @ Setup CPSR appropriately
2893 B TCT_HISR_Loop @ Return to HISR loop
2894 @ }
2895 @ while (REG_HISR_Ptr -> tc_activation_count);
2896
2897 TCT_HISR_Finished:
2898
2899 @ At this point, the HISR needs to be made inactive.
2900
2901 @ Determine if this is the only HISR on the given priority list.
2902 @ if (REG_HISR_Ptr == TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority])
2903 @ {
2904
2905 LDR r14,HISR_Tails @ Pickup tail pointers address
2906 LDRB r3,[r5,#0x1a] @ Pickup priority
2907 LDR r6,[r14,r3,LSL #2] @ Pickup this priority tail pointer
2908 LDR r2,Execute_HISR @ Build address to execute HISR ptr
2909 MOV r12,#0 @ Clear r12
2910 LDR r1,HISR_Heads @ Pickup head pointers address
2911 CMP r6,r5 @ Is this priority tail the same as
2912 @ the current HISR?
2913 BNE TCT_More_HISRs @ If not, more HISRs at this
2914 @ priority
2915
2916 @ The only HISR on the list. Clean up the list and check for the
2917 @ highest priority HISR.
2918 @ TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] = NU_NULL;
2919 @ TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority] = NU_NULL;
2920
2921 STR r12,[r1,r3,LSL #2] @ Set head pointer to NU_NULL
2922 STR r12,[r14,r3,LSL #2] @ Set tail pointer to NU_NULL
2923
2924 @ Determine the highest priority HISR.
2925 @ if (TCD_Active_HISR_Heads[0])
2926 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[0];
2927 @ else if (TCD_Active_HISR_Heads[1])
2928 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[1];
2929 @ else
2930 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[2];
2931
2932 LDR r3,[r1,#0] @ Pickup priority 0 head pointer
2933 CMP r3,#0 @ Is there an HISR active?
2934 LDREQ r3,[r1,#4] @ If not, pickup priority 1 pointer
2935 CMPEQ r3,#0 @ Is there an HISR active?
2936 LDREQ r3,[r1,#8] @ If not, pickup priority 2 pointer
2937 STR r3,[r2,#0] @ Setup execute HISR pointer
2938 B TCT_HISR_Exit @ Exit HISR processing
2939 @ }
2940 @ else
2941 @ {
2942
2943 TCT_More_HISRs:
2944
2945 @ Move the head pointer to the next HISR in the list.
2946 @ TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] =
2947 @ REG_HISR_Ptr -> tc_active_next;
2948
2949 @ Also set the TCD_Execute_HISR pointer.
2950 @ TCD_Execute_HISR = REG_HISR_Ptr -> tc_active_next;
2951
2952 LDR r14,[r5,#0x3c] @ Pickup next HISR to activate
2953 STR r14,[r1,r3,LSL #2] @ Setup new head pointer
2954 STR r14,[r2, #0] @ Setup execute HISR pointer
2955 @ }
2956
2957 TCT_HISR_Exit:
2958
2959 @ Build fake return to the top of this loop. The next time the HISR
2960 @ is activated, it will return to the top of this function.
2961
2962 LDR r14,HISR_Shell @ Pickup address of shell entry
2963 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
2964 @ the current stack
2965 MOV r2,#0 @ Build solicited stack type value
2966 @ and NU_NULL value
2967 #if 1 /* was .if THUMB */
2968 STR r2,[r13, #-4]! @ Save state mask
2969 #endif
2970 STR r2,[r13, #-4]! @ Place it on the top of the stack
2971
2972 @ Clear the current thread control block.
2973 @ TCD_Current_Thread = NU_NULL;
2974
2975 LDR r1,Current_Thread @ Pickup current thread ptr address
2976 STR r2,[r1, #0] @ Set current thread pointer to
2977 @ NU_NULL
2978
2979 @ Save off the current stack pointer in the control block.
2980 @ REG_HISR_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
2981
2982
2983 STR r13,[r5, #0x2c] @ Save the thread's stack pointer
2984
2985
2986 @ Switch to the system stack.
2987 @ REG_Stack_Ptr = (BYTE_PTR) TCD_System_Stack;
2988
2989 LDR r1,System_Stack @ Pickup address of stack pointer
2990 LDR r2,System_Limit @ Pickup address of stack limit ptr
2991 LDR r13,[r1, #0] @ Switch to system stack
2992 LDR r10,[r2, #0] @ Setup system stack limit
2993
2994 @ Transfer control to the main scheduling loop.
2995
2996 B TCT_Schedule @ Return to main scheduling loop
2997 @}
2998
2999 /* FreeCalypso addition, used by riviera/rvf/rvf_task.c: */
3000 .globl INT_Check_IRQ_Mask
3001 INT_Check_IRQ_Mask:
3002 MRS r0,CPSR
3003 BX lr
3004