line source
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* Copyright (c) 1993-1994 Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the */
+ − ;/* subject matter of this material. All manufacturing, reproduction, */
+ − ;/* use, and sales rights pertaining to this subject matter are governed */
+ − ;/* by the license agreement. The recipient of this software implicitly */
+ − ;/* accepts the terms of the license. */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FILE NAME VERSION */
+ − ;/* */
+ − ;/* tct.s PLUS/THUMB/T 1.2 */
+ − ;/* */
+ − ;/* COMPONENT */
+ − ;/* */
+ − ;/* TC - Thread Control */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This file contains the target processor dependent routines for */
+ − ;/* performing target-dependent scheduling functions. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* DATA STRUCTURES */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* FUNCTIONS */
+ − ;/* */
+ − ;/* TCT_Control_Interrupts Enable / disable interrupts */
+ − ;/* by changing */
+ − ;/* TCD_Interrupt_Level */
+ − ;/* TCT_Local_Control_Interrupts Enable/disable interrupts */
+ − ;/* by not changing */
+ − ;/* TCD_Interrupt_Level */
+ − ;/* TCT_Restore_Interrupts Restores interrupts to the */
+ − ;/* level in TCD_Interrupt_Level */
+ − ;/* 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 */
+ − ;/* */
+ − ;/* DEPENDENCIES */
+ − ;/* */
+ − ;/* cs_extr.h Common Service functions */
+ − ;/* tc_extr.h Thread Control functions */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* B. Sellew 04-19-1996 Added saving and restoring of */
+ − ;/* v5, v6, and ip, resulting in */
+ − ;/* version 1.2 (spr103) */
+ − ;/* P. Roussel (TI) 07-21-1999 Modified TCT_Schedule for GSM */
+ − ;/* small sleep implementation */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;#define NU_SOURCE_FILE
+ − ;
+ − ;#include "cs_extr.h" /* Common service functions */
+ − ;#include "tc_extr.h" /* Thread control functions */
+ − ;
+ − ;/* Define constants used in low-level initialization. */
+ − ;
+ − ;
+ − LOCKOUT .equ 00C0h ; Interrupt lockout value
+ − LOCK_MSK .equ 00C0h ; Interrupt lockout mask value
+ − MODE_MASK .equ 001Fh ; Processor Mode Mask
+ − SUP_MODE .equ 0013h ; Supervisor Mode (SVC)
+ − IRQ_MODE .equ 0012h ; Interrupt Mode (IRQ)
+ − FIQ_MODE .equ 0011h ; Fast Interrupt Mode (FIQ)
+ − ;
+ − ;
+ − ;
+ − ;/* Define a variable for saving the system stack limit in. This value is
+ − ; intialized in INT.S and is in effect whenever the system stack is in
+ − ; use. */
+ − ;
+ − ;VOID *TCT_System_Limit;
+ − ;
+ − ;/* Define internal variables so the C compiler can provide meaningful
+ − ; code with offsets into data structures. Typically, this section is
+ − ; removed after this file is compiled down to assembly language. */
+ − ;
+ − ;BYTE_PTR REG_Stack_Base;
+ − ;BYTE_PTR REG_Stack_End;
+ − ;BYTE_PTR REG_Stack_Ptr;
+ − ;UNSIGNED REG_Stack_Size;
+ − ;TC_TCB *REG_Thread_Ptr;
+ − ;TC_HCB *REG_HISR_Ptr;
+ − ;TC_PROTECT *REG_Protect_Ptr;
+ − ;VOID *REG_Function_Ptr;
+ − ;
+ − .def _TCT_System_Limit
+ − .bss _TCT_System_Limit, 4, 4
+ − ;
+ − ;
+ − .text
+ − ;
+ − ;/* Define external inner-component global data references. */
+ − ;
+ − ;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
+ − ;
+ − ;
+ − ;/* Define external function references. */
+ − ;VOID TCC_Task_Shell(VOID);
+ − ;VOID TCC_Signal_Shell(VOID);
+ − ;VOID TCT_HISR_Shell(VOID);
+ − ;VOID ERC_System_Error(INT error);
+ − ;
+ − .ref $TCC_Task_Shell
+ − .ref $TCC_Signal_Shell
+ − .ref $ERC_System_Error
+ − .ref IND_CALL
+ − ;
+ − ;/* Define internal function references. */
+ − ;VOID TCT_Schedule_Protected(VOID *thread);
+ − ;
+ − .def _TCT_Schedule_Protected
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* new_level New interrupt enable level */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* old_level Previous interrupt enable */
+ − ;/* level */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;INT TCT_Control_Interrupts (INT new_level)
+ − ;{
+ − .def $TCT_Control_Interrupts
+ − $TCT_Control_Interrupts ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Control_Interrupts
+ − ;
+ − .def _TCT_Control_Interrupts
+ − _TCT_Control_Interrupts
+ − ;
+ − ;INT old_level; /* Old interrupt level */
+ − ;
+ − ; /* lock out all interrupts before any checking or changing */
+ − ;
+ − ; /* Obtain the current interrupt lockout posture. */
+ − ; old_level = TCD_Interrupt_Level;
+ − ;
+ − ; /* Setup new interrupt lockout posture. */
+ − ; TCD_Interrupt_Level = new_level;
+ − ;
+ − ; /* renable interrupts for the specified lockout */
+ − ;
+ − ; /* Return old interrupt lockout level. */
+ − ; return(old_level);
+ − ;
+ − MRS a3,CPSR ; Pickup current CPSR
+ − ORR a3,a3,#LOCKOUT ; Build lockout CPSR
+ − MSR CPSR,a3 ; Lockout interrupts temporarily
+ − LDR a2,Int_Level ; Pickup interrupt level
+ − LDR a4,[a2, #0] ; Pickup current interrupt lockout
+ − BIC a3,a3,#LOCK_MSK ; Clear lockout mask
+ − ORR a3,a3,a1 ; Build new CPSR with appropriate
+ − ; interrupts locked out
+ − STR a1,[a2,#0] ; Save current lockout
+ − MSR CPSR,a3 ; Setup new CPSR lockout bits
+ − MOV a1,a4 ; Return previous lockout
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Local_Control_Interrupts */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function enables and disables interrupts as specified by */
+ − ;/* the caller. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* new_level New interrupt enable level */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* old_level Previous interrupt enable */
+ − ;/* level */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;INT TCT_Local_Control_Interrupts (INT new_level)
+ − ;{
+ − .def $TCT_Local_Control_Interrupts
+ − $TCT_Local_Control_Interrupts ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Local_Control_Interrupts
+ − ;
+ − .def _TCT_Local_Control_Interrupts
+ − _TCT_Local_Control_Interrupts
+ − ;
+ − ;INT old_level; /* Old interrupt level */
+ − ;
+ − ; /* read in the old level */
+ − ; old_level = current interrupt level of processor;
+ − ;
+ − MRS a3,CPSR ; Pickup current CPSR
+ − MOV a4,a3 ; save the old level
+ − ;
+ − ; /* clear out the old level and set the new level */
+ − ; current interrupt level of processor &= ~LOCKOUT;
+ − ; current interrupt level of processor |= new_level;
+ − ;
+ − BIC a3,a3,#LOCK_MSK ; Clear all current interrupts
+ − ORR a3,a3,a1 ; Build new CPSR with new
+ − ; interrupt level
+ − MSR CPSR,a3 ; Setup new CPSR interrupt bits
+ − ;
+ − ; /* Return old interrupt lockout level. */
+ − ; return(old_level);
+ − ;
+ − MOV a1,a4 ; Return previous lockout
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Restore_Interrupts */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function restores interrupts to that specified in the global*/
+ − ;/* TCD_Interrupt_Level variable. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None. */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None. */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Restore_Interrupts (VOID)
+ − ;{
+ − .def $TCT_Restore_Interrupts
+ − $TCT_Restore_Interrupts ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Restore_Interrupts
+ − ;
+ − .def _TCT_Restore_Interrupts
+ − _TCT_Restore_Interrupts
+ − ;
+ − ; /* lock out all interrupts before any checking or changing */
+ − ;
+ − ; /* Obtain the current interrupt lockout posture. */
+ − ;
+ − ; /* reload the level base on the TCD_Interrupt_Level variable */
+ − ;
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − MOV a3,a2 ; save the CPSR value
+ − ORR a2,a2,#LOCKOUT ; Build lockout CPSR
+ − MSR CPSR,a2 ; Lockout interrupts temporarily
+ − BIC a3,a3,#LOCK_MSK ; Clear current interrupt levels
+ − LDR a2,Int_Level ; Load address of TCD_Interrupt_Level
+ − LDR a1,[a2, #0] ; Pickup current interrupt lockout
+ − ORR a3,a3,a1 ; Build new CPSR with appropriate
+ − ; interrupts locked out
+ − MSR CPSR,a3 ; Setup new CPSR lockout bits
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC_Create_Task Create a new task */
+ − ;/* TCC_Reset_Task Reset the specified task */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* task Task control block pointer */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Build_Task_Stack(TC_TCB *task)
+ − ;{
+ − .def $TCT_Build_Task_Stack
+ − $TCT_Build_Task_Stack ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Build_Task_Stack
+ − ;
+ − .def _TCT_Build_Task_Stack
+ − _TCT_Build_Task_Stack
+ − ;
+ − ; /* Pickup the stack base. */
+ − ; REG_Stack_Base = (BYTE_PTR) task -> tc_stack_start;
+ − ;
+ − LDR a3,[a1,#24h] ; Pickup the stack starting address
+ − ;
+ − ; /* Pickup the stack size. */
+ − ; REG_Stack_Size = task -> tc_stack_size;
+ − ;
+ − LDR a2,[a1,#30h] ; Pickup the stack size in bytes
+ − ;
+ − ; /* Calculate the stack ending address. */
+ − ; REG_Stack_End = REG_Stack_Base + REG_Stack_Size - 1;
+ − ;
+ − ADD a4,a2,a3 ; Compute the beginning of stack
+ − BIC a4,a4,#3 ; Insure word alignment
+ − SUB a4,a4,#4 ; Reserve a word
+ − ;
+ − ; /* Save the stack ending address. */
+ − ; task -> tc_stack_end = REG_Stack_End;
+ − ;
+ − STR a4,[a1,#28h] ; Save the stack ending address
+ − ;
+ − ; /* Reference the task shell. */
+ − ; REG_Function_Ptr = (VOID *) TCC_Task_Shell;
+ − ;
+ − ; /* Build an initial stack. This initial stack frame facilitates an
+ − ; interrupt return to the TCC_Task_Shell function, which in turn
+ − ; invokes the application task. The initial stack frame has the
+ − ; following format:
+ − ;
+ − ; (Lower Address) Stack Top -> 1 (Interrupt stack type)
+ − ; CPSR Saved CPSR
+ − ; a1 Saved a1
+ − ; a2 Saved a2
+ − ; a3 Saved a3
+ − ; a4 Saved a4
+ − ; v1 Saved v1
+ − ; v2 Saved v2
+ − ; v3 Saved v3
+ − ; v4 Saved v4
+ − ; v5 Saved v5
+ − ; v6 Saved v6
+ − ; v7 Saved v7
+ − ; v8 Saved v8
+ − ; ip Saved ip
+ − ; sp Saved sp
+ − ; lr Saved lr
+ − ; (Higher Address) Stack Bottom-> pc Saved pc
+ − ; */
+ − ;
+ − LDR a3,Task_Shell ; Pickup address of shell entry
+ − STR a3,[a4], #-4 ; Store entry address on stack
+ − MOV a3,#0 ; Clear value for initial registers
+ − STR a3,[a4], #-4 ; Store initial lr
+ − ADD a3,a4,#8h ; Compute initial sp
+ − STR a3,[a4], #-4 ; Store initial sp (Stack Bottom)
+ − STR ip,[a4], #-4 ; Store ip
+ − STR a3,[a4], #-4 ; Store initial v8
+ − LDR a3,[a1,#24h] ; Pickup the stack starting address
+ − STR a3,[a4], #-4 ; Store initial v7
+ − MOV a3,#0 ; Clear value for initial registers
+ − STR v6,[a4], #-4 ; Store v6
+ − STR v5,[a4], #-4 ; Store v5
+ − STR a3,[a4], #-4 ; Store initial v4
+ − STR a3,[a4], #-4 ; Store initial v3
+ − STR a3,[a4], #-4 ; Store initial v2
+ − STR a3,[a4], #-4 ; Store initial v1
+ − STR a3,[a4], #-4 ; Store initial a4
+ − STR a3,[a4], #-4 ; Store initial a3
+ − STR a3,[a4], #-4 ; Store initial a2
+ − STR a3,[a4], #-4 ; Store initial a1
+ − MSR CPSR_FLG,a3 ; Clear the flags
+ − MRS a3,CPSR ; Pickup the CPSR
+ − BIC a3,a3,#LOCK_MSK ; Clear initial interrupt lockout
+ − ORR a3,a3,#20h ; Set to Thumb state
+ − STR a3,[a4], #-4 ; Store CPSR on the initial stack
+ − MOV a3,#1 ; Build interrupt stack type (1)
+ − STR a3,[a4, #0] ; Store stack type on the top
+ − ;
+ − ; /* Save the minimum amount of remaining stack memory. */
+ − ; task -> tc_stack_minimum = REG_Stack_Size - 72;
+ − ;
+ − MOV a3,#72 ; Size of interrupt stack frame
+ − SUB a2,a2,a3 ; Compute minimum available bytes
+ − STR a2,[a1, #34h] ; Save in minimum stack area
+ − ;
+ − ; /* Save the new stack pointer into the task's control block. */
+ − ; task -> tc_stack_pointer = (VOID *) Stack_Top;
+ − ;
+ − STR a4,[a1, #2Ch] ; Save stack pointer
+ − BX lr
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Build_HISR_Stack */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function builds an HISR stack frame that allows quick */
+ − ;/* scheduling of the HISR. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC_Create_HISR Create HISR function */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* hisr HISR control block pointer */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Build_HISR_Stack(TC_HCB *hisr)
+ − ;{
+ − .def $TCT_Build_HISR_Stack
+ − $TCT_Build_HISR_Stack ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Build_HISR_Stack
+ − ;
+ − .def _TCT_Build_HISR_Stack
+ − _TCT_Build_HISR_Stack
+ − ;
+ − ; /* Pickup the stack base. */
+ − ; REG_Stack_Base = (BYTE_PTR) hisr -> tc_stack_start;
+ − ;
+ − LDR a3,[a1,#24h] ; Pickup the stack starting address
+ − ;
+ − ; /* Pickup the stack size. */
+ − ; REG_Stack_Size = hisr -> tc_stack_size;
+ − ;
+ − LDR a2,[a1,#30h] ; Pickup the stack size in bytes
+ − ;
+ − ; /* Calculate the stack ending address. */
+ − ; REG_Stack_End = REG_Stack_Base + REG_Stack_Size;
+ − ;
+ − ADD a4,a2,a3 ; Compute the beginning of stack
+ − BIC a4,a4,#3 ; Insure word alignment
+ − SUB a4,a4,#4 ; Reserve a word
+ − ;
+ − ; /* Save the stack ending address. */
+ − ; hisr -> tc_stack_end = REG_Stack_End;
+ − ;
+ − STR a4,[a1,#28h] ; Save the stack ending address
+ − ;
+ − ; /* Reference the HISR shell. */
+ − ; REG_Function_Ptr = (VOID *) TCT_HISR_Shell;
+ − ;
+ − ; /* Build an initial stack. This initial stack frame facilitates an
+ − ; solicited return to the TCT_HISR_Shell function, which in turn
+ − ; invokes the appropriate HISR. The initial HISR stack frame has the
+ − ; following format:
+ − ;
+ − ; (Lower Address) Stack Top -> 0 (Solicited stack type)
+ − ; 0/0x20 Saved state mask
+ − ; v1 Saved v1
+ − ; v2 Saved v2
+ − ; v3 Saved v3
+ − ; v4 Saved v4
+ − ; v5 Saved v5
+ − ; v6 Saved v6
+ − ; v7 Saved v7
+ − ; v8 Saved v8
+ − ; ip Saved ip
+ − ; (Higher Address) Stack Bottom-> pc Saved pc
+ − ; */
+ − ;
+ − LDR a3,HISR_Shell ; Pickup address of shell entry
+ − STR a3,[a4], #-4 ; Store entry address on stack
+ − ADD a3,a4,#4h ; Compute initial sp
+ − STR ip,[a4], #-4 ; Store ip
+ − STR a3,[a4], #-4 ; Store initial v8
+ − LDR a3,[a1,#24h] ; Pickup the stack starting address
+ − STR a3,[a4], #-4 ; Store initial v7
+ − MOV a3,#0 ; Clear value for initial registers
+ − STR v6,[a4], #-4 ; Store v6
+ − STR v5,[a4], #-4 ; Store v5
+ − STR a3,[a4], #-4 ; Store initial v4
+ − STR a3,[a4], #-4 ; Store initial v3
+ − STR a3,[a4], #-4 ; Store initial v2
+ − STR a3,[a4], #-4 ; Store initial v1
+ − STR a3,[a4], #-4 ; Store initial state mask
+ − STR a3,[a4, #0] ; Store solicited stack type on the
+ − ; top of the stack
+ − ;
+ − ; /* Save the minimum amount of remaining stack memory. */
+ − ; hisr -> tc_stack_minimum = REG_Stack_Size - 44;
+ − ;
+ − MOV a3,#44 ; Size of solicited stack frame
+ − SUB a2,a2,a3 ; Compute minimum available bytes
+ − STR a2,[a1, #34h] ; Save in minimum stack area
+ − ;
+ − ; /* Save the new stack pointer into the task's control block. */
+ − ; hisr -> tc_stack_pointer = (VOID *) Stack_Top;
+ − ;
+ − STR a4,[a1, #2Ch] ; Save stack pointer
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC_Send_Signals Send signals to a task */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* task Task control block pointer */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Build_Signal_Frame(TC_TCB *task)
+ − ;{
+ − .def $TCT_Build_Signal_Frame
+ − $TCT_Build_Signal_Frame ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Build_Signal_Frame
+ − ;
+ − .def _TCT_Build_Signal_Frame
+ − _TCT_Build_Signal_Frame
+ − ;
+ − ; /* Pickup the stack pointer. */
+ − ; REG_Stack_Ptr = (BYTE_PTR) task -> tc_stack_pointer;
+ − ;
+ − LDR a4,[a1,#2ch] ; Pickup the current stack pointer
+ − ;
+ − ; /* Reference the Signal shell. */
+ − ; REG_Function_Ptr = (VOID *) TCC_Signal_Shell;
+ − ;
+ − ; /* Build a signal stack. This signal stack frame facilitates an
+ − ; solicited return to the TCC_Signal_Shell function, which in turn
+ − ; invokes the appropriate signal handler. The initial HISR stack frame
+ − ; has the following format:
+ − ;
+ − ; (Lower Address) Stack Top -> 0 (Solicited stack type)
+ − ; 0/0x20 Saved state mask
+ − ; v1 Saved v1
+ − ; v2 Saved v2
+ − ; v3 Saved v3
+ − ; v4 Saved v4
+ − ; v5 Saved v5
+ − ; v6 Saved v6
+ − ; v7 Saved v7
+ − ; v8 Saved v8
+ − ; ip Saved ip
+ − ; (Higher Address) Stack Bottom-> pc Saved pc
+ − ; */
+ − ;
+ − LDR a3,Signal_Shell ; Pickup address of shell entry
+ − STR a3,[a4], #-4 ; Store entry address on stack
+ − ADD a3,a4,#4h ; Compute initial sp
+ − STR ip,[a4], #-4 ; Store ip
+ − STR a3,[a4], #-4 ; Store initial v8
+ − LDR a3,[a1,#24h] ; Pickup the stack starting address
+ − STR a3,[a4], #-4 ; Store initial v7
+ − MOV a3,#0 ; Clear value for initial registers
+ − STR v6,[a4], #-4 ; Store v6
+ − STR v5,[a4], #-4 ; Store v5
+ − STR a3,[a4], #-4 ; Store initial v4
+ − STR a3,[a4], #-4 ; Store initial v3
+ − STR a3,[a4], #-4 ; Store initial v2
+ − STR a3,[a4], #-4 ; Store initial v1
+ − MOV a2,#20h ; Get initial state mask
+ − STR a2,[a4, #0] ; Store initial state mask
+ − STR a3,[a4, #0] ; Store solicited stack type on the
+ − ; top of the stack
+ − ;
+ − ; /* Save the new stack pointer into the task's control block. */
+ − ; task -> tc_stack_pointer = (VOID *) (REG_Stack_Ptr - REG_Stack_Size);
+ − ;
+ − STR a4,[a1, #2Ch] ; Save stack pointer
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC_Send_Signals Send signals to a task */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* ERC_System_Error System error handler */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* available bytes in stack */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;UNSIGNED TCT_Check_Stack(void)
+ − ;{
+ − .def $TCT_Check_Stack
+ − $TCT_Check_Stack ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Check_Stack
+ − ;
+ − .def _TCT_Check_Stack
+ − _TCT_Check_Stack
+ − ;
+ − ;TC_TCB *thread;
+ − ;UNSIGNED remaining;
+ − ;
+ − ; /* Pickup the current task/HISR pointer. */
+ − ; thread = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − LDR a1,Current_Thread ; Pickup address of thread pointer
+ − LDR a1,[a1,#0] ; Pickup thread pointer
+ − ;
+ − ; /* Determine if there is a current thread. */
+ − ; if (thread)
+ − ; {
+ − ;
+ − CMP a1,#0 ; Determine if a thread is active
+ − MOV a4,#0 ; Default remaining value
+ − BEQ TCT_Skip_Stack_Check ; If NU_NULL, skip stack checking
+ − ;
+ − ; /* Determine if the stack pointers are out of range. */
+ − ; if ((thread -> tc_stack_pointer < thread -> tc_stack_start) ||
+ − ; (thread -> tc_stack_pointer > thread -> tc_stack_end))
+ − ;
+ − LDR a3,[a1,#24h] ; Pickup start of stack area
+ − CMP sp,a3 ; Compare with current stack ptr
+ − BLT TCT_Stack_Range_Error ; If less, stack is out of range
+ − LDR a2,[a1,#28h] ; Pickup end of stack area
+ − CMP sp,a2 ; Compare with current stack ptr
+ − BLE TCT_Stack_Range_Okay ; If less, stack range is okay
+ − ;
+ − ; /* Stack overflow condition exits. */
+ − ; ERC_System_Error(NU_STACK_OVERFLOW);
+ − ;
+ − TCT_Stack_Range_Error
+ − ;
+ − STR lr,[sp, #4]! ; Store lr on the stack
+ − MOV a1,#3 ; Build NU_STACK_OVERFLOW code
+ − LDR a4,System_Error ; Call system error handler. Note:
+ − BX a4 ; control is not returned!
+ − ; Examine stack to find return
+ − ; address of this routine.
+ − TCT_Stack_Range_Okay
+ − ;
+ − ; /* Calculate the amount of available space on the stack. */
+ − ; remaining = (BYTE_PTR) thread -> tc_stack_pointer -
+ − ; (BYTE_PTR) thread -> tc_stack_start;
+ − ;
+ − SUB a4,sp,a3 ; Calculate remaining stack size
+ − ;
+ − ; /* Determine if there is enough memory on the stack to save all of the
+ − ; registers. */
+ − ; if (remaining < 80)
+ − ;
+ − CMP a4,#80 ; Is there enough room for an
+ − ; interrupt frame?
+ − BCS TCT_No_Stack_Error ; If so, no stack overflow yet
+ − ;
+ − ; /* Stack overflow condition is about to happen. */
+ − ; ERC_System_Error(NU_STACK_OVERFLOW);
+ − ;
+ − STR lr,[sp, #4]! ; Store lr on the stack
+ − MOV a1,#3 ; Build NU_STACK_OVERFLOW code
+ − LDR a4,System_Error ; Call system error handler. Note:
+ − BX a4 ; control is not returned!
+ − ; Examine stack to find return
+ − ; address of this routine.
+ − TCT_No_Stack_Error
+ − ;
+ − ; /* Determine if this is a new minimum amount of stack space. */
+ − ; if (remaining < thread -> tc_stack_minimum)
+ − ;
+ − LDR a3,[a1,#34h]
+ − CMP a4,a3
+ − STRCC a4,[a1,#34h]
+ − ;
+ − ; /* Save the new stack minimum. */
+ − ; thread -> tc_stack_minimum = remaining;
+ − ; }
+ − ; else
+ − ;
+ − ; /* Set the remaining bytes to 0. */
+ − ; remaining = 0;
+ − ;
+ − ; /* Return the remaining number of bytes on the stack. */
+ − ; return(remaining);
+ − ;
+ − TCT_Skip_Stack_Check
+ − MOV a1,a4 ; Return remaining bytes
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCC_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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* INC_Initialize Main initialization routine */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* TCT_Control_To_Thread Transfer control to a thread */
+ − ;/* INT_Small_Sleep GSM small sleep */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* TCD_Execute_Task Pointer to task to execute */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* P. Roussel (TI) 07-21-1999 Call GSM small sleep */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Schedule(void)
+ − ;{
+ − .def $TCT_Schedule
+ − $TCT_Schedule ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Schedule
+ − ;
+ − .def _TCT_Schedule
+ − _TCT_Schedule
+ − ;
+ − ; /* Restore interrupts according to the value contained in
+ − ; TCD_Interrupt_Level. */
+ − ;
+ − LDR a2,Int_Level ; Build address of interrupt level
+ − MRS a1,CPSR ; Pickup current CPSR
+ − LDR a3,[a2, #0] ; Pickup current interrupt lockout
+ − BIC a1,a1,#LOCK_MSK ; Clear the interrupt lockout bits
+ − ORR a1,a1,a3 ; Build new interrupt lockout CPSR
+ − MSR CPSR,a1 ; Setup new CPSR
+ − LDR a3,Execute_HISR ; Pickup TCD_Execute_HISR address
+ − LDR a4,Execute_Task ; Pickup TCD_Execute_Task address
+ − ;
+ − ; /* Wait until a thread (task or HISR) is available to execute. */
+ − ; do
+ − ; {
+ − .def TCT_Schedule_Loop
+ − TCT_Schedule_Loop
+ − ;
+ − ; } while ((!TCD_Execute_HISR) && (!TCD_Execute_Task));
+ − ;
+ − LDR a1,[a3, #0] ; Pickup highest priority HISR ptr
+ − CMP a1,#0 ; Is there a HISR active?
+ − BNE TCT_Schedule_Thread ; Found an HISR
+ − LDR a1,[a4, #0] ; Pickup highest priority Task ptr
+ − CMP a1,#0 ; Is there a task active?
+ −
+ − .ref INT_Small_Sleep
+ − BEQ INT_Small_Sleep ; No, enter the GSM Small Sleep mode
+ −
+ − ;
+ − ; /* Yes, either a task or an HISR is ready to execute. Lockout
+ − ; interrupts while the thread is transferred to. */
+ − ;
+ − TCT_Schedule_Thread
+ − MRS a2,CPSR ; Pickup CPSR again
+ − ORR a2,a2,#LOCKOUT ; Build interrupt lockout value
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; /* Transfer control to the thread by falling through to the following
+ − ; routine. */
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCT_Schedule Indirectly called */
+ − ;/* TCT_Protect Protection task switch */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* thread Thread control block pointer */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Control_To_Thread(TC_TCB *thread)
+ − ;{
+ − ;
+ − _TCT_Control_To_Thread
+ − ;
+ − ; /* Setup the current thread pointer. */
+ − ; TCD_Current_Thread = (VOID *) thread;
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a3,[a1, #1ch] ; Pickup scheduled count
+ − STR a1,[a2, #0] ; 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
+ − .endif
+ − ;
+ − ; /* Increment the thread scheduled counter. */
+ − ; thread -> tc_scheduled++;
+ − ;
+ − LDR a4,[a1, #20h] ; Pickup time slice value
+ − ADD a3,a3,#1 ; Increment the scheduled count
+ − STR a3,[a1, #1ch] ; Store new scheduled count
+ − ;
+ − ; /* Check for time slice option. */
+ − ; if (thread -> tc_cur_time_slice)
+ − ; {
+ − CMP a4,#0 ; Is there a time slice?
+ − BEQ TCT_No_Start_TS_1 ; If 0, there is no time slice
+ − ;
+ − ; /* Start a time slice. */
+ − ; TMD_Time_Slice = thread -> tc_cur_time_slice;
+ − ; TMD_Time_Slice_State = 0;
+ − ;
+ − LDR a3,Time_Slice ; Pickup address of TMD_Time_Slice
+ − LDR a2,Slice_State ; Pickup address of
+ − ; TMD_Time_Slice_State
+ − STR a4,[a3,#0] ; Setup the time slice
+ − MOV a3,#0 ; Build active state flag
+ − STR a3,[a2,#0] ; Set the active flag
+ − ; }
+ − TCT_No_Start_TS_1
+ − ;
+ − ; /* Pickup the stack pointer and resume the thread. */
+ − ; REG_Stack_Ptr = thread -> tc_stack_pointer;
+ − ;
+ − LDR sp,[a1, #2ch] ; Switch to thread's stack pointer
+ − ;
+ − ; /* Pop off the saved information associated with the thread. After we
+ − ; determine which type of stack is present. A 1 on the top of the
+ − ; stack indicates an interrupt stack, while a 0 on the top of the
+ − ; stack indicates a solicited type of stack. */
+ − ;
+ − ; /* Remember that the interrupt level that is restored must represent
+ − ; the interrupt level in TCD_Interrupt_Level. */
+ − ;
+ − LDR a2,[sp], #4 ; Pop off the stack type
+ − CMP a2,#1 ; See if it is an interrupt stack
+ − BEQ TCT_Interrupt_Resume ; If so, an interrupt resume of
+ − ; thread is required
+ − LDR a2,Int_Level ; Pickup address of interrupt
+ − ; lockout
+ − MRS a1,CPSR ; Pickup current CPSR
+ − BIC a1,a1,#LOCK_MSK ; Clear lockout mask
+ − LDR a3,[a2, #0] ; Pickup interrupt lockout mask
+ − ORR a1,a1,a3 ; Build new interrupt lockout mask
+ − LDR a3,[sp], #4 ; Pop off the state mask
+ − ORR a1,a1,a3 ; Set appropriate state
+ − MSR SPSR,a1 ; Place in the SPSR
+ − LDMIA sp!,{v1-ip,pc}^ ; A solicited return is required.
+ − ;
+ − TCT_Interrupt_Resume
+ − LDR a1,[sp],#4 ; Pop off the CPSR
+ − LDR a2,Int_Level ; Pickup address of interrupt
+ − ; lockout
+ − BIC a1,a1,#LOCK_MSK ; Clear lockout mask
+ − LDR a3,[a2, #0] ; Pickup interrupt lockout mask
+ − ORR a1,a1,a3 ; Build new interrupt lockout mask
+ − MSR SPSR,a1 ; Place it into the SPSR
+ − LDMIA sp,{a1-pc}^ ; Recover all registers and resume
+ − ; at point of interrupt
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Other Components */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* TCT_Schedule Schedule the next thread */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Control_To_System(void)
+ − ;{
+ − .def $TCT_Control_To_System
+ − $TCT_Control_To_System ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Control_To_System
+ − ;
+ − .def _TCT_Control_To_System
+ − _TCT_Control_To_System
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a1,CPSR ; Pickup current CPSR
+ − ORR a1,a1,#LOCKOUT ; Build interrupt lockout value
+ − MSR CPSR,a1 ; Lockout interrupts
+ − ;
+ − ; /* Save a minimal context of the thread. */
+ − ;
+ − STMDB sp!,{v1-ip,lr} ; Save minimal context of thread on
+ − ; the current stack
+ − MOV a3,lr ; Determine what state the
+ − MOV a3,a3,LSL #31 ; caller was in and build an
+ − MOV a3,a3,LSR #26 ; appropriate state mask
+ − STR a3,[sp, #-4]! ; Place it on the stack
+ − MOV a3,#0 ; Build solicited stack type value
+ − ; and NU_NULL value
+ − STR a3,[sp, #-4]! ; Place it on the top of the stack
+ − ;
+ − ; /* Setup a pointer to the thread control block. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a1,[a2, #0] ; Pickup current thread pointer
+ − ;
+ − ; /* Clear the current thread control block pointer. */
+ − ; TCD_Current_Thread = NU_NULL;
+ − ;
+ − LDR a4,Slice_State ; Pickup time slice state address
+ − STR a3,[a2, #0] ; Set current thread pointer to
+ − ; NU_NULL
+ − ;
+ − ; /* Check to see if a time slice is active. If so, copy the original time
+ − ; slice into the current time slice field of the task's control block. */
+ − ; if (TMD_Time_Slice_State == 0)
+ − ; {
+ − LDR a2,[a4, #0] ; Pickup time slice state flag
+ − CMP a2,#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. */
+ − ; REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
+ − ;
+ − LDR a2,[a1, #40h] ; Pickup original time slice
+ − ;
+ − ; /* Clear any active time slice by setting the state to NOT_ACTIVE. */
+ − ; TMD_Time_Slice_State = 1;
+ − ;
+ − MOV a3,#1 ; Build disable value
+ − STR a3,[a4, #0] ; Disable time slice
+ − STR a2,[a1, #20h] ; Reset current time slice
+ − ; }
+ − TCT_No_Stop_TS_1
+ − ;
+ − ; /* Save off the current stack pointer in the control block. */
+ − ; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
+ − ;
+ − STR sp,[a1, #2ch] ; Save the thread's stack pointer
+ − ;
+ − ; /* Clear the task's current protection. */
+ − ; (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
+ − ; REG_Thread_Ptr -> tc_current_protect = NU_NULL;
+ − ;
+ − LDR a2,[a1, #38h] ; Pickup current thread pointer
+ − MOV a3,#0 ; Build NU_NULL value
+ − STR a3,[a1, #38h] ; Clear the protect pointer field
+ − STR a3,[a2, #0] ; Release the actual protection
+ − ;
+ − ; /* Switch to the system stack. */
+ − ; REG_Stack_Ptr = TCD_System_Stack;
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC_Signal_Shell Signal handling shell func */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* TCT_Schedule Scheduler */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Signal_Exit(void)
+ − ;{
+ − .def $TCT_Signal_Exit
+ − $TCT_Signal_Exit ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Signal_Exit
+ − ;
+ − .def _TCT_Signal_Exit
+ − _TCT_Signal_Exit
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a4,CPSR ; Pickup current CPSR
+ − ORR a4,a4,#LOCKOUT ; Build lockout value
+ − MSR CPSR,a4 ; Lockout interrupts
+ − ;
+ − ; /* Setup a pointer to the thread control block. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − LDR a2,Current_Thread ; Pickup address of thread pointer
+ − MOV a3,#0 ; Build NU_NULL value
+ − LDR a1,[a2,#0] ; Pickup current thread pointer
+ − ;
+ − ; /* Clear the current thread control block. */
+ − ; TCD_Current_Thread = NU_NULL;
+ − ;
+ − LDR a4,Slice_State ; Pickup time slice state address
+ − STR a3,[a2, #0] ; Clear current thread pointer
+ − ;
+ − ; /* Check to see if a time slice is active. If so, copy the original time
+ − ; slice into the current time slice field of the task's control block. */
+ − ; if (TMD_Time_Slice_State == 0)
+ − ; {
+ − ;
+ − LDR a2,[a4, #0] ; Pickup time slice state flag
+ − CMP a2,#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. */
+ − ; REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
+ − ;
+ − LDR a2,[a1, #40h] ; Pickup original time slice
+ − ;
+ − ; /* Clear any active time slice by setting the state to NOT_ACTIVE. */
+ − ; TMD_Time_Slice_State = 1;
+ − ;
+ − MOV a3,#1 ; Build disable value
+ − STR a3,[a4, #0] ; Disable time slice
+ − STR a2,[a1, #20h] ; Reset current 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. */
+ − ; REG_Thread_Ptr -> tc_stack_pointer =
+ − ; REG_Thread_Ptr -> tc_saved_stack_ptr;
+ − ;
+ − LDR a2,[a1, #3ch] ; Pickup saved stack pointer
+ − STR a2,[a1, #2ch] ; Place in current stack pointer
+ − ;
+ − ; /* Clear the task's current protection. */
+ − ; (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
+ − ; REG_Thread_Ptr -> tc_current_protect = NU_NULL;
+ − ;
+ − LDR a2,[a1, #38h] ; Pickup current thread pointer
+ − MOV a3,#0 ; Build NU_NULL value
+ − STR a3,[a1, #38h] ; Clear the protect pointer field
+ − STR a3,[a2, #0] ; Release the actual protection
+ − ;
+ − ; /* Switch to the system stack. */
+ − ; REG_Stack_Ptr = (BYTE_PTR) TCD_System_Stack;
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* System Components */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* Pointer to current thread */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID *TCT_Current_Thread(void)
+ − ;{
+ − .def $TCT_Current_Thread
+ − $TCT_Current_Thread ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Current_Thread
+ − ;
+ − .def _TCT_Current_Thread
+ − _TCT_Current_Thread
+ − ;
+ − ; /* Return the current thread pointer. */
+ − ; return(TCD_Current_Thread);
+ − ;
+ − LDR a1,Current_Thread ; Pickup address of thread pointer
+ − LDR a1,[a1, #0] ; Pickup current thread pointer
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Set_Execute_Task */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function sets the current task to execute variable under */
+ − ;/* protection against interrupts. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC Scheduling Routines */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* task Pointer to task control block*/
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* TCD_Execute_Task Modified variable */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Set_Execute_Task(TC_TCB *task)
+ − ;{
+ − .def $TCT_Set_Execute_Task
+ − $TCT_Set_Execute_Task ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Set_Execute_Task
+ − ;
+ − .def _TCT_Set_Execute_Task
+ − _TCT_Set_Execute_Task
+ − ;
+ − ; /* Now setup the TCD_Execute_Task pointer. */
+ − ; TCD_Execute_Task = task;
+ − ;
+ − LDR a2,Execute_Task ; Pickup execute task ptr address
+ − STR a1,[a2,#0] ; Setup new task to execute
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Protect */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function protects against multiple thread access. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* System Components */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* protect Pointer to protection block */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Protect(TC_PROTECT *protect)
+ − ;{
+ − .def $TCT_Protect
+ − $TCT_Protect ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Protect
+ − ;
+ − .def _TCT_Protect
+ − _TCT_Protect
+ − ;
+ − ; /* Determine if the caller is in a task or HISR thread. */
+ − ; if (TCD_Current_Thread)
+ − ; {
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a4,[a2, #0] ; Pickup current thread pointer
+ − CMP a4,#0 ; Check to see if it is non-NULL
+ − BEQ TCT_Skip_Protect ; If NULL, skip protection
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Place lockout value in
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; /* Wait until the protect structure is available. */
+ − ; while (protect -> tc_tcb_pointer != NU_NULL)
+ − ; {
+ − ;
+ − TCT_Protect_Loop
+ − LDR a2,[a1, #0] ; Pickup protection owner field
+ − CMP a2,#0 ; Is there any protection?
+ − BEQ TCT_Protect_Available ; If NU_NULL, no current protection
+ − ;
+ − ; /* Protection structure is not available. */
+ − ;
+ − ; /* Indicate that another thread is waiting. */
+ − ; protect -> tc_thread_waiting = 1;
+ − ;
+ − MOV a3,#1 ; Build thread waiting flag
+ − STR a3,[a1, #4] ; Set waiting field
+ − ;
+ − ; /* Directly schedule the thread waiting. */
+ − ; TCT_Schedule_Protected(protect -> tc_tcb_pointer);
+ − ;
+ − STR a1,[sp, #-4]! ; Save a1 on the stack
+ − STR lr,[sp, #-4]! ; Save lr on the stack
+ − MOV a1,a4 ; Place current thread into a1
+ − BL _TCT_Schedule_Protected ; Call routine to schedule the
+ − ; owner of the thread
+ − ;
+ − LDR lr,[sp], #4 ; Recover saved lr
+ − LDR a1,[sp], #4 ; Recover saved a1
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a4,[a2, #0] ; Pickup current thread pointer
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Place lockout value in
+ − MSR CPSR,a2 ; Lockout interrupts
+ − B TCT_Protect_Loop ; Examine protect flags again
+ − ; }
+ − TCT_Protect_Available
+ − ;
+ − ; /* Protection structure is available. */
+ − ;
+ − ; /* Indicate that this thread owns the protection. */
+ − ; protect -> tc_tcb_pointer = TCD_Current_Thread;
+ − ;
+ − STR a4,[a1, #0] ; Indicate calling thread owns this
+ − ; protection
+ − ;
+ − ; /* Clear the thread waiting flag. */
+ − ; protect -> tc_thread_waiting = 0;
+ − ;
+ − MOV a3,#0 ; Clear value
+ − STR a3,[a1, #4] ; Clear the thread waiting flag
+ − ;
+ − ; /* Save the protection pointer in the thread's control block. Note
+ − ; that both task and HISR threads share the same control block
+ − ; format. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ; REG_Thread_Ptr -> tc_current_protect = protect;
+ − ;
+ − STR a1,[a4, #38h] ; Setup current protection
+ − ;
+ − ; /* Restore interrupts. */
+ − ;
+ − LDR a3,Int_Level ; Pickup address of interrupt level
+ − MRS a2,CPSR ; Pickup current CPSR
+ − LDR a4,[a3, #0] ; Pickup interrupt lockout level
+ − BIC a2,a2,#LOCK_MSK ; Clear lockout bits
+ − ORR a2,a2,a4 ; Build new interrupt lockout
+ − MSR CPSR,a2 ; Setup CPSR appropriately
+ − ; }
+ − ;
+ − TCT_Skip_Protect
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* System Components */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Unprotect(void)
+ − ;{
+ − .def $TCT_Unprotect
+ − $TCT_Unprotect ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Unprotect
+ − ;
+ − .def _TCT_Unprotect
+ − _TCT_Unprotect
+ − ;
+ − ;
+ − ; /* Determine if the caller is in a task or HISR thread. */
+ − ; if (TCD_Current_Thread)
+ − ; {
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a4,[a2, #0] ; Pickup current thread pointer
+ − CMP a4,#0 ; Check to see if it is non-NULL
+ − BEQ TCT_Skip_Unprotect ; If NULL, skip unprotection
+ − ;
+ − ; /* Setup a thread control block pointer. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − ; /* Determine if there is a currently active protection. */
+ − ; if (REG_Thread_Ptr -> tc_current_protect)
+ − ; {
+ − ;
+ − LDR a1,[a4, #38h] ; Pickup current protect field
+ − CMP a1,#0 ; Is there a protection in force?
+ − BEQ TCT_Skip_Unprotect ; If not, nothing is protected
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Place lockout value in
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; /* Yes, this thread still has this protection structure. */
+ − ; REG_Protect_Ptr = REG_Thread_Ptr -> tc_current_protect;
+ − ;
+ − ; /* Is there a higher priority thread waiting for the protection
+ − ; structure? */
+ − ; if (REG_Protect_Ptr -> tc_thread_waiting)
+ − ;
+ − LDR a3,[a1, #4] ; Pickup thread waiting flag
+ − CMP a3,#0 ; Are there any threads waiting?
+ − BEQ TCT_Not_Waiting_Unpr ; If not, just release protection
+ − ;
+ − ; /* Transfer control to the system. Note that this
+ − ; automatically clears the current protection and it returns
+ − ; to the caller of this routine instead of this routine. */
+ − ; TCT_Control_To_System();
+ − ;
+ − B _TCT_Control_To_System ; Return control to the system
+ − ;
+ − ; else
+ − ; {
+ − TCT_Not_Waiting_Unpr
+ − ;
+ − ; /* Clear the protection. */
+ − ; REG_Thread_Ptr -> tc_current_protect = NU_NULL;
+ − ; REG_Protect_Ptr -> tc_tcb_pointer = NU_NULL;
+ − ;
+ − MOV a3,#0 ; Build NU_NULL value
+ − STR a3,[a1, #0] ; Release the protection
+ − STR a3,[a4, #38h] ; Clear protection pointer in the
+ − ; control block
+ − ;
+ − ; }
+ − ;
+ − TCT_Not_Protected
+ − ; /* Restore interrupts again. */
+ − ;
+ − LDR a3,Int_Level ; Pickup address of interrupt level
+ − MRS a2,CPSR ; Pickup current CPSR
+ − LDR a4,[a3, #0] ; Pickup interrupt lockout level
+ − BIC a2,a2,#LOCK_MSK ; Clear lockout bits
+ − ORR a2,a2,a4 ; Build new interrupt lockout
+ − MSR CPSR,a2 ; Setup CPSR appropriately
+ − ;
+ − ; }
+ − ; }
+ − TCT_Skip_Unprotect
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Unprotect_Specific */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function releases a specific protection structure. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application */
+ − ;/* System Components */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* protect Pointer to protection block */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Unprotect_Specific(TC_PROTECT *protect)
+ − ;{
+ − .def $TCT_Unprotect_Specific
+ − $TCT_Unprotect_Specific ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Unprotect_Specific
+ − ;
+ − .def _TCT_Unprotect_Specific
+ − _TCT_Unprotect_Specific
+ − ;
+ − ; /* Determine if the caller is in a task or HISR thread. */
+ − ; if (TCD_Current_Thread)
+ − ; {
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a4,[a2, #0] ; Pickup current thread pointer
+ − CMP a4,#0 ; Check to see if it is non-NULL
+ − BEQ TCT_Skip_Unprot_Spec ; If NULL, skip unprotect specific
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Place lockout value in
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; /* Clear the protection pointer. */
+ − ; protect -> tc_tcb_pointer = NU_NULL;
+ − ;
+ − MOV a3,#0 ; Build NU_NULL value
+ − STR a3,[a1, #0] ; Clear protection ownership
+ − ;
+ − ; /* Determine if a thread is waiting. */
+ − ; if (protect -> tc_thread_waiting)
+ − ; {
+ − ;
+ − LDR a2,[a1, #4] ; Pickup the waiting field
+ − CMP a2,#0 ; Is there another thread waiting?
+ − BEQ TCT_Not_Waiting_Unspec ; No, restore interrupts and return
+ − ;
+ − ; /* A higher-priority thread is waiting. */
+ − ;
+ − ; /* Save a minimal context of the thread. */
+ − ;
+ − STMDB sp!,{v1-ip,lr} ; Save minimal context of thread on
+ − ; the current stack
+ − MOV a3,lr ; Determine what state the
+ − MOV a3,a3,LSL #31 ; caller was in and build an
+ − MOV a3,a3,LSR #26 ; appropriate state mask
+ − STR a3,[sp, #-4]! ; Place it on the stack
+ − MOV a3,#0 ; Build solicited stack type value
+ − ; and NU_NULL value
+ − STR a3,[sp, #-4]! ; Place it on the top of the stack
+ − ;
+ − ; /* Setup a pointer to the thread control block. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a1,[a2, #0] ; Pickup current thread pointer
+ − ;
+ − ; /* Clear the current thread control block pointer. */
+ − ; TCD_Current_Thread = NU_NULL;
+ − ;
+ − LDR a4,Slice_State ; Pickup time slice state address
+ − STR a3,[a2, #0] ; Set current thread pointer to
+ − ; NU_NULL
+ − ;
+ − ; /* Check to see if a time slice is active. If so, copy the
+ − ; original time slice into the current time slice field of the
+ − ; thread's control block. */
+ − ; if (TMD_Time_Slice_State == 0)
+ − ; {
+ − ;
+ − LDR a2,[a4, #0] ; Pickup time slice state flag
+ − CMP a2,#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. */
+ − ; REG_Thread_Ptr -> tc_cur_time_slice =
+ − ; REG_Thread_Ptr -> tc_time_slice;
+ − ;
+ − LDR a2,[a1, #40h] ; Pickup original time slice
+ − ;
+ − ; /* Clear any active time slice by setting the state to
+ − ; NOT_ACTIVE. */
+ − ; TMD_Time_Slice_State = 1;
+ − ;
+ − MOV a3,#1 ; Build disable value
+ − STR a3,[a4, #0] ; Disable time slice
+ − STR a2,[a1, #20h] ; Reset current time slice
+ − ; }
+ − ;
+ − TCT_No_Stop_TS_3
+ − ;
+ − ; /* Save off the current stack pointer in the control block. */
+ − ; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
+ − ;
+ − STR sp,[a1, #2ch] ; Save the thread's stack pointer
+ − ;
+ − ; /* Switch to the system stack. */
+ − ; REG_Stack_Ptr = TCD_System_Stack;
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; Setup system stack limit
+ − ;
+ − ; /* Finished, return to the scheduling loop. */
+ − ;
+ − B _TCT_Schedule ; Return to scheduling loop
+ − ;
+ − ; }
+ − ; else
+ − ; {
+ − TCT_Not_Waiting_Unspec
+ − ;
+ − ; /* No higher-priority thread is waiting. */
+ − ;
+ − ; /* Restore interrupts. */
+ − ;
+ − LDR a3,Int_Level ; Pickup address of interrupt level
+ − MRS a2,CPSR ; Pickup current CPSR
+ − LDR a4,[a3, #0] ; Pickup interrupt lockout level
+ − BIC a2,a2,#LOCK_MSK ; Clear lockout bits
+ − ORR a2,a2,a4 ; Build new interrupt lockout
+ − MSR CPSR,a2 ; Setup CPSR appropriately
+ − ;
+ − ; }
+ − ; }
+ − ;
+ − TCT_Skip_Unprot_Spec
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCC_Resume_Task Resume task function */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* protect Pointer to protection block */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Set_Current_Protect(TC_PROTECT *protect)
+ − ;{
+ − .def $TCT_Set_Current_Protect
+ − $TCT_Set_Current_Protect ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Set_Current_Protect
+ − ;
+ − .def _TCT_Set_Current_Protect
+ − _TCT_Set_Current_Protect
+ − ;
+ − ; /* Determine if the caller is in a task or HISR thread. */
+ − ; if (TCD_Current_Thread)
+ − ; {
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a4,[a2, #0] ; Pickup current thread pointer
+ − CMP a4,#0 ; Check to see if a thread is
+ − ; active
+ − ;
+ − ; /* Point at the current thread control block. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − ; /* Modify the current protection. */
+ − ; REG_Thread_Ptr -> tc_current_protect = protect;
+ − ;
+ − STRNE a1,[a4, #38h] ; Setup new protection
+ − ; }
+ − ;
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* System Components */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* thread Pointer to thread control blk */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Protect_Switch(VOID *thread)
+ − ;{
+ − .def $TCT_Protect_Switch
+ − $TCT_Protect_Switch ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Protect_Switch
+ − ;
+ − .def _TCT_Protect_Switch
+ − _TCT_Protect_Switch
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Place lockout value in
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; REG_Thread_Ptr = (TC_TCB *) thread;
+ − ;
+ − ; /* Wait until the specified task has no protection associated with it. */
+ − ; while (REG_Thread_Ptr -> tc_current_protect)
+ − ; {
+ − ;
+ − LDR a2,[a1, #38h] ; Pickup protection of specified
+ − ; thread
+ − CMP a2,#0 ; Does the specified thread have
+ − ; an active protection?
+ − BEQ TCT_Switch_Done ; If not, protect switch is done
+ − ;
+ − ; /* Let the task run again in an attempt to clear its protection. */
+ − ;
+ − ; /* Indicate that a higher priority thread is waiting. */
+ − ; (REG_Thread_Ptr -> tc_current_protect) -> tc_thread_waiting = 1;
+ − ;
+ − MOV a3,#1 ; Build waiting flag value
+ − STR a3,[a2, #4] ; Set waiting flag of the
+ − ; protection owned by the other
+ − ; thread
+ − ;
+ − ; /* Directly schedule the thread waiting. */
+ − ; TCT_Schedule_Protected((REG_Thread_Ptr -> tc_current_protect)
+ − ; -> tc_tcb_pointer);
+ − ;
+ − LDR a3,Current_Thread ; Pickup current thread ptr address
+ − STR a1,[sp, #-4]! ; Save a1 on the stack
+ − STR lr,[sp, #-4]! ; Save lr on the stack
+ − MOV a2,a1 ; Move new thread into a2
+ − LDR a1,[a3, #0] ; Pickup current thread pointer
+ − BL _TCT_Schedule_Protected ; Call routine to schedule the
+ − ; owner of the thread
+ − ;
+ − LDR lr,[sp], #4 ; Recover saved lr
+ − LDR a1,[sp], #4 ; Recover saved a1
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − B _TCT_Protect_Switch ; Branch to top of routine and
+ − ; start over
+ − ; }
+ − TCT_Switch_Done
+ − ;
+ − ; /* Restore interrupts. */
+ − ;
+ − LDR a3,Int_Level ; Pickup address of interrupt level
+ − MRS a2,CPSR ; Pickup current CPSR
+ − LDR a4,[a3, #0] ; Pickup interrupt lockout level
+ − BIC a2,a2,#LOCK_MSK ; Clear lockout bits
+ − ORR a2,a2,a4 ; Build new interrupt lockout
+ − MSR CPSR,a2 ; Setup CPSR appropriately
+ − ;
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* TCT_Protect */
+ − ;/* TCT_Protect_Switch */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* TCT_Control_To_Thread Transfer control to protected*/
+ − ;/* thread */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Schedule_Protected(VOID *thread)
+ − ;{
+ − ;
+ − _TCT_Schedule_Protected
+ − ;
+ − ; /* Interrupts are already locked out by the caller. */
+ − ;
+ − ; /* Save minimal context required by the system. */
+ − ;
+ − STMDB sp!,{v1-ip,lr} ; Save minimal context of thread on
+ − ; the current stack
+ − MOV a3,lr ; Determine what state the
+ − MOV a3,a3,LSL #31 ; caller was in and build an
+ − MOV a3,a3,LSR #26 ; appropriate state mask
+ − STR a3,[sp, #-4]! ; Place it on the stack
+ − MOV a3,#0 ; Build solicited stack type value
+ − ; and NU_NULL value
+ − STR a3,[sp, #-4]! ; Place it on the top of the stack
+ − MOV v1,a2 ; Save thread to schedule
+ − ;
+ − ; /* Setup a pointer to the thread control block. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − ;
+ − ; /* Clear the current thread control block. */
+ − ; TCD_Current_Thread = NU_NULL;
+ − ;
+ − LDR a4,Slice_State ; Pickup time slice state address
+ − STR a3,[a2, #0] ; Set current thread pointer to
+ − ; NU_NULL
+ − ;
+ − ; /* Check to see if a time slice is active. If so, copy the original time
+ − ; slice into the current time slice field of the task's control block. */
+ − ; if (TMD_Time_Slice_State == 0)
+ − ; {
+ − ;
+ − LDR a2,[a4, #0] ; Pickup time slice state flag
+ − CMP a2,#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. */
+ − ; REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
+ − ;
+ − LDR a2,[a1, #40h] ; Pickup original time slice
+ − ;
+ − ; /* Clear any active time slice by setting the state to NOT_ACTIVE. */
+ − ; TMD_Time_Slice_State = 1;
+ − ;
+ − MOV a3,#1 ; Build disable value
+ − STR a3,[a4, #0] ; Disable time slice
+ − STR a2,[a1, #20h] ; Reset current time slice
+ − ;
+ − ; }
+ − TCT_No_Stop_TS_4
+ − ;
+ − ; /* Save off the current stack pointer in the control block. */
+ − ; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
+ − ;
+ − STR sp,[a1, #2ch] ; Save the thread's stack pointer
+ − ;
+ − ; /* Switch to the system stack. */
+ − ; TCD_System_Stack = (VOID *) REG_Stack_Ptr;
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; Setup system stack limit
+ − ;
+ − ; /* Transfer control to the specified thread directly. */
+ − ; TCT_Control_To_Thread(thread);
+ − ;
+ − LDR a3,Int_Level ; Pickup address of interrupt level
+ − MRS a2,CPSR ; Pickup current CPSR
+ − LDR a4,[a3, #0] ; Pickup interrupt lockout level
+ − BIC a2,a2,#LOCK_MSK ; Clear lockout bits
+ − ORR a2,a2,a4 ; Build new interrupt lockout
+ − MOV a1,v1 ; Indicate thread to schedule
+ − MSR CPSR,a2 ; Setup CPSR appropriately
+ − ORR a2,a2,#LOCKOUT ; Build lockout value again
+ − MSR CPSR,a2 ; Lockout interrupts again
+ − B _TCT_Control_To_Thread ; Schedule the thread indirectly
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application ISRs Assembly language ISRs */
+ − ;/* INT_Interrupt_Shell Interrupt handler shell */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* vector Interrupt's vector number */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Interrupt_Context_Save(INT vector)
+ − ;{
+ − .def $TCT_Interrupt_Context_Save
+ − $TCT_Interrupt_Context_Save ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Interrupt_Context_Save
+ − ;
+ − .def _TCT_Interrupt_Context_Save
+ − _TCT_Interrupt_Context_Save
+ − ;
+ − ; /* This routine is designed to handle THUMB IRQ interrupts. The IRQ
+ − ; stack is used as a temporary area. Actual context is saved either
+ − ; on the interrupted thread's stack or the system stack- both of which
+ − ; are in the Supervisor (SVC) mode. Note: upon entry to this routine
+ − ; a1-a4 are saved on the current stack and a4 contains the original
+ − ; (interrupt return address) lr value. The current lr contains the
+ − ; ISR return address. */
+ − ;
+ − ; /* Determine if this is a nested interrupt. */
+ − ; if (TCD_Interrupt_Count++)
+ − ; {
+ − ;
+ − LDR a1,Int_Count ; Pickup address of interrupt count
+ − LDR a2,[a1, #0] ; Pickup interrupt counter
+ − CMP a2,#0 ; Is it the first interrupt?
+ − BEQ TCT_Not_Nested_Save ; If so, not a nested interrupt
+ − ;
+ − ; /* Nested interrupt. Save complete context on the current stack. */
+ − ;
+ − ADD a2,a2,#1 ; Increment the interrupt counter
+ − STR a2,[a1, #0] ; Store in interrupt counter
+ − STMDB sp!,{v1-v3} ; Save more registers on current
+ − ; stack
+ − MRS v1,SPSR ; Pickup and save current SPSR
+ − MOV v2,lr ; Save current lr
+ − MOV v3,sp ; Save current sp
+ − ADD sp,sp,#28 ; Adjust sp for future interrupts
+ − MRS a1,CPSR ; Pickup current CPSR
+ − BIC a1,a1,#MODE_MASK ; Clear the mode bits
+ − ORR a1,a1,#SUP_MODE ; Prepare to switch to supervisor
+ − ; mode (SVC)
+ − MSR CPSR,a1 ; Switch to SVC mode
+ − MOV a2,sp ; Use a non sp register
+ − NOP ;
+ − STR a4,[a2, #-4]! ; Save interrupted pc on sys stack
+ − STMDB a2!,{v4-lr} ; Save v4-lr on the system stack
+ − MOV sp,a2 ; Setup sp again
+ − LDMIA v3!,{v4-v6} ; Recover v1-v3 from int stack
+ − STMDB sp!,{v4-v6} ; Save v1-v3 on the system stack
+ − LDMIA v3,{a1-a4} ; Recover a1-a4
+ − STMDB sp!,{a1-a4} ; Save a1-a4 on the system stack
+ − STR v1,[sp, #-4]! ; Save CPSR on the stack
+ − BX v2 ; Return to calling ISR
+ − ; }
+ − ; else
+ − ; {
+ − TCT_Not_Nested_Save
+ − ;
+ − ADD a2,a2,#1 ; Increment the interrupt counter
+ − STR a2,[a1, #0] ; Store in interrupt counter
+ − ;
+ − ; /* Determine if a thread was interrupted. */
+ − ; if (TCD_Current_Thread)
+ − ; {
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a2,[a2, #0] ; Pickup the current thread pointer
+ − CMP a2,#0 ; Is it NU_NULL?
+ − BEQ TCT_Idle_Context_Save ; If no, no real save is necessary
+ −
+ − ;
+ − ; /* Yes, a thread was interrupted. Save complete context on the
+ − ; thread's stack. */
+ − ;
+ − STMDB sp!,{v1-v3} ; Save more registers on temp stack
+ − MOV v2,lr ; Save interrupt lr in v2
+ − MRS v1,SPSR ; Save interrupt SPSR in v1
+ − MOV v3,sp ; Save current sp in v3
+ − ADD sp,sp,#28 ; Adjust sp for future interrupts
+ − MRS a1,CPSR ; Pickup current CPSR
+ − BIC a1,a1,#MODE_MASK ; Clear the mode bits
+ − ORR a1,a1,#SUP_MODE ; Prepare to switch to supervisor
+ − ; mode (SVC)
+ − MSR CPSR,a1 ; Switch to supervisor mode (SVC)
+ − MOV a2,sp ; Use a non-stack pointer register
+ − NOP ;
+ − STR a4,[a2, #-4]! ; Save interrupted pc on the stack
+ − STMDB a2!,{v4-lr} ; Save v4-lr on the stack
+ − MOV sp,a2 ; Setup sp again
+ − LDMIA v3!,{v4-v6} ; Recover v1-v3 into v4-v6
+ − STMDB sp!,{v4-v6} ; Save v1-v3 on the stack
+ − LDMIA v3,{a1-a4} ; Recover a1-a4
+ − STMDB sp!,{a1-a4} ; Save a1-a4 on the stack
+ − STR v1,[sp, #-4]! ; Save CPSR on the stack
+ − MOV a2,#1 ; Interrupt stack type
+ − STR a2,[sp, #-4]! ; Put interrupt stack type on top
+ − ; of stack
+ − ;
+ − ; /* Save the thread's stack pointer in the control block. */
+ − ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
+ − ; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a1,[a2, #0] ; Pickup current thread pointer
+ − LDR a4,Slice_State ; Pickup time slice state address
+ − STR sp,[a1, #2ch] ; Save stack pointer
+ − ;
+ − ; /* Switch to the system stack. */
+ − ; REG_Stack_Ptr = TCD_System_Stack;
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; Setup system stack limit
+ − ;
+ − ; /* Return to caller ISR. */
+ − ;
+ − BX v2 ; Return to caller ISR
+ − ;
+ − ; }
+ − ;
+ − TCT_Idle_Context_Save
+ − ;
+ − MOV v2,lr ; Save lr in v2
+ − ADD sp,sp,#16 ; Adjust sp for future interrupts
+ − MRS a1,CPSR ; Pickup current CPSR
+ − BIC a1,a1,#MODE_MASK ; Clear the current mode
+ − ORR a1,a1,#SUP_MODE ; Prepare to switch to supervisor
+ − ; mode (SVC)
+ − MSR CPSR,a1 ; Switch to supervisor mode (SVC)
+ − BX v2 ; Return to caller ISR
+ − ; }
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application ISRs Assembly language ISRs */
+ − ;/* INT_Interrupt_Shell Interrupt handler shell */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* TCT_Schedule Thread scheduling function */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_Interrupt_Context_Restore(void)
+ − ;{
+ − .def $TCT_Interrupt_Context_Restore
+ − $TCT_Interrupt_Context_Restore ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Interrupt_Context_Restore
+ − ;
+ − .def _TCT_Interrupt_Context_Restore
+ − _TCT_Interrupt_Context_Restore
+ − ;
+ − ; /* It is assumed that anything pushed on the stack by ISRs has been
+ − ; removed upon entry into this routine. */
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Build lockout value
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; /* Decrement and check for nested interrupt conditions. */
+ − ; if (--TCD_Interrupt_Count)
+ − ; {
+ − ;
+ − LDR a1,Int_Count ; Pickup address of interrupt count
+ − LDR a2,[a1, #0] ; Pickup interrupt counter
+ − SUB a2,a2,#1 ; Decrement interrupt counter
+ − STR a2,[a1, #0] ; Store interrupt counter
+ − CMP a2,#0 ; Is this a nested interrupt?
+ − BEQ TCT_Not_Nested_Restore ; If not, skip nested interrupt
+ − ; restoration
+ − ;
+ − ; /* Restore previous context. */
+ − ;
+ − LDR a1,[sp], #4 ; Pickup the saved CPSR
+ − MSR SPSR,a1 ; Put in SPSR
+ − LDMIA sp,{a1-pc}^ ; Return to the point of interrupt
+ − ;
+ − ; }
+ − ; else
+ − ; {
+ − ;
+ − TCT_Not_Nested_Restore
+ − ;
+ − ; /* Determine if a thread is active. */
+ − ; if (TCD_Current_Thread)
+ − ; {
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − LDR a1,[a2, #0] ; Pickup current thread pointer
+ − CMP a1,#0 ; Determine if a thread is active
+ − BEQ TCT_Idle_Context_Restore ; If not, idle system restore
+ − ;
+ − ; /* Clear the current thread pointer. */
+ − ; TCD_Current_Thread = NU_NULL;
+ − ;
+ − LDR a4,Slice_State ; Pickup time slice state address
+ − MOV a3,#0 ; Build NU_NULL value
+ − STR a3,[a2, #0] ; Set current thread ptr to NU_NULL
+ − ;
+ − ; /* 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. */
+ − ; if (TMD_Time_Slice_State == 0)
+ − ; {
+ − ;
+ − LDR a2,[a4, #0] ; Pickup time slice state
+ − CMP a2,#0 ; Determine if time slice active
+ − BNE TCT_Idle_Context_Restore ; If not, skip time slice reset
+ − ;
+ − ; /* Pickup the remaining portion of the time slice and save it
+ − ; in the task's control block. */
+ − ; REG_Thread_Ptr -> tc_cur_time_slice = TMD_Time_Slice;
+ − ; TMD_Time_Slice_State = 1;
+ − ;
+ − LDR a3,Time_Slice ; Pickup address of time slice left
+ − MOV a2,#1 ; Build disable time slice value
+ − LDR a3,[a3, #0] ; Pickup remaining time slice
+ − STR a2,[a4, #0] ; Disable time slice
+ − STR a3,[a1, #20h] ; Store remaining time slice
+ − ;
+ − ; }
+ − ; }
+ − TCT_Idle_Context_Restore
+ − ;
+ − ; /* Reset the system stack pointer. */
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; Setup system stack limit
+ − ;
+ − ; /* Return to scheduler. */
+ − ;
+ − B _TCT_Schedule ; Return to scheduling loop
+ − ;
+ − ; }
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* FUNCTION */
+ − ;/* */
+ − ;/* TCT_Activate_HISR */
+ − ;/* */
+ − ;/* DESCRIPTION */
+ − ;/* */
+ − ;/* This function activates the specified HISR. If the HISR is */
+ − ;/* already activated, the HISR's activation count is simply */
+ − ;/* incremented. Otherwise, the HISR is placed on the appropriate */
+ − ;/* HISR priority list in preparation for execution. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* Application LISRs */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* hisr Pointer to HISR to activate */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* NU_SUCCESS Successful completion */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;STATUS TCT_Activate_HISR(TC_HCB *hisr)
+ − ;{
+ − .def $TCT_Activate_HISR
+ − $TCT_Activate_HISR ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_Activate_HISR
+ − ;
+ − .def _TCT_Activate_HISR
+ − _TCT_Activate_HISR
+ − ;
+ − ;INT priority;
+ − ;
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − STR v1,[sp, #-4]! ; Save v1
+ − MRS v1,CPSR ; Pickup current CPSR
+ − ORR a2,v1,#LOCKOUT ; Build interrupt lockout value
+ − MSR CPSR,a2 ; Lockout interrupts
+ − ;
+ − ; /* Determine if the HISR is already active. */
+ − ; if (hisr -> tc_activation_count)
+ − ; {
+ − ;
+ − LDR a2,[a1,#40h] ; Pickup current activation count
+ − CMP a2,#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. */
+ − ; hisr -> tc_activation_count++;
+ − ;
+ − ADDS a2,a2,#1 ; Increment the activation count
+ − STR a2,[a1,#40h] ; Store new activation count
+ − ;
+ − ; if (hisr -> tc_activation_count == 0)
+ − ;
+ − ; hisr -> tc_activation_count = 0xFFFFFFFFUL;
+ − ;
+ − MVNEQ a2,#0 ; If counter rolled-over reset
+ − STREQ a2,[a1,#40h] ; Store all ones count
+ − B TCT_Activate_Done ; Finished with activation
+ − ; }
+ − ; else
+ − ; {
+ − TCT_First_Activate
+ − ;
+ − ;
+ − ; /* Set the activation count to 1. */
+ − ; hisr -> tc_activation_count = 1;
+ − ;
+ − MOV a2,#1 ; Initial activation count
+ − STR a2,[a1,#40h] ; Store initial activation count
+ − ;
+ − ; /* Pickup the HISR's priority. */
+ − ; priority = hisr -> tc_priority;
+ − ;
+ − ; /* Determine if there is something in the given priority list. */
+ − ; if (TCD_Active_HISR_Tails[priority])
+ − ; {
+ − ;
+ − LDRB a2,[a1,#1ah] ; Pickup priority of HISR
+ − LDR a3,HISR_Tails ; Pickup tail pointer base
+ − LDR a4,[a3,a2,LSL #2] ; Pickup tail pointer for priority
+ − CMP a4,#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. */
+ − ; (TCD_Active_HISR_Tails[priority]) -> tc_active_next = hisr;
+ − ; TCD_Active_HISR_Tails[priority] = hisr;
+ − ;
+ − STR a1,[a4,#3ch] ; Setup the active next pointer
+ − STR a1,[a3,a2,LSL #2] ; Setup the tail pointer
+ − B TCT_Activate_Done ; Finished with activate processing
+ − ; }
+ − ; else
+ − ; {
+ − TCT_First_HISR
+ − ;
+ − ; /* Nothing is on this list. */
+ − ; TCD_Active_HISR_Heads[priority] = hisr;
+ − ; TCD_Active_HISR_Tails[priority] = hisr;
+ − ;
+ − LDR a4,HISR_Heads ; Pickup address of head pointers
+ − STR a1,[a3,a2,LSL #2] ; Set tail pointer to this HISR
+ − STR a1,[a4,a2,LSL #2] ; Set head pointer to this HISR
+ − ;
+ − ; /* Determine the highest priority HISR. */
+ − ; if (TCD_Active_HISR_Heads[0])
+ − ; TCD_Execute_HISR = TCD_Active_HISR_Heads[0];
+ − ; else if (TCD_Active_HISR_Heads[1])
+ − ; TCD_Execute_HISR = TCD_Active_HISR_Heads[1];
+ − ; else
+ − ; TCD_Execute_HISR = TCD_Active_HISR_Heads[2];
+ − ;
+ − LDR a2,[a4,#0] ; Pickup priority 0 head pointer
+ − LDR a1,Execute_HISR ; Build address to execute HISR ptr
+ − CMP a2,#0 ; Is priority 0 active?
+ − LDREQ a2,[a4,#4] ; If not, pickup priority 1 head
+ − CMPEQ a2,#0 ; Is priority 1 active?
+ − LDREQ a2,[a4,#8] ; Else, must be priority 2 active
+ − STR a2,[a1,#0] ; Store which ever priority is the
+ − ; active one
+ − ; }
+ − ; }
+ − TCT_Activate_Done
+ − ;
+ − MSR CPSR,v1 ; Restore interrupt lockout
+ − LDR v1,[sp], #4 ; Restore corrupted v1
+ − ;
+ − ; return(NU_SUCCESS);
+ − ;
+ − MOV a1,#0 ; Always return NU_SUCCESS
+ − BX lr ; Return to caller
+ − ;}
+ − ;
+ − ;
+ − ;
+ − ;/*************************************************************************/
+ − ;/* */
+ − ;/* 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. */
+ − ;/* */
+ − ;/* AUTHOR */
+ − ;/* */
+ − ;/* Barry Sellew, Accelerated Technology, Inc. */
+ − ;/* */
+ − ;/* CALLED BY */
+ − ;/* */
+ − ;/* HISR Scheduling */
+ − ;/* */
+ − ;/* CALLS */
+ − ;/* */
+ − ;/* hisr -> tc_entry Actual entry function of HISR*/
+ − ;/* */
+ − ;/* INPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* OUTPUTS */
+ − ;/* */
+ − ;/* None */
+ − ;/* */
+ − ;/* HISTORY */
+ − ;/* */
+ − ;/* NAME DATE REMARKS */
+ − ;/* */
+ − ;/* B. Sellew 01-19-1996 Created initial version 1.0 */
+ − ;/* B. Sellew 01-22-1996 Verified version 1.0 */
+ − ;/* */
+ − ;/*************************************************************************/
+ − ;VOID TCT_HISR_Shell(void)
+ − ;{
+ − .def $TCT_HISR_Shell
+ − $TCT_HISR_Shell ; Dual-state interworking veneer
+ − .state16
+ − BX pc
+ − NOP
+ − .state32
+ − B _TCT_HISR_Shell
+ − ;
+ − .def _TCT_HISR_Shell
+ − _TCT_HISR_Shell
+ − ;
+ − ; /* Point at the HISR. */
+ − ; REG_HISR_Ptr = (TC_HCB *) TCD_Current_Thread;
+ − ;
+ − LDR a1,Current_Thread ; Build address of thread pointer
+ − LDR v2,[a1, #0] ; Pickup control block pointer
+ − ;
+ − ; do
+ − ; {
+ − TCT_HISR_Loop
+ − ;
+ − ; /* Call the HISR's entry routine. */
+ − ; (*(REG_HISR_Ptr -> tc_entry)) ();
+ − ;
+ − LDR v1,[v2,#44h] ; Call HISR entry function
+ − BL IND_CALL ; indirectly
+ − ;
+ − ; /* Lockout interrupts. */
+ − ;
+ − MRS a2,CPSR ; Pickup current CPSR
+ − ORR a2,a2,#LOCKOUT ; Build interrupt lockout
+ − MSR CPSR,a2 ; 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. */
+ − ; REG_HISR_Ptr -> tc_activation_count--;
+ − ;
+ − LDR a1,[v2, #40h] ; Pickup current activation count
+ − SUBS a1,a1,#1 ; Subtract and set condition codes
+ − STR a1,[v2, #40h] ; Store new activation count
+ − BEQ TCT_HISR_Finished ; Finished processing HISR
+ −
+ − ; /* Restore interrupts. */
+ − ;
+ − LDR a3,Int_Level ; Pickup address of interrupt level
+ − MRS a2,CPSR ; Pickup current CPSR
+ − LDR a4,[a3, #0] ; Pickup interrupt lockout level
+ − BIC a2,a2,#LOCK_MSK ; Clear lockout bits
+ − ORR a2,a2,a4 ; Build new interrupt lockout
+ − MSR CPSR,a2 ; Setup CPSR appropriately
+ − B TCT_HISR_Loop ; Return to HISR loop
+ − ; }
+ − ; while (REG_HISR_Ptr -> tc_activation_count);
+ − ;
+ − TCT_HISR_Finished
+ − ;
+ − ; /* At this point, the HISR needs to be made inactive. */
+ − ;
+ − ; /* Determine if this is the only HISR on the given priority list. */
+ − ; if (REG_HISR_Ptr == TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority])
+ − ; {
+ − ;
+ − LDR lr,HISR_Tails ; Pickup tail pointers address
+ − LDRB a4,[v2,#1ah] ; Pickup priority
+ − LDR v3,[lr,a4,LSL #2] ; Pickup this priority tail pointer
+ − LDR a3,Execute_HISR ; Build address to execute HISR ptr
+ − MOV a1,#0 ; Clear a1
+ − LDR a2,HISR_Heads ; Pickup head pointers address
+ − CMP v3,v2 ; 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. */
+ − ; TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] = NU_NULL;
+ − ; TCD_Active_HISR_Tails[REG_HISR_Ptr -> tc_priority] = NU_NULL;
+ − ;
+ − STR a1,[a2,a4,LSL #2] ; Set head pointer to NU_NULL
+ − STR a1,[lr,a4,LSL #2] ; Set tail pointer to NU_NULL
+ − ;
+ − ; /* Determine the highest priority HISR. */
+ − ; if (TCD_Active_HISR_Heads[0])
+ − ; TCD_Execute_HISR = TCD_Active_HISR_Heads[0];
+ − ; else if (TCD_Active_HISR_Heads[1])
+ − ; TCD_Execute_HISR = TCD_Active_HISR_Heads[1];
+ − ; else
+ − ; TCD_Execute_HISR = TCD_Active_HISR_Heads[2];
+ − ;
+ − LDR a4,[a2,#0] ; Pickup priority 0 head pointer
+ − CMP a4,#0 ; Is there an HISR active?
+ − LDREQ a4,[a2,#4] ; If not, pickup priority 1 pointer
+ − CMPEQ a4,#0 ; Is there an HISR active?
+ − LDREQ a4,[a2,#8] ; If not, pickup priority 2 pointer
+ − STR a4,[a3,#0] ; Setup execute HISR pointer
+ − B TCT_HISR_Exit ; Exit HISR processing
+ − ; }
+ − ; else
+ − ; {
+ − ;
+ − TCT_More_HISRs
+ − ;
+ − ; /* Move the head pointer to the next HISR in the list. */
+ − ; TCD_Active_HISR_Heads[REG_HISR_Ptr -> tc_priority] =
+ − ; REG_HISR_Ptr -> tc_active_next;
+ − ;
+ − ; /* Also set the TCD_Execute_HISR pointer. */
+ − ; TCD_Execute_HISR = REG_HISR_Ptr -> tc_active_next;
+ − ;
+ − LDR lr,[v2,#3ch] ; Pickup next HISR to activate
+ − STR lr,[a2,a4,LSL #2] ; Setup new head pointer
+ − STR lr,[a3, #0] ; 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,HISR_Shell ; Pickup address of shell entry
+ − STMDB sp!,{v1-ip,lr} ; Save minimal context of thread on
+ − ; the current stack
+ − MOV a3,#0 ; Build solicited stack type value
+ − ; and NU_NULL value
+ − STR a3,[sp, #-4]! ; Save state mask
+ − STR a3,[sp, #-4]! ; Place it on the top of the stack
+ − ;
+ − ; /* Clear the current thread control block. */
+ − ; TCD_Current_Thread = NU_NULL;
+ − ;
+ − LDR a2,Current_Thread ; Pickup current thread ptr address
+ − STR a3,[a2, #0] ; Set current thread pointer to
+ − ; NU_NULL
+ − ;
+ − ; /* Save off the current stack pointer in the control block. */
+ − ; REG_HISR_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
+ − ;
+ − STR sp,[v2, #2ch] ; Save the thread's stack pointer
+ − ;
+ − ; /* Switch to the system stack. */
+ − ; REG_Stack_Ptr = (BYTE_PTR) TCD_System_Stack;
+ − ;
+ − LDR a2,System_Stack ; Pickup address of stack pointer
+ − LDR a3,System_Limit ; Pickup address of stack limit ptr
+ − LDR sp,[a2, #0] ; Switch to system stack
+ − LDR v7,[a3, #0] ; Setup system stack limit
+ − ;
+ − ; /* Transfer control to the main scheduling loop. */
+ − ;
+ − B _TCT_Schedule ; Return to main scheduling loop
+ − ;}
+ − ;
+ − ;/* Define the global addresses used in this section */
+ − ;
+ − System_Limit
+ − .word _TCT_System_Limit
+ − ;
+ − Int_Level
+ − .word _TCD_Interrupt_Level
+ − ;
+ − Task_Shell
+ − .word $TCC_Task_Shell
+ − ;
+ − HISR_Shell
+ − .word _TCT_HISR_Shell
+ − ;
+ − Signal_Shell
+ − .word $TCC_Signal_Shell
+ − ;
+ − Current_Thread
+ − .word _TCD_Current_Thread
+ − ;
+ − Execute_HISR
+ − .word _TCD_Execute_HISR
+ − ;
+ − Execute_Task
+ − .word _TCD_Execute_Task
+ − ;
+ − Time_Slice
+ − .word _TMD_Time_Slice
+ − ;
+ − Slice_State
+ − .word _TMD_Time_Slice_State
+ − ;
+ − System_Stack
+ − .word _TCD_System_Stack
+ − ;
+ − Int_Count
+ − .word _TCD_Interrupt_Count
+ − ;
+ − HISR_Tails
+ − .word _TCD_Active_HISR_Tails
+ − ;
+ − HISR_Heads
+ − .word _TCD_Active_HISR_Heads
+ − ;
+ − System_Error
+ − .word $ERC_System_Error
+ − ;
+ − .end