FreeCalypso > hg > fc-magnetite
view src/cs/os/nucleus/tct.s @ 234:b870b6a44d31
l1audio and l1tm reconstructed source imported from tcs211-l1-reconst
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 20 Mar 2017 00:51:20 +0000 |
parents | 945cf7f506b2 |
children |
line wrap: on
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