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