comparison nuc-fw/nucleus/tct.S @ 79:947b1f473960

beginning of nuc-fw
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 11 Aug 2013 07:17:25 +0000
parents
children 2c5160a9d652
comparison
equal deleted inserted replaced
78:2c266d4339ff 79:947b1f473960
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 TCT_Schedule_Loop:
960
961 @ } while ((!TCD_Execute_HISR) && (!TCD_Execute_Task));
962
963 LDR r0,[r2, #0] @ Pickup highest priority HISR ptr
964 CMP r0,#0 @ Is there a HISR active?
965 BNE TCT_Schedule_Thread @ Found an HISR
966 LDR r0,[r3, #0] @ Pickup highest priority Task ptr
967 CMP r0,#0 @ Is there a task active?
968 BEQ TCT_Schedule_Loop @ If not, continue the search
969
970 @ Yes, either a task or an HISR is ready to execute. Lockout
971 @ interrupts while the thread is transferred to.
972
973 TCT_Schedule_Thread:
974 MRS r1,CPSR @ Pickup CPSR again
975 ORR r1,r1,#LOCKOUT @ Build interrupt lockout value
976 MSR CPSR,r1 @ Lockout interrupts
977
978 @ Transfer control to the thread by falling through to the following
979 @ routine.
980 @}
981
982 /*
983 ************************************************************************
984 *
985 * FUNCTION
986 *
987 * TCT_Control_To_Thread
988 *
989 * DESCRIPTION
990 *
991 * This function transfers control to the specified thread. Each
992 * time control is transferred to a thread, its scheduled counter
993 * is incremented. Additionally, time-slicing for task threads is
994 * enabled in this routine. The TCD_Current_Thread pointer is
995 * setup by this function.
996 *
997 * CALLED BY
998 *
999 * TCT_Schedule Indirectly called
1000 * TCT_Protect Protection task switch
1001 *
1002 * CALLS
1003 *
1004 * None
1005 *
1006 * INPUTS
1007 *
1008 * thread Thread control block pointer
1009 *
1010 * OUTPUTS
1011 *
1012 * None
1013 *
1014 * HISTORY
1015 *
1016 * NAME DATE REMARKS
1017 *
1018 * W. Lamie 02-15-1994 Created initial version 1.0
1019 * D. Lamie 02-15-1994 Verified version 1.0
1020 *
1021 ************************************************************************
1022 */
1023
1024 @VOID TCT_Control_To_Thread(TC_TCB *thread)
1025 @{
1026 TCT_Control_To_Thread:
1027
1028 @ Setup the current thread pointer.
1029 @ TCD_Current_Thread = (VOID *) thread;
1030
1031 LDR r1,Current_Thread @ Pickup current thread ptr address
1032 LDR r2,[r0, #0x1c] @ Pickup scheduled count
1033 STR r0,[r1, #0] @ Setup current thread pointer
1034
1035 @ Increment the thread scheduled counter.
1036 @ thread -> tc_scheduled++;
1037
1038 LDR r3,[r0, #0x20] @ Pickup time slice value
1039 ADD r2,r2,#1 @ Increment the scheduled count
1040 STR r2,[r0, #0x1c] @ Store new scheduled count
1041
1042 @ Check for time slice option.
1043 @ if (thread -> tc_cur_time_slice)
1044 @ {
1045 CMP r3,#0 @ Is there a time slice?
1046 BEQ TCT_No_Start_TS_1 @ If 0, there is no time slice
1047
1048 @ Start a time slice.
1049 @ TMD_Time_Slice = thread -> tc_cur_time_slice;
1050 @ TMD_Time_Slice_State = 0;
1051
1052 LDR r2,Time_Slice @ Pickup address of TMD_Time_Slice
1053 LDR r1,Slice_State @ Pickup address of
1054 @ TMD_Time_Slice_State
1055 STR r3,[r2, #0] @ Setup the time slice
1056 MOV r2,#0 @ Build active state flag
1057 STR r2,[r1,#0] @ Set the active flag
1058 @ }
1059 TCT_No_Start_TS_1:
1060 #ifdef INCLUDE_PROVIEW
1061 @ Nucleus ProView Hook
1062
1063 STR r0,[r13, #-4]! @ Save r0 on the stack
1064 BL _NU_Schedule_Task_Hook @ Branch to RTView
1065 LDR r0,[r13], #4 @ Recover return address
1066 #endif
1067
1068
1069 @ Pickup the stack pointer and resume the thread.
1070 @ REG_Stack_Ptr = thread -> tc_stack_pointer;
1071
1072 LDR r13,[r0, #0x2c] @ Switch to thread's stack pointer
1073
1074 @ Pop off the saved information associated with the thread. After we
1075 @ determine which type of stack is present. A 1 on the top of the
1076 @ stack indicates an interrupt stack, while a 0 on the top of the
1077 @ stack indicates a solicited type of stack.
1078
1079 @ Remember that the interrupt level that is restored must represent
1080 @ the interrupt level in TCD_Interrupt_Level.
1081
1082 LDR r1,[r13], #4 @ Pop off the stack type
1083 CMP r1,#1 @ See if it is an interrupt stack
1084 BEQ TCT_Interrupt_Resume @ If so, an interrupt resume of
1085 @ thread is required
1086 LDR r1, Int_Level @ Pickup address of interrupt
1087 @ lockout
1088 MRS r0,CPSR @ Pickup current CPSR
1089 BIC r0,r0,#LOCK_MSK @ Clear lockout mask
1090
1091 BIC r0,r0,#0x80000000
1092
1093
1094 LDR r2,[r1, #0] @ Pickup interrupt lockout mask
1095 ORR r0,r0,r2 @ Build new interrupt lockout mask
1096 #if 1 /* was .if THUMB */
1097 LDR r2,[r13], #4 @ Pop off the state mask
1098 ORR r0,r0,r2 @ Set appropriate state
1099 #endif
1100 MSR SPSR,r0 @ Place it into the SPSR
1101 LDMIA r13!,{r4-r12,r15}^ @ A solicited return is required.
1102 @ This type of return only
1103 @ recovers r4-r13 & r15
1104 TCT_Interrupt_Resume:
1105 LDR r0,[r13], #4 @ Pop off the CPSR
1106 LDR r1,Int_Level @ Pickup address of interrupt
1107 @ lockout
1108 BIC r0,r0,#LOCK_MSK @ Clear lockout mask
1109 LDR r2,[r1, #0] @ Pickup interrupt lockout mask
1110 ORR r0,r0,r2 @ Build new interrupt lockout mask
1111 MSR SPSR,r0 @ Place it into the SPSR
1112 LDMIA r13,{r0-r15}^ @ Recover all registers and resume
1113 @ at point of interrupt
1114 @}
1115
1116 /*
1117 ************************************************************************
1118 *
1119 * FUNCTION
1120 *
1121 * TCT_Control_To_System
1122 *
1123 * DESCRIPTION
1124 *
1125 * This function returns control from a thread to the system. Note
1126 * that this service is called in a solicited manner, i.e. it is
1127 * not called from an interrupt thread. Registers required by the
1128 * compiler to be preserved across function boundaries are saved by
1129 * this routine. Note that this is usually a sub-set of the total
1130 * number of available registers.
1131 *
1132 * CALLED BY
1133 *
1134 * Other Components
1135 *
1136 * CALLS
1137 *
1138 * TCT_Schedule Schedule the next thread
1139 *
1140 * INPUTS
1141 *
1142 * None
1143 *
1144 * OUTPUTS
1145 *
1146 * None
1147 *
1148 * HISTORY
1149 *
1150 * NAME DATE REMARKS
1151 *
1152 * W. Lamie 02-15-1994 Created initial version 1.0
1153 * D. Lamie 02-15-1994 Verified version 1.0
1154 * C. Meredith 03-01-1994 Corrected problem in time-slice
1155 * reset logic, resulting in
1156 * version 1.1
1157 * D. Lamie 03-18-1994 Verified version 1.1
1158 *
1159 ************************************************************************
1160 */
1161
1162 @VOID TCT_Control_To_System(void)
1163 @{
1164
1165 .globl TCT_Control_To_System
1166 TCT_Control_To_System:
1167
1168 @ Lockout interrupts.
1169
1170 MRS r0,CPSR @ Pickup current CPSR
1171 ORR r0,r0,#LOCKOUT @ Build interrupt lockout value
1172 MSR CPSR,r0 @ Lockout interrupts
1173
1174 @ Save a minimal context of the thread.
1175
1176 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
1177 @ the current stack
1178 #if 1 /* was .if THUMB */
1179 MOV r2,r14 @ Determine what state the caller
1180 MOV r2,r2,LSL #31 @ was in and build an
1181 MOV r2,r2,LSR #26 @ appropriate state mask
1182 STR r2,[r13, #-4]! @ Place it on the stack
1183 #endif
1184
1185 MOV r2,#0 @ Build solicited stack type value
1186 @ and NU_NULL value
1187 STR r2,[r13, #-4]! @ Place it on the top of the stack
1188
1189 @ Setup a pointer to the thread control block.
1190 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1191
1192 LDR r1,Current_Thread @ Pickup current thread ptr address
1193 LDR r0,[r1, #0] @ Pickup current thread pointer
1194
1195 @ Clear the current thread control block pointer.
1196 @ TCD_Current_Thread = NU_NULL;
1197
1198 LDR r3,Slice_State @ Pickup time slice state address
1199 STR r2,[r1, #0] @ Set current thread pointer to
1200 @ NU_NULL
1201
1202 @ Check to see if a time slice is active. If so, copy the original time
1203 @ slice into the current time slice field of the task's control block.
1204 @ if (TMD_Time_Slice_State == 0)
1205 @ {
1206 LDR r1,[r3, #0] @ Pickup time slice state flag
1207 CMP r1,#0 @ Compare with active value
1208 BNE TCT_No_Stop_TS_1 @ If non-active, don't disable
1209
1210
1211 @ Insure that the next time the task runs it gets a fresh time
1212 @ slice.
1213 @ REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
1214
1215 LDR r1,[r0, #0x40] @ Pickup original time slice
1216
1217 @ Clear any active time slice by setting the state to NOT_ACTIVE.
1218 @ TMD_Time_Slice_State = 1;
1219
1220 MOV r2,#1 @ Build disable value
1221 STR r2,[r3, #0] @ Disable time slice
1222 STR r1,[r0, #0x20] @ Reset current time slice
1223 @ }
1224 TCT_No_Stop_TS_1:
1225
1226 @ Save off the current stack pointer in the control block.
1227 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
1228
1229 STR r13,[r0, #0x2c] @ Save the thread's stack pointer
1230
1231 @ Clear the task's current protection.
1232 @ (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
1233 @ REG_Thread_Ptr -> tc_current_protect = NU_NULL;
1234
1235 LDR r1,[r0, #0x38] @ Pickup current thread pointer
1236 MOV r2,#0 @ Build NU_NULL value
1237 STR r2,[r0, #0x38] @ Clear the protect pointer field
1238 STR r2,[r1, #0] @ Release the actual protection
1239
1240 @ Switch to the system stack.
1241 @ REG_Stack_Ptr = TCD_System_Stack;
1242
1243 LDR r1, System_Stack @ Pickup address of stack pointer
1244 LDR r2, System_Limit @ Pickup address of stack limit ptr
1245 LDR r13,[r1, #0] @ Switch to system stack
1246 LDR r10,[r2, #0] @ Setup system stack limit
1247
1248 @ Finished, return to the scheduling loop.
1249
1250 B TCT_Schedule @ Return to scheduling loop
1251 @}
1252
1253 /*
1254 ************************************************************************
1255 *
1256 * FUNCTION
1257 *
1258 * TCT_Signal_Exit
1259 *
1260 * DESCRIPTION
1261 *
1262 * This function exits from a signal handler. The primary purpose
1263 * of this function is to clear the scheduler protection and switch
1264 * the stack pointer back to the normal task's stack pointer.
1265 *
1266 * CALLED BY
1267 *
1268 * TCC_Signal_Shell Signal handling shell func
1269 *
1270 * CALLS
1271 *
1272 * TCT_Schedule Scheduler
1273 *
1274 * INPUTS
1275 *
1276 * None
1277 *
1278 * OUTPUTS
1279 *
1280 * None
1281 *
1282 * HISTORY
1283 *
1284 * NAME DATE REMARKS
1285 *
1286 * W. Lamie 02-15-1994 Created initial version 1.0
1287 * D. Lamie 02-15-1994 Verified version 1.0
1288 * C. Meredith 03-01-1994 Corrected problem in time-slice
1289 * reset logic, resulting in
1290 * version 1.1
1291 * D. Lamie 03-18-1994 Verified version 1.1
1292 *
1293 ************************************************************************
1294 */
1295
1296 @VOID TCT_Signal_Exit(void)
1297 @{
1298
1299 .globl TCT_Signal_Exit
1300 TCT_Signal_Exit:
1301
1302 @ Lockout interrupts.
1303
1304 MRS r3,CPSR @ Pickup current CPSR
1305 ORR r3,r3,#LOCKOUT @ Build lockout value
1306 MSR CPSR,r3 @ Lockout interrupts
1307
1308 @ Setup a pointer to the thread control block.
1309 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1310
1311 LDR r1,Current_Thread @ Pickup address of thread pointer
1312 MOV r2,#0 @ Build NU_NULL value
1313 LDR r0,[r1,#0] @ Pickup current thread pointer
1314
1315 @ Clear the current thread control block.
1316 @ TCD_Current_Thread = NU_NULL;
1317
1318 LDR r3,Slice_State @ Pickup time slice state address
1319 STR r2,[r1, #0] @ Clear current thread pointer
1320
1321 @ Check to see if a time slice is active. If so, copy the original time
1322 @ slice into the current time slice field of the task's control block.
1323 @ if (TMD_Time_Slice_State == 0)
1324 @ {
1325
1326 LDR r1,[r3, #0] @ Pickup time slice state flag
1327 CMP r1,#0 @ Compare with active value
1328 BNE TCT_No_Stop_TS_2 @ If non-active, don't disable
1329
1330 @ Insure that the next time the task runs it gets a fresh time
1331 @ slice.
1332 @ REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
1333
1334 LDR r1,[r0, #0x40] @ Pickup original time slice
1335
1336 @ Clear any active time slice by setting the state to NOT_ACTIVE.
1337 @ TMD_Time_Slice_State = 1;
1338
1339 MOV r2,#1 @ Build disable value
1340 STR r2,[r3, #0] @ Disable time slice
1341 STR r1,[r0, #0x20] @ Reset current time slice
1342 @ }
1343 TCT_No_Stop_TS_2:
1344
1345 @ Switch back to the saved stack. The saved stack pointer was saved
1346 @ before the signal frame was built.
1347 @ REG_Thread_Ptr -> tc_stack_pointer =
1348 @ REG_Thread_Ptr -> tc_saved_stack_ptr;
1349
1350 LDR r1,[r0, #0x3c] @ Pickup saved stack pointer
1351 STR r1,[r0, #0x2c] @ Place in current stack pointer
1352
1353 @ Clear the task's current protection.
1354 @ (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
1355 @ REG_Thread_Ptr -> tc_current_protect = NU_NULL;
1356
1357 LDR r1,[r0, #0x38] @ Pickup current thread pointer
1358 MOV r2,#0 @ Build NU_NULL value
1359 STR r2,[r0, #0x38] @ Clear the protect pointer field
1360 STR r2,[r1, #0] @ Release the actual protection
1361
1362 @ Switch to the system stack.
1363 @ REG_Stack_Ptr = (BYTE_PTR) TCD_System_Stack;
1364
1365 LDR r1, System_Stack @ Pickup address of stack pointer
1366 LDR r2, System_Limit @ Pickup address of stack limit ptr
1367 LDR r13,[r1, #0] @ Switch to system stack
1368 LDR r10,[r2, #0] @ Setup system stack limit
1369
1370 @ Finished, return to the scheduling loop.
1371
1372 B TCT_Schedule @ Return to scheduling loop
1373 @}
1374
1375 /*
1376 ************************************************************************
1377 *
1378 * FUNCTION
1379 *
1380 * TCT_Current_Thread
1381 *
1382 * DESCRIPTION
1383 *
1384 * This function returns the current thread pointer.
1385 *
1386 * CALLED BY
1387 *
1388 * Application
1389 * System Components
1390 *
1391 * CALLS
1392 *
1393 * None
1394 *
1395 * INPUTS
1396 *
1397 * None
1398 *
1399 * OUTPUTS
1400 *
1401 * Pointer to current thread
1402 *
1403 * HISTORY
1404 *
1405 * NAME DATE REMARKS
1406 *
1407 * W. Lamie 02-15-1994 Created initial version 1.0
1408 * D. Lamie 02-15-1994 Verified version 1.0
1409 *
1410 ************************************************************************
1411 */
1412
1413 @VOID *TCT_Current_Thread(void)
1414 @{
1415
1416 .globl TCT_Current_Thread
1417 TCT_Current_Thread:
1418
1419 @ Return the current thread pointer.
1420 @ return(TCD_Current_Thread);
1421
1422 LDR r0, Current_Thread @ Pickup address of thread pointer
1423 LDR r0,[r0, #0] @ Pickup current thread pointer
1424
1425 BX r14 @ Return to caller
1426
1427 @}
1428
1429 /*
1430 ************************************************************************
1431 *
1432 * FUNCTION
1433 *
1434 * TCT_Set_Execute_Task
1435 *
1436 * DESCRIPTION
1437 *
1438 * This function sets the current task to execute variable under
1439 * protection against interrupts.
1440 *
1441 * CALLED BY
1442 *
1443 * TCC Scheduling Routines
1444 *
1445 * CALLS
1446 *
1447 * None
1448 *
1449 * INPUTS
1450 *
1451 * task Pointer to task control block
1452 *
1453 * OUTPUTS
1454 *
1455 * TCD_Execute_Task Modified variable
1456 *
1457 * HISTORY
1458 *
1459 * NAME DATE REMARKS
1460 *
1461 * W. Lamie 02-15-1994 Created initial version 1.0
1462 * D. Lamie 02-15-1994 Verified version 1.0
1463 *
1464 ************************************************************************
1465 */
1466
1467 @VOID TCT_Set_Execute_Task(TC_TCB *task)
1468 @{
1469
1470 .globl TCT_Set_Execute_Task
1471 TCT_Set_Execute_Task:
1472
1473 @ Now setup the TCD_Execute_Task pointer.
1474 @ TCD_Execute_Task = task;
1475
1476 LDR r1, Execute_Task @ Pickup execute task ptr address
1477 STR r0,[r1,#0] @ Setup new task to execute
1478
1479 BX r14 @ Return to caller
1480
1481 @}
1482
1483 /*
1484 ************************************************************************
1485 *
1486 * FUNCTION
1487 *
1488 * TCT_Protect
1489 *
1490 * DESCRIPTION
1491 *
1492 * This function protects against multiple thread access.
1493 *
1494 * CALLED BY
1495 *
1496 * Application
1497 * System Components
1498 *
1499 * CALLS
1500 *
1501 * None
1502 *
1503 * INPUTS
1504 *
1505 * protect Pointer to protection block
1506 *
1507 * OUTPUTS
1508 *
1509 * None
1510 *
1511 * HISTORY
1512 *
1513 * NAME DATE REMARKS
1514 *
1515 * W. Lamie 02-15-1994 Created initial version 1.0
1516 * D. Lamie 02-15-1994 Verified version 1.0
1517 *
1518 ************************************************************************
1519 */
1520
1521 @VOID TCT_Protect(TC_PROTECT *protect)
1522 @{
1523
1524 .globl TCT_Protect
1525 TCT_Protect:
1526
1527 @ Determine if the caller is in a task or HISR thread.
1528 @ if (TCD_Current_Thread)
1529 @ {
1530
1531 LDR r1,Current_Thread @ Pickup current thread ptr address
1532 LDR r3,[r1, #0] @ Pickup current thread pointer
1533 CMP r3,#0 @ Check to see if it is non-NULL
1534 BEQ TCT_Skip_Protect @ If NULL, skip protection
1535
1536 @ Lockout interrupts.
1537
1538 MRS r1,CPSR @ Pickup current CPSR
1539 ORR r1,r1,#LOCKOUT @ Place lockout value in
1540 MSR CPSR,r1 @ Lockout interrupts
1541
1542 @ Wait until the protect structure is available.
1543 @ while (protect -> tc_tcb_pointer != NU_NULL)
1544 @ {
1545
1546 TCT_Protect_Loop:
1547 LDR r1,[r0, #0] @ Pickup protection owner field
1548 CMP r1,#0 @ Is there any protection?
1549 BEQ TCT_Protect_Available @ If NU_NULL, no current protection
1550
1551 @ Protection structure is not available.
1552
1553 @ Indicate that another thread is waiting.
1554 @ protect -> tc_thread_waiting = 1;
1555
1556 MOV r2,#1 @ Build thread waiting flag
1557 STR r2,[r0, #4] @ Set waiting field
1558
1559 @ Directly schedule the thread waiting.
1560 @ TCT_Schedule_Protected(protect -> tc_tcb_pointer);
1561
1562 STR r0,[r13, #-4]! @ Save r0 on the stack
1563 STR r14,[r13, #-4]! @ Save r14 on the stack
1564 MOV r0,r3 @ Place current thread into r0
1565 BL TCT_Schedule_Protected @ Call routine to schedule the
1566 @ owner of the thread
1567
1568 LDR r14,[r13], #4 @ Recover saved r14
1569 LDR r0,[r13], #4 @ Recover saved r0
1570
1571 @ Lockout interrupts.
1572
1573 LDR r1,Current_Thread @ Pickup current thread ptr address
1574 LDR r3,[r1, #0] @ Pickup current thread pointer
1575 MRS r1,CPSR @ Pickup current CPSR
1576 ORR r1,r1,#LOCKOUT @ Place lockout value in
1577 MSR CPSR,r1 @ Lockout interrupts
1578 B TCT_Protect_Loop @ Examine protect flags again
1579 @ }
1580 TCT_Protect_Available:
1581
1582 @ Protection structure is available.
1583
1584 @ Indicate that this thread owns the protection.
1585 @ protect -> tc_tcb_pointer = TCD_Current_Thread;
1586
1587 STR r3,[r0, #0] @ Indicate calling thread owns this
1588 @ protection
1589
1590 @ Clear the thread waiting flag.
1591 @ protect -> tc_thread_waiting = 0;
1592
1593 MOV r2,#0 @ Clear value
1594 STR r2,[r0, #4] @ Clear the thread waiting flag
1595
1596 @ Save the protection pointer in the thread's control block. Note
1597 @ that both task and HISR threads share the same control block
1598 @ format.
1599 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1600 @ REG_Thread_Ptr -> tc_current_protect = protect;
1601
1602 STR r0,[r3, #0x38] @ Setup current protection
1603
1604 @ Restore interrupts.
1605
1606 LDR r2,Int_Level @ Pickup address of interrupt level
1607 MRS r1,CPSR @ Pickup current CPSR
1608 LDR r3,[r2, #0] @ Pickup interrupt lockout level
1609 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
1610 ORR r1,r1,r3 @ Build new interrupt lockout
1611 MSR CPSR,r1 @ Setup CPSR appropriately
1612 @ }
1613
1614 TCT_Skip_Protect:
1615
1616 BX r14 @ Return to caller
1617
1618 @}
1619
1620 /*
1621 ************************************************************************
1622 *
1623 * FUNCTION
1624 *
1625 * TCT_Unprotect
1626 *
1627 * DESCRIPTION
1628 *
1629 * This function releases protection of the currently active
1630 * thread. If the caller is not an active thread, then this
1631 * request is ignored.
1632 *
1633 * CALLED BY
1634 *
1635 * Application
1636 * System Components
1637 *
1638 * CALLS
1639 *
1640 * None
1641 *
1642 * INPUTS
1643 *
1644 * None
1645 *
1646 * OUTPUTS
1647 *
1648 * None
1649 *
1650 * HISTORY
1651 *
1652 * NAME DATE REMARKS
1653 *
1654 * W. Lamie 02-15-1994 Created initial version 1.0
1655 * D. Lamie 02-15-1994 Verified version 1.0
1656 *
1657 ************************************************************************
1658 */
1659
1660 @VOID TCT_Unprotect(void)
1661 @{
1662
1663 .globl TCT_Unprotect
1664 TCT_Unprotect:
1665
1666
1667 @ Determine if the caller is in a task or HISR thread.
1668 @ if (TCD_Current_Thread)
1669 @ {
1670
1671 LDR r1,Current_Thread @ Pickup current thread ptr address
1672 LDR r3,[r1, #0] @ Pickup current thread pointer
1673 CMP r3,#0 @ Check to see if it is non-NULL
1674 BEQ TCT_Skip_Unprotect @ If NULL, skip unprotection
1675
1676 @ Setup a thread control block pointer.
1677 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1678
1679 @ Determine if there is a currently active protection.
1680 @ if (REG_Thread_Ptr -> tc_current_protect)
1681 @ {
1682
1683 LDR r0,[r3, #0x38] @ Pickup current protect field
1684 CMP r0,#0 @ Is there a protection in force?
1685 BEQ TCT_Skip_Unprotect @ If not, nothing is protected
1686
1687 @ Lockout interrupts.
1688
1689 MRS r1,CPSR @ Pickup current CPSR
1690 ORR r1,r1,#LOCKOUT @ Place lockout value in
1691 MSR CPSR,r1 @ Lockout interrupts
1692
1693 @ Yes, this thread still has this protection structure.
1694 @ REG_Protect_Ptr = REG_Thread_Ptr -> tc_current_protect;
1695
1696 @ Is there a higher priority thread waiting for the protection
1697 @ structure?
1698 @ if (REG_Protect_Ptr -> tc_thread_waiting)
1699
1700 LDR r2,[r0, #4] @ Pickup thread waiting flag
1701 CMP r2,#0 @ Are there any threads waiting?
1702 BEQ TCT_Not_Waiting_Unpr @ If not, just release protection
1703
1704 @ Transfer control to the system. Note that this
1705 @ automatically clears the current protection and it returns
1706 @ to the caller of this routine instead of this routine.
1707 @ TCT_Control_To_System();
1708
1709 B TCT_Control_To_System @ Return control to the system
1710
1711 @ else
1712 @ {
1713 TCT_Not_Waiting_Unpr:
1714
1715 @ Clear the protection.
1716 @ REG_Thread_Ptr -> tc_current_protect = NU_NULL;
1717 @ REG_Protect_Ptr -> tc_tcb_pointer = NU_NULL;
1718
1719 MOV r2,#0 @ Build NU_NULL value
1720 STR r2,[r0, #0] @ Release the protection
1721 STR r2,[r3, #0x38] @ Clear protection pointer in the
1722 @ control block
1723
1724 @ }
1725
1726 TCT_Not_Protected:
1727 @ Restore interrupts again.
1728
1729 LDR r2,Int_Level @ Pickup address of interrupt level
1730 MRS r1,CPSR @ Pickup current CPSR
1731 LDR r3,[r2, #0] @ Pickup interrupt lockout level
1732 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
1733 ORR r1,r1,r3 @ Build new interrupt lockout
1734 MSR CPSR,r1 @ Setup CPSR appropriately
1735
1736 @ }
1737 @ }
1738 TCT_Skip_Unprotect:
1739
1740 BX r14 @ Return to caller
1741
1742 @}
1743
1744 /*
1745 ************************************************************************
1746 *
1747 * FUNCTION
1748 *
1749 * TCT_Unprotect_Specific
1750 *
1751 * DESCRIPTION
1752 *
1753 * This function releases a specific protection structure.
1754 *
1755 * CALLED BY
1756 *
1757 * Application
1758 * System Components
1759 *
1760 * CALLS
1761 *
1762 * None
1763 *
1764 * INPUTS
1765 *
1766 * protect Pointer to protection block
1767 *
1768 * OUTPUTS
1769 *
1770 * None
1771 *
1772 * HISTORY
1773 *
1774 * NAME DATE REMARKS
1775 *
1776 * W. Lamie 02-15-1994 Created initial version 1.0
1777 * D. Lamie 02-15-1994 Verified version 1.0
1778 * C. Meredith 03-01-1994 Corrected problem in time-slice
1779 * reset logic, corrected bug
1780 * using protect ptr, resulting
1781 * in version 1.1
1782 * D. Lamie 03-18-1994 Verified version 1.1
1783 *
1784 ************************************************************************
1785 */
1786
1787 @VOID Specific(TC_PROTECT *protect)
1788 @{
1789
1790 .globl TCT_Unprotect_Specific
1791 TCT_Unprotect_Specific:
1792
1793 @ Determine if the caller is in a task or HISR thread.
1794 @ if (TCD_Current_Thread)
1795 @ {
1796
1797 LDR r1,Current_Thread @ Pickup current thread ptr address
1798 LDR r3,[r1, #0] @ Pickup current thread pointer
1799 CMP r3,#0 @ Check to see if it is non-NULL
1800 BEQ TCT_Skip_Unprot_Spec @ If NULL, skip unprotect specific
1801
1802 @ Lockout interrupts.
1803
1804 MRS r1,CPSR @ Pickup current CPSR
1805 ORR r1,r1,#LOCKOUT @ Place lockout value in
1806 MSR CPSR,r1 @ Lockout interrupts
1807
1808 @ Clear the protection pointer.
1809 @ protect -> tc_tcb_pointer = NU_NULL;
1810
1811 MOV r2,#0 @ Build NU_NULL value
1812 STR r2,[r0, #0] @ Clear protection ownership
1813
1814 @ Determine if a thread is waiting.
1815 @ if (protect -> tc_thread_waiting)
1816 @ {
1817
1818 LDR r1,[r0, #4] @ Pickup the waiting field
1819 CMP r1,#0 @ Is there another thread waiting?
1820 BEQ TCT_Not_Waiting_Unspec @ No, restore interrupts and return
1821
1822 @ A higher-priority thread is waiting.
1823
1824 @ Save a minimal context of the thread.
1825
1826 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
1827 @ the current stack
1828
1829 #if 1 /* was .if THUMB */
1830 MOV r2,r14 @ Determine what state the caller
1831 MOV r2,r2,LSL #31 @ was in and build an
1832 MOV r2,r2,LSR #26 @ appropriate state mask
1833 STR r2,[r13, #-4]! @ Place it on the stack
1834 #endif
1835
1836 MOV r2,#0 @ Build solicited stack type value
1837 @ and NU_NULL value
1838 STR r2,[r13, #-4]! @ Place it on the top of the stack
1839
1840 @ Setup a pointer to the thread control block.
1841 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1842
1843 LDR r1,Current_Thread @ Pickup current thread ptr address
1844 LDR r0,[r1, #0] @ Pickup current thread pointer
1845
1846 @ Clear the current thread control block pointer.
1847 @ TCD_Current_Thread = NU_NULL;
1848
1849 LDR r3,Slice_State @ Pickup time slice state address
1850 STR r2,[r1, #0] @ Set current thread pointer to
1851 @ NU_NULL
1852
1853 @ Check to see if a time slice is active. If so, copy the
1854 @ original time slice into the current time slice field of the
1855 @ thread's control block.
1856 @ if (TMD_Time_Slice_State == 0)
1857 @ {
1858
1859 LDR r1,[r3, #0] @ Pickup time slice state flag
1860 CMP r1,#0 @ Compare with active value
1861 BNE TCT_No_Stop_TS_3 @ If non-active, don't disable
1862
1863 @ Insure that the next time the task runs it gets a fresh time
1864 @ slice.
1865 @ REG_Thread_Ptr -> tc_cur_time_slice =
1866 @ REG_Thread_Ptr -> tc_time_slice;
1867
1868 LDR r1,[r0, #0x40] @ Pickup original time slice
1869
1870 @ Clear any active time slice by setting the state to
1871 @ NOT_ACTIVE.
1872 @ TMD_Time_Slice_State = 1;
1873
1874 MOV r2,#1 @ Build disable value
1875 STR r2,[r3, #0] @ Disable time slice
1876 STR r1,[r0, #0x20] @ Reset current time slice
1877 @ }
1878
1879 TCT_No_Stop_TS_3:
1880
1881 @ Save off the current stack pointer in the control block.
1882 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
1883
1884 STR r13,[r0, #0x2c] @ Save the thread's stack pointer
1885
1886 @ Switch to the system stack.
1887 @ REG_Stack_Ptr = TCD_System_Stack;
1888
1889 LDR r1,System_Stack @ Pickup address of stack pointer
1890 LDR r2,System_Limit @ Pickup address of stack limit ptr
1891 LDR r13,[r1, #0] @ Switch to system stack
1892 LDR r10,[r2, #0] @ Setup system stack limit
1893
1894 @ Finished, return to the scheduling loop.
1895
1896 B TCT_Schedule @ Return to scheduling loop
1897
1898 @ }
1899 @ else
1900 @ {
1901 TCT_Not_Waiting_Unspec:
1902
1903 @ No higher-priority thread is waiting.
1904
1905 @ Restore interrupts.
1906
1907 LDR r2,Int_Level @ Pickup address of interrupt level
1908 MRS r1,CPSR @ Pickup current CPSR
1909 LDR r3,[r2, #0] @ Pickup interrupt lockout level
1910 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
1911 ORR r1,r1,r3 @ Build new interrupt lockout
1912 MSR CPSR,r1 @ Setup CPSR appropriately
1913
1914 @ }
1915 @ }
1916
1917 TCT_Skip_Unprot_Spec:
1918
1919 BX r14 @ Return to caller
1920
1921 @}
1922
1923 /*
1924 ************************************************************************
1925 *
1926 * FUNCTION
1927 *
1928 * TCT_Set_Current_Protect
1929 *
1930 * DESCRIPTION
1931 *
1932 * This function sets the current protection field of the current
1933 * thread's control block to the specified protection pointer.
1934 *
1935 * CALLED BY
1936 *
1937 * TCC_Resume_Task Resume task function
1938 *
1939 * CALLS
1940 *
1941 * None
1942 *
1943 * INPUTS
1944 *
1945 * protect Pointer to protection block
1946 *
1947 * OUTPUTS
1948 *
1949 * None
1950 *
1951 * HISTORY
1952 *
1953 * NAME DATE REMARKS
1954 *
1955 * W. Lamie 02-15-1994 Created initial version 1.0
1956 * D. Lamie 02-15-1994 Verified version 1.0
1957 *
1958 ************************************************************************
1959 */
1960
1961 @VOID TCT_Set_Current_Protect(TC_PROTECT *protect)
1962 @{
1963
1964 .globl TCT_Set_Current_Protect
1965 TCT_Set_Current_Protect:
1966
1967 @ Determine if the caller is in a task or HISR thread.
1968 @ if (TCD_Current_Thread)
1969 @ {
1970
1971 LDR r1,Current_Thread @ Pickup current thread ptr address
1972 LDR r3,[r1, #0] @ Pickup current thread pointer
1973 CMP r3,#0 @ Check to see if a thread is
1974 @ active
1975
1976 @ Point at the current thread control block.
1977 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
1978
1979 @ Modify the current protection.
1980 @ REG_Thread_Ptr -> tc_current_protect = protect;
1981
1982 STRNE r0,[r3, #0x38] @ Setup new protection
1983 @ }
1984
1985
1986 BX r14 @ Return to caller
1987
1988 @}
1989
1990 /*
1991 ************************************************************************
1992 *
1993 * FUNCTION
1994 *
1995 * TCT_Protect_Switch
1996 *
1997 * DESCRIPTION
1998 *
1999 * This function waits until a specific task no longer has any
2000 * protection associated with it. This is necessary since task's
2001 * cannot be suspended or terminated unless they have released all
2002 * of their protection.
2003 *
2004 * CALLED BY
2005 *
2006 * System Components
2007 *
2008 * CALLS
2009 *
2010 * None
2011 *
2012 * INPUTS
2013 *
2014 * thread Pointer to thread control blk
2015 *
2016 * OUTPUTS
2017 *
2018 * None
2019 *
2020 * HISTORY
2021 *
2022 * NAME DATE REMARKS
2023 *
2024 * W. Lamie 02-15-1994 Created initial version 1.0
2025 * D. Lamie 02-15-1994 Verified version 1.0
2026 *
2027 ************************************************************************
2028 */
2029
2030 @VOID TCT_Protect_Switch(VOID *thread)
2031 @{
2032
2033 .globl TCT_Protect_Switch
2034 TCT_Protect_Switch:
2035
2036 @ Lockout interrupts.
2037
2038 MRS r1,CPSR @ Pickup current CPSR
2039 ORR r1,r1,#LOCKOUT @ Place lockout value in
2040 MSR CPSR,r1 @ Lockout interrupts
2041
2042 @ REG_Thread_Ptr = (TC_TCB *) thread;
2043
2044 @ Wait until the specified task has no protection associated with it.
2045 @ while (REG_Thread_Ptr -> tc_current_protect)
2046 @ {
2047
2048 LDR r1,[r0, #0x38] @ Pickup protection of specified
2049 @ thread
2050 CMP r1,#0 @ Does the specified thread have
2051 @ an active protection?
2052 BEQ TCT_Switch_Done @ If not, protect switch is done
2053
2054 @ Let the task run again in an attempt to clear its protection.
2055
2056 @ Indicate that a higher priority thread is waiting.
2057 @ (REG_Thread_Ptr -> tc_current_protect) -> tc_thread_waiting = 1;
2058
2059 MOV r2,#1 @ Build waiting flag value
2060 STR r2,[r1, #4] @ Set waiting flag of the
2061 @ protection owned by the other
2062 @ thread
2063
2064 @ Directly schedule the thread waiting.
2065 @ TCT_Schedule_Protected((REG_Thread_Ptr -> tc_current_protect)
2066 @ -> tc_tcb_pointer);
2067
2068 LDR r2,Current_Thread @ Pickup current thread ptr address
2069 STR r0,[r13, #-4]! @ Save r0 on the stack
2070 STR r14,[r13, #-4]! @ Save r14 on the stack
2071 MOV r1,r0 @ Move new thread into r1
2072 LDR r0,[r2, #0] @ Pickup current thread pointer
2073 BL TCT_Schedule_Protected @ Call routine to schedule the
2074 @ owner of the thread
2075
2076 LDR r14,[r13], #4 @ Recover saved r14
2077 LDR r0,[r13], #4 @ Recover saved r0
2078
2079 @ Lockout interrupts.
2080
2081 B TCT_Protect_Switch @ Branch to top of routine and
2082 @ start over
2083 @ }
2084 TCT_Switch_Done:
2085
2086 @ Restore interrupts.
2087
2088 LDR r2,Int_Level @ Pickup address of interrupt level
2089 MRS r1,CPSR @ Pickup current CPSR
2090 LDR r3,[r2, #0] @ Pickup interrupt lockout level
2091 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
2092 ORR r1,r1,r3 @ Build new interrupt lockout
2093 MSR CPSR,r1 @ Setup CPSR appropriately
2094
2095
2096 BX r14 @ Return to caller
2097
2098 @}
2099
2100 /*
2101 ************************************************************************
2102 *
2103 * FUNCTION
2104 *
2105 * TCT_Schedule_Protected
2106 *
2107 * DESCRIPTION
2108 *
2109 * This function saves the minimal context of the thread and then
2110 * directly schedules the thread that has protection over the
2111 * the thread that called this routine.
2112 *
2113 * CALLED BY
2114 *
2115 * TCT_Protect
2116 * TCT_Protect_Switch
2117 *
2118 * CALLS
2119 *
2120 * TCT_Control_To_Thread Transfer control to protected
2121 * thread
2122 *
2123 * INPUTS
2124 *
2125 * None
2126 *
2127 * OUTPUTS
2128 *
2129 * None
2130 *
2131 * HISTORY
2132 *
2133 * NAME DATE REMARKS
2134 *
2135 * W. Lamie 02-15-1994 Created initial version 1.0
2136 * D. Lamie 02-15-1994 Verified version 1.0
2137 * C. Meredith 03-01-1994 Corrected problem in time-slice
2138 * reset logic, resulting in
2139 * version 1.1
2140 * D. Lamie 03-18-1994 Verified version 1.1
2141 *
2142 ************************************************************************
2143 */
2144
2145 @VOID TCT_Schedule_Protected(VOID *thread)
2146 @{
2147
2148 .globl TCT_Schedule_Protected
2149 TCT_Schedule_Protected:
2150
2151 @ Interrupts are already locked out by the caller.
2152
2153 @ Save minimal context required by the system.
2154
2155 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
2156 @ the current stack
2157
2158 #if 1 /* was .if THUMB */
2159 MOV r2,r14 @ Determine what state the caller
2160 MOV r2,r2,LSL #31 @ was in and build an
2161 MOV r2,r2,LSR #26 @ appropriate state mask
2162 STR r2,[r13, #-4]! @ Place it on the stack
2163 #endif
2164
2165 MOV r2,#0 @ Build solicited stack type value
2166 @ and NU_NULL value
2167 STR r2,[r13, #-4]! @ Place it on the top of the stack
2168 MOV r4,r1 @ Save thread to schedule
2169
2170 @ Setup a pointer to the thread control block.
2171 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
2172
2173 LDR r1,Current_Thread @ Pickup current thread ptr address
2174
2175 @ Clear the current thread control block.
2176 @ TCD_Current_Thread = NU_NULL;
2177
2178 LDR r3,Slice_State @ Pickup time slice state address
2179 STR r2,[r1, #0] @ Set current thread pointer to
2180 @ NU_NULL
2181
2182 @ Check to see if a time slice is active. If so, copy the original time
2183 @ slice into the current time slice field of the task's control block.
2184 @ if (TMD_Time_Slice_State == 0)
2185 @ {
2186
2187 LDR r1,[r3, #0] @ Pickup time slice state flag
2188 CMP r1,#0 @ Compare with active value
2189 BNE TCT_No_Stop_TS_4 @ If non-active, don't disable
2190
2191 @ Insure that the next time the task runs it gets a fresh time
2192 @ slice.
2193 @ REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
2194
2195 LDR r1,[r0, #0x40] @ Pickup original time slice
2196
2197 @ Clear any active time slice by setting the state to NOT_ACTIVE.
2198 @ TMD_Time_Slice_State = 1;
2199
2200 MOV r2,#1 @ Build disable value
2201 STR r2,[r3, #0] @ Disable time slice
2202 STR r1,[r0, #0x20] @ Reset current time slice
2203
2204 @ }
2205 TCT_No_Stop_TS_4:
2206
2207 @ Save off the current stack pointer in the control block.
2208 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
2209
2210 STR r13,[r0, #0x2c] @ Save the thread's stack pointer
2211
2212 @ Switch to the system stack.
2213 @ TCD_System_Stack = (VOID *) REG_Stack_Ptr;
2214
2215 LDR r1,System_Stack @ Pickup address of stack pointer
2216 LDR r2,System_Limit @ Pickup address of stack limit ptr
2217 LDR r13,[r1, #0] @ Switch to system stack
2218 LDR r10,[r2, #0] @ Setup system stack limit
2219
2220 @ Transfer control to the specified thread directly.
2221 @ TCT_Control_To_Thread(thread);
2222
2223 LDR r2,Int_Level @ Pickup address of interrupt level
2224 MRS r1,CPSR @ Pickup current CPSR
2225 LDR r3,[r2, #0] @ Pickup interrupt lockout level
2226 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
2227 ORR r1,r1,r3 @ Build new interrupt lockout
2228 MOV r0,r4 @ Indicate thread to schedule
2229 MSR CPSR,r1 @ Setup CPSR appropriately
2230 ORR r1,r1,#LOCKOUT @ Build lockout value again
2231 MSR CPSR,r1 @ Lockout interrupts again
2232 B TCT_Control_To_Thread @ Schedule the thread indirectly
2233 @}
2234
2235 /*
2236 ************************************************************************
2237 *
2238 * FUNCTION
2239 *
2240 * TCT_Interrupt_Context_Save
2241 *
2242 * DESCRIPTION
2243 *
2244 * This function saves the interrupted thread's context. Nested
2245 * interrupts are also supported. If a task or HISR thread was
2246 * interrupted, the stack pointer is switched to the system stack
2247 * after the context is saved.
2248 *
2249 * CALLED BY
2250 *
2251 * Application ISRs Assembly language ISRs
2252 * INT_Interrupt_Shell Interrupt handler shell
2253 *
2254 * CALLS
2255 *
2256 * None
2257 *
2258 * INPUTS
2259 *
2260 * vector Interrupt's vector number
2261 *
2262 * OUTPUTS
2263 *
2264 * None
2265 *
2266 * HISTORY
2267 *
2268 * NAME DATE REMARKS
2269 *
2270 * W. Lamie 02-15-1994 Created initial version 1.0
2271 * D. Lamie 02-15-1994 Verified version 1.0
2272 * D. Driscoll 01-04-2002 Released version 1.13.3.
2273 * Updated to handle nested /
2274 * prioritized IRQs
2275 ************************************************************************
2276 */
2277
2278 @VOID TCT_Interrupt_Context_Save(INT vector)
2279 @{
2280
2281 .globl TCT_Interrupt_Context_Save
2282 TCT_Interrupt_Context_Save:
2283 @ Determine if this is a nested interrupt.
2284 LDR r1,Int_Count @ Pickup address of interrupt count
2285 LDR r2,[r1, #0] @ Pickup interrupt counter
2286 ADD r2,r2,#1 @ Add 1 to interrupt counter
2287 STR r2,[r1, #0] @ Store new interrupt counter value
2288 CMP r2,#1 @ Is it nested?
2289 BEQ TCT_Not_Nested_Save @ No
2290
2291 @ Nested interrupt. Save complete context on the current stack.
2292 TCT_Nested_Save:
2293
2294 @ 1. Save another register on the exception stack so we have enough to work with
2295 STMDB r13!,{r5}
2296
2297 @ 2. Save the necessary exception registers into r1-r3
2298 MOV r1,r13 @ Put the exception r13 into r1
2299 MOV r2,r14 @ Move the return address for the caller
2300 @ of this function into r2
2301 MRS r3,spsr @ Put the exception spsr into r3
2302
2303 @ 3. Adjust the exception stack pointer for future exceptions
2304 ADD r13,r13,#24 @ r13 will point to enable reg value when done
2305
2306 @ 4. Switch CPU modes to save context on system stack
2307 MRS r5,CPSR @ Pickup the current CPSR
2308 BIC r5,r5,#MODE_MASK @ Clear the mode bits
2309
2310 ORR r5,r5,#SUP_MODE @ Change to supervisor mode (SVD)
2311
2312 MSR CPSR,r5 @ Switch modes (IRQ->SVC)
2313
2314 @ 5. Store the SVC r13 into r5 so the r13 can be saved as is.
2315 MOV r5,r13
2316
2317 @ 6. Save the exception return address on the stack (r15).
2318 STMDB r5!,{r4}
2319
2320 @ 7. Save r6-r14 on stack
2321 STMDB r5!,{r6-r14}
2322
2323 @ 8. Switch back to using r13 now that the original r13 has been saved.
2324 MOV r13,r5
2325
2326 @ 9. Get r5 and exception enable registers off of exception stack and
2327 @ save r5 (stored in r4) back to the system stack.
2328 LDMIA r1!,{r4-r5}
2329 STMDB r13!,{r4}
2330 MOV r4,r5 @ Put exception enable value into r4
2331
2332 @ 10. Get the rest of the registers off the exception stack and
2333 @ save them onto the system stack.
2334 LDMIA r1!,{r5-r8,r11} @ Get r0-r4 off exception stack
2335 STMDB r13!,{r5-r8,r11} @ Put r0-r4 on system stack
2336
2337 @ 11. Store the exception enable value back on the exception stack.
2338 STMDB r1,{r4}
2339
2340 @ 12. Save the SPSR on the system stack (CPSR)
2341 STMDB r13!,{r3}
2342
2343 @ 13. Re-enable interrupts
2344 MRS r1,CPSR
2345 BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT)
2346 MSR CPSR,r1
2347
2348 BX r2 @ Return to calling ISR
2349 @ }
2350 @ else
2351 @ {
2352 TCT_Not_Nested_Save:
2353
2354 @ Determine if a thread was interrupted.
2355 @ if (TCD_Current_Thread)
2356 @ {
2357
2358 LDR r1,Current_Thread @ Pickup current thread ptr address
2359 LDR r1,[r1, #0] @ Pickup the current thread pointer
2360 CMP r1,#0 @ Is it NU_NULL?
2361 BEQ TCT_Idle_Context_Save @ If no, no real save is necessary
2362
2363
2364 @ Yes, a thread was interrupted. Save complete context on the
2365 @ thread's stack.
2366
2367 @ 1. Save another register on the exception stack so we have enough to work with
2368 STMDB r13!,{r5}
2369
2370 @ 2. Save the necessary exception registers into r1-r3
2371 MOV r1,r13 @ Put the exception r13 into r1
2372 MOV r2,r14 @ Move the return address for the caller
2373 @ of this function into r2
2374 MRS r3,spsr @ Put the exception spsr into r3
2375
2376 @ 3. Adjust the exception stack pointer for future exceptions
2377 ADD r13,r13,#24 @ r13 will point to enable reg value when done
2378
2379 @ 4. Switch CPU modes to save context on system stack
2380 MRS r5,CPSR @ Pickup the current CPSR
2381 BIC r5,r5,#MODE_MASK @ Clear the mode bits
2382
2383 ORR r5,r5,#SUP_MODE @ Change to supervisor mode (SVD)
2384
2385 MSR CPSR,r5 @ Switch modes (IRQ->SVC)
2386
2387 @ 5. Store the SVC r13 into r5 so the r13 can be saved as is.
2388 MOV r5,r13
2389
2390 @ 6. Save the exception return address on the stack (r15).
2391 STMDB r5!,{r4}
2392
2393 @ 7. Save r6-r14 on stack
2394 STMDB r5!,{r6-r14}
2395
2396 @ 8. Switch back to using r13 now that the original r13 has been saved.
2397 MOV r13,r5
2398
2399 @ 9. Get r5 and exception enable registers off of exception stack and
2400 @ save r5 (stored in r4) back to the system stack.
2401 LDMIA r1!,{r4-r5}
2402 STMDB r13!,{r4}
2403 MOV r4,r5 @ Put exception enable value into r4
2404
2405 @ 10. Get the rest of the registers off the exception stack and
2406 @ save them onto the system stack.
2407 LDMIA r1!,{r5-r8,r11} @ Get r0-r4 off exception stack
2408 STMDB r13!,{r5-r8,r11} @ Put r0-r4 on system stack
2409
2410 @ 11. Store the exception enable value back on the exception stack.
2411 STMDB r1,{r4}
2412
2413 @ 12. Save the SPSR on the system stack (CPSR)
2414 STMDB r13!,{r3}
2415
2416 @ 13. Save stack type to the task stack (1=interrupt stack)
2417 MOV r1,#1 @ Interrupt stack type
2418 STMDB r13!,{r1}
2419
2420 @ Save the thread's stack pointer in the control block.
2421 @ REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread
2422 @ REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr
2423
2424 LDR r1,Current_Thread @ Pickup current thread ptr address
2425 LDR r3,[r1, #0] @ Pickup current thread pointer
2426 STR r13,[r3, #TC_STACK_POINTER] @ Save stack pointer
2427
2428 @ Switch to the system stack.
2429 @ REG_Stack_Ptr = TCD_System_Stack
2430
2431 LDR r1,System_Stack @ Pickup address of stack pointer
2432 LDR r3,System_Limit @ Pickup address of stack limit ptr
2433 LDR r13,[r1, #0] @ Switch to system stack
2434 LDR r10,[r3, #0] @ Setup system stack limit
2435
2436 @ Re-enable interrupts
2437 MRS r1,CPSR
2438 BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT)
2439 MSR CPSR,r1
2440
2441 @ Return to caller ISR.
2442
2443 BX r2 @ Return to caller ISR
2444
2445 @ }
2446
2447 TCT_Idle_Context_Save:
2448
2449 MOV r2,r14 @ Save r14 in r2
2450 LDR r3,[r13] @ Get exception enable value from stack
2451 ADD r13,r13,#20 @ Adjust exception r13 for future interrupts
2452 STR r3,[r13] @ Put exception enable value back on stack
2453
2454 MRS r1,CPSR @ Pickup current CPSR
2455 BIC r1,r1,#MODE_MASK @ Clear the current mode
2456 BIC r1,r1,#(IRQ_BIT_OR_FIQ_BIT) @ Re-enable interrupts
2457
2458 ORR r1,r1,#SUP_MODE @ Prepare to switch to supervisor
2459 @ mode (SVC)
2460 MSR CPSR,r1 @ Switch to supervisor mode (SVC)
2461
2462 BX r2 @ Return to caller ISR
2463
2464 @ }
2465 @}
2466
2467 /*
2468 ************************************************************************
2469 *
2470 * FUNCTION
2471 *
2472 * TCT_Interrupt_Context_Restore
2473 *
2474 * DESCRIPTION
2475 *
2476 * This function restores the interrupt context if a nested
2477 * interrupt condition is present. Otherwise, this routine
2478 * transfers control to the scheduling function.
2479 *
2480 * CALLED BY
2481 *
2482 * Application ISRs Assembly language ISRs
2483 * INT_Interrupt_Shell Interrupt handler shell
2484 *
2485 * CALLS
2486 *
2487 * TCT_Schedule Thread scheduling function
2488 *
2489 * INPUTS
2490 *
2491 * None
2492 *
2493 * OUTPUTS
2494 *
2495 * None
2496 *
2497 * HISTORY
2498 *
2499 * NAME DATE REMARKS
2500 *
2501 * W. Lamie 02-15-1994 Created initial version 1.0
2502 * D. Lamie 02-15-1994 Verified version 1.0
2503 * D. Driscoll 01-04-2002 Released version 1.13.3.
2504 * Updated to handle nested /
2505 * prioritized IRQs
2506 *
2507 ************************************************************************
2508 */
2509
2510 @VOID TCT_Interrupt_Context_Restore(void)
2511 @{
2512
2513 .globl TCT_Interrupt_Context_Restore
2514 TCT_Interrupt_Context_Restore:
2515 @ It is assumed that anything pushed on the stack by ISRs has been
2516 @ removed upon entry into this routine.
2517
2518 @ Decrement and check for nested interrupt conditions.
2519 @ if (--TCD_Interrupt_Count)
2520 @ {
2521
2522 LDR r1,Int_Count @ Pickup address of interrupt count
2523 LDR r2,[r1, #0] @ Pickup interrupt counter
2524 SUB r2,r2,#1 @ Decrement interrupt counter
2525 STR r2,[r1, #0] @ Store interrupt counter
2526 CMP r2,#0
2527 BEQ TCT_Not_Nested_Restore
2528
2529 @ Restore previous context.
2530
2531 LDR r1,[r13], #4 @ Pickup the saved CPSR
2532
2533 MSR SPSR,r1 @ Place into saved SPSR
2534 LDMIA r13,{r0-r15}^ @ Return to the point of interrupt
2535
2536 @ }
2537 @ else
2538 @ {
2539
2540 TCT_Not_Nested_Restore:
2541
2542 @ Determine if a thread is active.
2543 @ if (TCD_Current_Thread)
2544 @ {
2545
2546 LDR r1,Current_Thread @ Pickup current thread ptr address
2547 LDR r0,[r1, #0] @ Pickup current thread pointer
2548 CMP r0,#0 @ Determine if a thread is active
2549 BEQ TCT_Idle_Context_Restore @ If not, idle system restore
2550
2551 @ Clear the current thread pointer.
2552 @ TCD_Current_Thread = NU_NULL
2553
2554 MOV r2,#0 @ Build NU_NULL value
2555 STR r2,[r1, #0] @ Set current thread ptr to NU_NULL
2556
2557 @ Determine if a time slice is active. If so, the remaining
2558 @ time left on the time slice must be saved in the task's
2559 @ control block.
2560 @ if (TMD_Time_Slice_State == 0)
2561 @ {
2562
2563 LDR r3,Slice_State @ Pickup time slice state address
2564 LDR r1,[r3, #0] @ Pickup time slice state
2565 CMP r1,#0 @ Determine if time slice active
2566 BNE TCT_Idle_Context_Restore @ If not, skip time slice reset
2567
2568 @ Pickup the remaining portion of the time slice and save it
2569 @ in the task's control block.
2570 @ REG_Thread_Ptr -> tc_cur_time_slice = TMD_Time_Slice
2571 @ TMD_Time_Slice_State = 1
2572
2573 LDR r2,Time_Slice @ Pickup address of time slice left
2574 MOV r1,#1 @ Build disable time slice value
2575 LDR r2,[r2, #0] @ Pickup remaining time slice
2576 STR r1,[r3, #0] @ Disable time slice
2577 STR r2,[r0, #TC_CUR_TIME_SLICE] @ Store remaining time slice
2578
2579 @ }
2580 @ }
2581 TCT_Idle_Context_Restore:
2582
2583 @ Reset the system stack pointer.
2584 LDR r1,System_Stack @ Pickup address of stack pointer
2585 LDR r2,System_Limit @ Pickup address of stack limit ptr
2586 LDR r13,[r1, #0] @ Switch to system stack
2587 LDR r10,[r2, #0] @ Setup system stack limit
2588
2589 @ Return to scheduler.
2590
2591 B TCT_Schedule @ Return to scheduling loop
2592
2593 @ }
2594 @}
2595
2596 /*
2597 ************************************************************************
2598 *
2599 * FUNCTION
2600 *
2601 * TCT_Activate_HISR
2602 *
2603 * DESCRIPTION
2604 *
2605 * This function activates the specified HISR. If the HISR is
2606 * already activated, the HISR's activation count is simply
2607 * incremented. Otherwise, the HISR is placed on the appropriate
2608 * HISR priority list in preparation for execution.
2609 *
2610 * CALLED BY
2611 *
2612 * Application LISRs
2613 *
2614 * CALLS
2615 *
2616 * None
2617 *
2618 * INPUTS
2619 *
2620 * hisr Pointer to HISR to activate
2621 *
2622 * OUTPUTS
2623 *
2624 * NU_SUCCESS Successful completion
2625 *
2626 * HISTORY
2627 *
2628 * NAME DATE REMARKS
2629 *
2630 * W. Lamie 02-15-1994 Created initial version 1.0
2631 * D. Lamie 02-15-1994 Verified version 1.0
2632 *
2633 ************************************************************************
2634 */
2635
2636 @STATUS TCT_Activate_HISR(TC_HCB *hisr)
2637 @{
2638
2639 .globl TCT_Activate_HISR
2640 TCT_Activate_HISR:
2641
2642 @INT priority;
2643
2644
2645 @ Lockout interrupts.
2646
2647 STR r4,[r13, #-4]! @ Save r4
2648 MRS r4,CPSR @ Pickup current CPSR
2649 ORR r1,r4,#LOCKOUT @ Build interrupt lockout value
2650 MSR CPSR,r1 @ Lockout interrupts
2651
2652 @ Determine if the HISR is already active.
2653 @ if (hisr -> tc_activation_count)
2654 @ {
2655
2656 LDR r1,[r0,#0x40] @ Pickup current activation count
2657 CMP r1,#0 @ Is it the first activation?
2658 BEQ TCT_First_Activate @ Yes, place it on the correct list
2659
2660 @ Increment the activation count. Make sure that it does not go
2661 @ to zero.
2662 @ hisr -> tc_activation_count++;
2663
2664 ADDS r1,r1,#1 @ Increment the activation count
2665 STR r1,[r0,#0x40] @ Store new activation count
2666
2667 @ if (hisr -> tc_activation_count == 0)
2668
2669 @ hisr -> tc_activation_count = 0xFFFFFFFFUL;
2670
2671 MVNEQ r1,#0 @ If counter rolled-over reset
2672 STREQ r1,[r0,#0x40] @ Store all ones count
2673 B TCT_Activate_Done @ Finished with activation
2674 @ }
2675 @ else
2676 @ {
2677 TCT_First_Activate:
2678
2679
2680 @ Set the activation count to 1.
2681 @ hisr -> tc_activation_count = 1;
2682
2683 MOV r1,#1 @ Initial activation count
2684 STR r1,[r0,#0x40] @ Store initial activation count
2685
2686 @ Pickup the HISR's priority.
2687 @ priority = hisr -> tc_priority;
2688
2689 @ Determine if there is something in the given priority list.
2690 @ if (TCD_Active_HISR_Tails[priority])
2691 @ {
2692
2693 LDRB r1,[r0,#0x1a] @ Pickup priority of HISR
2694 LDR r2,HISR_Tails @ Pickup tail pointer base
2695 LDR r3,[r2,r1,LSL #2] @ Pickup tail pointer for priority
2696 CMP r3,#0 @ Is this first HISR at priority?
2697 BEQ TCT_First_HISR @ No, append to end of HISR list
2698
2699 @ Something is already on this list. Add after the tail.
2700 @ (TCD_Active_HISR_Tails[priority]) -> tc_active_next = hisr;
2701 @ TCD_Active_HISR_Tails[priority] = hisr;
2702
2703 STR r0,[r3,#0x3c] @ Setup the active next pointer
2704 STR r0,[r2,r1,LSL #2] @ Setup the tail pointer
2705 B TCT_Activate_Done @ Finished with activate processing
2706 @ }
2707 @ else
2708 @ {
2709 TCT_First_HISR:
2710
2711 @ Nothing is on this list.
2712 @ TCD_Active_HISR_Heads[priority] = hisr;
2713 @ TCD_Active_HISR_Tails[priority] = hisr;
2714
2715 LDR r3,HISR_Heads @ Pickup address of head pointers
2716 STR r0,[r2,r1,LSL #2] @ Set tail pointer to this HISR
2717 STR r0,[r3,r1,LSL #2] @ Set head pointer to this HISR
2718
2719 @ Determine the highest priority HISR.
2720 @ if (TCD_Active_HISR_Heads[0])
2721 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[0];
2722 @ else if (TCD_Active_HISR_Heads[1])
2723 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[1];
2724 @ else
2725 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[2];
2726
2727 LDR r1,[r3,#0] @ Pickup priority 0 head pointer
2728 LDR r0,Execute_HISR @ Build address to execute HISR ptr
2729 CMP r1,#0 @ Is priority 0 active?
2730 LDREQ r1,[r3,#4] @ If not, pickup priority 1 head
2731 CMPEQ r1,#0 @ Is priority 1 active?
2732 LDREQ r1,[r3,#8] @ Else, must be priority 2 active
2733 STR r1,[r0,#0] @ Store which ever priority is the
2734 @ active one
2735 @ }
2736 @ }
2737 TCT_Activate_Done:
2738
2739 MSR CPSR,r4 @ Restore interrupt lockout
2740 LDR r4,[r13], #4 @ Restore corrupted r4
2741
2742 @ return(NU_SUCCESS);
2743
2744 MOV r0,#0 @ Always return NU_SUCCESS
2745
2746 BX r14 @ Return to caller
2747
2748 @}
2749
2750 /*
2751 ************************************************************************
2752 *
2753 * FUNCTION
2754 *
2755 * TCT_HISR_Shell
2756 *
2757 * DESCRIPTION
2758 *
2759 * This function is the execution shell of each and every HISR. If
2760 * the HISR has completed its processing, this shell routine exits
2761 * back to the system. Otherwise, it sequentially calls the HISR
2762 * routine until the activation count goes to zero.
2763 *
2764 * CALLED BY
2765 *
2766 * HISR Scheduling
2767 *
2768 * CALLS
2769 *
2770 * hisr -> tc_entry Actual entry function of HISR
2771 *
2772 * INPUTS
2773 *
2774 * None
2775 *
2776 * OUTPUTS
2777 *
2778 * None
2779 *
2780 * HISTORY
2781 *
2782 * NAME DATE REMARKS
2783 *
2784 * W. Lamie 02-15-1994 Created initial version 1.0
2785 * D. Lamie 02-15-1994 Verified version 1.0
2786 *
2787 ************************************************************************
2788 */
2789
2790 @VOID TCT_HISR_Shell(void)
2791 @{
2792 .globl TCT_HISR_Shell
2793 TCT_HISR_Shell:
2794
2795 @ Point at the HISR.
2796 @ REG_HISR_Ptr = (TC_HCB *) TCD_Current_Thread;
2797
2798 LDR r0,Current_Thread @ Build address of thread pointer
2799 LDR r5,[r0, #0] @ Pickup control block pointer
2800
2801 @ do
2802 @ {
2803 TCT_HISR_Loop:
2804
2805 @ Call the HISR's entry routine.
2806 @ (*(REG_HISR_Ptr -> tc_entry)) ();
2807
2808 /* old TMS470 code:
2809
2810 .if THUMB = 0
2811
2812 MOV r14,r15 ; Setup return value
2813 LDR r15,[r5,#44h] ; Call HISR entry function
2814 .else
2815 LDR r4,[r5,#44h] ; Get HISR entry function
2816 TST r4,#1 ; See if calling Thumb or ARM
2817 BNE Thumbsec
2818 MOV r14,r15 ; Setup return value
2819 BX r4
2820 B ARMCODE
2821 Thumbsec:
2822 ADD r14, r15, #1
2823 BX r4
2824 .state16
2825 ThumbAfterHisr
2826 MOV r1, r15
2827 BX r1
2828 .state32
2829 .endif
2830 */
2831
2832 /* new code for the GNU style of ARM/Thumb interworking */
2833 ldr r4, [r5, #TC_HISR_ENTRY]
2834 mov lr, pc
2835 bx r4
2836
2837 @ Lockout interrupts.
2838
2839 MRS r1,CPSR @ Pickup current CPSR
2840 ORR r1,r1,#LOCKOUT @ Build interrupt lockout
2841 MSR CPSR,r1 @ Lockout interrupts
2842
2843 @ On return, decrement the activation count and check to see if
2844 @ it is 0. Once it reaches 0, the HISR should be made inactive.
2845 @ REG_HISR_Ptr -> tc_activation_count--;
2846
2847
2848 LDR r0,[r5, #0x40] @ Pickup current activation count
2849 SUBS r0,r0,#1 @ Subtract and set condition codes
2850 STR r0,[r5, #0x40] @ Store new activation count
2851 BEQ TCT_HISR_Finished @ Finished processing HISR
2852
2853 @ Restore interrupts.
2854
2855 LDR r2,Int_Level @ Pickup address of interrupt level
2856 MRS r1,CPSR @ Pickup current CPSR
2857 LDR r3,[r2, #0] @ Pickup interrupt lockout level
2858 BIC r1,r1,#LOCK_MSK @ Clear lockout bits
2859 ORR r1,r1,r3 @ Build new interrupt lockout
2860 MSR CPSR,r1 @ Setup CPSR appropriately
2861 B TCT_HISR_Loop @ Return to HISR loop
2862 @ }
2863 @ while (REG_HISR_Ptr -> tc_activation_count);
2864
2865 TCT_HISR_Finished:
2866
2867 @ At this point, the HISR needs to be made inactive.
2868
2869 @ Determine if this is the only HISR on the given priority list.
2870 @ if (REG_HISR_Ptr == TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority])
2871 @ {
2872
2873 LDR r14,HISR_Tails @ Pickup tail pointers address
2874 LDRB r3,[r5,#0x1a] @ Pickup priority
2875 LDR r6,[r14,r3,LSL #2] @ Pickup this priority tail pointer
2876 LDR r2,Execute_HISR @ Build address to execute HISR ptr
2877 MOV r12,#0 @ Clear r12
2878 LDR r1,HISR_Heads @ Pickup head pointers address
2879 CMP r6,r5 @ Is this priority tail the same as
2880 @ the current HISR?
2881 BNE TCT_More_HISRs @ If not, more HISRs at this
2882 @ priority
2883
2884 @ The only HISR on the list. Clean up the list and check for the
2885 @ highest priority HISR.
2886 @ TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] = NU_NULL;
2887 @ TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority] = NU_NULL;
2888
2889 STR r12,[r1,r3,LSL #2] @ Set head pointer to NU_NULL
2890 STR r12,[r14,r3,LSL #2] @ Set tail pointer to NU_NULL
2891
2892 @ Determine the highest priority HISR.
2893 @ if (TCD_Active_HISR_Heads[0])
2894 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[0];
2895 @ else if (TCD_Active_HISR_Heads[1])
2896 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[1];
2897 @ else
2898 @ TCD_Execute_HISR = TCD_Active_HISR_Heads[2];
2899
2900 LDR r3,[r1,#0] @ Pickup priority 0 head pointer
2901 CMP r3,#0 @ Is there an HISR active?
2902 LDREQ r3,[r1,#4] @ If not, pickup priority 1 pointer
2903 CMPEQ r3,#0 @ Is there an HISR active?
2904 LDREQ r3,[r1,#8] @ If not, pickup priority 2 pointer
2905 STR r3,[r2,#0] @ Setup execute HISR pointer
2906 B TCT_HISR_Exit @ Exit HISR processing
2907 @ }
2908 @ else
2909 @ {
2910
2911 TCT_More_HISRs:
2912
2913 @ Move the head pointer to the next HISR in the list.
2914 @ TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] =
2915 @ REG_HISR_Ptr -> tc_active_next;
2916
2917 @ Also set the TCD_Execute_HISR pointer.
2918 @ TCD_Execute_HISR = REG_HISR_Ptr -> tc_active_next;
2919
2920 LDR r14,[r5,#0x3c] @ Pickup next HISR to activate
2921 STR r14,[r1,r3,LSL #2] @ Setup new head pointer
2922 STR r14,[r2, #0] @ Setup execute HISR pointer
2923 @ }
2924
2925 TCT_HISR_Exit:
2926
2927 @ Build fake return to the top of this loop. The next time the HISR
2928 @ is activated, it will return to the top of this function.
2929
2930 LDR r14,HISR_Shell @ Pickup address of shell entry
2931 STMDB r13!,{r4-r12,r14} @ Save minimal context of thread on
2932 @ the current stack
2933 MOV r2,#0 @ Build solicited stack type value
2934 @ and NU_NULL value
2935 #if 1 /* was .if THUMB */
2936 STR r2,[r13, #-4]! @ Save state mask
2937 #endif
2938 STR r2,[r13, #-4]! @ Place it on the top of the stack
2939
2940 @ Clear the current thread control block.
2941 @ TCD_Current_Thread = NU_NULL;
2942
2943 LDR r1,Current_Thread @ Pickup current thread ptr address
2944 STR r2,[r1, #0] @ Set current thread pointer to
2945 @ NU_NULL
2946
2947 @ Save off the current stack pointer in the control block.
2948 @ REG_HISR_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
2949
2950
2951 STR r13,[r5, #0x2c] @ Save the thread's stack pointer
2952
2953
2954 @ Switch to the system stack.
2955 @ REG_Stack_Ptr = (BYTE_PTR) TCD_System_Stack;
2956
2957 LDR r1,System_Stack @ Pickup address of stack pointer
2958 LDR r2,System_Limit @ Pickup address of stack limit ptr
2959 LDR r13,[r1, #0] @ Switch to system stack
2960 LDR r10,[r2, #0] @ Setup system stack limit
2961
2962 @ Transfer control to the main scheduling loop.
2963
2964 B TCT_Schedule @ Return to main scheduling loop
2965 @}