⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tct.s

📁 test file nucleus source
💻 S
📖 第 1 页 / 共 5 页
字号:
;*
;*  OUTPUTS
;*
;*      r0 -    Available bytes on stack
;*
;*  REGISTERS MODIFIED
;*
;*      r0, r1, r2, r3
;*
;*  HISTORY
;*
;*      NAME            DATE            REMARKS
;*
;*      Driscoll, D     01/24/2003      Released Version 1.14.1
;************************************************************************
;INT    TCT_Check_Stack(VOID);

    EXPORT  TCT_Check_Stack
TCT_Check_Stack

    ; Pickup the current thread pointer.

    LDR     r0,TCT_Current_Thread1
    LDR     r0,[r0]

    ; Determine if there is a current thread.

    CMP     r0,#0                           ; Determine if a thread is active
    MOV     r3,#0                           ; Default remaining value
    BEQ     TCT_Skip_Stack_Check            ; If NU_NULL, skip stack checking

    ; Determine if the stack pointer has overflowed

    LDR     r2,[r0,#TC_STACK_START]         ; Pickup start of stack area
    CMP     sp,r2                           ; Compare with current stack ptr
    BLT     TCT_Stack_Range_Error           ; If less, stack is out of range

    ; Determine if the stack pointer has underflowed

    LDR     r1,[r0,#TC_STACK_END]           ; Pickup end of stack area
    CMP     sp,r1                           ; Compare with current stack ptr
    BLE     TCT_Stack_Range_Okay            ; If less, stack range is okay

TCT_Stack_Range_Error

    MOV     r0,#3                           ; Build NU_STACK_OVERFLOW code
    BL      ERC_System_Error                ; Call system error handler

TCT_Stack_Range_Okay

    ; Calculate the amount of available space on the stack.

    SUB     r3,sp,r2

    ; Determine if there is enough memory on the stack to save
    ; all of the registers.

    CMP     r3,#INT_STACK_SIZE

    ; If there is enough memory, there is no stack overflow yet

    BGE     TCT_No_Stack_Error

    ; Stack overflow condition is about to happen.

    MOV     r0,#3                           ; Build NU_STACK_OVERFLOW code
    BL      ERC_System_Error                ; Call system error handler

TCT_No_Stack_Error

    ; Determine if this is a new minimum amount of stack space.
    ; If so, save the new stack minimum.

    LDR     r2,[r0,#TC_STACK_MINIMUM]
    CMP     r3,r2
    STRCC   r3,[r0,#TC_STACK_MINIMUM]

TCT_Skip_Stack_Check

    ; Return the remaining number of bytes on the stack.

    MOV     r0,r3

    ; Return to caller

    BX      lr


;************************************************************************
;*
;*  FUNCTION
;*
;*      TCT_Schedule
;*
;*  DESCRIPTION
;*
;*      This function waits for a thread to become ready.  Once a thread
;*      is ready, this function initiates a transfer of control to that
;*      thread.
;*
;*  CALLED BY
;*
;*      INC_Initialize                  Main initialization routine
;*      TCT_Control_To_System           Transfers control to system
;*      TCT_Signal_Exit                 Exit routine for signals
;*      TCT_Unprotect_Specific          Unprotects specific protect
;*      TCT_Interrupt_Context_Restore   Restore context after interrupt
;*      TCT_HISR_Shell                  Entry point for HISRs
;*
;*  CALLS
;*
;*      TCT_Control_To_Thread           Transfer control to a thread
;*
;*  INPUTS
;*
;*      None
;*
;*  OUTPUTS
;*
;*      r0 -    Pointer to scheduled thread
;*
;*  REGISTERS MODIFIED
;*
;*      r0, r1, r2
;*
;*  HISTORY
;*
;*      NAME            DATE            REMARKS
;*
;*      Driscoll, D     01/24/2003      Released Version 1.14.1
;************************************************************************
;VOID  TCT_Schedule(VOID)

    EXPORT  TCT_Schedule
TCT_Schedule

    IF  NU_TEST2_SUPPORT

    ; Set suspension time for Nucleus Timing Test

    BL      Set_Suspend_Time

    ENDIF

    ; Restore interrupts according to the value contained in TCD_Interrupt_Level.

    LDR     r1,TCT_Int_Level                ; Get address of interrupt level
    LDR     r1,[r1]                         ; Pickup current interrupt lockout
    MRS     r0,CPSR                         ; Pickup current CPSR
    BIC     r0,r0,#LOCK_MSK                 ; Clear the interrupt lockout bits
    ORR     r0,r0,r1                        ; Build new interrupt lockout CPSR
    MSR     CPSR_cxsf,r0                    ; Setup new CPSR

    ; Get the addresses of the HISR and Task to execute

    LDR     r2,TCT_Execute_HISR
    LDR     r3,TCT_Execute_Task

    IF INCLUDE_PROVIEW

    ; Check to see if there is a task to execute upon entering TCT_Schedule.
    ; If not, we start IDLE.

    LDR     r0,[r2]                         ; Pickup highest priority HISR ptr
    CMP     r0,#0                           ; Is there a HISR active?
    BNE     TCT_Schedule_Thread             ; Found an HISR
    LDR     r0,[r3]                         ; Pickup highest priority Task ptr
    CMP     r0,#0                           ; Is there a task active?
    BNE     TCT_Schedule_Thread             ; If not, start IDLE.
    STMDB   sp!,{r2-r3}                     ; Save r2-r3
    BL      _NU_Idle_Hook
    LDMIA   sp!,{r2-r3}                     ; Restore r2-r3

    ENDIF

TCT_Schedule_Loop

    ; Wait until a thread (task or HISR) is available to execute.
    ; When a thread is available, branch to TCT_Schedule_Thread.

    LDR     r0,[r2]                         ; Pickup highest priority HISR ptr
    CMP     r0,#0                           ; Is there a HISR active?
    BNE     TCT_Schedule_Thread             ; Found a HISR
    LDR     r0,[r3]                         ; Pickup highest priority Task ptr
    CMP     r0,#0                           ; Is there a task active?
    BEQ     TCT_Schedule_Loop               ; If not, continue the search

TCT_Schedule_Thread

    ; Either a task or HISR is ready to execute.  Lockout interrupts while
    ; the thread is transferred (by falling through to the following routine).

    MRS     r1,CPSR                         ; Pickup CPSR again
    ORR     r1,r1,#LOCKOUT                  ; Build interrupt lockout value
    MSR     CPSR_cxsf,r1                    ; Lockout interrupts


;************************************************************************
;*
;*  FUNCTION
;*
;*      TCT_Control_To_Thread
;*
;*  DESCRIPTION
;*
;*      This function transfers control to the specified thread.  Each
;*      time control is transferred to a thread, its scheduled counter
;*      is incremented.  Additionally, time-slicing for task threads is
;*      enabled in this routine.  The TCD_Current_Thread pointer is
;*      setup by this function.
;*
;*  CALLED BY
;*
;*      TCT_Schedule                    Indirectly called
;*      TCT_Protect                     Protection task switch
;*
;*  CALLS
;*
;*      None
;*
;*  INPUTS
;*
;*      r0 -    Thread pointer to schedule
;*
;*  OUTPUTS
;*
;*      None
;*
;*  REGISTERS MODIFIED
;*
;*      r0, r1, r2, r3, sp, pc, SPSR
;*
;*  HISTORY
;*
;*      NAME            DATE            REMARKS
;*
;*      Driscoll, D     01/24/2003      Released Version 1.14.1
;************************************************************************
;VOID  TCT_Control_To_Thread(VOID *thread)

    EXPORT  TCT_Control_To_Thread
TCT_Control_To_Thread

    ; Put thread pointer into TCD_Current_Thread

    LDR     r1,TCT_Current_Thread1          ; Pickup current thread ptr address
    STR     r0,[r1]                         ; Setup current thread pointer

    ; Increment the thread scheduled counter

    LDR     r2,[r0, #TC_SCHEDULED]          ; Pickup scheduled count
    ADD     r2,r2,#1                        ; Increment the scheduled count
    STR     r2,[r0, #TC_SCHEDULED]          ; Store new scheduled count

    ; Check for time slice option

    LDR     r3,[r0, #TC_CUR_TIME_SLICE]     ; Pickup time slice value
    CMP     r3,#0                           ; Is there a time slice?
    BEQ     TCT_No_Start_TS_1               ; If 0, there is no time slice

    ; Set-up the time slice value

    LDR     r2,TCT_Time_Slice               ; Pickup address of TMD_Time_Slice
    STR     r3,[r2]                         ; Setup the time slice

    ; Enable the time-slice timer

    LDR     r1,TCT_Slice_State              ; Pickup address of TMD_Time_Slice_State
    MOV     r2,#0                           ; Build active state flag
    STR     r2,[r1]                         ; Set the active flag

TCT_No_Start_TS_1

    ; Nucleus MMU
    ; Get module pointer, switch Translation Table, flush TLBs, and
    ; flush cache for the new thread

    IF NU_MODULE_SUPPORT
    
    LDR     r1,Current_Module               ; load current module pointer
    LDR     r2,[r1, #0]                     ; setup module pointer

    LDR     r3,[r0, #TC_ID]                 ; Pickup id for current thread
    LDR     r4,=TC_TASK_ID
    CMP     r3,r4                           ; determine if thread is task or HISR
    BNE     TCT_HISR_Module                 ; if not equal this is a HISR

    LDR     r3,[r0, #TC_MODULE]             ; Pickup module pointer of task thread
    B       TCT_Check_Same_Module           ; skip the HISR code

TCT_HISR_Module

    LDR     r3,[r0, #TC_HISR_MODULE]        ; Pickup module pointer of HISR thread

TCT_Check_Same_Module

    CMP     r2,r3                           ; is new thread part of current module?
    BEQ     TCT_Same_Module                 ; if so, do nothing

    STR     r3,[r1, #0]                     ; update the current module pointer

    IF NU_MMU_MODE

    STMDB   sp!,{r0}                        ; Save r0 so we can pass TTBR to
                                            ; MMT_Set_Translation_Table
    LDR     r0,[r3, #MS_TARGET]             ; Get Level 1 base from module and set it up
    BL      MMT_Set_Translation_Table

    LDMIA   sp!,{r0}                        ; restore r0 from stack

    ENDIF

TCT_Same_Module

    IF NU_MMU_MODE

    LDR     r2,Kernel_Module                ; Get the kernel module
    CMP     r3,r2                           ; compare to the current module
    MOV     r2,#0                           ; initialize the register
    BNE     TCT_Skip_Kernel_Check           ; leave zero for possible MMU Enable
    MOV     r2,#1                           ; change to 1 so we don't enable MMU

TCT_Skip_Kernel_Check
    ENDIF                                   ; End NU_MMU_MODE

    ENDIF                                   ; End NU_MMU_API

    ; If Nucleus Proview is defined.

    IF INCLUDE_PROVIEW

    STMDB   sp!,{r0}                        ; Push r0
    BL      _NU_Schedule_Task_Hook          ; Branch to RTView
    LDMIA   sp!,{r0}                        ; Pop r0

    ENDIF

    ; Pickup the thread's stack pointer and resume the thread.

    LDR     sp,[r0, #TC_STACK_POINTER]

    ; Find out if we need to turn on MMU

    IF NU_MMU_MODE
    
    LDR     r3,[r0, #TC_SU_MODE]
    ORR     r3,r3,r2
    
    ENDIF

    ; Pop off the stack top to determine stack type

    LDR     r1,[sp], #4

    ; Remove CPSR from stack and put in SPSR

    LDR     r0,[sp], #4                     ; Pop off the CPSR

    IF NU_MMU_MODE
    
    CMP     r3,#0
    BNE     TCT_Skip_MMU_Enable
    MMU_ENABLE

TCT_Skip_MMU_Enable
    ENDIF

    ; Check if interrupt stack or solicited stack

    CMP     r1,#1                           ; Compare stack type with 1
    BEQ     TCT_Interrupt_Resume            ; If equal to 1, interrupt stack frame

    IF NU_SUPERV_USER_MODE
    
    MOV     r2,sp                           ; save current stack pointer
    ADD     sp,sp,#40                       ; calculate new stack pointer for system mode
    MRS     r1,CPSR                         ; Pickup current CPSR
    BIC     r1,r1,#MODE_MASK                ; Clear mode
    ORR     r1,r1,#SUP_MODE                 ; Set to supervisor
    MSR     CPSR_cxsf,r1                    ; change to supervisor

    MSR     SPSR_cxsf,r0                    ; Place thread CPSR into the SPSR.
                                            ; With mode switching this must be done
                                            ; after the switch to supervisor mode
                                            ; so that we have a SPSR register available

    LDMIA   r2,{r4-r12,pc}^                 ; A solicited return is required.
                                            ; This type of return only
                                            ; recovers r4-r12 & pc
    ELSE

    MSR     SPSR_cxsf,r0                    ; Place thread CPSR into the SPSR.
                                            ; With mode switching this must be done
                                            ; after the switch to supervisor mode
                                            ; so that we have a SPSR register available

    ; Recover all solicited stack frame registers and return
    LDMIA   sp!,{r4-r12,pc}^                ; A solicited return is required.
                                            ; This type of return only
                                            ; recovers r4-r12 & pc
    ENDIF

TCT_Interrupt_Resume

    IF NU_SUPERV_USER_MODE
    
    ADD     r3,sp,#56                       ; calculate lr start
    LDMIA   r3,{lr}                         ; restore lr in system mode
    MOV     r3,sp                           ; save current stack pointer
    ADD     sp,sp,#64                       ; calculate new stack pointer
    MRS     r2,CPSR                         ; Pickup current CPSR
    BIC     r2,r2,#MODE_MASK                ; Clear mode
    ORR     r2,r2,#SUP_MODE                 ; Set to supervisor
    MSR     CPSR_cxsf,r2                    ; change to supervisor
    MOV     sp,r3                           ; restore stack pointer

    MSR     SPSR_cxsf,r0                    ; Place thread CPSR into the SPSR.
                                            ; With mode switching this must be done
                                            ; after the switch to supervisor mode
                                            ; so that we have a SPSR register available

    LDMIA   sp,{r0-pc}^

    ELSE

    MSR     SPSR_cxsf,r0                    ; Place thread CPSR into the SPSR.
                                            ; With mode switching this must be done
                                            ; after the switch to supervisor mode
                                            ; so that we have a SPSR register available

    ; Recover all registers and resume at point of interrupt
    
    LDMIA   sp,{r0-pc}^

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -