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