300 lines
14 KiB
NASM
300 lines
14 KiB
NASM
;/***************************************************************************
|
|
; * Copyright (c) 2024 Microsoft Corporation
|
|
; *
|
|
; * This program and the accompanying materials are made available under the
|
|
; * terms of the MIT License which is available at
|
|
; * https://opensource.org/licenses/MIT.
|
|
; *
|
|
; * SPDX-License-Identifier: MIT
|
|
; **************************************************************************/
|
|
;
|
|
;
|
|
;/**************************************************************************/
|
|
;/**************************************************************************/
|
|
;/** */
|
|
;/** ThreadX Component */
|
|
;/** */
|
|
;/** Timer */
|
|
;/** */
|
|
;/**************************************************************************/
|
|
;/**************************************************************************/
|
|
;
|
|
;#define TX_SOURCE_CODE
|
|
;
|
|
;
|
|
;/* Include necessary system files. */
|
|
;
|
|
;#include "tx_api.h"
|
|
;#include "tx_timer.h"
|
|
;#include "tx_thread.h"
|
|
;
|
|
FP .set A15
|
|
DP .set B14
|
|
SP .set B15
|
|
;
|
|
;Define Assembly language external references...
|
|
;
|
|
.global _tx_timer_time_slice
|
|
.global _tx_timer_system_clock
|
|
.global _tx_timer_current_ptr
|
|
.global _tx_timer_list_start
|
|
.global _tx_timer_list_end
|
|
.global _tx_timer_expired_time_slice
|
|
.global _tx_timer_expired
|
|
.global _tx_timer_expiration_process
|
|
.global _tx_thread_time_slice
|
|
.global _tx_thread_context_save
|
|
.global _tx_thread_context_restore
|
|
;
|
|
;
|
|
.sect ".text"
|
|
;/**************************************************************************/
|
|
;/* */
|
|
;/* FUNCTION RELEASE */
|
|
;/* */
|
|
;/* _tx_timer_interrupt C667x/TI */
|
|
;/* 6.1 */
|
|
;/* AUTHOR */
|
|
;/* */
|
|
;/* William E. Lamie, Microsoft Corporation */
|
|
;/* */
|
|
;/* DESCRIPTION */
|
|
;/* */
|
|
;/* This function processes the hardware timer interrupt. This */
|
|
;/* processing includes incrementing the system clock and checking for */
|
|
;/* time slice and/or timer expiration. If either is found, the */
|
|
;/* interrupt context save/restore functions are called along with the */
|
|
;/* expiration functions. */
|
|
;/* */
|
|
;/* INPUT */
|
|
;/* */
|
|
;/* None */
|
|
;/* */
|
|
;/* OUTPUT */
|
|
;/* */
|
|
;/* None */
|
|
;/* */
|
|
;/* CALLS */
|
|
;/* */
|
|
;/* _tx_thread_context_save Context save */
|
|
;/* _tx_thread_context_restore Context restore */
|
|
;/* _tx_thread_time_slice Time slice interrupted thread */
|
|
;/* _tx_timer_expiration_process Timer expiration processing */
|
|
;/* */
|
|
;/* CALLED BY */
|
|
;/* */
|
|
;/* interrupt vector */
|
|
;/* */
|
|
;/* RELEASE HISTORY */
|
|
;/* */
|
|
;/* DATE NAME DESCRIPTION */
|
|
;/* */
|
|
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
|
;/* */
|
|
;/**************************************************************************/
|
|
;VOID _tx_timer_interrupt(VOID)
|
|
;{
|
|
.global _tx_timer_interrupt
|
|
_tx_timer_interrupt:
|
|
;
|
|
; /* Upon entry to this routine, it is assumed that registers B3, A0-A4 have
|
|
; already been saved and the space for saving additional registers has
|
|
; already been reserved. In addition, interrupts are locked out and must
|
|
; remain so until context save returns. */
|
|
;
|
|
; /* Increment the system clock. */
|
|
; _tx_timer_system_clock++;
|
|
;
|
|
MVKL _tx_timer_system_clock,A0 ; Build address of system clock
|
|
MVKH _tx_timer_system_clock,A0 ;
|
|
LDW *A0,A2 ; Pickup system clock
|
|
MVKL _tx_timer_time_slice,A3 ; Build address of time slice
|
|
MVKH _tx_timer_time_slice,A3 ;
|
|
LDW *A3,A1 ; Pickup time slice
|
|
NOP 2 ; Delay
|
|
ADD 1,A2,A2 ; Increment the system clock
|
|
STW A2,*A0 ; Store it back in memory
|
|
;
|
|
; /* Test for time-slice expiration. */
|
|
; if (_tx_timer_time_slice)
|
|
; {
|
|
;
|
|
[!A1] B _tx_timer_no_time_slice ; If 0, skip time slice processing
|
|
SUB A1,1,A1 ; Decrement time-slice value
|
|
NOP 4 ; Delay slots
|
|
;
|
|
; /* Decrement the time_slice. */
|
|
; _tx_timer_time_slice--;
|
|
;
|
|
; /* Check for expiration. */
|
|
; if (_tx_timer_time_slice == 0)
|
|
;
|
|
[A1] B _tx_timer_no_time_slice ; If non-zero, not expired yet
|
|
STW A1,*A3 ; Store new time-slice
|
|
MVKL _tx_timer_expired_time_slice,A0 ; Build address of expired flag
|
|
MVKH _tx_timer_expired_time_slice,A0 ;
|
|
MVKL 1,A4 ; Expired flag
|
|
NOP ; Delay
|
|
;
|
|
; /* Set the time-slice expired flag. */
|
|
; _tx_timer_expired_time_slice = TX_TRUE;
|
|
;
|
|
STW A4,*A0 ; Set expired flag
|
|
; }
|
|
;
|
|
_tx_timer_no_time_slice:
|
|
;
|
|
; /* Test for timer expiration. */
|
|
; if (*_tx_timer_current_ptr)
|
|
; {
|
|
;
|
|
MVKL _tx_timer_current_ptr,A2 ; Build address of current timer pointer
|
|
MVKH _tx_timer_current_ptr,A2 ;
|
|
LDW *A2,A0 ; Pickup timer list address
|
|
MVKL _tx_timer_expired,A3 ; Build address of expired flag
|
|
MVKH _tx_timer_expired,A3 ;
|
|
NOP 2 ; Delay slots
|
|
LDW *A0,A1 ; Pickup current timer entry
|
|
ADD 4,A0,A0 ; Increment the current pointer
|
|
NOP 3 ; Delay slots
|
|
[A1] B _tx_timer_done ; If non-NULL, something has expired
|
|
;
|
|
;
|
|
; /* Set expiration flag. */
|
|
; _tx_timer_expired = TX_TRUE;
|
|
;
|
|
MVKL 1,A4 ; Build expired flag
|
|
[A1] STW A4,*A3 ; Set expired flag
|
|
NOP 3 ; Delay slots
|
|
;
|
|
; }
|
|
; else
|
|
; {
|
|
_tx_timer_no_timer:
|
|
;
|
|
; /* No timer expired, increment the timer pointer. */
|
|
; _tx_timer_current_ptr++;
|
|
;
|
|
; /* Check for wrap-around. */
|
|
; if (_tx_timer_current_ptr == _tx_timer_list_end)
|
|
;
|
|
MVKL _tx_timer_list_end,A3 ; Build timer list end address
|
|
MVKH _tx_timer_list_end,A3 ;
|
|
LDW *A3,A4 ; Pickup list end address
|
|
MVKL _tx_timer_list_start,A3 ; Build timer list start address
|
|
MVKH _tx_timer_list_start,A3 ;
|
|
NOP 2 ; Delay slots
|
|
CMPEQ A4,A0,A1 ; Compare current pointer with end
|
|
[A1] LDW *A3,A0 ; If at the end, pickup timer list start
|
|
NOP 4 ; Delay slots
|
|
;
|
|
; /* Wrap to beginning of list. */
|
|
; _tx_timer_current_ptr = _tx_timer_list_start;
|
|
;
|
|
_tx_timer_skip_wrap:
|
|
;
|
|
;
|
|
STW A0,*A2 ; Store current timer pointer
|
|
; }
|
|
;
|
|
_tx_timer_done:
|
|
;
|
|
;
|
|
; /* See if anything has expired. */
|
|
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
|
; {
|
|
;
|
|
MVKL _tx_timer_expired_time_slice,A3 ; Build time-slice expired flag
|
|
MVKH _tx_timer_expired_time_slice,A3 ;
|
|
LDW *A3,A4 ; Pickup time-slice expired flag
|
|
MVKL _tx_timer_expired,A0 ; Build timer expired flag
|
|
MVKH _tx_timer_expired,A0 ;
|
|
LDW *A0,A2 ; Pickup timer expired flag
|
|
NOP 4 ; Delay slots
|
|
OR A2,A4,A1 ; Combine expired flags
|
|
[!A1] B _tx_timer_nothing_expired
|
|
NOP 5 ; Delay slots
|
|
;
|
|
_tx_something_expired:
|
|
;
|
|
;
|
|
; /* Something expired, call context save. */
|
|
; _tx_thread_context_save();
|
|
;
|
|
B _tx_thread_context_save ; Call context save routine
|
|
MVKL _tx_timer_ISR_return,B3 ; Build return address
|
|
MVKH _tx_timer_ISR_return,B3 ;
|
|
NOP 3 ; Delay slots
|
|
_tx_timer_ISR_return:
|
|
;
|
|
; /* Did a timer expire? */
|
|
; if (_tx_timer_expired)
|
|
; {
|
|
;
|
|
MVKL _tx_timer_expired,A0 ; Build timer expired address
|
|
MVKH _tx_timer_expired,A0 ;
|
|
LDW *A0,A1 ; Pickup expired flag
|
|
NOP 4 ; Delay slots
|
|
[!A1] B _tx_timer_dont_activate ; If not set, skip timer activation
|
|
NOP 5 ; Delay slots
|
|
;
|
|
; /* Process timer expiration. */
|
|
; _tx_timer_expiration_process();
|
|
;
|
|
B _tx_timer_expiration_process ; Process timer expiration
|
|
MVKL _tx_timer_ISR_return_1,B3 ; Build return address
|
|
MVKH _tx_timer_ISR_return_1,B3 ;
|
|
NOP 3 ; Delay slots
|
|
_tx_timer_ISR_return_1:
|
|
;
|
|
; }
|
|
_tx_timer_dont_activate:
|
|
;
|
|
; /* Did time slice expire? */
|
|
; if (_tx_timer_expired_time_slice)
|
|
; {
|
|
;
|
|
MVKL _tx_timer_expired_time_slice,A0 ; Build address of expired flag
|
|
MVKH _tx_timer_expired_time_slice,A0 ;
|
|
LDW *A0,A1 ; Pickup expired flag
|
|
NOP 4 ; Delay slots
|
|
[!A1] B _tx_timer_not_ts_expiration ; If not set, skip time-slice processing
|
|
NOP 5 ; Delay slots
|
|
;
|
|
; /* Time slice interrupted thread. */
|
|
; _tx_thread_time_slice();
|
|
;
|
|
B _tx_thread_time_slice ; Call time-slice processing
|
|
MVKL _tx_timer_ISR_return_2,B3 ; Build return address
|
|
MVKH _tx_timer_ISR_return_2,B3 ;
|
|
NOP 3 ; Delay slots
|
|
_tx_timer_ISR_return_2:
|
|
;
|
|
; }
|
|
;
|
|
_tx_timer_not_ts_expiration:
|
|
;
|
|
;
|
|
; /* Call context restore. */
|
|
; _tx_thread_context_restore();
|
|
;
|
|
B _tx_thread_context_restore ; Jump to context restore - no return!
|
|
NOP 5 ; Delay slots
|
|
;
|
|
; }
|
|
;
|
|
_tx_timer_nothing_expired:
|
|
;
|
|
LDW *+SP(20),A0 ; Recover A0
|
|
LDW *+SP(24),A1 ; Recover A1
|
|
LDW *+SP(28),A2 ; Recover A2
|
|
LDW *+SP(32),A3 ; Recover A3
|
|
B IRP ; Return to point of interrupt
|
|
|| LDW *+SP(36),A4 ; Recover A4
|
|
LDW *+SP(96),B3 ; Recover B3
|
|
ADDK.S2 288,SP ; Recover stack space
|
|
NOP 3 ; Delay slots
|
|
;
|
|
;}
|
|
|