FreeCalypso > hg > fc-tourmaline
view src/cs/os/nucleus/tct.s @ 303:f76436d19a7a default tip
!GPRS config: fix long-standing AT+COPS chance hanging bug
There has been a long-standing bug in FreeCalypso going back years:
sometimes in the AT command bring-up sequence of an ACI-only MS,
the AT+COPS command would produce only a power scan followed by
cessation of protocol stack activity (only L1 ADC traces), instead
of the expected network search sequence. This behaviour was seen
in different FC firmware versions going back to Citrine, and seemed
to follow some law of chance, not reliably repeatable.
This bug has been tracked down and found to be specific to !GPRS
configuration, stemming from our TCS2/TCS3 hybrid and reconstruction
of !GPRS support that was bitrotten in TCS3.2/LoCosto version.
ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3
version and had to be pulled from TCS2 - but as it turns out,
there is a new field in the MMR_REG_REQ primitive that needs to be
set correctly, and that psa_mms.c module is the place where this
initialization needed to be added.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 08 Jun 2023 08:23:37 +0000 |
parents | 4e78acac3d88 |
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