FreeCalypso > hg > ffs-editor
diff src/cs/os/nucleus/tct.s @ 0:92470e5d0b9e
src: partial import from FC Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 15 May 2020 01:28:16 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cs/os/nucleus/tct.s Fri May 15 01:28:16 2020 +0000 @@ -0,0 +1,3073 @@ +;/*************************************************************************/ +;/* */ +;/* 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