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