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