www.pudn.com > os.rar > tct.s


;************************************************************************ 
;* 
;*               Copyright Mentor Graphics Corporation 2005 
;*                         All Rights Reserved. 
;* 
;* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS 
;* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS 
;* SUBJECT TO LICENSE TERMS. 
;* 
;************************************************************************ 
;************************************************************************ 
;* 
;* FILE NAME                                          VERSION                 
;*                 
;*   tct.s                       Nucleus PLUS\ARM926 DM320\Code Composer 1.15.1 
;* 
;*  COMPONENT 
;* 
;*      TC - Thread Control 
;* 
;*  DESCRIPTION 
;* 
;*      This file contains the target processor dependent routines for 
;*      performing target-dependent scheduling functions. 
;* 
;*  GLOBAL FUNCTIONS 
;* 
;*      ***************************** 
;*      * GENERIC FUNCTIONS         * 
;*      ***************************** 
;* 
;*      TCT_Control_Interrupts          Enable / disable interrupts 
;*      TCT_Local_Control_Interrupts    Local enable / disable ints 
;*      TCT_Restore_Interrupts          Restore global interrupts 
;*      TCT_Build_Task_Stack            Build initial task stack 
;*      TCT_Build_HISR_Stack            Build initial HISR stack 
;*      TCT_Build_Signal_Frame          Build signal handler frame 
;*      TCT_Check_Stack                 Check current stack 
;*      TCT_Schedule                    Schedule the next thread 
;*      TCT_Control_To_Thread           Transfer control to a thread 
;*      TCT_Control_To_System           Transfer control from thread 
;*      TCT_Signal_Exit                 Exit from signal handler 
;*      TCT_Current_Thread              Returns a pointer to current 
;*                                      thread 
;*      TCT_Set_Execute_Task            Sets TCD_Execute_Task under 
;*                                      protection from interrupts 
;*      TCT_Protect                     Protect critical section 
;*      TCT_Unprotect                   Unprotect critical section 
;*      TCT_Unprotect_Specific          Release specific protection 
;*      TCT_Set_Current_Protect         Set the thread's current 
;*                                      protection field 
;*      TCT_Protect_Switch              Switch to protected thread 
;*      TCT_Schedule_Protected          Schedule the protected thread 
;*      TCT_Interrupt_Context_Save      Save interrupted context 
;*      TCT_Interrupt_Context_Restore   Restore interrupted context 
;*      TCT_Activate_HISR               Activate a HISR 
;*      TCT_HISR_Shell                  HISR execution shell 
;* 
;*      ***************************** 
;*      * TARGET SPECIFIC FUNCTIONS * 
;*      ***************************** 
;* 
;*      None 
;* 
;*  LOCAL FUNCTIONS 
;* 
;*      None 
;* 
;************************************************************************ 
 
;********************************** 
;* INCLUDE ASSEMBLY CONSTANTS     * 
;********************************** 
 
    .include     asm_defs.inc 
 
;********************************** 
;* EXTERNAL VARIABLE DECLARATIONS * 
;********************************** 
 
;extern TC_TCB      *TCD_Execute_Task; 
;extern TC_HCB      *TCD_Execute_HISR; 
;extern VOID        *TCD_Current_Thread; 
;extern VOID        *TCD_System_Stack; 
;extern INT         TCD_Interrupt_Count; 
;extern TC_HCB      *TCD_Active_HISR_Heads[TC_HISR_PRIORITIES]; 
;extern TC_HCB      *TCD_Active_HISR_Tails[TC_HISR_PRIORITIES]; 
;extern INT         TCD_Interrupt_Level; 
;extern UNSIGNED    TMD_Time_Slice; 
;extern INT         TMD_Time_Slice_State; 
 
    .ref          _TCD_Execute_Task 
    .ref          _TCD_Execute_HISR 
    .ref          _TCD_Current_Thread 
    .ref          _TCD_System_Stack 
    .ref          _TCD_Interrupt_Count 
    .ref          _TCD_Active_HISR_Heads 
    .ref          _TCD_Active_HISR_Tails 
    .ref          _TCD_Interrupt_Level 
    .ref          _TMD_Time_Slice 
    .ref          _TMD_Time_Slice_State 
 
;********************************** 
;* EXTERNAL FUNCTION DECLARATIONS * 
;********************************** 
 
;extern VOID        TCC_Task_Shell(VOID); 
;extern VOID        TCC_Signal_Shell(VOID); 
;extern VOID        ERC_System_Error(INT); 
 
    .ref          _TCC_Task_Shell 
    .ref          _TCC_Signal_Shell 
    .ref          _ERC_System_Error 
     
    .if NU_TEST2_SUPPORT 
     
    .ref          _Set_Suspend_Time 
     
    .endif 
     
    .if NU_TEST3_SUPPORT 
     
    .ref          _Set_Context_Save_Start 
    .ref          _Set_Context_Save_End 
    .ref          _Set_Context_Restore_Start 
    .ref          _Set_Context_Restore_End 
     
    .endif 
 
    .if NU_PROFILE_PLUS 
 
    .ref          __NU_Idle_Hook 
    .ref          __NU_Schedule_Task_Hook 
 
    .endif 
 
;********************************** 
;* GLOBAL VARIABLE DECLARATIONS   * 
;********************************** 
 
    ; Define variable used to hold system stack limit.  The stack limit is utilized 
    ; by the ARM tools when the /swst switch is invoked.  This will allow 
    ; stack over-flows to be checked. 
 
    .def    _TCT_System_Limit 
    .bss    _TCT_System_Limit, 4, 4          ; Reserve 4-bytes with 4-byte alignment 
 
    .if  NU_FIQ_SUPPORT 
 
    ; Define variable used as flag to indicate when a "special" nested interrupt 
    ; occurs.  This situation occurs when an FIQ nests on top of an IRQ before 
    ; the global interrupt count has been incremented.  This flag is used to 
    ; help correct context save/restore routines in this situation. 
 
    .bss    TCT_Special_Nested, 4, 4        ; Reserve 4-bytes with 4-byte alignment 
 
    .endif 
 
;********************************** 
;* LOCAL VARIABLES                * 
;********************************** 
    .text 
    .align 4 
 
    ; The following are local variables.  ARM Architecture uses 
    ; PC relative addressing, so all global data accessed must 
    ; reside within close proximity (<4Kb in ARM, <1Kb in THUMB) 
    ; to the instructions that access them. 
    ; These are essentially pointers to global data. 
 
    .if  NU_FIQ_SUPPORT 
 
TCT_Special_Nested1 
    .word     TCT_Special_Nested 
 
    .endif 
 
TCT_System_Limit1 
    .word     _TCT_System_Limit 
 
TCT_Int_Level 
    .word     _TCD_Interrupt_Level 
 
TCT_Task_Shell 
    .word     _TCC_Task_Shell 
 
TCT_Signal_Shell 
    .word     _TCC_Signal_Shell 
 
TCT_Current_Thread1 
    .word     _TCD_Current_Thread 
 
TCT_Execute_HISR 
    .word     _TCD_Execute_HISR 
 
TCT_Execute_Task 
    .word     _TCD_Execute_Task 
 
TCT_Time_Slice 
    .word     _TMD_Time_Slice 
 
TCT_Slice_State 
    .word     _TMD_Time_Slice_State 
 
TCT_System_Stack 
    .word     _TCD_System_Stack 
 
TCT_Int_Count 
    .word     _TCD_Interrupt_Count 
 
TCT_HISR_Tails 
    .word     _TCD_Active_HISR_Tails 
 
TCT_HISR_Heads 
    .word     _TCD_Active_HISR_Heads 
 
TCT_HISR_Shell1 
    .word     TCT_HISR_Shell 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Control_Interrupts 
;* 
;*  DESCRIPTION 
;* 
;*      This function enables and disables interrupts as specified by 
;*      the caller.  Interrupts disabled by this call are left disabled 
;*      until the another call is made to enable them. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    New Interrupt Level 
;* 
;*  OUTPUTS 
;* 
;*      r0 -    Old Interrupt Level 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;INT    TCT_Control_Interrupts(INT interrupt_level); 
 
    .def    _TCT_Control_Interrupts 
_TCT_Control_Interrupts 
 
    ; Lock out all interrupts before any checking or changing 
 
    MRS     r2,CPSR                         ; Pickup current CPSR 
    ORR     r2,r2,#LOCKOUT                  ; Build lockout CPSR 
    MSR     CPSR,r2                         ; Lockout interrupts temporarily 
 
    ; Obtain the current interrupt lockout posture. 
 
    LDR     r1,TCT_Int_Level                ; Pickup interrupt level 
    LDR     r3,[r1]                         ; Pickup current interrupt lockout 
 
    ; Setup new interrupt lockout posture. 
 
    BIC     r2,r2,#LOCK_MSK                 ; Clear lockout mask 
    ORR     r2,r2,r0                        ; Set correct lock-out bits in CPSR 
    STR     r0,[r1]                         ; Save current lockout 
 
    ; Reenable interrupts for the specified lockout 
 
    MSR     CPSR,r2                         ; Setup new CPSR lockout bits 
 
    ; Get old lock-out value in return register (r0) 
 
    AND     r0,r3,#LOCK_MSK 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Local_Control_Interrupts 
;* 
;*  DESCRIPTION 
;* 
;*      This function enables and disables interrupts as specified by 
;*      the caller. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    New Interrupt Level 
;* 
;*  OUTPUTS 
;* 
;*      r0 -    Old Interrupt Level 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;INT    TCT_Local_Control_Interrupts(INT interrupt_level); 
 
    .def    _TCT_Local_Control_Interrupts 
_TCT_Local_Control_Interrupts 
 
    ; Read in and save the old level 
 
    MRS     r3,CPSR                         ; Pickup current CPSR 
 
    ; Clear out the old level and set the new level 
 
    BIC     r2,r3,#LOCK_MSK                 ; Clear all current interrupts bits 
    ORR     r2,r2,r0                        ; Build new CPSR with new lock-out bits 
 
    ; Reenable interrupts for the specified lockout 
 
    MSR     CPSR,r2 
 
    ; Get old lock-out value in return register (r0) 
 
    AND     r0,r3,#LOCK_MSK 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Restore_Interrupts 
;* 
;*  DESCRIPTION 
;* 
;*      This function restores interrupts to the specified value in 
;*      the global TCD_Interrupt_Level variable. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID   TCT_Restore_Interrupts(VOID); 
 
    .def    _TCT_Restore_Interrupts 
_TCT_Restore_Interrupts 
 
    ; Lock-out all interrupts before any checking or changing 
 
    MRS     r2,CPSR                         ; Pickup current CPSR 
    ORR     r1,r2,#LOCKOUT                  ; Build lockout CPSR 
    MSR     CPSR,r1                         ; Lockout interrupts temporarily 
 
    ; Obtain the current interrupt lockout posture. 
 
    BIC     r2,r2,#LOCK_MSK                 ; Clear current interrupt levels 
    LDR     r1,TCT_Int_Level                ; Load address of TCD_Interrupt_Level 
    LDR     r0,[r1]                         ; Pickup current interrupt lockout 
    ORR     r2,r2,r0                        ; Build new CPSR with appropriate 
                                            ; interrupts locked out 
 
    ; Setup new CPSR lockout bits 
 
    MSR     CPSR,r2 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Build_Task_Stack 
;* 
;*  DESCRIPTION 
;* 
;*      This function builds an initial stack frame for a task.  The 
;*      initial stack contains information concerning initial values of 
;*      registers and the task's point of entry.  Furthermore, the 
;*      initial stack frame is in the same form as an interrupt stack 
;*      frame. 
;* 
;*  CALLED BY 
;* 
;*      TCC_Create_Task 
;*      TCC_Reset_Task 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Task Control Block pointer 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID   TCT_Build_Task_Stack(TC_TCB *task); 
 
    .def    _TCT_Build_Task_Stack 
_TCT_Build_Task_Stack 
 
    ; Pickup the stack starting address from task control block 
 
    LDR     r2,[r0,#TC_STACK_START] 
 
    ; Pickup the stack size (in bytes) from task control block 
 
    LDR     r1,[r0,#TC_STACK_SIZE] 
 
    ; Calculate the stack ending address 
 
    ADD     r3,r1,r2                        ; Compute the stack end (start + size) 
    BIC     r3,r3,#3                        ; Insure 4-byte alignment 
    SUB     r3,r3,#4                        ; Reserve a word 
 
    ; Save the stack ending address in control block 
 
    STR     r3,[r0,#TC_STACK_END] 
 
    ; Build an initial stack frame as follows: 
    ; 
    ;     (Lower Address) Stack Top ->    1       (Interrupt stack type) 
    ;                                     CPSR    Saved CPSR 
    ;                                     r0      Saved r0 
    ;                                     r1      Saved r1 
    ;                                     r2      Saved r2 
    ;                                     r3      Saved r3 
    ;                                     r4      Saved r4 
    ;                                     r5      Saved r5 
    ;                                     r6      Saved r6 
    ;                                     r7      Saved r7 
    ;                                     r8      Saved r8 
    ;                                     r9      Saved r9 
    ;                                     r10     Saved r10 
    ;                                     r11     Saved r11 
    ;                                     r12     Saved r12 
    ;                                     sp      Saved sp 
    ;                                     lr      Saved lr 
    ;     (Higher Address) Stack Bottom-> pc      Saved pc 
 
    ; Get address of task shell 
 
    LDR     r2,TCT_Task_Shell 
 
    BIC     r2,r2,#1                        ; Clear low bit 
 
    STR     r2,[r3], #-4                    ; Push pc (task shell address) 
    MOV     r2,#0                           ; Clear value for initial registers 
    STR     r2,[r3], #-4                    ; Push lr 
    ADD     r2,r3,#0x8                      ; Compute initial sp 
    STR     r2,[r3], #-4                    ; Push sp 
    STR     r2,[r3], #-4                    ; Push r12 
    STR     r2,[r3], #-4                    ; Push r11 
    LDR     r2,[r0,#TC_STACK_START]         ; Pickup the stack starting address 
    STR     r2,[r3], #-4                    ; Push r10 (stack limit) 
    MOV     r2,#0                           ; Clear value for initial registers 
    STR     r9,[r3], #-4                    ; Push r9 
    STR     r2,[r3], #-4                    ; Push r8 
    STR     r2,[r3], #-4                    ; Push r7 
    STR     r2,[r3], #-4                    ; Push r6 
    STR     r2,[r3], #-4                    ; Push r5 
    STR     r2,[r3], #-4                    ; Push r4 
    STR     r2,[r3], #-4                    ; Push r3 
    STR     r2,[r3], #-4                    ; Push r2 
    STR     r2,[r3], #-4                    ; Push r1 
    STR     r2,[r3], #-4                    ; Push r0 
    MRS     r2,CPSR                         ; Pickup the CPSR 
    BIC     r2,r2,#LOCK_MSK                 ; Clear initial interrupt lockout 
 
    ; Check to see if Task shell is build in thumb state 
 
    LDR     r1,TCT_Task_Shell               ; Get address of task shell 
    TST     r1,#1                           ; Check bit 0 (set if THUMB) 
    ORRNE   r2,r2,#THUMB_BIT                ; If bit 0 set, add THUMB bit to CPSR 
 
    STR     r2,[r3], #-4                    ; Push CPSR 
    MOV     r2,#1                           ; Build interrupt stack type (1) 
    STR     r2,[r3]                         ; Push stack type 
 
    ; Save the new stack pointer into the task's control block. 
 
    STR     r3,[r0, #TC_STACK_POINTER] 
 
    ; Pickup the stack size (in bytes) from task control block 
 
    LDR     r1,[r0,#TC_STACK_SIZE] 
 
    ; Save the minimum amount of remaining stack memory. 
 
    MOV     r2,#INT_STACK_SIZE              ; Size of interrupt stack frame 
    SUB     r1,r1,r2                        ; Compute minimum available bytes 
    STR     r1,[r0, #TC_STACK_MINIMUM]      ; Save in minimum stack area 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Build_HISR_Stack 
;* 
;*  DESCRIPTION 
;* 
;*      This function builds an initial stack frame for a HISR.  The 
;*      initial stack contains information concerning initial values of 
;*      registers and the HISR's point of entry.  Furthermore, the 
;*      initial stack frame is in the same form as a solicited stack 
;*      frame. 
;* 
;*  CALLED BY 
;* 
;*      TCC_Create_HISR 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    HISR Control Block pointer 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID   TCT_Build_HISR_Stack(TC_HCB *hisr); 
 
    .def    _TCT_Build_HISR_Stack 
_TCT_Build_HISR_Stack 
 
    ; Pickup the stack starting address from task control block 
 
    LDR     r2,[r0,#TC_STACK_START] 
 
    ; Pickup the stack size (in bytes) from task control block 
 
    LDR     r1,[r0,#TC_STACK_SIZE] 
 
    ; Calculate the stack ending address 
 
    ADD     r3,r1,r2                        ; Compute the stack end (start + size) 
    BIC     r3,r3,#3                        ; Insure 4-byte alignment 
    SUB     r3,r3,#4                        ; Reserve a word 
 
    ; Save the stack ending address in control block 
 
    STR     r3,[r0,#TC_STACK_END] 
 
    ; Build an initial stack.with the following format: 
    ; 
    ;     (Lower Address) Stack Top ->    0       (Solicited stack type) 
    ;                                     CPSR    Saved CPSR 
    ;                                     r4      Saved r4 
    ;                                     r5      Saved r5 
    ;                                     r6      Saved r6 
    ;                                     r7      Saved r7 
    ;                                     r8      Saved r8 
    ;                                     r9      Saved r9 
    ;                                     r10     Saved r10 
    ;                                     r11     Saved r11 
    ;                                     r12     Saved r12 
    ;     (Higher Address) Stack Bottom-> pc      Saved pc 
 
    ; Get address of HISR shell 
 
    LDR     r2, TCT_HISR_Shell1             ; Pickup address of shell entry 
    STR     r2,[r3], #-4                    ; Store entry address on stack 
    ADD     r2,r3,#0x4                      ; Compute initial sp 
    STR     r2,[r3], #-4                    ; Push r12 
    STR     r2,[r3], #-4                    ; Push r11 
    LDR     r2,[r0,#TC_STACK_START]         ; Pickup the stack starting address 
    STR     r2,[r3], #-4                    ; Push r10 (stack limit) 
    MOV     r2,#0                           ; Clear value for initial registers 
    STR     r9,[r3], #-4                    ; Store initial r9 
    STR     r2,[r3], #-4                    ; Store initial r8 
    STR     r2,[r3], #-4                    ; Store initial r7 
    STR     r2,[r3], #-4                    ; Store initial r6 
    STR     r2,[r3], #-4                    ; Store initial r5 
    STR     r2,[r3], #-4                    ; Store initial r4 
    MRS     r1,CPSR                         ; Pickup the CPSR 
    BIC     r1,r1,#LOCK_MSK                 ; Clear initial interrupt lockout 
    STR     r1,[r3], #-4                    ; Push CPSR 
 
    ; Store solicited stack type on the top of the stack 
 
    STR     r2,[r3] 
 
    ; Save the new stack pointer into the task's control block. 
 
    STR     r3,[r0, #TC_STACK_POINTER] 
 
    ; Get size of solicited stack frame 
 
    MOV     r2,#SOL_STACK_SIZE 
 
    ; Pickup the stack size (in bytes) from task control block 
 
    LDR     r1,[r0,#TC_STACK_SIZE] 
 
    ; Compute minimum available bytes and save in minimum stack area. 
 
    SUB     r1,r1,r2 
    STR     r1,[r0, #TC_STACK_MINIMUM] 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Build_Signal_Frame 
;* 
;*  DESCRIPTION 
;* 
;*      This function builds a frame on top of the task's stack to 
;*      cause the task's signal handler to execute the next time 
;*      the task is executed.  This is built as a solicited stack 
;*      frame. 
;* 
;*  CALLED BY 
;* 
;*      TCC_Send_Signals 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Task Control Block pointer 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID   TCT_Build_Signal_Frame(TC_TCB *task); 
 
    .def    _TCT_Build_Signal_Frame 
_TCT_Build_Signal_Frame 
 
    ; Pickup the stack pointer. 
 
    LDR     r3,[r0,#TC_STACK_POINTER]       ; Pickup the current stack pointer 
 
    ; Reserve a word on stack top 
 
    SUB     r3,r3,#4 
 
    ; Build a signal stack with the following format: 
    ; 
    ;     (Lower Address) Stack Top ->    0       (Solicited stack type) 
    ;                                     CPSR    Saved CPSR 
    ;                                     r4      Saved r4 
    ;                                     r5      Saved r5 
    ;                                     r6      Saved r6 
    ;                                     r7      Saved r7 
    ;                                     r8      Saved r8 
    ;                                     r9      Saved r9 
    ;                                     r10     Saved r10 
    ;                                     r11     Saved r11 
    ;                                     r12     Saved r12 
    ;     (Higher Address) Stack Bottom-> pc      Saved pc 
 
    ; Get address of signal shell 
 
    LDR     r2,TCT_Signal_Shell             ; Pickup address of shell entry 
 
    ; If in THUMB state, clear low bit. 
 
    BIC     r2,r2,#1 
 
    STR     r2,[r3], #-4                    ; Push pc (signal shell) 
    ADD     r2,r3,#0x4                      ; Compute initial sp 
    STR     r2,[r3], #-4                    ; Push r12 
    STR     r2,[r3], #-4                    ; Push r11 
    LDR     r2,[r0,#TC_STACK_START]         ; Pickup the stack starting address 
    STR     r2,[r3], #-4                    ; Push r10 (stack limit) 
    MOV     r2,#0                           ; Clear value for initial registers 
    STR     r9,[r3], #-4                    ; Push r9 
    STR     r2,[r3], #-4                    ; Push r8 
    STR     r2,[r3], #-4                    ; Push r7 
    STR     r2,[r3], #-4                    ; Push r6 
    STR     r2,[r3], #-4                    ; Push r5 
    STR     r2,[r3], #-4                    ; Push r4 
 
    ; Build CPSR value to put on stack 
 
    MRS     r1,CPSR                         ; Pickup the CPSR 
    BIC     r1,r1,#LOCK_MSK                 ; Clear initial interrupt lockout 
 
    ; Check to see if Signal shell is build in thumb state 
 
    LDR     r2,TCT_Signal_Shell             ; Get address of signal shell 
    TST     r2,#1                           ; Check bit 0 (set if THUMB) 
    ORRNE   r1,r1,#THUMB_BIT                ; If bit 0 set, add THUMB bit to CPSR 
 
    ; Push CPSR on stack 
 
    STR     r1,[r3], #-4 
 
    ; Store solicited stack type on the top of the stack (0 = solicited) 
 
    MOV     r2,#0 
    STR     r2,[r3] 
 
    ; Save the new stack pointer into the task's control block. 
 
    STR     r3,[r0, #TC_STACK_POINTER] 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Check_Stack 
;* 
;*  DESCRIPTION 
;* 
;*      This function checks the current stack for overflow conditions. 
;*      Additionally, this function keeps track of the minimum amount 
;*      of stack space for the calling thread and returns the current 
;*      available stack space. 
;* 
;*  CALLED BY 
;* 
;*      TCC_Send_Signals                Send signals to a task 
;* 
;*  CALLS 
;* 
;*      ERC_System_Error                System error handler 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      r0 -    Available bytes on stack 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;INT    TCT_Check_Stack(VOID); 
 
    .def    _TCT_Check_Stack 
_TCT_Check_Stack 
 
    ; Pickup the current thread pointer. 
 
    LDR     r0,TCT_Current_Thread1 
    LDR     r0,[r0] 
 
    ; Determine if there is a current thread. 
 
    CMP     r0,#0                           ; Determine if a thread is active 
    MOV     r3,#0                           ; Default remaining value 
    BEQ     TCT_Skip_Stack_Check            ; If NU_NULL, skip stack checking 
 
    ; Determine if the stack pointer has overflowed 
 
    LDR     r2,[r0,#TC_STACK_START]         ; Pickup start of stack area 
    CMP     sp,r2                           ; Compare with current stack ptr 
    BLT     TCT_Stack_Range_Error           ; If less, stack is out of range 
 
    ; Determine if the stack pointer has underflowed 
 
    LDR     r1,[r0,#TC_STACK_END]           ; Pickup end of stack area 
    CMP     sp,r1                           ; Compare with current stack ptr 
    BLE     TCT_Stack_Range_Okay            ; If less, stack range is okay 
 
TCT_Stack_Range_Error 
 
    MOV     r0,#3                           ; Build NU_STACK_OVERFLOW code 
    BL      _ERC_System_Error               ; Call system error handler 
 
TCT_Stack_Range_Okay 
 
    ; Calculate the amount of available space on the stack. 
 
    SUB     r3,sp,r2 
 
    ; Determine if there is enough memory on the stack to save 
    ; all of the registers. 
 
    CMP     r3,#INT_STACK_SIZE 
 
    ; If there is enough memory, there is no stack overflow yet 
 
    BGE     TCT_No_Stack_Error 
 
    ; Stack overflow condition is about to happen. 
 
    MOV     r0,#3                           ; Build NU_STACK_OVERFLOW code 
    BL      _ERC_System_Error               ; Call system error handler 
 
TCT_No_Stack_Error 
 
    ; Determine if this is a new minimum amount of stack space. 
    ; If so, save the new stack minimum. 
 
    LDR     r2,[r0,#TC_STACK_MINIMUM] 
    CMP     r3,r2 
    STRCC   r3,[r0,#TC_STACK_MINIMUM] 
 
TCT_Skip_Stack_Check 
 
    ; Return the remaining number of bytes on the stack. 
 
    MOV     r0,r3 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Schedule 
;* 
;*  DESCRIPTION 
;* 
;*      This function waits for a thread to become ready.  Once a thread 
;*      is ready, this function initiates a transfer of control to that 
;*      thread. 
;* 
;*  CALLED BY 
;* 
;*      INC_Initialize                  Main initialization routine 
;*      TCT_Control_To_System           Transfers control to system 
;*      TCT_Signal_Exit                 Exit routine for signals 
;*      TCT_Unprotect_Specific          Unprotects specific protect 
;*      TCT_Interrupt_Context_Restore   Restore context after interrupt 
;*      TCT_HISR_Shell                  Entry point for HISRs 
;* 
;*  CALLS 
;* 
;*      TCT_Control_To_Thread           Transfer control to a thread 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      r0 -    Pointer to scheduled thread 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Schedule(VOID) 
 
    .def    _TCT_Schedule 
_TCT_Schedule 
 
 
    .if NU_TEST2_SUPPORT 
 
    BL      _Set_Suspend_Time 
     
    .endif 
     
     
    ; Restore interrupts according to the value contained in TCD_Interrupt_Level. 
 
    LDR     r1,TCT_Int_Level                ; Get address of interrupt level 
    LDR     r1,[r1]                         ; Pickup current interrupt lockout 
    MRS     r0,CPSR                         ; Pickup current CPSR 
    BIC     r0,r0,#LOCK_MSK                 ; Clear the interrupt lockout bits 
    ORR     r0,r0,r1                        ; Build new interrupt lockout CPSR 
    MSR     CPSR,r0                         ; Setup new CPSR 
 
    ; Get the addresses of the HISR and Task to execute 
 
    LDR     r2,TCT_Execute_HISR 
    LDR     r3,TCT_Execute_Task 
 
    .if NU_PROFILE_PLUS 
 
    ; Check to see if there is a task to execute upon entering TCT_Schedule. 
    ; If not, we start IDLE. 
 
    LDR     r0,[r2]                         ; Pickup highest priority HISR ptr 
    CMP     r0,#0                           ; Is there a HISR active? 
    BNE     TCT_Schedule_Thread             ; Found an HISR 
    LDR     r0,[r3]                         ; Pickup highest priority Task ptr 
    CMP     r0,#0                           ; Is there a task active? 
    BNE     TCT_Schedule_Thread             ; If not, start IDLE. 
    STMDB   sp!,{r2-r3}                     ; Save r2-r3 
    BL      __NU_Idle_Hook 
    LDMIA   sp!,{r2-r3}                     ; Restore r2-r3 
 
    .endif 
 
    .def	TCT_Schedule_Loop 
TCT_Schedule_Loop 
 
    ; Wait until a thread (task or HISR) is available to execute. 
    ; When a thread is available, branch to TCT_Schedule_Thread. 
 
    LDR     r0,[r2]                         ; Pickup highest priority HISR ptr 
    CMP     r0,#0                           ; Is there a HISR active? 
    BNE     TCT_Schedule_Thread             ; Found a HISR 
    LDR     r0,[r3]                         ; Pickup highest priority Task ptr 
         
    CMP     r0,#0                           ; Is there a task active? 
     
;;;;; TI CODE : modification starts 
 
    .ref    INT_Small_Sleep 
    BEQ     INT_Small_Sleep		    ; No, enter the GSM Small Sleep mode 
         
;;;;;BEQ     TCT_Schedule_Loop               ; If not, continue the search 
 
;;;;!; TI CODE : modification ends 
 
TCT_Schedule_Thread 
 
    ; Either a task or HISR is ready to execute.  Lockout interrupts while 
    ; the thread is transferred (by falling through to the following routine). 
 
    MRS     r1,CPSR                         ; Pickup CPSR again 
    ORR     r1,r1,#LOCKOUT                  ; Build interrupt lockout value 
    MSR     CPSR,r1                         ; Lockout interrupts 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Control_To_Thread 
;* 
;*  DESCRIPTION 
;* 
;*      This function transfers control to the specified thread.  Each 
;*      time control is transferred to a thread, its scheduled counter 
;*      is incremented.  Additionally, time-slicing for task threads is 
;*      enabled in this routine.  The TCD_Current_Thread pointer is 
;*      setup by this function. 
;* 
;*  CALLED BY 
;* 
;*      TCT_Schedule                    Indirectly called 
;*      TCT_Protect                     Protection task switch 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Thread pointer to schedule 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3, sp, pc, SPSR 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Control_To_Thread(VOID *thread) 
 
    .def    _TCT_Control_To_Thread 
_TCT_Control_To_Thread 
 
    ; Put thread pointer into TCD_Current_Thread 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    STR     r0,[r1]                         ; Setup current thread pointer 
 
; TI CODE : Call the Function that log the Current Thread. 
 
  .if OP_L1_STANDALONE = 0 
    .if TI_NUC_MONITOR = 1 
  		.global _ti_nuc_monitor_Thread_log 
		STMFD	sp!,{r0-r5} 
		BL		_ti_nuc_monitor_Thread_log		; Call the Thread Log function. 
		LDMFD	sp!,{r0-r5} 
    .endif 
 
    ; WCP Profiler 
    .if WCP_PROF = 1 
       .global _prf_LogTaskSwitch 
       STMFD    sp!,{a1-a4} 
       BL       _prf_LogTaskSwitch 
       LDMFD	sp!,{a1-a4} 
    .endif 
  .endif 
 
    ; Increment the thread scheduled counter 
 
    LDR     r2,[r0, #TC_SCHEDULED]          ; Pickup scheduled count 
    ADD     r2,r2,#1                        ; Increment the scheduled count 
    STR     r2,[r0, #TC_SCHEDULED]          ; Store new scheduled count 
 
    ; Check for time slice option 
 
    LDR     r3,[r0, #TC_CUR_TIME_SLICE]     ; Pickup time slice value 
    CMP     r3,#0                           ; Is there a time slice? 
    BEQ     TCT_No_Start_TS_1               ; If 0, there is no time slice 
 
    ; Set-up the time slice value 
 
    LDR     r2,TCT_Time_Slice               ; Pickup address of TMD_Time_Slice 
    STR     r3,[r2]                         ; Setup the time slice 
 
    ; Enable the time-slice timer 
 
    LDR     r1,TCT_Slice_State              ; Pickup address of TMD_Time_Slice_State 
    MOV     r2,#0                           ; Build active state flag 
    STR     r2,[r1]                         ; Set the active flag 
 
TCT_No_Start_TS_1 
 
    .if NU_PROFILE_PLUS 
 
    STMDB   sp!,{r0}                        ; Push r0 
    BL      _NU_Schedule_Task_Hook          ; Branch to RTView 
    LDMIA   sp!,{r0}                        ; Pop r0 
 
    .endif 
 
    ; Pickup the thread's stack pointer and resume the thread. 
 
    LDR     sp,[r0, #TC_STACK_POINTER] 
 
    ; Pop off the stack top to determine stack type 
 
    LDR     r1,[sp], #4 
 
    ; Remove CPSR from stack and put in SPSR 
 
    LDR     r0,[sp], #4                     ; Pop off the CPSR 
    MSR     SPSR,r0                         ; Place it into the SPSR 
 
    ; Check if interrupt stack or solicited stack 
 
    CMP     r1,#1                           ; Compare stack type with 1 
    BEQ     TCT_Interrupt_Resume            ; If equal to 1, interrupt stack frame 
 
    ; Recover all solicited stack frame registers and return 
 
    LDMIA   sp!,{r4-r12,pc}^                ; A solicited return is required. 
                                            ; This type of return only 
                                            ; Recovers r4-r12 & pc 
TCT_Interrupt_Resume 
 
    ; Recover all registers and resume at point of interrupt 
 
    LDMIA   sp,{r0-pc}^ 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Control_To_System 
;* 
;*  DESCRIPTION 
;* 
;*      This function returns control from a thread to the system.  Note 
;*      that this service is called in a solicited manner, i.e. it is 
;*      not called from an interrupt thread.  Registers required by the 
;*      compiler to be preserved across function boundaries are saved by 
;*      this routine.  Note that this is usually a sub-set of the total 
;*      number of available registers. 
;* 
;*  CALLED BY 
;* 
;*      Other Components 
;* 
;*  CALLS 
;* 
;*      TCT_Schedule                        Schedule the next thread 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3, r10, sp, CPSR 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Control_To_System(VOID) 
 
    .def    _TCT_Control_To_System 
_TCT_Control_To_System 
 
    ; Lockout interrupts. 
 
    MRS     r0,CPSR                         ; Pickup current CPSR 
    ORR     r1,r0,#LOCKOUT                  ; Build interrupt lockout value 
    MSR     CPSR,r1                         ; Lockout interrupts 
 
    ; Save a minimal context of the thread on the current stack. 
 
    STMDB   sp!,{r4-r12,lr} 
 
    ; Check to see if caller was in THUMB mode 
    ; and update saved CPSR accordingly 
 
    TST     lr,#1                           ; Check bit 0 (set if THUMB mode) 
    ORRNE   r0,r0,#THUMB_BIT                ; Set THUMB bit if caller in THUMB mode 
 
    ; Save CPSR on stack (with caller's lock-out bits / mode set correctly) 
 
    STR     r0,[sp, #-4]! 
 
    ; Push solicited stack type on the top of the stack. 
 
    MOV     r2,#0 
    STR     r2,[sp, #-4]! 
 
    ; Setup a pointer to the thread control block and set the current 
    ; thread pointer to NU_NULL. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r0,[r1]                         ; Pickup current thread pointer 
    STR     r2,[r1]                         ; Set current thread pointer to 
                                            ; NU_NULL 
 
    ; Check to see if a time slice is active. 
 
    LDR     r3,TCT_Slice_State              ; Pickup time slice state address 
    LDR     r1,[r3]                         ; Pickup time slice state flag 
    CMP     r1,#0                           ; Compare with active value 
    BNE     TCT_No_Stop_TS_1                ; If non-active, don't disable 
 
    ; Insure that the next time the task runs it gets a fresh time slice. 
 
    LDR     r1,[r0, #TC_TIME_SLICE]         ; Pickup original time slice 
    STR     r1,[r0, #TC_CUR_TIME_SLICE]     ; Reset current time slice 
 
    ; Clear any active time slice by setting the state to NOT_ACTIVE. 
 
    MOV     r2,#1                           ; Build disable value 
    STR     r2,[r3]                         ; Disable time slice 
 
TCT_No_Stop_TS_1 
 
    ; Save off the current stack pointer in the control block. 
 
    STR     sp,[r0, #TC_STACK_POINTER]      ; Save the thread's stack pointer 
 
    ; Clear the task's current protection. 
 
    LDR     r1,[r0, #TC_CURRENT_PROTECT]    ; Pickup current thread pointer 
    MOV     r2,#0                           ; Build NU_NULL value 
    STR     r2,[r0, #TC_CURRENT_PROTECT]    ; Clear the protect pointer field 
    STR     r2,[r1]                         ; Release the actual protection 
 
    ; Switch to the system stack / system stack limit 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r2,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r2]                        ; Setup system stack limit 
 
    ; Finished, return to the scheduling loop. 
 
    B       _TCT_Schedule                   ; Return to scheduling loop 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Signal_Exit 
;* 
;*  DESCRIPTION 
;* 
;*      This function exits from a signal handler.  The primary purpose 
;*      of this function is to clear the scheduler protection and switch 
;*      the stack pointer back to the normal task's stack pointer. 
;* 
;*  CALLED BY 
;* 
;*      TCC_Signal_Shell                Signal handling shell function 
;* 
;*  CALLS 
;* 
;*      TCT_Schedule                    Scheduler 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3, r10, sp, CPSR 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Signal_Exit(VOID) 
 
    .def    _TCT_Signal_Exit 
_TCT_Signal_Exit 
 
    ; Lockout interrupts. 
 
    MRS     r3,CPSR                         ; Pickup current CPSR 
    ORR     r3,r3,#LOCKOUT                  ; Build lockout value 
    MSR     CPSR,r3                         ; Lockout interrupts 
 
    ; Setup a pointer to the thread control block. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup address of thread pointer 
    LDR     r0,[r1]                         ; Pickup current thread pointer 
 
    ; Clear the current thread control block. 
 
    MOV     r2,#0                           ; Build NU_NULL value 
    STR     r2,[r1]                         ; Clear current thread pointer 
 
    ; Check to see if a time slice is active. 
 
    LDR     r3,TCT_Slice_State              ; Pickup time slice state address 
    LDR     r1,[r3]                         ; Pickup time slice state flag 
    CMP     r1,#0                           ; Compare with active value 
    BNE     TCT_No_Stop_TS_2                ; If non-active, don't disable 
 
    ; Insure that the next time the task runs it gets a fresh time slice. 
 
    LDR     r1,[r0, #TC_TIME_SLICE]         ; Pickup original time slice 
    STR     r1,[r0, #TC_CUR_TIME_SLICE]     ; Reset current time slice 
 
    ; Clear any active time slice by setting the state to NOT_ACTIVE. 
 
    MOV     r2,#1                           ; Build disable value 
    STR     r2,[r3]                         ; Disable time slice 
 
 
TCT_No_Stop_TS_2 
 
    ; Switch back to the saved stack.  The saved stack pointer was saved 
    ; before the signal frame was built. 
 
    LDR     r1,[r0, #TC_SAVED_STACK_PTR]    ; Pickup saved stack pointer 
    STR     r1,[r0, #TC_STACK_POINTER]      ; Place in current stack pointer 
 
    ; Clear the task's current protection. 
 
    LDR     r1,[r0, #TC_CURRENT_PROTECT]    ; Pickup current thread pointer 
    MOV     r2,#0                           ; Build NU_NULL value 
    STR     r2,[r0, #TC_CURRENT_PROTECT]    ; Clear the protect pointer field 
    STR     r2,[r1]                         ; Release the actual protection 
 
    ; Switch to the system stack / system stack limit 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r2,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r2]                        ; Setup system stack limit 
 
    ; Finished, return to the scheduling loop. 
 
    B       _TCT_Schedule                   ; Return to scheduling loop 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Current_Thread 
;* 
;*  DESCRIPTION 
;* 
;*      This function returns the current thread pointer. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;*      System Components 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      r0 -    Pointer to current thread 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  *TCT_Current_Thread(VOID) 
 
    .def    _TCT_Current_Thread 
_TCT_Current_Thread 
 
    ; Return the current thread pointer. 
 
    LDR     r0,TCT_Current_Thread1          ; Pickup address of thread pointer 
    LDR     r0,[r0]                         ; Pickup current thread pointer 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Set_Execute_Task 
;* 
;*  DESCRIPTION 
;* 
;*      This function sets the current task to execute variable under 
;*      protection against interrupts. 
;* 
;*  CALLED BY 
;* 
;*      TCC Scheduling Routines 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Pointer to task control block 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Set_Execute_Task(TC_TCB *task) 
 
    .def    _TCT_Set_Execute_Task 
_TCT_Set_Execute_Task 
 
    ; Setup the TCD_Execute_Task pointer. 
 
    LDR     r1,TCT_Execute_Task             ; Pickup execute task ptr address 
    STR     r0,[r1]                         ; Setup new task to execute 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Protect 
;* 
;*  DESCRIPTION 
;* 
;*      This function protects against multiple thread access. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;*      System Components 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Pointer to protection block 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Protect(TC_PROTECT *protect) 
 
    .def    _TCT_Protect 
_TCT_Protect 
 
    ; Determine if the caller is in a task or HISR thread. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r1,[r1]                         ; Pickup current thread pointer 
    CMP     r1,#0                           ; Check to see if it is non-NULL 
    BEQ     TCT_Skip_Protect                ; If NULL, skip protection 
 
    ; Save current CPSR 
 
    MRS     r2,CPSR                         ; Pickup current CPSR 
    STMDB   sp!,{r2}                        ; Save CPSR on stack 
 
TCT_Protect_Loop 
 
    ; Lock-out interrupts 
 
    ORR     r2,r2,#LOCKOUT                  ; Place lockout value in r2 
    MSR     CPSR,r2                         ; Lockout interrupts 
 
    ; Wait until the protect structure is available. 
 
    LDR     r2,[r0, #TC_TCB_PTR]            ; Pickup protection owner field 
    CMP     r2,#0                           ; Does another thread own this protection? 
    BEQ     TCT_Protect_Available           ; If NU_NULL, protection not owned 
 
    ; Protection structure is not available. 
    ; Indicate that another thread is waiting. 
 
    MOV     r3,#1                           ; Build thread waiting flag 
    STR     r3,[r0, #TC_THREAD_WAIT]        ; Set waiting field 
 
    ; Save r0-r1 and lr on stack 
 
    STMDB   sp!,{r0-r1,lr} 
 
    ; Directly schedule the thread holding the protection 
 
    MOV     r0,r2                           ; Place thread owning protect into r0 
    BL      _TCT_Schedule_Protected         ; Call routine to schedule the 
                                            ; owner of the protection 
 
    ; Recover r0-r1 and lr off stack 
 
    LDMIA   sp!,{r0-r1,lr} 
 
    ; Pickup current CPSR 
 
    MRS     r2,CPSR 
 
    ; Loop until protection available 
 
    B       TCT_Protect_Loop 
 
TCT_Protect_Available 
 
    ; Protection structure is available. 
    ; Indicate that current thread owns the protection. 
 
    STR     r1,[r0, #TC_TCB_PTR] 
 
    ; Clear the thread waiting flag. 
 
    MOV     r3,#0 
    STR     r3,[r0, #TC_THREAD_WAIT]        ; Clear the thread waiting flag 
 
    ; Save the protection pointer in the thread's control block. 
 
    STR     r0,[r1, #TC_CURRENT_PROTECT] 
 
    ; Restore interrupts to entry level 
 
    LDMIA   sp!,{r2} 
    MSR     CPSR,r2 
 
TCT_Skip_Protect 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Unprotect 
;* 
;*  DESCRIPTION 
;* 
;*      This function releases protection of the currently active 
;*      thread.  If the caller is not an active thread, then this 
;*      request is ignored. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;*      System Components 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Unprotect(void) 
 
    .def    _TCT_Unprotect 
_TCT_Unprotect 
 
    ; Determine if the caller is in a task or HISR thread. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r1,[r1]                         ; Pickup current thread pointer 
    CMP     r1,#0                           ; Check to see if it is non-NULL 
    BEQ     TCT_Skip_Unprotect              ; If NULL, skip unprotection 
 
    ; Lockout interrupts. 
 
    MRS     r2,CPSR                         ; Pickup current CPSR 
    STMDB   sp!,{r2}                        ; Save CPSR on stack 
    ORR     r2,r2,#LOCKOUT                  ; Place lockout value in 
    MSR     CPSR,r2                         ; Lockout interrupts 
 
    ; Determine if there is a currently active protection. 
 
    LDR     r0,[r1, #TC_CURRENT_PROTECT]    ; Pickup current protect field 
    CMP     r0,#0                           ; Is there a protection in force? 
    BEQ     TCT_Not_Protected               ; If not, nothing to unprotect 
 
    ; Check for a higher priority thread waiting for the protection structure. 
 
    LDR     r2,[r0, #TC_THREAD_WAIT]        ; Pickup thread waiting flag 
    CMP     r2,#0                           ; Are there any threads waiting? 
    BEQ     TCT_Not_Waiting_Unpr            ; If not, just release protection 
 
    ; Save link register 
 
    STMDB   sp!,{lr} 
 
    ; Transfer control to the system.  Note that this 
    ; automatically clears the current protection 
 
    BL      _TCT_Control_To_System           ; Return control to the system 
 
    ; Restore link register 
 
    LDMIA   sp!,{lr} 
 
    B       TCT_Not_Protected 
 
TCT_Not_Waiting_Unpr 
 
    ; Clear the protection. 
 
    MOV     r2,#0                           ; Build NU_NULL value 
    STR     r2,[r0, #TC_TCB_PTR]            ; Release the protection 
    STR     r2,[r1, #TC_CURRENT_PROTECT]    ; Clear protection pointer in the 
                                            ; control block 
 
TCT_Not_Protected 
 
    ; Restore interrupts from stack 
 
    LDMIA   sp!,{r1} 
    MSR     CPSR,r1 
 
TCT_Skip_Unprotect 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Unprotect_Specific 
;* 
;*  DESCRIPTION 
;* 
;*      This function releases a specific protection structure. 
;* 
;*  CALLED BY 
;* 
;*      Application 
;*      System Components 
;* 
;*  CALLS 
;* 
;*      TCT_Schedule 
;* 
;*  INPUTS 
;* 
;*      r0 -    Pointer to protection block 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3, sp 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Unprotect_Specific(TC_PROTECT *protect) 
 
    .def    _TCT_Unprotect_Specific 
_TCT_Unprotect_Specific 
 
    ; Determine if the caller is in a task or HISR thread. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r3,[r1]                         ; Pickup current thread pointer 
    CMP     r3,#0                           ; Check to see if it is non-NULL 
    BEQ     TCT_Skip_Unprot_Spec            ; If NULL, skip unprotect specific 
 
    ; Lockout interrupts. 
 
    MRS     r3,CPSR                         ; Pickup current CPSR 
    ORR     r2,r3,#LOCKOUT                  ; Place lockout value in 
    MSR     CPSR,r2                         ; Lockout interrupts 
 
    ; Clear the protection pointer. 
 
    MOV     r2,#0                           ; Build NU_NULL value 
    STR     r2,[r0, #TC_TCB_PTR]            ; Clear protection ownership 
 
    ; Determine if a thread is waiting. 
 
    LDR     r2,[r0, #TC_THREAD_WAIT]        ; Pickup the waiting field 
    CMP     r2,#0                           ; Is there another thread waiting? 
    BEQ     TCT_Not_Waiting_Unspec          ; No, restore interrupts and return 
 
    ; Save a minimal context of the thread on the current stack. 
 
    STMDB   sp!,{r4-r12,lr} 
 
    ; Check to see if caller was in THUMB mode 
    ; and update saved CPSR accordingly 
 
    TST     lr,#1                           ; Check bit 0 (set if THUMB mode) 
    ORRNE   r3,r3,#THUMB_BIT                ; Set THUMB bit if caller in THUMB mode 
 
    ; Save CPSR on stack (with caller's lock-out bits / mode set correctly) 
 
    STR     r3,[sp, #-4]! 
 
    ; Place the solicited stack type value on the top of the stack 
 
    MOV     r2,#0                           ; Build solicited stack type value 
    STR     r2,[sp, #-4]!                   ; Place it on the top of the stack 
 
    ; Setup a pointer to the thread control block and clear the current 
    ; thread control block pointer. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r0,[r1]                         ; Pickup current thread pointer 
    STR     r2,[r1]                         ; Set current thread pointer to NU_NULL 
 
    ; Check to see if a time slice is active. 
 
    LDR     r3,TCT_Slice_State              ; Pickup time slice state address 
    LDR     r1,[r3]                         ; Pickup time slice state flag 
    CMP     r1,#0                           ; Compare with active value 
    BNE     TCT_No_Stop_TS_3                ; If non-active, don't disable 
 
    ; Insure that the next time the task runs it gets a fresh time slice 
 
    LDR     r1,[r0, #TC_TIME_SLICE]         ; Pickup original time slice 
    STR     r1,[r0, #TC_CUR_TIME_SLICE]     ; Reset current time slice 
 
    ; Set the time-slice state to NOT_ACTIVE. 
 
    MOV     r2,#1                           ; Build disable value 
    STR     r2,[r3]                         ; Disable time slice 
 
TCT_No_Stop_TS_3 
 
    ; Save off the current stack pointer in the control block. 
 
    STR     sp,[r0, #TC_STACK_POINTER] 
 
    ; Switch to the system stack. 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r2,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r2]                        ; Setup system stack limit 
 
    ; Finished, return to the scheduling loop 
 
    B       _TCT_Schedule 
 
TCT_Not_Waiting_Unspec 
 
    ; Restore interrupts to original level 
 
    MSR     CPSR,r3 
 
TCT_Skip_Unprot_Spec 
 
    ; Return to caller. 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Set_Current_Protect 
;* 
;*  DESCRIPTION 
;* 
;*      This function sets the current protection field of the current 
;*      thread's control block to the specified protection pointer. 
;* 
;*  CALLED BY 
;* 
;*      TCC_Resume_Task                 Resume task function 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Pointer to protection block 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Set_Current_Protect(TC_PROTECT *protect) 
 
    .def    _TCT_Set_Current_Protect 
_TCT_Set_Current_Protect 
 
    ; Determine if the caller is in a task or HISR thread. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r1,[r1]                         ; Pickup current thread pointer 
    CMP     r1,#0                           ; Check to see if a thread is active 
 
    ; If the caller is in a task or HISR, modify the current protection. 
 
    STRNE   r0,[r1, #TC_CURRENT_PROTECT] 
 
    ; Return to caller. 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Protect_Switch 
;* 
;*  DESCRIPTION 
;* 
;*      This function waits until a specific task no longer has any 
;*      protection associated with it.  This is necessary since task's 
;*      cannot be suspended or terminated unless they have released all 
;*      of their protection. 
;* 
;*  CALLED BY 
;* 
;*      System Components 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Pointer to protection block 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Protect_Switch(TC_TCB *task) 
 
    .def    _TCT_Protect_Switch 
_TCT_Protect_Switch 
 
    ; Lockout interrupts. 
 
    MRS     r1,CPSR                         ; Pickup current CPSR 
    STMDB   sp!,{r1}                        ; Save CPSR on stack 
 
TCT_Swtich_Loop 
 
    ORR     r1,r1,#LOCKOUT                  ; Place lockout value in 
    MSR     CPSR,r1                         ; Lockout interrupts 
 
    ; Wait until the specified task has no protection associated with it. 
 
    LDR     r1,[r0, #TC_CURRENT_PROTECT]    ; Pickup protection of specified thread 
    CMP     r1,#0                           ; Does the specified thread have 
                                            ; an active protection? 
    BEQ     TCT_Switch_Done                 ; If not, protect switch is done 
 
    ; Indicate that a higher priority thread is waiting. 
 
    MOV     r2,#1                           ; Build waiting flag value 
    STR     r2,[r1, #TC_THREAD_WAIT]        ; Set waiting flag 
 
    ; Save r0 and lr on stack 
 
    STMDB   sp!,{r0,lr} 
 
    ; Get address of thread holding protection 
 
    LDR     r0,[r1, #TC_TCB_PTR] 
 
    ; Schedule the protected thread 
 
    BL      _TCT_Schedule_Protected 
 
    ; Restore registers 
 
    LDMIA   sp!,{r0,lr} 
 
    ; Pickup current CPSR 
 
    MRS     r1,CPSR 
 
    ; Keep looping until switch complete (protection free) 
 
    B       TCT_Swtich_Loop 
 
TCT_Switch_Done 
 
    ; Restore interrupts. 
 
    LDMIA   sp!,{r1}                        ; Get saved CPSR off stack 
    MSR     CPSR,r1                         ; Restore CPSR 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Schedule_Protected 
;* 
;*  DESCRIPTION 
;* 
;*      This function saves the minimal context of the thread and then 
;*      directly schedules the thread that has protection over the 
;*      the thread that called this routine. 
;* 
;*  CALLED BY 
;* 
;*      TCT_Protect 
;*      TCT_Protect_Switch 
;* 
;*  CALLS 
;* 
;*      TCT_Control_To_Thread           Transfer control to protected 
;*                                      thread 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      EAX, EDX, ESP 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Schedule_Protected(TC_TCB *task) 
 
    .def    _TCT_Schedule_Protected 
_TCT_Schedule_Protected 
 
    ; Interrupts are already locked out by the caller. 
    ; Save minimal context required by the system. 
 
    STMDB   sp!,{r4-r12,lr}                 ; Save minimal context 
 
    ; Pickup current CPSR 
 
    MRS     r1,CPSR 
 
    ; Check to see if caller was in THUMB mode 
    ; and update saved CPSR accordingly 
 
    TST     lr,#1                           ; Check bit 0 (set if THUMB mode) 
    ORRNE   r1,r1,#THUMB_BIT                ; Set THUMB bit if caller in THUMB mode 
 
    ; Save CPSR on stack (with caller's lock-out bits / mode set correctly) 
 
    STR     r1,[sp, #-4]! 
 
    ; Put solicited stack type on top of the stack 
 
    MOV     r2,#0                           ; Build solicited stack type value 
                                            ; and NU_NULL value 
    STR     r2,[sp, #-4]!                   ; Place it on the top of the stack 
 
    ; Setup a pointer to the thread control block and clear it. 
 
    LDR     r3,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r1,[r3]                         ; Get current thread pointer address 
    STR     r2,[r3]                         ; Set current thread pointer to NU_NULL 
 
    ; Check to see if a time slice is active. 
 
    LDR     r3,TCT_Slice_State              ; Pickup time slice state address 
    LDR     r2,[r3]                         ; Pickup time slice state flag 
    CMP     r2,#0                           ; Compare with active value 
    BNE     TCT_No_Stop_TS_4                ; If non-active, don't disable 
 
    ; Insure that the next time the task runs it gets a fresh time slice 
 
    LDR     r2,[r1, #TC_TIME_SLICE]         ; Pickup original time slice 
    STR     r2,[r1, #TC_CUR_TIME_SLICE]     ; Reset current time slice 
 
    ; Set time-slice state to NOT_ACTIVE. 
 
    MOV     r2,#1                           ; Build disable value 
    STR     r2,[r3]                         ; Disable time slice 
 
TCT_No_Stop_TS_4 
 
    ; Save off the current stack pointer in the control block. 
 
    STR     sp,[r1, #TC_STACK_POINTER] 
 
    ; Switch to the system stack and system stack limit 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r2,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r2]                        ; Setup system stack limit 
 
    ; Transfer control to the specified thread directly. 
 
    B       _TCT_Control_To_Thread 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Interrupt_Context_Save 
;* 
;*  DESCRIPTION 
;* 
;*      This function saves the interrupted thread's context.  Nested 
;*      interrupts are also supported.  If a task or HISR thread was 
;*      interrupted, the stack pointer is switched to the system stack 
;*      after the context is saved. 
;* 
;*  CALLED BY 
;* 
;*      Application ISRs                Assembly language ISRs 
;*      INT_IRQ_Shell                   IRQ Interrupt handler shell 
;*      INT_FIQ_Shell                   FIQ Interrupt handler shell 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Interrupt's vector number 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3, r4, r5, sp, CPSR 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID  TCT_Interrupt_Context_Save(vector) 
 
    .def    _TCT_Interrupt_Context_Save 
_TCT_Interrupt_Context_Save 
 
 
    .if NU_TEST3_SUPPORT 
     
    STMDB   sp!,{r0,r12,lr} 
    BL      _Set_Context_Save_Start 
    LDMIA   sp!,{r0,r12,lr}  
     
    .endif 
     
    ; Determine if this is a nested interrupt. 
 
    LDR     r1,TCT_Int_Count                ; Pickup address of interrupt count 
    LDR     r2,[r1]                         ; Pickup interrupt counter 
    ADD     r2,r2,#1                        ; Add 1 to interrupt counter 
    STR     r2,[r1]                         ; Store new interrupt counter value 
    CMP     r2,#1                           ; Is this first interrupt? 
    BNE     TCT_Nested_Save                 ; If not first interrupt, do nested save 
 
    .if  NU_FIQ_SUPPORT 
 
    ; Check for a special nested case.  A special nested case occurs when 
    ; a second interrupt goes off before TCT_Int_Count is incremented. 
 
    MRS     r1,SPSR                         ; Pickup value of SPSR 
    AND     r1,r1,#MODE_MASK                ; Clear all but mode from SPSR 
    TEQ     r1,#IRQ_MODE                    ; Check to see if in IRQ Mode 
    BNE     TCT_Normal_Save                 ; If not equal, a normal save is done 
 
    ; Set special nested flag 
 
    MOV     r1,#1 
    LDR     r2,TCT_Special_Nested1          ; Get address of special nested flag 
    STR     r1,[r2]                         ; Set flag to 1 
 
    ; Check if a thread is executing 
 
    LDR     r1,TCT_Current_Thread1          ; Get current thread pointer 
    LDR     r1,[r1]                         ; Get current thread 
    CMP     r1,#0                           ; Is a thread running? 
    BNE     TCT_Thread_Save                 ; No, just do a normal context save 
 
    .else 
 
    B       TCT_Normal_Save 
 
    .endif   ; NU_FIQ_SUPPORT 
 
TCT_Nested_Save 
 
    ; Save the necessary exception registers into r1-r3 
 
    MOV     r1,sp                           ; Put the exception sp into r1 
    MOV     r2,lr                           ; Move the return address for the caller 
                                            ; of this function into r2 
    MRS     r3,spsr                         ; Put the exception spsr into r3 
 
    ; Adjust the exception stack pointer for future exceptions 
 
    ADD     sp,sp,#24                       ; sp will point to enable reg value when done 
 
    ; Switch CPU modes to save context on system stack 
 
    MRS     r5,CPSR                         ; Pickup the current CPSR 
    BIC     r5,r5,#MODE_MASK                ; Clear the mode bits 
    ORR     r5,r5,#SUP_MODE                 ; Change to supervisor mode (SVD) 
    MSR     CPSR,r5                         ; Switch modes (IRQ->SVC) 
 
    ; Store the SVC sp into r5 so the sp can be saved as is 
 
    MOV     r5,sp 
 
    ; Save the exception return address on the stack (PC). 
 
    STMDB   r5!,{r4} 
 
    ; Save r6-r14 on stack 
 
    STMDB   r5!,{r6-r14} 
 
    ; Switch back to using sp now that the original sp has been saved. 
 
    MOV     sp,r5 
 
    ; Get r0-r5 off exception stack and save on system stack 
 
    LDMIA   r1!,{r5-r10} 
    STMDB   sp!,{r5-r10} 
 
    ; Save the SPSR on the system stack (CPSR) 
 
    STMDB   sp!,{r3} 
 
    ; Return to caller 
 
    BX      r2 
 
TCT_Normal_Save 
 
    ; Determine if a thread was interrupted. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r1,[r1]                         ; Pickup the current thread pointer 
    CMP     r1,#0                           ; Is it NU_NULL? 
    BEQ     TCT_Idle_Context_Save           ; If no, no real save is necessary 
 
TCT_Thread_Save 
 
    ; Yes, a thread was interrupted.  Save complete context on the 
    ; thread's stack. 
 
    ; Save the necessary exception registers into r1-r3 
 
    MOV     r1,sp                           ; Put the exception sp into r1 
    MOV     r2,lr                           ; Move the return address for the caller 
                                            ; of this function into r2 
    MRS     r3,spsr                         ; Put the exception spsr into r3 
 
    ; Adjust the exception stack pointer for future exceptions 
 
    ADD     sp,sp,#24                       ; sp will point to interrupt mask register(s) 
 
    ; Switch CPU modes to save context on thread's stack 
 
    MRS     r5,CPSR                         ; Pickup the current CPSR 
    BIC     r5,r5,#MODE_MASK                ; Clear the mode bits 
    ORR     r5,r5,#SUP_MODE                 ; Change to supervisor mode (SVC) 
    MSR     CPSR,r5                         ; Switch modes 
 
    ; Store the thread's sp into r5 so the sp can be saved as is 
 
    MOV     r5,sp 
 
    ; Save the exception return address on the stack (PC) 
 
    STMDB   r5!,{r4} 
 
    ; Save r6-r14 on stack 
 
    STMDB   r5!,{r6-r14} 
 
    ; Switch back to using sp now that the original sp has been saved. 
 
    MOV     sp,r5 
 
    ; Get r0-r5 off exception stack and save on thread's stack 
 
    LDMIA   r1!,{r5-r10} 
    STMDB   sp!,{r5-r10} 
 
    ; Save the SPSR on the system stack (CPSR) 
 
    STMDB   sp!,{r3} 
 
    ; Save stack type to the task stack (1=interrupt stack) 
 
    MOV     r1,#1 
    STMDB   sp!,{r1} 
 
    ; Save the thread's stack pointer in the control block. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r3,[r1]                         ; Pickup current thread pointer 
    STR     sp,[r3, #TC_STACK_POINTER]      ; Save stack pointer 
 
    ; Switch to the system stack / system stack limit 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r3,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r3]                        ; Setup system stack limit 
 
    ; Determine if a time slice is active.  If so, the remaining time left on 
    ; the time slice must be saved in the task's control block. 
 
    LDR     r4,TCT_Slice_State              ; Pickup time slice state address 
    LDR     r1,[r4]                         ; Pickup time slice state 
    CMP     r1,#0                           ; Determine if time slice active 
    BNE     TCT_Save_Exit                   ; If not, skip time slice reset 
 
    ; Pickup the remaining portion of the time slice and save it 
    ; in the task's control block.  */ 
 
    LDR     r5,TCT_Time_Slice               ; Pickup address of time slice left 
    LDR     r5,[r5]                         ; Pickup remaining time slice 
    STR     r5,[r3, #TC_CUR_TIME_SLICE]     ; Store remaining time slice 
 
    ; Disable time-slice timer 
 
    MOV     r1,#1                           ; Build disable time slice value 
    STR     r1,[r4]                         ; Disable time slice 
 
 
TCT_Save_Exit 
 
    .if NU_TEST3_SUPPORT 
     
    STMDB   sp!,{r0} 
    BL      _Set_Context_Save_End 
    LDMIA   sp!,{r0} 
     
    .endif 
 
    ; Return to caller ISR. 
 
    BX      r2 
 
TCT_Idle_Context_Save 
 
    MOV     r2,lr                           ; Save lr in r2 
    ADD     sp,sp,#24                       ; Adjust exception sp for future interrupts 
 
    ; Switch to supervisor mode (SVC) 
 
    MRS     r1,CPSR                         ; Pickup current CPSR 
    BIC     r1,r1,#MODE_MASK                ; Clear the current mode 
    ORR     r1,r1,#SUP_MODE                 ; Prepare to switch to supervisor mode (SVC) 
    MSR     CPSR,r1                         ; Switch mode 
 
    .if NU_TEST3_SUPPORT 
     
    STMDB   sp!,{r0} 
    BL      _Set_Context_Save_End 
    LDMIA   sp!,{r0} 
     
    .endif 
 
    ; Return to caller ISR 
 
    BX      r2 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Interrupt_Context_Restore 
;* 
;*  DESCRIPTION 
;* 
;*      This function restores the interrupt context if a nested 
;*      interrupt condition is present.  Otherwise, this routine 
;*      transfers control to the scheduling function. 
;* 
;*  CALLED BY 
;* 
;*      Application ISRs                Assembly language ISRs 
;*      INT_IRQ_Shell                   IRQ Interrupt handler shell 
;*      INT_FIQ_Shell                   FIQ Interrupt handler shell 
;* 
;*  CALLS 
;* 
;*      TCT_Schedule                    Thread scheduling function 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID    TCT_Interrupt_Context_Restore(VOID) 
 
    .def    _TCT_Interrupt_Context_Restore 
_TCT_Interrupt_Context_Restore 
 
 
    .if NU_TEST3_SUPPORT 
     
    BL      _Set_Context_Restore_Start 
     
    .endif 
     
    ; Decrement and check for nested interrupt conditions. 
 
    LDR     r1,TCT_Int_Count                ; Pickup address of interrupt count 
    LDR     r2,[r1]                         ; Pickup interrupt counter 
    SUB     r2,r2,#1                        ; Decrement interrupt counter 
    STR     r2,[r1]                         ; Store interrupt counter 
    CMP     r2,#0                           ; Is interrupt count 0? 
    BNE     TCT_Nested_Restore              ; If not 0, nested interrupt restore 
 
    .if  NU_FIQ_SUPPORT 
 
    ; Check for special nested case 
 
    LDR     r1,TCT_Special_Nested1 
    LDR     r2,[r1] 
    CMP     r2,#1 
    BNE     TCT_Not_Nested_Restore 
 
    ; Clear Special nested flag 
 
    MOV     r2,#0 
    STR     r2,[r1] 
 
    ; See if a thread was active during special nested situation 
 
    LDR     r0,TCT_Current_Thread1          ; Pickup current thread ptr address 
    LDR     r0,[r0]                         ; Pickup current thread pointer 
    CMP     r0,#0                           ; Determine if a thread is active 
    BEQ     TCT_Nested_Restore              ; If not, just do a nested restore 
 
    ; A thread was active during this special situation 
    ; Switch to this thread's stack 
 
    LDR     sp,[r0,#TC_STACK_POINTER] 
 
    ; Adjust the SP below the stack type 
 
    ADD     sp,sp,#4 
 
    .else 
 
    B       TCT_Not_Nested_Restore 
     
    .endif   ; NU_FIQ_SUPPORT 
 
TCT_Nested_Restore 
 
    LDR     r1,[sp], #4                     ; Pickup the saved CPSR 
 
    MSR     SPSR,r1                         ; Place into saved SPSR 
 
    ; Return to the point of interrupt. 
 
    LDMIA   sp,{r0-r15}^ 
 
TCT_Not_Nested_Restore 
 
    ; Clear TCD_Current_Thread 
 
    MOV     r2,#0 
    LDR     r1,TCT_Current_Thread1 
    STR     r2,[r1] 
 
    ; Reset the system stack pointer / system stack limit 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r2,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r2]                        ; Setup system stack limit 
 
    .if NU_TEST3_SUPPORT 
     
    BL      _Set_Context_Restore_End 
     
    .endif 
 
    ; Return to scheduling loop 
     
    B       _TCT_Schedule 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_Activate_HISR 
;* 
;*  DESCRIPTION 
;* 
;*      This function activates the specified HISR.  If the HISR is 
;*      already activated, the HISR's activation count is simply 
;*      decremented.  Otherwise, the HISR is placed on the appropriate 
;*      HISR priority list in preparation for execution. 
;* 
;*  CALLED BY 
;* 
;*      Application LISRs 
;* 
;*  CALLS 
;* 
;*      None 
;* 
;*  INPUTS 
;* 
;*      r0 -    Pointer to HISR to activate 
;* 
;*  OUTPUTS 
;* 
;*      r0 -    Successful completion (0 = NU_SUCCESS) 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r1, r2, r3, r4 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;STATUS  TCT_Activate_HISR(TC_HCB *HISR) 
 
    .def    _TCT_Activate_HISR 
_TCT_Activate_HISR 
 
    ; Save working registers 
 
    STR     r4,[sp, #-4]! 
 
    ; Lockout interrupts. 
 
    MRS     r4,CPSR                         ; Pickup current CPSR 
    ORR     r1,r4,#LOCKOUT                  ; Build interrupt lockout value 
    MSR     CPSR,r1                         ; Lockout interrupts 
 
    ; Determine if the HISR is already active. 
 
    LDR     r1,[r0,#TC_ACTIVATION_COUNT]    ; Pickup current activation count 
    CMP     r1,#0                           ; Is it the first activation? 
    BEQ     TCT_First_Activate              ; Yes, place it on the correct list 
 
    ; Increment the activation count.  Make sure that it does not go to zero 
 
    ADDS    r1,r1,#1                        ; Increment the activation count 
    MVNEQ   r1,#0                           ; If counter rolled-over reset 
    STR     r1,[r0,#TC_ACTIVATION_COUNT]    ; Store all ones count 
 
    ; Finished with activation 
 
    B       TCT_Activate_Done 
 
TCT_First_Activate 
 
    ; Set the activation count to 1 
 
    MOV     r1,#1                           ; Initial activation count 
    STR     r1,[r0,#TC_ACTIVATION_COUNT]    ; Store initial activation count 
 
    ; Get HISR Tails address 
 
    LDR     r2,TCT_HISR_Tails               ; Pickup tail pointer base 
 
    ; Pickup the HISR's priority and adjust for offset in HISR head / tail lists 
 
    LDRB    r1,[r0,#TC_PRIORITY]            ; Pickup priority of HISR 
    MOV     r1,r1,LSL #2                    ; Multiply by 4 to get offset 
 
    ; Determine if there is something in the given priority list. 
 
    LDR     r3,[r2,r1]                      ; Pickup tail pointer for priority 
    CMP     r3,#0                           ; Is this first HISR at priority? 
    BEQ     TCT_First_HISR                  ; No, append to end of HISR list 
 
    ; Something is already on this list.  Add after the tail. 
 
    STR     r0,[r3,#TC_ACTIVE_NEXT]         ; Setup the active next pointer 
    STR     r0,[r2,r1]                      ; Setup the tail pointer 
    B       TCT_Activate_Done               ; Finished with activate processing 
 
TCT_First_HISR 
 
    ; Nothing is on this list. 
 
    LDR     r3,TCT_HISR_Heads               ; Pickup address of head pointers 
    STR     r0,[r2,r1]                      ; Set tail pointer to this HISR 
    STR     r0,[r3,r1]                      ; Set head pointer to this HISR 
 
    ; Determine the highest priority HISR. 
 
    LDR     r1,[r3]                         ; Pickup priority 0 head pointer 
    CMP     r1,#0                           ; Is priority 0 active? 
    LDREQ   r1,[r3,#4]                      ; If not, pickup priority 1 head 
    CMPEQ   r1,#0                           ; Is priority 1 active? 
    LDREQ   r1,[r3,#8]                      ; Else, must be priority 2 active 
 
    ; Set execute HISR pointer to highest priority active HISR 
 
    LDR     r0,TCT_Execute_HISR             ; Build address to execute HISR ptr 
    STR     r1,[r0]                         ; Set execute HISR to highest priority 
 
TCT_Activate_Done 
 
    ; Restore interrupt lockout 
 
    MSR     CPSR,r4 
 
    ; Build NU_SUCCESS return value 
 
    MOV     r0,#0 
 
    ; Restore working registers 
 
    LDR     r4,[sp], #4 
 
    ; Return to caller 
 
    BX      lr 
 
 
;************************************************************************ 
;* 
;*  FUNCTION 
;* 
;*      TCT_HISR_Shell 
;* 
;*  DESCRIPTION 
;* 
;*      This function is the execution shell of each and every HISR.  If 
;*      the HISR has completed its processing, this shell routine exits 
;*      back to the system.  Otherwise, it sequentially calls the HISR 
;*      routine until the activation count goes to zero. 
;* 
;*  CALLED BY 
;* 
;*      TCT_Control_To_Thread 
;* 
;*  CALLS 
;* 
;*      hisr -> tc_entry                Actual entry function of HISR 
;* 
;*  INPUTS 
;* 
;*      None 
;* 
;*  OUTPUTS 
;* 
;*      None 
;* 
;*  REGISTERS MODIFIED 
;* 
;*      r0, r1, r2, r3, r4, r5, sp, CPSR 
;* 
;*  HISTORY 
;* 
;*      NAME            DATE            REMARKS 
;* 
;*      S. Nguyen       03/28/2005      Released version 1.15.1 
;* 
;************************************************************************ 
;VOID   TCT_HISR_Shell(VOID) 
 
    .def    TCT_HISR_Shell 
TCT_HISR_Shell 
 
    ; Point at the HISR. 
 
    LDR     r0,TCT_Current_Thread1          ; Build address of thread pointer 
    LDR     r5,[r0]                         ; Pickup control block pointer 
 
TCT_HISR_Loop 
 
    ; Get global interrupt level 
 
    LDR     r2,TCT_Int_Level                ; Pickup address of interrupt level 
    LDR     r3,[r2]                         ; Pickup interrupt lockout level 
 
    ; Restore interrupts to global level 
 
    MRS     r1,CPSR                         ; Pickup current CPSR 
    BIC     r1,r1,#LOCK_MSK                 ; Clear lockout bits 
    ORR     r1,r1,r3                        ; Build new interrupt lockout 
    MSR     CPSR,r1                         ; Setup CPSR appropriately 
 
    ; Get address of HISR entry function 
 
    LDR     r4,[r5,#TC_HISR_ENTRY] 
 
    ; Check to see if HISR entry function is in THUMB mode 
 
    TST     r4,#0x01 
 
    ; Set return address based on THUMB mode 
 
    ADRNE   lr,TCT_Thumb_Return 
    ADREQ   lr,TCT_Arm_Return 
 
    ; Jump to HISR entry function 
 
    BX      r4                              ; Jump to sub-routine 
 
    .state16 
TCT_Thumb_Return 
 
    ; Use BX instruction to switch back to ARM mode 
 
    ADR     r4,TCT_Arm_Return 
    BX      r4 
 
    .state32 
TCT_Arm_Return 
 
    ; Lockout interrupts. 
 
    MRS     r1,CPSR                         ; Pickup current CPSR 
    ORR     r1,r1,#LOCKOUT                  ; Build interrupt lockout 
    BIC     r1,r1,#THUMB_BIT                ; Ensure in ARM mode 
    MSR     CPSR,r1                         ; Lockout interrupts 
 
    ; On return, decrement the activation count and check to see if 
    ; it is 0.  Once it reaches 0, the HISR should be made inactive. 
 
    LDR     r0,[r5, #TC_ACTIVATION_COUNT]   ; Pickup current activation count 
    SUBS    r0,r0,#1                        ; Subtract and set condition codes 
    STR     r0,[r5, #TC_ACTIVATION_COUNT]   ; Store new activation count 
 
    ; Keep looping until activation count is 0 
 
    BNE     TCT_HISR_Loop 
 
    ; Get addresses of HISR_Heads array, Execute HISR, and HISR_Tails 
 
    LDR     r1,TCT_HISR_Heads               ; Pickup head pointers address 
    LDR     r2,TCT_Execute_HISR             ; Build address to execute HISR ptr 
    LDR     r4,TCT_HISR_Tails               ; Pickup tail pointers address 
 
    ; Get the current HISR's priority and adjust for offset into 
    ; HISR_Heads and HISR_Tails arrays 
 
    LDRB    r3,[r5,#TC_PRIORITY]            ; Get HISR priority 
    MOV     r3,r3,LSL #2                    ; Multiply by 4 to get offset 
 
    ; Determine if this is the only HISR on the given priority list. 
 
    LDR     r6,[r4,r3]                      ; Get tail pointer for this priority 
    CMP     r6,r5                           ; Is this priority tail the same as 
                                            ; the current HISR? 
    BNE     TCT_More_HISRs                  ; If not, more HISRs at this 
                                            ; priority 
 
    ; The only HISR on the list.  Clean up the list and check for the 
    ; highest priority HISR. 
 
    MOV     r12,#0                          ; Clear r12 
    STR     r12,[r1,r3]                     ; Set head pointer to NU_NULL 
    STR     r12,[r4,r3]                     ; Set tail pointer to NU_NULL 
 
    ; Determine the highest priority HISR. 
 
    LDR     r4,[r1]                         ; Pickup priority 0 head pointer 
    CMP     r4,#0                           ; Is there a HISR active? 
    LDREQ   r4,[r1,#4]                      ; If not, pickup priority 1 pointer 
    CMPEQ   r4,#0                           ; Is there a HISR active? 
    LDREQ   r4,[r1,#8]                      ; If not, pickup priority 2 pointer 
 
    ; Jump to set the new highest priority active HISR 
 
    B       TCT_Set_Execute_HISR 
 
TCT_More_HISRs 
 
    ; Move to the next HISR on this thread's priority list 
 
    LDR     r4,[r5,#TC_ACTIVE_NEXT]         ; Pickup next HISR to activate 
 
    ; Move head pointer for this priority to next HISR on list 
 
    STR     r4,[r1,r3] 
 
TCT_Set_Execute_HISR 
 
    ; Set-up TCD_Execute_HISR with highest priority HISR 
 
    STR     r4,[r2]                         ; Setup execute HISR pointer 
 
TCT_HISR_Exit 
 
    ; Build fake return to the top of this loop.  The next time the HISR 
    ; is activated, it will return to the top of this function. 
 
    LDR     lr,TCT_HISR_Shell1              ; Pickup address of shell entry 
    STMDB   sp!,{r4-r12,lr}                 ; Save minimal context of thread on 
                                            ; the current stack 
 
    ; Pickup the CPSR 
 
    MRS     r1,CPSR                      
 
    ; Ensure interrupt bits are clear (enabled) 
 
    BIC     r1,r1,#LOCK_MSK                 ; Clear initial interrupt lockout 
 
    ; Save CPSR on stack 
 
    STR     r1,[sp, #-4]! 
 
    ; Save stack type (0 = solicited stack) 
 
    MOV     r2, #0 
    STR     r2,[sp, #-4]! 
 
    ; Clear the current thread control block. 
 
    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address 
    STR     r2,[r1]                         ; Set current thread pointer to NU_NULL 
 
    ; Save off the current stack pointer in the control block. 
 
    STR     sp,[r5, #TC_STACK_POINTER]      ; Save the thread's stack pointer 
 
    ; Switch to the system stack / system stack limit 
 
    LDR     r1,TCT_System_Stack             ; Pickup address of stack pointer 
    LDR     r2,TCT_System_Limit1            ; Pickup address of stack limit ptr 
    LDR     sp,[r1]                         ; Switch to system stack 
    LDR     r10,[r2]                        ; Setup system stack limit 
 
    ; Transfer control to the main scheduling loop. 
 
    B       _TCT_Schedule 
 
 
;****************** 
;* THUMB SUPPORT  * 
;****************** 
 
    .if NU_THUMB_SUPPORT 
 
    ; The following section provides veneers utilized when C code calls 
    ; the Nucleus PLUS assembly files when built in THUMB mode.  These 
    ; labels allow inter-working between THUMB build C code and ARM built 
    ; assembly code.  All PLUS assembly files are build in ARM mode. 
 
;******************************** 
;* TCT_Protect Veneer for THUMB * 
;******************************** 
    .def    $TCT_Protect 
$TCT_Protect 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Protect 
 
 
;******************************************* 
;* TCT_Control_Interrupts Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Control_Interrupts 
$TCT_Control_Interrupts 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Control_Interrupts 
 
 
;************************************************** 
;* _TCT_Local_Control_Interrupts Veneer for THUMB * 
;************************************************** 
    .def    $TCT_Local_Control_Interrupts 
$TCT_Local_Control_Interrupts 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Local_Control_Interrupts 
 
;******************************************* 
;* TCT_Restore_Interrupts Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Restore_Interrupts 
$TCT_Restore_Interrupts 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Restore_Interrupts 
 
;******************************************* 
;* TCT_Build_Task_Stack Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Build_Task_Stack 
$TCT_Build_Task_Stack 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Build_Task_Stack 
 
;******************************************* 
;* TCT_Build_HISR_Stack Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Build_HISR_Stack 
$TCT_Build_HISR_Stack 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Build_HISR_Stack 
 
;******************************************* 
;* TCT_Build_Signal_Frame Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Build_Signal_Frame 
$TCT_Build_Signal_Frame 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Build_Signal_Frame 
 
;************************************ 
;* TCT_Check_Stack Veneer for THUMB * 
;************************************ 
    .def    $TCT_Check_Stack 
$TCT_Check_Stack 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Check_Stack 
 
;********************************* 
;* TCT_Schedule Veneer for THUMB * 
;********************************* 
    .def    $TCT_Schedule 
$TCT_Schedule 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Schedule 
 
;******************************************* 
;* TCT_Control_To_Thread Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Control_To_Thread 
$TCT_Control_To_Thread 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Control_To_Thread 
 
 
;******************************************* 
;* TCT_Control_To_System Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Control_To_System 
$TCT_Control_To_System 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Control_To_System 
 
 
;************************************ 
;* TCT_Signal_Exit Veneer for THUMB * 
;************************************ 
    .def    $TCT_Signal_Exit 
$TCT_Signal_Exit 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Signal_Exit 
 
 
;*************************************** 
;* TCT_Current_Thread Veneer for THUMB * 
;*************************************** 
    .def    $TCT_Current_Thread 
$TCT_Current_Thread 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Current_Thread 
 
 
;***************************************** 
;* TCT_Set_Execute_Task Veneer for THUMB * 
;***************************************** 
    .def    $TCT_Set_Execute_Task 
$TCT_Set_Execute_Task 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Set_Execute_Task 
 
 
;********************************** 
;* TCT_Unprotect Veneer for THUMB * 
;********************************** 
    .def    $TCT_Unprotect 
$TCT_Unprotect 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Unprotect 
 
 
;******************************************* 
;* TCT_Unprotect_Specific Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Unprotect_Specific 
$TCT_Unprotect_Specific 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Unprotect_Specific 
 
 
;******************************************** 
;* TCT_Set_Current_Protect Veneer for THUMB * 
;******************************************** 
    .def    $TCT_Set_Current_Protect 
$TCT_Set_Current_Protect 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Set_Current_Protect 
 
 
;*************************************** 
;* TCT_Protect_Switch Veneer for THUMB * 
;*************************************** 
    .def    $TCT_Protect_Switch 
$TCT_Protect_Switch 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Protect_Switch 
 
 
;******************************************* 
;* TCT_Schedule_Protected Veneer for THUMB * 
;******************************************* 
    .def    $TCT_Schedule_Protected 
$TCT_Schedule_Protected 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Schedule_Protected 
 
 
;************************************** 
;* TCT_Activate_HISR Veneer for THUMB * 
;************************************** 
    .def    $TCT_Activate_HISR 
$TCT_Activate_HISR 
 
    .state16 
    BX      pc 
    NOP 
 
    .state32 
    B       _TCT_Activate_HISR 
 
    .endif  ; NU_THUMB_SUPPORT 
 
    .end