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