comparison src/nucleus/gcc/tct.S @ 0:4e78acac3d88

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