FreeCalypso > hg > fc-tourmaline
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 |