mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2025-11-16 04:24:48 +00:00
Add RXv1 port.
This commit is contained in:
281
ports/rxv1/ccrx/inc/tx_port.h
Normal file
281
ports/rxv1/ccrx/inc/tx_port.h
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
/* */
|
||||||
|
/* This software is licensed under the Microsoft Software License */
|
||||||
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
/* and in the root directory of this software. */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
/** */
|
||||||
|
/** ThreadX Component */
|
||||||
|
/** */
|
||||||
|
/** Port Specific */
|
||||||
|
/** */
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||||
|
/* */
|
||||||
|
/* tx_port.h RXv1/CCRX */
|
||||||
|
/* 6.1.8 */
|
||||||
|
/* */
|
||||||
|
/* AUTHOR */
|
||||||
|
/* */
|
||||||
|
/* William E. Lamie, Microsoft Corporation */
|
||||||
|
/* */
|
||||||
|
/* DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* This file contains data type definitions that make the ThreadX */
|
||||||
|
/* real-time kernel function identically on a variety of different */
|
||||||
|
/* processor architectures. For example, the size or number of bits */
|
||||||
|
/* in an "int" data type vary between microprocessor architectures and */
|
||||||
|
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||||
|
/* directly use native C data types. Instead, ThreadX creates its */
|
||||||
|
/* own special types that can be mapped to actual data types by this */
|
||||||
|
/* file to guarantee consistency in the interface and functionality. */
|
||||||
|
/* */
|
||||||
|
/* RELEASE HISTORY */
|
||||||
|
/* */
|
||||||
|
/* DATE NAME DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TX_PORT_H
|
||||||
|
#define TX_PORT_H
|
||||||
|
|
||||||
|
/* Determine if the optional ThreadX user define file should be used. */
|
||||||
|
|
||||||
|
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||||
|
|
||||||
|
|
||||||
|
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||||
|
alternately be defined on the command line. */
|
||||||
|
|
||||||
|
#include "tx_user.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define ThreadX basic types for this port. */
|
||||||
|
|
||||||
|
#define VOID void
|
||||||
|
typedef char CHAR;
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
typedef long LONG;
|
||||||
|
typedef unsigned long ULONG;
|
||||||
|
typedef short SHORT;
|
||||||
|
typedef unsigned short USHORT;
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the priority levels for ThreadX. Legal values range
|
||||||
|
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||||
|
|
||||||
|
#ifndef TX_MAX_PRIORITIES
|
||||||
|
#define TX_MAX_PRIORITIES 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||||
|
thread creation is less than this value, the thread create call will return an error. */
|
||||||
|
|
||||||
|
#ifndef TX_MINIMUM_STACK
|
||||||
|
#define TX_MINIMUM_STACK 256 /* Minimum stack size for this port */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||||
|
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||||
|
|
||||||
|
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||||
|
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||||
|
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX_TRACE_TIME_SOURCE
|
||||||
|
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
|
||||||
|
#endif
|
||||||
|
#ifndef TX_TRACE_TIME_MASK
|
||||||
|
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||||
|
how the ThreadX library was built. */
|
||||||
|
|
||||||
|
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the in-line initialization constant so that modules with in-line
|
||||||
|
initialization capabilities can prevent their initialization from being
|
||||||
|
a function call. */
|
||||||
|
|
||||||
|
#define TX_INLINE_INITIALIZATION
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||||
|
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||||
|
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||||
|
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||||
|
logic. */
|
||||||
|
|
||||||
|
#ifdef TX_ENABLE_STACK_CHECKING
|
||||||
|
#undef TX_DISABLE_STACK_FILLING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||||
|
for the multiple macros is so that backward compatibility can be maintained with
|
||||||
|
existing ThreadX kernel awareness modules. */
|
||||||
|
|
||||||
|
#define TX_THREAD_EXTENSION_0
|
||||||
|
#define TX_THREAD_EXTENSION_1
|
||||||
|
#define TX_THREAD_EXTENSION_2
|
||||||
|
#define TX_THREAD_EXTENSION_3
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the port extensions of the remaining ThreadX objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_EXTENSION
|
||||||
|
#define TX_BYTE_POOL_EXTENSION
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||||
|
#define TX_MUTEX_EXTENSION
|
||||||
|
#define TX_QUEUE_EXTENSION
|
||||||
|
#define TX_SEMAPHORE_EXTENSION
|
||||||
|
#define TX_TIMER_EXTENSION
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the user extension field of the thread control block. Nothing
|
||||||
|
additional is needed for this port so it is defined as white space. */
|
||||||
|
|
||||||
|
#ifndef TX_THREAD_USER_EXTENSION
|
||||||
|
#define TX_THREAD_USER_EXTENSION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||||
|
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||||
|
|
||||||
|
|
||||||
|
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||||
|
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||||
|
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||||
|
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||||
|
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||||
|
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||||
|
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||||
|
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||||
|
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define ThreadX interrupt lockout and restore macros for protection on
|
||||||
|
access of critical kernel information. The restore interrupt macro must
|
||||||
|
restore the interrupt posture of the running thread prior to the value
|
||||||
|
present prior to the disable macro. In most cases, the save area macro
|
||||||
|
is used to define a local function save area for the disable and restore
|
||||||
|
macros. */
|
||||||
|
|
||||||
|
/* UINT _tx_thread_interrupt_control(UINT new_posture); */
|
||||||
|
|
||||||
|
#pragma inline_asm _tx_thread_interrupt_disable
|
||||||
|
static UINT _tx_thread_interrupt_disable(void){
|
||||||
|
MVFC PSW,R1 ;
|
||||||
|
CLRPSW I ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma inline_asm _tx_thread_interrupt_restore
|
||||||
|
static void _tx_thread_interrupt_restore(UINT old_posture){
|
||||||
|
MVFC PSW, R2 ;
|
||||||
|
BTST #16,r1 ;
|
||||||
|
BMC #16,r2 ;
|
||||||
|
MVTC r2,PSW ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||||
|
|
||||||
|
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||||
|
|
||||||
|
|
||||||
|
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||||
|
|
||||||
|
|
||||||
|
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||||
|
|
||||||
|
static void _tx_thread_system_return_inline(void)
|
||||||
|
{
|
||||||
|
UINT interrupt_save;
|
||||||
|
|
||||||
|
interrupt_save = _tx_thread_interrupt_disable();
|
||||||
|
|
||||||
|
*((volatile UCHAR *)(0x872E0u)) = 1u;
|
||||||
|
|
||||||
|
_tx_thread_interrupt_restore(interrupt_save);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||||
|
|
||||||
|
#pragma inline_asm _get_psw
|
||||||
|
static UINT _get_psw(void){
|
||||||
|
MVFC PSW,R1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern volatile ULONG _tx_thread_system_state;
|
||||||
|
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | ((~_get_psw()) & (1u << 17u)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||||
|
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||||
|
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||||
|
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||||
|
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||||
|
|
||||||
|
#ifdef TX_THREAD_INIT
|
||||||
|
CHAR _tx_version_id[] =
|
||||||
|
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX RXv1/CCRX Version 6.1.8 *";
|
||||||
|
#else
|
||||||
|
extern CHAR _tx_version_id[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
164
ports/rxv1/ccrx/readme_threadx.txt
Normal file
164
ports/rxv1/ccrx/readme_threadx.txt
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
Microsoft's Azure RTOS ThreadX for Renesas RXv1
|
||||||
|
|
||||||
|
Using the CC-RX Tools
|
||||||
|
|
||||||
|
1. Building the ThreadX run-time Library
|
||||||
|
|
||||||
|
Please see the Samples repository on GitHub for the Azure RTOS demonstrations
|
||||||
|
for the RXv1.
|
||||||
|
|
||||||
|
|
||||||
|
2. Demonstration System
|
||||||
|
|
||||||
|
Please see the Samples repository on GitHub for the Azure RTOS demonstrations
|
||||||
|
for the RXv1
|
||||||
|
|
||||||
|
|
||||||
|
3. System Initialization
|
||||||
|
|
||||||
|
The system entry point using Renesas tools is at the label _PowerON_Reset_PC.
|
||||||
|
Use the resetprg.c file that comes with your release. Most notable is that Threadx
|
||||||
|
applications run in supervisor mode and do not use user mode. Hence switching to
|
||||||
|
user mode has been commented out.
|
||||||
|
|
||||||
|
The vector area is set up using either intprg.c or in the file tx_initialize_low_level.src.
|
||||||
|
The file tx_initialize_low_level.src is responsible for setting up various system data
|
||||||
|
structures, interrupt vectors, and a periodic timer. This is the ideal place add
|
||||||
|
application specific hardware initialization code.
|
||||||
|
|
||||||
|
ThreadX utilizes CMT0 as a periodic timer interrupt source. The CMT0 interrupt is
|
||||||
|
typically setup for 10ms periodic interrupts and the interrupt priority level is set to
|
||||||
|
level 7. You may change any of the timer parameters to suit your needs.
|
||||||
|
|
||||||
|
In addition, _tx_initialize_low_level determines the first available address for use by
|
||||||
|
the application, which is supplied as the sole input parameter to your application
|
||||||
|
definition function, tx_application_define(). The mechanism is implemented by creating the
|
||||||
|
FREEMEM section, this section should be linked last in the RAM area. tx_initialize_low_level
|
||||||
|
will pick up the starting label of this section and put it in the global variable:
|
||||||
|
_tx_initialize_unused_memory
|
||||||
|
|
||||||
|
|
||||||
|
4. Context Switch, Register Usage and Stack Frames
|
||||||
|
|
||||||
|
The RXv1 port for ThreadX uses the first software interrupt, SWINT, i.e., interrupt #17,
|
||||||
|
to perform context switch. This ISR is thus reserved when using ThreadX and the SWINT
|
||||||
|
should not be manipulated in any way by the application. The port will setup the
|
||||||
|
interrupt within _tx_initialize_low_level and the compiler will automatically install
|
||||||
|
the necessary interrupt vector. As such no additional initialization is necessary by the
|
||||||
|
application.
|
||||||
|
|
||||||
|
The following defines the saved context stack frame used by the ThreadX port. The
|
||||||
|
state of the CPU registers at the time of a context switch is saved on the running
|
||||||
|
thread's stack The top of the suspended thread's stack is pointed to by
|
||||||
|
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
|
||||||
|
|
||||||
|
Offset Interrupted Stack Frame
|
||||||
|
|
||||||
|
0x00 1
|
||||||
|
0x04 ACC0
|
||||||
|
0x0C R6
|
||||||
|
0x10 R7
|
||||||
|
0x14 R8
|
||||||
|
0x18 R9
|
||||||
|
0x1C R10
|
||||||
|
0x20 R11
|
||||||
|
0x24 R12
|
||||||
|
0x28 R13
|
||||||
|
0x30 R14
|
||||||
|
0x34 R15
|
||||||
|
0x38 R3
|
||||||
|
0x3C R4
|
||||||
|
0x40 R5
|
||||||
|
0x44 R1
|
||||||
|
0x48 R2
|
||||||
|
0x4C PC - return address
|
||||||
|
0x50 PSW
|
||||||
|
|
||||||
|
Note: By default ccrx does not save the state of the accumulator register ACC0
|
||||||
|
when entering an ISR. This means that if the ISR uses any of the DSP instructions the
|
||||||
|
content of the register could be corrupted. Saving and restoring of the accumulator
|
||||||
|
can be enabled by adding the -save_acc command line option.
|
||||||
|
|
||||||
|
|
||||||
|
5. Improving Performance
|
||||||
|
|
||||||
|
The distribution version of ThreadX is built without any compiler
|
||||||
|
optimizations. This makes it easy to debug because you can trace or set
|
||||||
|
breakpoints inside of ThreadX itself. Of course, this costs some
|
||||||
|
performance. To make ThreadX run faster, you can change the ThreadX Library
|
||||||
|
project to disable debug information and enable the desired optimizations.
|
||||||
|
|
||||||
|
In addition, you can eliminate the ThreadX basic API error checking by
|
||||||
|
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
|
||||||
|
defined before tx_api.h is included.
|
||||||
|
|
||||||
|
|
||||||
|
6. Timer Processing
|
||||||
|
|
||||||
|
Timer processign is performed by calling __tx_timer_interrupt(). This should usually be done
|
||||||
|
from within the callback of a periodic timer with a period of 100Hz. In the sample projects
|
||||||
|
a Renesas Fit CMT periodic timer module (rx_cmt) is used as the timer source.
|
||||||
|
|
||||||
|
|
||||||
|
7. Interrupt Handling
|
||||||
|
|
||||||
|
Interrupt handling is unaffected by the ThreadX port as such user interrupts can be
|
||||||
|
written according to the toolchain's documentation. It is recommended not to use interrupt
|
||||||
|
priority 15 as this is the priority of the context switch interrupt. However using interrupt
|
||||||
|
priority 15 won't cause any negative side effectd but doing so may may slightly reduce
|
||||||
|
performance. Please refer to the toolchain documentation for additional details on how to
|
||||||
|
define interupt service routines.
|
||||||
|
|
||||||
|
|
||||||
|
8. Execution Profiling
|
||||||
|
|
||||||
|
The RX port adds support for the Execution Profiling Kit (EPK). The EPK consists
|
||||||
|
of the files tx_execution_profile.c and tx_execution_profile.h. See the documentation
|
||||||
|
of the EPK for generic usage details.
|
||||||
|
|
||||||
|
To add the EPK to your RXv1 release make the following modifications:
|
||||||
|
|
||||||
|
* Enable the following define for both the Threadx library and the application
|
||||||
|
TX_EXECUTION_PROFILE_ENABLE
|
||||||
|
|
||||||
|
* Setup CMT1 as a free running 16 bit timer.
|
||||||
|
|
||||||
|
* In tx_execution_profile.h, change following around line 52:
|
||||||
|
|
||||||
|
#ifdef TX_EXECUTION_64BIT_TIME
|
||||||
|
typedef unsigned long long EXECUTION_TIME;
|
||||||
|
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFFFFFFFFFF
|
||||||
|
#else
|
||||||
|
typedef unsigned long EXECUTION_TIME;
|
||||||
|
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define basic constants for the execution profile kit. */
|
||||||
|
|
||||||
|
#define TX_EXECUTION_TIME_SOURCE (EXECUTION_TIME) *((USHORT *) 0x8800A)
|
||||||
|
|
||||||
|
Rebuild the Threadx library and the application.
|
||||||
|
Refer to the EPK documentation how to interpret the results.
|
||||||
|
|
||||||
|
|
||||||
|
9. Revision History
|
||||||
|
|
||||||
|
For generic code revision information, please refer to the readme_threadx_generic.txt
|
||||||
|
file, which is included in your distribution. The following details the revision
|
||||||
|
information associated with this specific port of ThreadX:
|
||||||
|
|
||||||
|
For generic code revision information, please refer to the readme_threadx_generic.txt
|
||||||
|
file, which is included in your distribution. The following details the revision
|
||||||
|
information associated with this specific port of ThreadX:
|
||||||
|
|
||||||
|
08-02-2021 Initial ThreadX release for the RXv1 using CC-RXX tools, version 6.1.8
|
||||||
|
|
||||||
|
|
||||||
|
Copyright(c) 1996-2021 Microsoft Corporation
|
||||||
|
|
||||||
|
|
||||||
|
https://azure.com/rtos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
www.expresslogic.com
|
||||||
101
ports/rxv1/ccrx/src/tx_initialize_low_level.src
Normal file
101
ports/rxv1/ccrx/src/tx_initialize_low_level.src
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Initialize */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
|
||||||
|
.GLB __tx_initialize_unused_memory
|
||||||
|
|
||||||
|
IPR03 .EQU 87303H
|
||||||
|
IEN03 .EQU 87203H
|
||||||
|
|
||||||
|
.SECTION P,CODE
|
||||||
|
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_low_level RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is responsible for any low-level processor */
|
||||||
|
;/* initialization, including setting up interrupt vectors, setting */
|
||||||
|
;/* up a periodic timer interrupt source, saving the system stack */
|
||||||
|
;/* pointer for use in ISR processing later, and finding the first */
|
||||||
|
;/* available RAM memory address for tx_application_define. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.GLB __tx_initialize_low_level
|
||||||
|
__tx_initialize_low_level:
|
||||||
|
;
|
||||||
|
; /* Save the first available memory address. */
|
||||||
|
; _tx_initialize_unused_memory = (VOID_PTR) &free_mem_start;
|
||||||
|
;
|
||||||
|
MOV.L #free_mem_start, R1 ; Pickup unused memory address
|
||||||
|
MOV.L #__tx_initialize_unused_memory,R2
|
||||||
|
MOV.L R1,[R2] ; Save first free memory address
|
||||||
|
|
||||||
|
; /* Set priority of SWINT to 1. */
|
||||||
|
MOV.L #IPR03, r1
|
||||||
|
MOV.L #1, r2
|
||||||
|
MOV.B r2, [r1]
|
||||||
|
|
||||||
|
; /* Enable SWINT. */
|
||||||
|
MOV.L #IEN03,r1
|
||||||
|
MOV.B [r1], r2
|
||||||
|
OR #(1 << 3), r2
|
||||||
|
MOV.B r2, [r1]
|
||||||
|
|
||||||
|
RTS
|
||||||
|
|
||||||
|
.SECTION FREEMEM ,DATA, ALIGN=4
|
||||||
|
free_mem_start:
|
||||||
|
.BLKL 8 ; this section is last in the link map so we can access the end of RAM memory
|
||||||
|
|
||||||
|
.END
|
||||||
200
ports/rxv1/ccrx/src/tx_thread_context_restore.src
Normal file
200
ports/rxv1/ccrx/src/tx_thread_context_restore.src
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;#include "tx_timer.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
.GLB __tx_thread_system_state
|
||||||
|
.GLB __tx_thread_current_ptr
|
||||||
|
.GLB __tx_thread_system_stack_ptr
|
||||||
|
.GLB __tx_thread_execute_ptr
|
||||||
|
.GLB __tx_timer_time_slice
|
||||||
|
.GLB __tx_thread_schedule
|
||||||
|
.GLB __tx_thread_preempt_disable
|
||||||
|
;
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_context_restore RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function restores the interrupt context if it is processing a */
|
||||||
|
;/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||||
|
;/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||||
|
;/* if no thread was running, the function returns to the scheduler. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule Thread scheduling routine */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ISRs Interrupt Service Routines */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_context_restore(VOID)
|
||||||
|
;{
|
||||||
|
.GLB __tx_thread_context_restore
|
||||||
|
__tx_thread_context_restore:
|
||||||
|
;
|
||||||
|
; /* Lockout interrupts. */
|
||||||
|
|
||||||
|
CLRPSW I ; disable interrupts
|
||||||
|
|
||||||
|
; /* Determine if interrupts are nested. */
|
||||||
|
; if (--_tx_thread_system_state)
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_system_state, R1
|
||||||
|
MOV.L [R1], R2
|
||||||
|
SUB #1, R2
|
||||||
|
MOV.L R2,[R1]
|
||||||
|
BEQ __tx_thread_not_nested_restore
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Interrupts are nested. */
|
||||||
|
;
|
||||||
|
; /* Recover the saved registers from the interrupt stack
|
||||||
|
; and return to the point of interrupt. */
|
||||||
|
;
|
||||||
|
__tx_thread_nested_restore:
|
||||||
|
POPM R14-R15 ; restore R14-R15
|
||||||
|
POPM R3-R5 ; restore R3-R5
|
||||||
|
POPM R1-R2 ; restore R1-R2
|
||||||
|
RTE ; return to point of interrupt, restore PSW including IPL
|
||||||
|
; }
|
||||||
|
|
||||||
|
__tx_thread_not_nested_restore:
|
||||||
|
;
|
||||||
|
; /* Determine if a thread was interrupted and no preemption is required. */
|
||||||
|
; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||||
|
; || (_tx_thread_preempt_disable))
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_current_ptr, R1 ; Pickup current thread ptr address
|
||||||
|
MOV.L [R1], R2
|
||||||
|
CMP #0, R2
|
||||||
|
BEQ __tx_thread_idle_system_restore
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_preempt_disable, R3 ; pick up preempt disable flag
|
||||||
|
MOV.L [R3], R3
|
||||||
|
CMP #0, R3
|
||||||
|
BNE __tx_thread_no_preempt_restore ; if pre-empt disable flag set, we simply return to the original point of interrupt regardless
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_execute_ptr, R3 ; (_tx_thread_current_ptr != _tx_thread_execute_ptr)
|
||||||
|
CMP [R3], R2
|
||||||
|
BNE __tx_thread_preempt_restore ; jump to pre-empt restoring
|
||||||
|
;
|
||||||
|
__tx_thread_no_preempt_restore:
|
||||||
|
SETPSW U ; user stack
|
||||||
|
POPM R14-R15 ; restore R14-R15
|
||||||
|
POPM R3-R5 ; restore R3-R5
|
||||||
|
POPM R1-R2 ; restore R1-R2
|
||||||
|
RTE ; return to point of interrupt, restore PSW including IPL
|
||||||
|
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
|
||||||
|
__tx_thread_preempt_restore:
|
||||||
|
|
||||||
|
; /* Save the remaining time-slice and disable it. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_time_slice, R3 ; Pickup time-slice address
|
||||||
|
MOV.L [R3],R4 ; Pickup actual time-slice
|
||||||
|
CMP #0, R4
|
||||||
|
BEQ __tx_thread_dont_save_ts ; no time slice to save
|
||||||
|
;
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||||
|
; _tx_timer_time_slice = 0;
|
||||||
|
;
|
||||||
|
MOV.L R4,24[R2] ; Save thread's time slice
|
||||||
|
MOV.L #0,R4 ; Clear value
|
||||||
|
MOV.L R4,[R3] ; Disable global time slice flag
|
||||||
|
; }
|
||||||
|
__tx_thread_dont_save_ts:
|
||||||
|
;
|
||||||
|
; /* Now store the remaining registers! */
|
||||||
|
|
||||||
|
SETPSW U ; user stack
|
||||||
|
PUSHM R6-R13
|
||||||
|
|
||||||
|
MVFACHI R5
|
||||||
|
MVFACMI R6
|
||||||
|
PUSHM R5-R6
|
||||||
|
|
||||||
|
MOV.L #1, R3 ; indicate interrupt stack frame
|
||||||
|
PUSH.L R3
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Clear the current task pointer. */
|
||||||
|
; _tx_thread_current_ptr = TX_NULL;
|
||||||
|
; R1 -> _tx_thread_current_ptr
|
||||||
|
; R2 -> *_tx_thread_current_ptr
|
||||||
|
|
||||||
|
MOV.L R0,8[R2] ; Save thread's stack pointer in thread control block
|
||||||
|
MOV.L #0,R2 ; Build NULL value
|
||||||
|
MOV.L R2,[R1] ; Set current thread to NULL
|
||||||
|
|
||||||
|
; /* Return to the scheduler. */
|
||||||
|
; _tx_thread_schedule();
|
||||||
|
|
||||||
|
__tx_thread_idle_system_restore:
|
||||||
|
MVTC #0, PSW ; reset interrupt priority level to 0
|
||||||
|
BRA __tx_thread_schedule ; jump to scheduler
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
.END
|
||||||
|
|
||||||
168
ports/rxv1/ccrx/src/tx_thread_context_save.src
Normal file
168
ports/rxv1/ccrx/src/tx_thread_context_save.src
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;#include "tx_timer.h"
|
||||||
|
;
|
||||||
|
.GLB __tx_thread_system_state
|
||||||
|
.GLB __tx_thread_current_ptr
|
||||||
|
.GLB __tx_thread_system_stack_ptr
|
||||||
|
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_context_save RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function saves the context of an executing thread in the */
|
||||||
|
;/* beginning of interrupt processing. The function also ensures that */
|
||||||
|
;/* the system stack is used upon return to the calling ISR. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ISRs */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_context_save(VOID)
|
||||||
|
;{
|
||||||
|
.GLB __tx_thread_context_save
|
||||||
|
__tx_thread_context_save:
|
||||||
|
;
|
||||||
|
; /* Upon entry to this routine, it is assumed that interrupts are locked
|
||||||
|
; out and the (interrupt) stack frame looks like the following:
|
||||||
|
;
|
||||||
|
; (lower address) SP -> [return address of this call]
|
||||||
|
; SP+4 -> Saved R1
|
||||||
|
; SP+8 -> Saved R2
|
||||||
|
; SP+12-> Interrupted PC
|
||||||
|
; SP+16-> Interrupted PSW
|
||||||
|
;
|
||||||
|
; /* Check for a nested interrupt condition. */
|
||||||
|
; if (_tx_thread_system_state++)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_system_state, R1 ; pick up address of system state
|
||||||
|
MOV.L [R1], R2 ; pick up system state
|
||||||
|
CMP #0, R2 ; 0 -> no nesting
|
||||||
|
BEQ __tx_thread_not_nested_save
|
||||||
|
;
|
||||||
|
; /* Nested interrupt condition. */
|
||||||
|
;
|
||||||
|
ADD #1, r2 ; _tx_thread_system_state++
|
||||||
|
MOV.L r2, [r1]
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Save the rest of the scratch registers on the interrupt stack and return to the
|
||||||
|
; calling ISR. */
|
||||||
|
POP R1 ; recuperate return address from stack
|
||||||
|
PUSHM R3-R5
|
||||||
|
PUSHM R14-R15
|
||||||
|
JMP R1 ; return address was preserved in R1
|
||||||
|
|
||||||
|
;
|
||||||
|
__tx_thread_not_nested_save:
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; /* Otherwise, not nested, check to see if a thread was running. */
|
||||||
|
; else if (_tx_thread_current_ptr)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
ADD #1, R2 ; _tx_thread_system_state++
|
||||||
|
MOV.L R2, [R1]
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_current_ptr, R2 ; Pickup current thread pointer
|
||||||
|
MOV.L [R2], R2
|
||||||
|
CMP #0,R2 ; Is it NULL?
|
||||||
|
BEQ __tx_thread_idle_system_save ; Yes, idle system is running - idle restore
|
||||||
|
;
|
||||||
|
; /* Move stack frame over to the current threads stack. */
|
||||||
|
; /* complete stack frame with registers not saved yet (R3-R5, R14-R15) */
|
||||||
|
;
|
||||||
|
MVFC USP, R1 ; pick up user stack pointer
|
||||||
|
MOV.L 16[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save PSW on thread stack
|
||||||
|
MOV.L 12[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save PC on thread stack
|
||||||
|
MOV.L 8[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save R2 on thread stack
|
||||||
|
MOV.L 4[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save R1 on thread stack
|
||||||
|
MOV.L R5, [-R1] ; save R5 on thread stack
|
||||||
|
MOV.L R4, [-R1] ; save R4 on thread stack
|
||||||
|
MOV.L R3, [-R1] ; save R3 on thread stack
|
||||||
|
MOV.L R15, [-R1] ; save R15 on thread stack
|
||||||
|
MOV.L R14, [-R1] ; save R14 on thread stack
|
||||||
|
|
||||||
|
POP R2 ; pick up return address from interrupt stack
|
||||||
|
ADD #16, R0, R0 ; correct interrupt stack pointer back to the bottom
|
||||||
|
MVTC R1, USP ; set user/thread stack pointer
|
||||||
|
JMP R2 ; return to ISR
|
||||||
|
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
__tx_thread_idle_system_save:
|
||||||
|
;
|
||||||
|
; /* Interrupt occurred in the scheduling loop. */
|
||||||
|
;
|
||||||
|
POP R1 ; pick up return address
|
||||||
|
ADD #16, R0, R0 ; correct interrupt stack pointer back to the bottom (PC), don't care about saved registers
|
||||||
|
JMP R1 ; return to caller
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
;}
|
||||||
|
.END
|
||||||
|
|
||||||
96
ports/rxv1/ccrx/src/tx_thread_interrupt_control.src
Normal file
96
ports/rxv1/ccrx/src/tx_thread_interrupt_control.src
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_interrupt_control RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is responsible for changing the interrupt lockout */
|
||||||
|
;/* posture of the system. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* new_posture New interrupt lockout posture */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* old_posture Old interrupt lockout posture */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* Application Code */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||||
|
;{
|
||||||
|
|
||||||
|
.GLB __tx_thread_interrupt_control
|
||||||
|
__tx_thread_interrupt_control:
|
||||||
|
;
|
||||||
|
; /* Pickup current interrupt lockout posture. */
|
||||||
|
;
|
||||||
|
|
||||||
|
MVFC PSW, R2 ; Save PSW to R2
|
||||||
|
MOV.L R2, R3 ; Make a copy of PSW in r3
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Apply the new interrupt posture. */
|
||||||
|
;
|
||||||
|
|
||||||
|
BTST #16, R1 ; test I bit of PSW of "new posture"
|
||||||
|
BMNE #16, R2 ; conditionally set I bit of intermediate posture
|
||||||
|
|
||||||
|
MVTC R2, PSW ; save intermediate posture to PSW
|
||||||
|
|
||||||
|
MOV.L R3,R1 ; Get original SR
|
||||||
|
RTS ; Return to caller
|
||||||
|
;}
|
||||||
|
.END
|
||||||
|
|
||||||
174
ports/rxv1/ccrx/src/tx_thread_schedule.src
Normal file
174
ports/rxv1/ccrx/src/tx_thread_schedule.src
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;#include "tx_timer.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
.GLB __tx_thread_execute_ptr
|
||||||
|
.GLB __tx_thread_current_ptr
|
||||||
|
.GLB __tx_timer_time_slice
|
||||||
|
;
|
||||||
|
.SECTION P,CODE
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function waits for a thread control block pointer to appear in */
|
||||||
|
;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||||
|
;/* in the variable, the corresponding thread is resumed. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||||
|
;/* _tx_thread_system_return Return to system from thread */
|
||||||
|
;/* _tx_thread_context_restore Restore thread's context */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_schedule(VOID)
|
||||||
|
;{
|
||||||
|
.GLB __tx_thread_schedule
|
||||||
|
__tx_thread_schedule:
|
||||||
|
;
|
||||||
|
; /* Enable interrupts. */
|
||||||
|
;
|
||||||
|
SETPSW I
|
||||||
|
;
|
||||||
|
; /* Wait for a thread to execute. */
|
||||||
|
; do
|
||||||
|
; {
|
||||||
|
MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr
|
||||||
|
__tx_thread_schedule_loop:
|
||||||
|
MOV.L [R1],R2 ; Pickup next thread to execute
|
||||||
|
CMP #0,R2 ; Is it NULL?
|
||||||
|
BEQ __tx_thread_schedule_loop ; Yes, idle system, keep checking
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
; while(_tx_thread_execute_ptr == TX_NULL);
|
||||||
|
;
|
||||||
|
; /* Yes! We have a thread to execute. Lockout interrupts and
|
||||||
|
; transfer control to it. */
|
||||||
|
;
|
||||||
|
CLRPSW I ; disable interrupts
|
||||||
|
;
|
||||||
|
; /* Setup the current thread pointer. */
|
||||||
|
; _tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_thread_current_ptr, R3
|
||||||
|
MOV.L R2,[R3] ; Setup current thread pointer
|
||||||
|
;
|
||||||
|
; /* Increment the run count for this thread. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_run_count++;
|
||||||
|
;
|
||||||
|
MOV.L 4[R2],R3 ; Pickup run count
|
||||||
|
ADD #1,R3 ; Increment run counter
|
||||||
|
MOV.L R3,4[R2] ; Store it back in control block
|
||||||
|
;
|
||||||
|
; /* Setup time-slice, if present. */
|
||||||
|
; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||||
|
;
|
||||||
|
MOV.L 24[R2],R3 ; Pickup thread time-slice
|
||||||
|
MOV.L #__tx_timer_time_slice,R4 ; Pickup pointer to time-slice
|
||||||
|
MOV.L R3, [R4] ; Setup time-slice
|
||||||
|
;
|
||||||
|
; /* Switch to the thread's stack. */
|
||||||
|
; SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr;
|
||||||
|
SETPSW U ; user stack mode
|
||||||
|
MOV.L 8[R2],R0 ; Pickup stack pointer
|
||||||
|
;
|
||||||
|
; /* Determine if an interrupt frame or a synchronous task suspension frame
|
||||||
|
; is present. */
|
||||||
|
;
|
||||||
|
POP R1 ; Pickup stack type
|
||||||
|
CMP #1, R1 ; Is it an interrupt stack?
|
||||||
|
BNE __tx_thread_synch_return ; No, a synchronous return frame is present.
|
||||||
|
|
||||||
|
POPM R1-R2 ; Restore accumulator.
|
||||||
|
MVTACLO R2
|
||||||
|
MVTACHI R1
|
||||||
|
|
||||||
|
POPM R6-R13 ; Recover interrupt stack frame
|
||||||
|
POPM R14-R15
|
||||||
|
POPM R3-R5
|
||||||
|
POPM R1-R2
|
||||||
|
RTE ; return to point of interrupt, this restores PC and PSW
|
||||||
|
|
||||||
|
__tx_thread_synch_return:
|
||||||
|
POPC PSW
|
||||||
|
POPM R6-R13 ; Recover solicited stack frame
|
||||||
|
RTS
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
|
||||||
|
|
||||||
|
.GLB __tx_thread_context_save
|
||||||
|
.GLB __tx_thread_context_restore
|
||||||
|
|
||||||
|
; Software triggered interrupt used to perform context switches.
|
||||||
|
; The priority of this interrupt is set to the lowest priority within
|
||||||
|
; tx_initialize_low_level() and triggered by ThreadX when calling
|
||||||
|
; _tx_thread_system_return().
|
||||||
|
.RVECTOR 27, _tx_software_interrupt_entry
|
||||||
|
.GLB _tx_software_interrupt_entry
|
||||||
|
_tx_software_interrupt_entry:
|
||||||
|
|
||||||
|
PUSHM R1-R2
|
||||||
|
|
||||||
|
BSR __tx_thread_context_save
|
||||||
|
|
||||||
|
BRA __tx_thread_context_restore
|
||||||
|
|
||||||
|
.END
|
||||||
145
ports/rxv1/ccrx/src/tx_thread_stack_build.src
Normal file
145
ports/rxv1/ccrx/src/tx_thread_stack_build.src
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_stack_build RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function builds a stack frame on the supplied thread's stack. */
|
||||||
|
;/* The stack frame results in a fake interrupt return to the supplied */
|
||||||
|
;/* function pointer. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* thread_ptr Pointer to thread control blk */
|
||||||
|
;/* function_ptr Pointer to return function */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_create Create thread service */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||||
|
;{
|
||||||
|
.GLB __tx_thread_stack_build
|
||||||
|
__tx_thread_stack_build:
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; /* Build an interrupt frame. The form of the fake interrupt stack
|
||||||
|
; on the Renesas RX should look like the following after it is built:
|
||||||
|
;
|
||||||
|
; Stack Top: 1 Interrupt stack frame type
|
||||||
|
; ACC0
|
||||||
|
; R6
|
||||||
|
; R7
|
||||||
|
; R8
|
||||||
|
; R9
|
||||||
|
; R10
|
||||||
|
; R11
|
||||||
|
; R12
|
||||||
|
; R13
|
||||||
|
; R14
|
||||||
|
; R15
|
||||||
|
; R3
|
||||||
|
; R4
|
||||||
|
; R5
|
||||||
|
; R1
|
||||||
|
; R2
|
||||||
|
; PC
|
||||||
|
; PSW
|
||||||
|
|
||||||
|
;
|
||||||
|
; Stack Bottom: (higher memory address) */
|
||||||
|
;
|
||||||
|
MOV.L 16[R1],R3 ; Pickup end of stack area
|
||||||
|
BCLR #0, R3 ; mask for 4-byte alignment
|
||||||
|
BCLR #1, R3
|
||||||
|
;
|
||||||
|
; /* Build the stack frame. */
|
||||||
|
;
|
||||||
|
MOV.L #30000h, R4
|
||||||
|
MOV.L R4, [-R3] ; initial PSW (SVC mode, U flag set)
|
||||||
|
MOV.L R2, [-R3] ; initial PC
|
||||||
|
MOV.L #0, R4
|
||||||
|
MOV.L R4,[-R3] ; initial R2 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R1 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R5 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R4 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R3 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R15 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R14 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R13 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R12 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R11 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R10 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R9 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R8 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R7 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R6 ...
|
||||||
|
|
||||||
|
MOV.L R4,[-R3] ; Accumulator 0
|
||||||
|
MOV.L R4,[-R3]
|
||||||
|
|
||||||
|
MOV.L #1, R4
|
||||||
|
MOV.L R4,[-R3] ; indicate interrupt stack frame
|
||||||
|
; /* Setup stack pointer. */
|
||||||
|
; thread_ptr -> tx_thread_stack_ptr = R1;
|
||||||
|
MOV.L R3, 8[R1]
|
||||||
|
; store initial SP in thread control block
|
||||||
|
RTS
|
||||||
|
|
||||||
|
;}
|
||||||
|
.END
|
||||||
|
|
||||||
127
ports/rxv1/ccrx/src/tx_thread_system_return.src
Normal file
127
ports/rxv1/ccrx/src/tx_thread_system_return.src
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;#include "tx_timer.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
.GLB __tx_thread_current_ptr
|
||||||
|
.GLB __tx_timer_time_slice
|
||||||
|
.GLB __tx_thread_schedule
|
||||||
|
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_system_return RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is target processor specific. It is used to transfer */
|
||||||
|
;/* control from a thread back to the system. Only a minimal context */
|
||||||
|
;/* is saved since the compiler assumes temp registers are going to get */
|
||||||
|
;/* slicked by a function call anyway. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule Thread scheduling loop */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ThreadX components */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_system_return(VOID)
|
||||||
|
;{
|
||||||
|
.GLB __tx_thread_system_return
|
||||||
|
__tx_thread_system_return:
|
||||||
|
;
|
||||||
|
; /* Save call save registers on the stack. */
|
||||||
|
;
|
||||||
|
PUSHM R6-R13
|
||||||
|
PUSHC PSW
|
||||||
|
MOV.L #0, R1
|
||||||
|
PUSH.L R1 ; solicited stack frame
|
||||||
|
;
|
||||||
|
; /* Lockout interrupts. */
|
||||||
|
;
|
||||||
|
CLRPSW I ; Lockout interrupts
|
||||||
|
;
|
||||||
|
; /* Save current stack in current Thread controle block. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_stack_ptr = SP;
|
||||||
|
MOV.L #__tx_thread_current_ptr, R2
|
||||||
|
MOV.L [R2], R3
|
||||||
|
MOV.L R0, 8[R3]
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_time_slice, R4
|
||||||
|
MOV.L [R4], R5
|
||||||
|
|
||||||
|
; /* Determine if the time-slice is active. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
CMP #0,R5 ; Is a time-slice present?
|
||||||
|
BEQ __tx_thread_dont_save_ts ; No, don't save the time-slice
|
||||||
|
;
|
||||||
|
; /* Save time-slice for the thread and clear the current time-slice. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||||
|
MOV.L R5,24[R3]
|
||||||
|
; _tx_timer_time_slice = 0;
|
||||||
|
;
|
||||||
|
MOV.L R1, [R4] ; Disable the time-slice
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
__tx_thread_dont_save_ts:
|
||||||
|
;
|
||||||
|
; /* Clear the current thread pointer. */
|
||||||
|
; _tx_thread_current_ptr = TX_NULL;
|
||||||
|
;
|
||||||
|
MOV.L R1, [R2]
|
||||||
|
BRA __tx_thread_schedule
|
||||||
|
;}
|
||||||
|
.END
|
||||||
|
|
||||||
251
ports/rxv1/ccrx/src/tx_timer_interrupt.src
Normal file
251
ports/rxv1/ccrx/src/tx_timer_interrupt.src
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Timer */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_timer.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;Define Assembly language external references...
|
||||||
|
;
|
||||||
|
.GLB __tx_timer_time_slice
|
||||||
|
.GLB __tx_timer_system_clock
|
||||||
|
.GLB __tx_timer_current_ptr
|
||||||
|
.GLB __tx_timer_list_start
|
||||||
|
.GLB __tx_timer_list_end
|
||||||
|
.GLB __tx_timer_expired_time_slice
|
||||||
|
.GLB __tx_timer_expired
|
||||||
|
.GLB __tx_timer_expiration_process
|
||||||
|
.GLB __tx_thread_context_save
|
||||||
|
.GLB __tx_thread_time_slice
|
||||||
|
.GLB __tx_thread_context_restore
|
||||||
|
;
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_timer_interrupt RXv1/CCRX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* 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 Save interrupted context */
|
||||||
|
;/* _tx_timer_expiration_process Timer expiration processing */
|
||||||
|
;/* _tx_thread_time_slice Time slice interrupted thread */
|
||||||
|
;/* _tx_thread_context_restore Restore interrupted context */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* interrupt vector */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_timer_interrupt(VOID)
|
||||||
|
;{
|
||||||
|
.GLB __tx_timer_interrupt
|
||||||
|
__tx_timer_interrupt:
|
||||||
|
;
|
||||||
|
; /* Upon entry to this routine, it is assumed that all interrupts are locked
|
||||||
|
; out and the stack looks like the following:
|
||||||
|
; SP+4 -> Interrupted PC
|
||||||
|
; SP+8-> Interrupted SR
|
||||||
|
; */
|
||||||
|
;
|
||||||
|
; /* Increment the system clock. */
|
||||||
|
; _tx_timer_system_clock++;
|
||||||
|
;
|
||||||
|
PUSHM R14-R15
|
||||||
|
PUSHM R1-R5
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_system_clock, R1 ; Pickup address of system clock
|
||||||
|
MOV.L [R1], R2 ; Pickup system clock
|
||||||
|
ADD #1, R2 ; Increment system clock
|
||||||
|
MOV.L R2,[R1] ; Store new system clock
|
||||||
|
;
|
||||||
|
; /* Test for time-slice expiration. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_time_slice, R1 ; Pickup address of time slice
|
||||||
|
MOV.L [R1], R2 ; Pickup the current time slice
|
||||||
|
CMP #0, R2 ; Is a time slice active?
|
||||||
|
BEQ __tx_timer_no_time_slice ; No, skip timer slice processing
|
||||||
|
;
|
||||||
|
; /* Decrement the time_slice. */
|
||||||
|
; _tx_timer_time_slice--;
|
||||||
|
;
|
||||||
|
SUB #1, R2 ; Decrement the time-slice
|
||||||
|
MOV.L R2, [R1] ; Store time-slice
|
||||||
|
;
|
||||||
|
; /* Check for expiration. */
|
||||||
|
; if (__tx_timer_time_slice == 0)
|
||||||
|
;
|
||||||
|
CMP #0, R2 ; Has it expired?
|
||||||
|
BNE __tx_timer_no_time_slice ; No, time-slice has not expired
|
||||||
|
;
|
||||||
|
; /* Set the time-slice expired flag. */
|
||||||
|
; _tx_timer_expired_time_slice = TX_TRUE;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup address of expired time-slice
|
||||||
|
MOV.L #1, R2 ; Build expired value
|
||||||
|
MOV.L R2, [R1] ; Set expired time slice variable
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_no_time_slice:
|
||||||
|
;
|
||||||
|
; /* Test for timer expiration. */
|
||||||
|
; if (*_tx_timer_current_ptr)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_current_ptr, R1 ; Pickup address of current timer ptr
|
||||||
|
MOV.L [R1], R2 ; Pickup current pointer
|
||||||
|
MOV.L [R2+], R1 ; pickup timer list entry, _tx_timer_current_ptr++
|
||||||
|
CMP #0, R1 ; Is timer pointer NULL?
|
||||||
|
BEQ __tx_timer_no_timer ; Yes, no timer has expired
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Set expiration flag. */
|
||||||
|
; _tx_timer_expired = TX_TRUE;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired,R2 ; Build address of expired flag
|
||||||
|
MOV.L #1, R1 ; Build expired value
|
||||||
|
MOV.L R1, [R2]
|
||||||
|
BRA __tx_timer_done ; Finished with timer processing
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
__tx_timer_no_timer:
|
||||||
|
;
|
||||||
|
; /* No timer expired, increment the timer pointer. */
|
||||||
|
; _tx_timer_current_ptr++;
|
||||||
|
;
|
||||||
|
; /* R2 already contains __tx_timer_current_ptr++ */
|
||||||
|
;
|
||||||
|
; /* Check for wrap-around. */
|
||||||
|
; if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_list_end, R1 ; Pickup the timer list end ptr
|
||||||
|
MOV.L [R1], R1 ; Pickup actual timer list end
|
||||||
|
CMP R1, R2 ; Are we at list end?
|
||||||
|
BNE __tx_timer_skip_wrap ; No, don't move pointer to the
|
||||||
|
; top of the list
|
||||||
|
;
|
||||||
|
; /* Wrap to beginning of list. */
|
||||||
|
; _tx_timer_current_ptr = _tx_timer_list_start;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_list_start, R2 ; Pickup the timer list start ptr
|
||||||
|
MOV.L [R2], R2 ; Pickup the start of the list
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_skip_wrap:
|
||||||
|
MOV.L #__tx_timer_current_ptr,R1
|
||||||
|
MOV.L R2, [R1] ; store in updated pointer in _tx_timer_current_ptr
|
||||||
|
|
||||||
|
__tx_timer_done:
|
||||||
|
;
|
||||||
|
; /* See if anything has expired. */
|
||||||
|
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup expired time slice addr
|
||||||
|
MOV.L [R1], R1 ; Pickup expired time slice
|
||||||
|
MOV.L #__tx_timer_expired, R2 ; Pickup expired timer flag address
|
||||||
|
MOV.L [R2], R2 ; Pickup actual flag
|
||||||
|
OR R1, R2 ; Or flags together
|
||||||
|
BEQ __tx_timer_nothing_expired ; If Z set, nothing has expired
|
||||||
|
|
||||||
|
__tx_something_expired:
|
||||||
|
; /* Did a timer expire? */
|
||||||
|
; if (_tx_timer_expired)
|
||||||
|
; {
|
||||||
|
MOV.L #__tx_timer_expired,R1 ; Pickup expired flag address
|
||||||
|
MOV.L [R1], R1 ; Pickup expired flag
|
||||||
|
CMP #0,R1 ; Is the expired timer flag set?
|
||||||
|
BEQ __tx_timer_dont_activate ; No, skip timer activation
|
||||||
|
;
|
||||||
|
; /* Process timer expiration. */
|
||||||
|
; _tx_timer_expiration_process();
|
||||||
|
;
|
||||||
|
BSR __tx_timer_expiration_process ; Call the timer expiration handling routine
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
__tx_timer_dont_activate:
|
||||||
|
;
|
||||||
|
; /* Did time slice expire? */
|
||||||
|
; if (_tx_timer_expired_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup time-slice expired flag addr
|
||||||
|
MOV.L [R1], R1 ; Pickup actual flag
|
||||||
|
CMP #0,R1 ; Has time-slice expired?
|
||||||
|
BEQ __tx_timer_not_ts_expiration ; No, skip time-slice expiration
|
||||||
|
;
|
||||||
|
; /* Time slice interrupted thread. */
|
||||||
|
; _tx_thread_time_slice();
|
||||||
|
|
||||||
|
BSR __tx_thread_time_slice ; Call time-slice processing
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_not_ts_expiration:
|
||||||
|
|
||||||
|
__tx_timer_nothing_expired:
|
||||||
|
|
||||||
|
POPM R1-R5
|
||||||
|
POPM R14-R15
|
||||||
|
;
|
||||||
|
RTS ; return to point of interrupt
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
|
||||||
|
.END
|
||||||
|
|
||||||
264
ports/rxv1/gnu/inc/tx_port.h
Normal file
264
ports/rxv1/gnu/inc/tx_port.h
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
/* */
|
||||||
|
/* This software is licensed under the Microsoft Software License */
|
||||||
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
/* and in the root directory of this software. */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
/** */
|
||||||
|
/** ThreadX Component */
|
||||||
|
/** */
|
||||||
|
/** Port Specific */
|
||||||
|
/** */
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||||
|
/* */
|
||||||
|
/* tx_port.h RXv1/GNURX */
|
||||||
|
/* 6.1.8 */
|
||||||
|
/* */
|
||||||
|
/* AUTHOR */
|
||||||
|
/* */
|
||||||
|
/* William E. Lamie, Microsoft Corporation */
|
||||||
|
/* */
|
||||||
|
/* DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* This file contains data type definitions that make the ThreadX */
|
||||||
|
/* real-time kernel function identically on a variety of different */
|
||||||
|
/* processor architectures. For example, the size or number of bits */
|
||||||
|
/* in an "int" data type vary between microprocessor architectures and */
|
||||||
|
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||||
|
/* directly use native C data types. Instead, ThreadX creates its */
|
||||||
|
/* own special types that can be mapped to actual data types by this */
|
||||||
|
/* file to guarantee consistency in the interface and functionality. */
|
||||||
|
/* */
|
||||||
|
/* RELEASE HISTORY */
|
||||||
|
/* */
|
||||||
|
/* DATE NAME DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TX_PORT_H
|
||||||
|
#define TX_PORT_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
//#include <intrinsics.h>
|
||||||
|
|
||||||
|
/* Determine if the optional ThreadX user define file should be used. */
|
||||||
|
|
||||||
|
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||||
|
|
||||||
|
|
||||||
|
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||||
|
alternately be defined on the command line. */
|
||||||
|
|
||||||
|
#include "tx_user.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define ThreadX basic types for this port. */
|
||||||
|
|
||||||
|
#define VOID void
|
||||||
|
typedef char CHAR;
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
typedef long LONG;
|
||||||
|
typedef unsigned long ULONG;
|
||||||
|
typedef short SHORT;
|
||||||
|
typedef unsigned short USHORT;
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the priority levels for ThreadX. Legal values range
|
||||||
|
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||||
|
|
||||||
|
#ifndef TX_MAX_PRIORITIES
|
||||||
|
#define TX_MAX_PRIORITIES 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||||
|
thread creation is less than this value, the thread create call will return an error. */
|
||||||
|
|
||||||
|
#ifndef TX_MINIMUM_STACK
|
||||||
|
#define TX_MINIMUM_STACK 256 /* Minimum stack size for this port */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||||
|
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||||
|
|
||||||
|
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||||
|
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||||
|
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TX_TRACE_TIME_SOURCE
|
||||||
|
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
|
||||||
|
#endif
|
||||||
|
#ifndef TX_TRACE_TIME_MASK
|
||||||
|
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||||
|
how the ThreadX library was built. */
|
||||||
|
|
||||||
|
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the in-line initialization constant so that modules with in-line
|
||||||
|
initialization capabilities can prevent their initialization from being
|
||||||
|
a function call. */
|
||||||
|
|
||||||
|
#define TX_INLINE_INITIALIZATION
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||||
|
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||||
|
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||||
|
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||||
|
logic. */
|
||||||
|
|
||||||
|
#ifdef TX_ENABLE_STACK_CHECKING
|
||||||
|
#undef TX_DISABLE_STACK_FILLING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||||
|
for the multiple macros is so that backward compatibility can be maintained with
|
||||||
|
existing ThreadX kernel awareness modules. */
|
||||||
|
|
||||||
|
#define TX_THREAD_EXTENSION_0
|
||||||
|
#define TX_THREAD_EXTENSION_1
|
||||||
|
#define TX_THREAD_EXTENSION_2
|
||||||
|
#define TX_THREAD_EXTENSION_3
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the port extensions of the remaining ThreadX objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_EXTENSION
|
||||||
|
#define TX_BYTE_POOL_EXTENSION
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||||
|
#define TX_MUTEX_EXTENSION
|
||||||
|
#define TX_QUEUE_EXTENSION
|
||||||
|
#define TX_SEMAPHORE_EXTENSION
|
||||||
|
#define TX_TIMER_EXTENSION
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the user extension field of the thread control block. Nothing
|
||||||
|
additional is needed for this port so it is defined as white space. */
|
||||||
|
|
||||||
|
#ifndef TX_THREAD_USER_EXTENSION
|
||||||
|
#define TX_THREAD_USER_EXTENSION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||||
|
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||||
|
|
||||||
|
|
||||||
|
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||||
|
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||||
|
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||||
|
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||||
|
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||||
|
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||||
|
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||||
|
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||||
|
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||||
|
|
||||||
|
/* Define ThreadX interrupt lockout and restore macros for protection on
|
||||||
|
access of critical kernel information. The restore interrupt macro must
|
||||||
|
restore the interrupt posture of the running thread prior to the value
|
||||||
|
present prior to the disable macro. In most cases, the save area macro
|
||||||
|
is used to define a local function save area for the disable and restore
|
||||||
|
macros. */
|
||||||
|
|
||||||
|
#ifdef TX_DISABLE_INLINE
|
||||||
|
|
||||||
|
UINT _tx_thread_interrupt_disable(VOID);
|
||||||
|
VOID _tx_thread_interrupt_restore(UINT previous_posture);
|
||||||
|
|
||||||
|
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
|
||||||
|
|
||||||
|
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||||
|
|
||||||
|
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||||
|
#define TX_DISABLE {interrupt_save = ((UINT)__builtin_rx_mvfc(0u) && 0x8u); __builtin_rx_clrpsw(8u);};
|
||||||
|
#define TX_RESTORE {if(interrupt_save != 0u) {__builtin_rx_setpsw(8u);}};
|
||||||
|
|
||||||
|
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||||
|
|
||||||
|
static void _tx_thread_system_return_inline(void)
|
||||||
|
{
|
||||||
|
TX_INTERRUPT_SAVE_AREA
|
||||||
|
|
||||||
|
TX_DISABLE
|
||||||
|
|
||||||
|
*((volatile UCHAR *)(0x872E0u)) = 1u;
|
||||||
|
|
||||||
|
TX_RESTORE
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||||
|
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||||
|
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||||
|
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||||
|
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||||
|
|
||||||
|
#ifdef TX_THREAD_INIT
|
||||||
|
CHAR _tx_version_id[] =
|
||||||
|
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX RXv1/GNURX Version 6.1.8 *";
|
||||||
|
#else
|
||||||
|
extern CHAR _tx_version_id[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
157
ports/rxv1/gnu/readme_threadx.txt
Normal file
157
ports/rxv1/gnu/readme_threadx.txt
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
Microsoft's Azure RTOS ThreadX for Renesas RXv1
|
||||||
|
|
||||||
|
Using the GNU Tools
|
||||||
|
|
||||||
|
|
||||||
|
1. Building the ThreadX run-time Library
|
||||||
|
|
||||||
|
Please see the Samples repository on GitHub for the Azure RTOS demonstrations
|
||||||
|
for the RXv1.
|
||||||
|
|
||||||
|
|
||||||
|
2. Demonstration System
|
||||||
|
|
||||||
|
|
||||||
|
Please see the Samples repository on GitHub for the Azure RTOS demonstrations
|
||||||
|
for the RXv1.
|
||||||
|
|
||||||
|
|
||||||
|
3. System Initialization
|
||||||
|
|
||||||
|
The system entry point using the GNU tools is at the label _PowerON_Reset.
|
||||||
|
|
||||||
|
The vector area is setup in the file tx_initialize_low_level.S. This file is also
|
||||||
|
responsible for setting up various system data structures, interrupt vectors, and
|
||||||
|
the periodic timer interrupt. This file is also an ideal place to add additional hardware
|
||||||
|
initialization code.
|
||||||
|
|
||||||
|
The ThreadX demonstration for the RXv1 utilizes CMT0 as a periodic timer interrupt
|
||||||
|
source. The CMT0 interrupt is typically setup for 10ms periodic interrupts and the
|
||||||
|
interrupt priority level is set to level 7. You may change any of the timer
|
||||||
|
parameters as needed. Increasing the timer interrupt frequency increases the overhead
|
||||||
|
of the timer handling code on the system.
|
||||||
|
|
||||||
|
In addition, _tx_initialize_low_level determines the first available address for use
|
||||||
|
by the application, which is supplied as the sole input parameter to your application
|
||||||
|
definition function, tx_application_define. The first available memory is determined
|
||||||
|
by the location of the '_end' label the is defined in the linker script.
|
||||||
|
'_end' should reference the first memory AFTER all other RAM
|
||||||
|
sections in your linker control file.
|
||||||
|
|
||||||
|
|
||||||
|
4. Context Switch, Register Usage and Stack Frames
|
||||||
|
|
||||||
|
The RXv1 port for ThreadX uses the first software interrupt, SWINT, i.e., interrupt #17,
|
||||||
|
to perform context switch. This ISR is thus reserved when using ThreadX and the SWINT
|
||||||
|
should not be manipulated in any way by the application. The port will setup the
|
||||||
|
interrupt within _tx_initialize_low_level and the compiler will automatically install
|
||||||
|
the necessary interrupt vector. As such no additional initialization is necessary by the
|
||||||
|
application.
|
||||||
|
|
||||||
|
The following defines the saved context stack frame used by the ThreadX port. The
|
||||||
|
state of the CPU registers at the time of a context switch is saved on the running
|
||||||
|
thread's stack The top of the suspended thread's stack is pointed to by
|
||||||
|
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
|
||||||
|
|
||||||
|
Offset Interrupted Stack Frame
|
||||||
|
|
||||||
|
0x00 1
|
||||||
|
0x04 ACC0
|
||||||
|
0x0C R6
|
||||||
|
0x10 R7
|
||||||
|
0x14 R8
|
||||||
|
0x18 R9
|
||||||
|
0x1C R10
|
||||||
|
0x20 R11
|
||||||
|
0x24 R12
|
||||||
|
0x28 R13
|
||||||
|
0x30 R14
|
||||||
|
0x34 R15
|
||||||
|
0x38 R3
|
||||||
|
0x3C R4
|
||||||
|
0x40 R5
|
||||||
|
0x44 R1
|
||||||
|
0x48 R2
|
||||||
|
0x4C PC - return address
|
||||||
|
0x50 PSW
|
||||||
|
|
||||||
|
Note: By default GNURX does not save the state of the accumulator register ACC0
|
||||||
|
when entering an ISR. This means that if the ISR uses any of the DSP instructions the
|
||||||
|
content of the accumulator could be corrupted. Saving and restoring of the accumulator
|
||||||
|
can be enabled by adding the -msave-acc-in-interrupts command line option.
|
||||||
|
|
||||||
|
|
||||||
|
5. Improving Performance
|
||||||
|
|
||||||
|
The distribution version of ThreadX is built without any compiler optimizations. This
|
||||||
|
makes it easy to debug because you can trace or set breakpoints inside of ThreadX itself.
|
||||||
|
Of course, this costs some performance. To make ThreadX run faster, you can change the
|
||||||
|
ThreadX Library project to disable debug information and enable the desired optimizations.
|
||||||
|
|
||||||
|
In addition, you can eliminate the ThreadX basic API error checking by compiling your
|
||||||
|
application code with the symbol TX_DISABLE_ERROR_CHECKING defined before tx_api.h
|
||||||
|
is included.
|
||||||
|
|
||||||
|
|
||||||
|
6. Timer Processing
|
||||||
|
|
||||||
|
Timer processign is performed by calling __tx_timer_interrupt(). This should usually be done
|
||||||
|
from within the callback of a periodic timer with a period of 100Hz. In the sample projects
|
||||||
|
a Renesas Fit CMT periodic timer module (rx_cmt) is used as the timer source.
|
||||||
|
|
||||||
|
|
||||||
|
7. Interrupt Handling
|
||||||
|
|
||||||
|
Interrupt handling is unaffected by the ThreadX port as such user interrupts can be
|
||||||
|
written according to the toolchain's documentation. It is recommended not to use interrupt
|
||||||
|
priority 15 as this is the priority of the context switch interrupt. However using interrupt
|
||||||
|
priority 15 won't cause any negative side effects but doing so may slightly reduce
|
||||||
|
performance. Please refer to the toolchain documentation for additional details on how to
|
||||||
|
define interrupt service routines.
|
||||||
|
|
||||||
|
|
||||||
|
8. Execution Profiling
|
||||||
|
|
||||||
|
The RX port adds support for the Execution Profiling Kit (EPK). The EPK consists
|
||||||
|
of the files tx_execution_profile.c and tx_execution_profile.h. See the documentation
|
||||||
|
of the EPK for generic usage details.
|
||||||
|
|
||||||
|
To add the EPK to your RXv1 release make the following modifications:
|
||||||
|
|
||||||
|
* Enable the following define for both the Threadx library and the application
|
||||||
|
TX_EXECUTION_PROFILE_ENABLE
|
||||||
|
|
||||||
|
* Setup CMT1 as a free running 16 bit timer.
|
||||||
|
|
||||||
|
* In tx_execution_profile.h, change following around line 52:
|
||||||
|
|
||||||
|
#ifdef TX_EXECUTION_64BIT_TIME
|
||||||
|
typedef unsigned long long EXECUTION_TIME;
|
||||||
|
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFFFFFFFFFF
|
||||||
|
#else
|
||||||
|
typedef unsigned long EXECUTION_TIME;
|
||||||
|
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define basic constants for the execution profile kit. */
|
||||||
|
|
||||||
|
#define TX_EXECUTION_TIME_SOURCE (EXECUTION_TIME) *((USHORT *) 0x8800A)
|
||||||
|
|
||||||
|
Rebuild the Threadx library and the application.
|
||||||
|
Refer to the EPK documentation how to interpret the results.
|
||||||
|
|
||||||
|
|
||||||
|
9. Revision History
|
||||||
|
|
||||||
|
For generic code revision information, please refer to the readme_threadx_generic.txt
|
||||||
|
file, which is included in your distribution. The following details the revision
|
||||||
|
information associated with this specific port of ThreadX:
|
||||||
|
|
||||||
|
08-02-2021 Initial ThreadX release for the RXv1 using GNURX tools, version 6.1.8
|
||||||
|
|
||||||
|
|
||||||
|
Copyright(c) 1996-2021 Microsoft Corporation
|
||||||
|
|
||||||
|
|
||||||
|
https://azure.com/rtos
|
||||||
|
|
||||||
93
ports/rxv1/gnu/src/tx_initialize_low_level.S
Normal file
93
ports/rxv1/gnu/src/tx_initialize_low_level.S
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Initialize */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_low_level RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is responsible for any low-level processor */
|
||||||
|
;/* initialization, including setting up interrupt vectors, setting */
|
||||||
|
;/* up a periodic timer interrupt source, saving the system stack */
|
||||||
|
;/* pointer for use in ISR processing later, and finding the first */
|
||||||
|
;/* available RAM memory address for tx_application_define. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
.global __tx_initialize_low_level
|
||||||
|
__tx_initialize_low_level:
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Save the first available memory address. */
|
||||||
|
; _tx_initialize_unused_memory = (VOID_PTR) &free_mem_start;
|
||||||
|
;
|
||||||
|
MOV.L #_end, R1 ; Pickup unused memory address
|
||||||
|
MOV.L #__tx_initialize_unused_memory, R2
|
||||||
|
MOV.L R1,[R2] ; Save first free memory address
|
||||||
|
|
||||||
|
; /* Set priority of SWINT to 1. */
|
||||||
|
MOV.L #0x87303, r1
|
||||||
|
MOV.L #1, r2
|
||||||
|
MOV.B r2, [r1]
|
||||||
|
|
||||||
|
; /* Enable SWINT. */
|
||||||
|
MOV.L #0x87203,r1
|
||||||
|
MOV.B [r1], r2
|
||||||
|
OR #(1 << 3), r2
|
||||||
|
MOV.B r2, [r1]
|
||||||
|
|
||||||
|
RTS
|
||||||
|
|
||||||
|
|
||||||
|
.end
|
||||||
200
ports/rxv1/gnu/src/tx_thread_context_restore.S
Normal file
200
ports/rxv1/gnu/src/tx_thread_context_restore.S
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;#define TX_SOURCE_CODE
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/* Include necessary system files. */
|
||||||
|
;
|
||||||
|
;#include "tx_api.h"
|
||||||
|
;#include "tx_thread.h"
|
||||||
|
;#include "tx_timer.h"
|
||||||
|
;
|
||||||
|
;
|
||||||
|
.global __tx_thread_system_state
|
||||||
|
.global __tx_thread_current_ptr
|
||||||
|
.global __tx_thread_system_stack_ptr
|
||||||
|
.global __tx_thread_execute_ptr
|
||||||
|
.global __tx_timer_time_slice
|
||||||
|
.global __tx_thread_schedule
|
||||||
|
.global __tx_thread_preempt_disable
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_context_restore RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function restores the interrupt context if it is processing a */
|
||||||
|
;/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||||
|
;/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||||
|
;/* if no thread was running, the function returns to the scheduler. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule Thread scheduling routine */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ISRs Interrupt Service Routines */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_context_restore(VOID)
|
||||||
|
;{
|
||||||
|
.global __tx_thread_context_restore
|
||||||
|
__tx_thread_context_restore:
|
||||||
|
;
|
||||||
|
; /* Lockout interrupts. */
|
||||||
|
|
||||||
|
CLRPSW I ; disable interrupts
|
||||||
|
|
||||||
|
; /* Determine if interrupts are nested. */
|
||||||
|
; if (--_tx_thread_system_state)
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_system_state, R1
|
||||||
|
MOV.L [R1], R2
|
||||||
|
SUB #1, R2
|
||||||
|
MOV.L R2,[R1]
|
||||||
|
BEQ __tx_thread_not_nested_restore
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Interrupts are nested. */
|
||||||
|
;
|
||||||
|
; /* Recover the saved registers from the interrupt stack
|
||||||
|
; and return to the point of interrupt. */
|
||||||
|
;
|
||||||
|
__tx_thread_nested_restore:
|
||||||
|
POPM R14-R15 ; restore R14-R15
|
||||||
|
POPM R3-R5 ; restore R3-R5
|
||||||
|
POPM R1-R2 ; restore R1-R2
|
||||||
|
RTE ; return to point of interrupt, restore PSW including IPL
|
||||||
|
; }
|
||||||
|
|
||||||
|
__tx_thread_not_nested_restore:
|
||||||
|
;
|
||||||
|
; /* Determine if a thread was interrupted and no preemption is required. */
|
||||||
|
; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||||
|
; || (_tx_thread_preempt_disable))
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_current_ptr, R1 ; Pickup current thread ptr address
|
||||||
|
MOV.L [R1], R2
|
||||||
|
CMP #0, R2
|
||||||
|
BEQ __tx_thread_idle_system_restore
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_preempt_disable, R3 ; pick up preempt disable flag
|
||||||
|
MOV.L [R3], R3
|
||||||
|
CMP #0, R3
|
||||||
|
BNE __tx_thread_no_preempt_restore ; if pre-empt disable flag set, we simply return to the original point of interrupt regardless
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_execute_ptr, R3 ; (_tx_thread_current_ptr != _tx_thread_execute_ptr)
|
||||||
|
CMP [R3], R2
|
||||||
|
BNE __tx_thread_preempt_restore ; jump to pre-empt restoring
|
||||||
|
;
|
||||||
|
__tx_thread_no_preempt_restore:
|
||||||
|
SETPSW U ; user stack
|
||||||
|
POPM R14-R15 ; restore R14-R15
|
||||||
|
POPM R3-R5 ; restore R3-R5
|
||||||
|
POPM R1-R2 ; restore R1-R2
|
||||||
|
RTE ; return to point of interrupt, restore PSW including IPL
|
||||||
|
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
|
||||||
|
__tx_thread_preempt_restore:
|
||||||
|
|
||||||
|
; /* Save the remaining time-slice and disable it. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_time_slice, R3 ; Pickup time-slice address
|
||||||
|
MOV.L [R3],R4 ; Pickup actual time-slice
|
||||||
|
CMP #0, R4
|
||||||
|
BEQ __tx_thread_dont_save_ts ; no time slice to save
|
||||||
|
;
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||||
|
; _tx_timer_time_slice = 0;
|
||||||
|
;
|
||||||
|
MOV.L R4,24[R2] ; Save thread's time slice
|
||||||
|
MOV.L #0,R4 ; Clear value
|
||||||
|
MOV.L R4,[R3] ; Disable global time slice flag
|
||||||
|
; }
|
||||||
|
__tx_thread_dont_save_ts:
|
||||||
|
;
|
||||||
|
; /* Now store the remaining registers! */
|
||||||
|
|
||||||
|
SETPSW U ; user stack
|
||||||
|
PUSHM R6-R13
|
||||||
|
|
||||||
|
MVFACHI R5
|
||||||
|
MVFACMI R6
|
||||||
|
PUSHM R5-R6
|
||||||
|
|
||||||
|
MOV.L #1, R3 ; indicate interrupt stack frame
|
||||||
|
PUSH.L R3
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Clear the current task pointer. */
|
||||||
|
; _tx_thread_current_ptr = TX_NULL;
|
||||||
|
; R1 -> _tx_thread_current_ptr
|
||||||
|
; R2 -> *_tx_thread_current_ptr
|
||||||
|
|
||||||
|
MOV.L R0,8[R2] ; Save thread's stack pointer in thread control block
|
||||||
|
MOV.L #0,R2 ; Build NULL value
|
||||||
|
MOV.L R2,[R1] ; Set current thread to NULL
|
||||||
|
|
||||||
|
; /* Return to the scheduler. */
|
||||||
|
; _tx_thread_schedule();
|
||||||
|
|
||||||
|
__tx_thread_idle_system_restore:
|
||||||
|
MVTC #0, PSW ; reset interrupt priority level to 0
|
||||||
|
BRA __tx_thread_schedule ; jump to scheduler
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
.end
|
||||||
158
ports/rxv1/gnu/src/tx_thread_context_save.S
Normal file
158
ports/rxv1/gnu/src/tx_thread_context_save.S
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.global __tx_thread_system_state
|
||||||
|
.global __tx_thread_current_ptr
|
||||||
|
.global __tx_thread_system_stack_ptr
|
||||||
|
|
||||||
|
.text
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_context_save RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function saves the context of an executing thread in the */
|
||||||
|
;/* beginning of interrupt processing. The function also ensures that */
|
||||||
|
;/* the system stack is used upon return to the calling ISR. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ISRs */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_context_save(VOID)
|
||||||
|
;{
|
||||||
|
.global __tx_thread_context_save
|
||||||
|
__tx_thread_context_save:
|
||||||
|
;
|
||||||
|
; /* Upon entry to this routine, it is assumed that interrupts are locked
|
||||||
|
; out and the (interrupt) stack frame looks like the following:
|
||||||
|
;
|
||||||
|
; (lower address) SP -> [return address of this call]
|
||||||
|
; SP+4 -> Saved R1
|
||||||
|
; SP+8 -> Saved R2
|
||||||
|
; SP+12-> Interrupted PC
|
||||||
|
; SP+16-> Interrupted PSW
|
||||||
|
;
|
||||||
|
; /* Check for a nested interrupt condition. */
|
||||||
|
; if (_tx_thread_system_state++)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_system_state, R1 ; pick up address of system state
|
||||||
|
MOV.L [R1], R2 ; pick up system state
|
||||||
|
CMP #0, R2 ; 0 -> no nesting
|
||||||
|
BEQ __tx_thread_not_nested_save
|
||||||
|
;
|
||||||
|
; /* Nested interrupt condition. */
|
||||||
|
;
|
||||||
|
ADD #1, r2 ; _tx_thread_system_state++
|
||||||
|
MOV.L r2, [r1]
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Save the rest of the scratch registers on the interrupt stack and return to the
|
||||||
|
; calling ISR. */
|
||||||
|
POP R1 ; recuperate return address from stack
|
||||||
|
PUSHM R3-R5
|
||||||
|
PUSHM R14-R15
|
||||||
|
JMP R1 ; return address was preserved in R1
|
||||||
|
|
||||||
|
;
|
||||||
|
__tx_thread_not_nested_save:
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; /* Otherwise, not nested, check to see if a thread was running. */
|
||||||
|
; else if (_tx_thread_current_ptr)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
ADD #1, R2 ; _tx_thread_system_state++
|
||||||
|
MOV.L R2, [R1]
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_current_ptr, R2 ; Pickup current thread pointer
|
||||||
|
MOV.L [R2], R2
|
||||||
|
CMP #0,R2 ; Is it NULL?
|
||||||
|
BEQ __tx_thread_idle_system_save ; Yes, idle system is running - idle restore
|
||||||
|
;
|
||||||
|
; /* Move stack frame over to the current threads stack. */
|
||||||
|
; /* complete stack frame with registers not saved yet (R3-R5, R14-R15, FPSW) */
|
||||||
|
;
|
||||||
|
MVFC USP, R1 ; pick up user stack pointer
|
||||||
|
MOV.L 16[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save PSW on thread stack
|
||||||
|
MOV.L 12[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save PC on thread stack
|
||||||
|
MOV.L 8[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save R2 on thread stack
|
||||||
|
MOV.L 4[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save R1 on thread stack
|
||||||
|
MOV.L R5, [-R1] ; save R5 on thread stack
|
||||||
|
MOV.L R4, [-R1] ; save R4 on thread stack
|
||||||
|
MOV.L R3, [-R1] ; save R3 on thread stack
|
||||||
|
MOV.L R15, [-R1] ; save R15 on thread stack
|
||||||
|
MOV.L R14, [-R1] ; save R14 on thread stack
|
||||||
|
|
||||||
|
POP R2 ; pick up return address from interrupt stack
|
||||||
|
ADD #16, R0, R0 ; correct interrupt stack pointer back to the bottom
|
||||||
|
MVTC R1, USP ; set user/thread stack pointer
|
||||||
|
JMP R2 ; return to ISR
|
||||||
|
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
__tx_thread_idle_system_save:
|
||||||
|
;
|
||||||
|
; /* Interrupt occurred in the scheduling loop. */
|
||||||
|
;
|
||||||
|
POP R1 ; pick up return address
|
||||||
|
ADD #16, R0, R0 ; correct interrupt stack pointer back to the bottom (PC), don't care about saved registers
|
||||||
|
JMP R1 ; return to caller
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
;}
|
||||||
|
.end
|
||||||
|
|
||||||
87
ports/rxv1/gnu/src/tx_thread_interrupt_control.S
Normal file
87
ports/rxv1/gnu/src/tx_thread_interrupt_control.S
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_interrupt_control RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is responsible for changing the interrupt lockout */
|
||||||
|
;/* posture of the system. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* new_posture New interrupt lockout posture */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* old_posture Old interrupt lockout posture */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* Application Code */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||||
|
;{
|
||||||
|
|
||||||
|
.global __tx_thread_interrupt_control
|
||||||
|
__tx_thread_interrupt_control:
|
||||||
|
;
|
||||||
|
; /* Pickup current interrupt lockout posture. */
|
||||||
|
;
|
||||||
|
|
||||||
|
MVFC PSW, R2 ; Save PSW to R2
|
||||||
|
MOV.L R2, R3 ; Make a copy of PSW in r3
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Apply the new interrupt posture. */
|
||||||
|
;
|
||||||
|
|
||||||
|
BTST #16, R1 ; test I bit of PSW of "new posture"
|
||||||
|
BMNE #16, R2 ; conditionally set I bit of intermediate posture
|
||||||
|
|
||||||
|
MVTC R2, PSW ; save intermediate posture to PSW
|
||||||
|
|
||||||
|
MOV.L R3,R1 ; Get original SR
|
||||||
|
RTS ; Return to caller
|
||||||
|
;}
|
||||||
|
.end
|
||||||
|
|
||||||
163
ports/rxv1/gnu/src/tx_thread_schedule.S
Normal file
163
ports/rxv1/gnu/src/tx_thread_schedule.S
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.global __tx_thread_execute_ptr
|
||||||
|
.global __tx_thread_current_ptr
|
||||||
|
.global __tx_timer_time_slice
|
||||||
|
;
|
||||||
|
.text
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function waits for a thread control block pointer to appear in */
|
||||||
|
;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||||
|
;/* in the variable, the corresponding thread is resumed. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||||
|
;/* _tx_thread_system_return Return to system from thread */
|
||||||
|
;/* _tx_thread_context_restore Restore thread's context */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_schedule(VOID)
|
||||||
|
;{
|
||||||
|
.global __tx_thread_schedule
|
||||||
|
__tx_thread_schedule:
|
||||||
|
;
|
||||||
|
; /* Enable interrupts. */
|
||||||
|
;
|
||||||
|
SETPSW I
|
||||||
|
;
|
||||||
|
; /* Wait for a thread to execute. */
|
||||||
|
; do
|
||||||
|
; {
|
||||||
|
MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr
|
||||||
|
__tx_thread_schedule_loop:
|
||||||
|
MOV.L [R1],R2 ; Pickup next thread to execute
|
||||||
|
CMP #0,R2 ; Is it NULL?
|
||||||
|
BEQ __tx_thread_schedule_loop ; Yes, idle system, keep checking
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
; while(_tx_thread_execute_ptr == TX_NULL);
|
||||||
|
;
|
||||||
|
; /* Yes! We have a thread to execute. Lockout interrupts and
|
||||||
|
; transfer control to it. */
|
||||||
|
;
|
||||||
|
CLRPSW I ; disable interrupts
|
||||||
|
;
|
||||||
|
; /* Setup the current thread pointer. */
|
||||||
|
; _tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_thread_current_ptr, R3
|
||||||
|
MOV.L R2,[R3] ; Setup current thread pointer
|
||||||
|
;
|
||||||
|
; /* Increment the run count for this thread. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_run_count++;
|
||||||
|
;
|
||||||
|
MOV.L 4[R2],R3 ; Pickup run count
|
||||||
|
ADD #1,R3 ; Increment run counter
|
||||||
|
MOV.L R3,4[R2] ; Store it back in control block
|
||||||
|
;
|
||||||
|
; /* Setup time-slice, if present. */
|
||||||
|
; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||||
|
;
|
||||||
|
MOV.L 24[R2],R3 ; Pickup thread time-slice
|
||||||
|
MOV.L #__tx_timer_time_slice,R4 ; Pickup pointer to time-slice
|
||||||
|
MOV.L R3, [R4] ; Setup time-slice
|
||||||
|
;
|
||||||
|
; /* Switch to the thread's stack. */
|
||||||
|
; SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr;
|
||||||
|
SETPSW U ; user stack mode
|
||||||
|
MOV.L 8[R2],R0 ; Pickup stack pointer
|
||||||
|
;
|
||||||
|
; /* Determine if an interrupt frame or a synchronous task suspension frame
|
||||||
|
; is present. */
|
||||||
|
;
|
||||||
|
POP R1 ; Pickup stack type
|
||||||
|
CMP #1, R1 ; Is it an interrupt stack?
|
||||||
|
BNE __tx_thread_synch_return ; No, a synchronous return frame is present.
|
||||||
|
|
||||||
|
POPM R1-R2 ; Restore accumulator.
|
||||||
|
MVTACLO R2
|
||||||
|
MVTACHI R1
|
||||||
|
|
||||||
|
POPM R6-R13 ; Recover interrupt stack frame
|
||||||
|
POPM R14-R15
|
||||||
|
POPM R3-R5
|
||||||
|
POPM R1-R2
|
||||||
|
RTE ; return to point of interrupt, this restores PC and PSW
|
||||||
|
|
||||||
|
__tx_thread_synch_return:
|
||||||
|
POPC PSW
|
||||||
|
POPM R6-R13 ; Recover solicited stack frame
|
||||||
|
RTS
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
|
||||||
|
|
||||||
|
.global __tx_thread_context_save
|
||||||
|
.global __tx_thread_context_restore
|
||||||
|
|
||||||
|
|
||||||
|
; Software triggered interrupt used to perform context switches.
|
||||||
|
; The priority of this interrupt is set to the lowest priority within
|
||||||
|
; tx_initialize_low_level() and triggered by ThreadX when calling
|
||||||
|
; _tx_thread_system_return().
|
||||||
|
.global $tableentry$27$.rvectors
|
||||||
|
$tableentry$27$.rvectors:
|
||||||
|
|
||||||
|
PUSHM R1-R2
|
||||||
|
|
||||||
|
BSR __tx_thread_context_save
|
||||||
|
|
||||||
|
BRA __tx_thread_context_restore
|
||||||
|
|
||||||
|
.end
|
||||||
137
ports/rxv1/gnu/src/tx_thread_stack_build.S
Normal file
137
ports/rxv1/gnu/src/tx_thread_stack_build.S
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_stack_build RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function builds a stack frame on the supplied thread's stack. */
|
||||||
|
;/* The stack frame results in a fake interrupt return to the supplied */
|
||||||
|
;/* function pointer. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* thread_ptr Pointer to thread control blk */
|
||||||
|
;/* function_ptr Pointer to return function */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_create Create thread service */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||||
|
;{
|
||||||
|
.global __tx_thread_stack_build
|
||||||
|
__tx_thread_stack_build:
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; /* Build an interrupt frame. The form of the fake interrupt stack
|
||||||
|
; on the Renesas RX should look like the following after it is built:
|
||||||
|
;
|
||||||
|
; Stack Top: 1 Interrupt stack frame type
|
||||||
|
; ACC0
|
||||||
|
; ACC1
|
||||||
|
; R6
|
||||||
|
; R7
|
||||||
|
; R8
|
||||||
|
; R9
|
||||||
|
; R10
|
||||||
|
; R11
|
||||||
|
; R12
|
||||||
|
; R13
|
||||||
|
; FPSW
|
||||||
|
; R14
|
||||||
|
; R15
|
||||||
|
; R3
|
||||||
|
; R4
|
||||||
|
; R5
|
||||||
|
; R1
|
||||||
|
; R2
|
||||||
|
; PC
|
||||||
|
; PSW
|
||||||
|
|
||||||
|
;
|
||||||
|
; Stack Bottom: (higher memory address) */
|
||||||
|
;
|
||||||
|
MOV.L 16[R1],R3 ; Pickup end of stack area
|
||||||
|
BCLR #0, R3 ; mask for 4-byte alignment
|
||||||
|
BCLR #1, R3
|
||||||
|
;
|
||||||
|
; /* Build the stack frame. */
|
||||||
|
;
|
||||||
|
MOV.L #30000h, R4
|
||||||
|
MOV.L R4, [-R3] ; initial PSW (SVC mode, U flag set)
|
||||||
|
MOV.L R2, [-R3] ; initial PC
|
||||||
|
MOV.L #0, R4
|
||||||
|
MOV.L R4,[-R3] ; initial R2 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R1 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R5 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R4 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R3 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R15 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R14 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R13 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R12 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R11 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R10 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R9 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R8 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R7 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R6 ...
|
||||||
|
|
||||||
|
MOV.L R4,[-R3] ; Accumulator 0
|
||||||
|
MOV.L R4,[-R3]
|
||||||
|
|
||||||
|
MOV.L #1, R4
|
||||||
|
MOV.L R4,[-R3] ; indicate interrupt stack frame
|
||||||
|
; /* Setup stack pointer. */
|
||||||
|
; thread_ptr -> tx_thread_stack_ptr = R1;
|
||||||
|
MOV.L R3, 8[R1]
|
||||||
|
; store initial SP in thread control block
|
||||||
|
RTS
|
||||||
|
|
||||||
|
;}
|
||||||
|
.end
|
||||||
|
|
||||||
117
ports/rxv1/gnu/src/tx_thread_system_return.S
Normal file
117
ports/rxv1/gnu/src/tx_thread_system_return.S
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.global __tx_thread_current_ptr
|
||||||
|
.global __tx_timer_time_slice
|
||||||
|
.global __tx_thread_schedule
|
||||||
|
|
||||||
|
.text
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_system_return RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is target processor specific. It is used to transfer */
|
||||||
|
;/* control from a thread back to the system. Only a minimal context */
|
||||||
|
;/* is saved since the compiler assumes temp registers are going to get */
|
||||||
|
;/* slicked by a function call anyway. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule Thread scheduling loop */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ThreadX components */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_system_return(VOID)
|
||||||
|
;{
|
||||||
|
.GLB __tx_thread_system_return
|
||||||
|
__tx_thread_system_return:
|
||||||
|
;
|
||||||
|
; /* Save call save registers on the stack. */
|
||||||
|
;
|
||||||
|
PUSHM R6-R13
|
||||||
|
PUSHC PSW
|
||||||
|
MOV.L #0, R1
|
||||||
|
PUSH.L R1 ; solicited stack frame
|
||||||
|
;
|
||||||
|
; /* Lockout interrupts. */
|
||||||
|
;
|
||||||
|
CLRPSW I ; Lockout interrupts
|
||||||
|
;
|
||||||
|
; /* Save current stack in current Thread controle block. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_stack_ptr = SP;
|
||||||
|
MOV.L #__tx_thread_current_ptr, R2
|
||||||
|
MOV.L [R2], R3
|
||||||
|
MOV.L R0, 8[R3]
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_time_slice, R4
|
||||||
|
MOV.L [R4], R5
|
||||||
|
|
||||||
|
; /* Determine if the time-slice is active. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
CMP #0,R5 ; Is a time-slice present?
|
||||||
|
BEQ __tx_thread_dont_save_ts ; No, don't save the time-slice
|
||||||
|
;
|
||||||
|
; /* Save time-slice for the thread and clear the current time-slice. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||||
|
MOV.L R5,24[R3]
|
||||||
|
; _tx_timer_time_slice = 0;
|
||||||
|
;
|
||||||
|
MOV.L R1, [R4] ; Disable the time-slice
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
__tx_thread_dont_save_ts:
|
||||||
|
;
|
||||||
|
; /* Clear the current thread pointer. */
|
||||||
|
; _tx_thread_current_ptr = TX_NULL;
|
||||||
|
;
|
||||||
|
MOV.L R1, [R2]
|
||||||
|
BRA __tx_thread_schedule
|
||||||
|
;}
|
||||||
|
.end
|
||||||
|
|
||||||
239
ports/rxv1/gnu/src/tx_timer_interrupt.S
Normal file
239
ports/rxv1/gnu/src/tx_timer_interrupt.S
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Timer */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
.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_context_save
|
||||||
|
.global __tx_thread_time_slice
|
||||||
|
.global __tx_thread_context_restore
|
||||||
|
|
||||||
|
.SECTION P,CODE
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_timer_interrupt RXv1/GNURX */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* 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 Save interrupted context */
|
||||||
|
;/* _tx_timer_expiration_process Timer expiration processing */
|
||||||
|
;/* _tx_thread_time_slice Time slice interrupted thread */
|
||||||
|
;/* _tx_thread_context_restore Restore interrupted context */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* interrupt vector */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_timer_interrupt(VOID)
|
||||||
|
;{
|
||||||
|
.global __tx_timer_interrupt
|
||||||
|
__tx_timer_interrupt:
|
||||||
|
;
|
||||||
|
; /* Upon entry to this routine, it is assumed that all interrupts are locked
|
||||||
|
; out and the stack looks like the following:
|
||||||
|
; SP+4 -> Interrupted PC
|
||||||
|
; SP+8-> Interrupted SR
|
||||||
|
; */
|
||||||
|
;
|
||||||
|
; /* Increment the system clock. */
|
||||||
|
; _tx_timer_system_clock++;
|
||||||
|
;
|
||||||
|
PUSHM R14-R15
|
||||||
|
PUSHM R1-R5
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_system_clock, R1 ; Pickup address of system clock
|
||||||
|
MOV.L [R1], R2 ; Pickup system clock
|
||||||
|
ADD #1, R2 ; Increment system clock
|
||||||
|
MOV.L R2,[R1] ; Store new system clock
|
||||||
|
;
|
||||||
|
; /* Test for time-slice expiration. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_time_slice, R1 ; Pickup address of time slice
|
||||||
|
MOV.L [R1], R2 ; Pickup the current time slice
|
||||||
|
CMP #0, R2 ; Is a time slice active?
|
||||||
|
BEQ __tx_timer_no_time_slice ; No, skip timer slice processing
|
||||||
|
;
|
||||||
|
; /* Decrement the time_slice. */
|
||||||
|
; _tx_timer_time_slice--;
|
||||||
|
;
|
||||||
|
SUB #1, R2 ; Decrement the time-slice
|
||||||
|
MOV.L R2, [R1] ; Store time-slice
|
||||||
|
;
|
||||||
|
; /* Check for expiration. */
|
||||||
|
; if (__tx_timer_time_slice == 0)
|
||||||
|
;
|
||||||
|
CMP #0, R2 ; Has it expired?
|
||||||
|
BNE __tx_timer_no_time_slice ; No, time-slice has not expired
|
||||||
|
;
|
||||||
|
; /* Set the time-slice expired flag. */
|
||||||
|
; _tx_timer_expired_time_slice = TX_TRUE;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup address of expired time-slice
|
||||||
|
MOV.L #1, R2 ; Build expired value
|
||||||
|
MOV.L R2, [R1] ; Set expired time slice variable
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_no_time_slice:
|
||||||
|
;
|
||||||
|
; /* Test for timer expiration. */
|
||||||
|
; if (*_tx_timer_current_ptr)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_current_ptr, R1 ; Pickup address of current timer ptr
|
||||||
|
MOV.L [R1], R2 ; Pickup current pointer
|
||||||
|
MOV.L [R2+], R1 ; pickup timer list entry, _tx_timer_current_ptr++
|
||||||
|
CMP #0, R1 ; Is timer pointer NULL?
|
||||||
|
BEQ __tx_timer_no_timer ; Yes, no timer has expired
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Set expiration flag. */
|
||||||
|
; _tx_timer_expired = TX_TRUE;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired,R2 ; Build address of expired flag
|
||||||
|
MOV.L #1, R1 ; Build expired value
|
||||||
|
MOV.L R1, [R2]
|
||||||
|
BRA __tx_timer_done ; Finished with timer processing
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
__tx_timer_no_timer:
|
||||||
|
;
|
||||||
|
; /* No timer expired, increment the timer pointer. */
|
||||||
|
; _tx_timer_current_ptr++;
|
||||||
|
;
|
||||||
|
; /* R2 already contains __tx_timer_current_ptr++ */
|
||||||
|
;
|
||||||
|
; /* Check for wrap-around. */
|
||||||
|
; if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_list_end, R1 ; Pickup the timer list end ptr
|
||||||
|
MOV.L [R1], R1 ; Pickup actual timer list end
|
||||||
|
CMP R1, R2 ; Are we at list end?
|
||||||
|
BNE __tx_timer_skip_wrap ; No, don't move pointer to the
|
||||||
|
; top of the list
|
||||||
|
;
|
||||||
|
; /* Wrap to beginning of list. */
|
||||||
|
; _tx_timer_current_ptr = _tx_timer_list_start;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_list_start, R2 ; Pickup the timer list start ptr
|
||||||
|
MOV.L [R2], R2 ; Pickup the start of the list
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_skip_wrap:
|
||||||
|
MOV.L #__tx_timer_current_ptr,R1
|
||||||
|
MOV.L R2, [R1] ; store in updated pointer in _tx_timer_current_ptr
|
||||||
|
|
||||||
|
__tx_timer_done:
|
||||||
|
;
|
||||||
|
; /* See if anything has expired. */
|
||||||
|
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup expired time slice addr
|
||||||
|
MOV.L [R1], R1 ; Pickup expired time slice
|
||||||
|
MOV.L #__tx_timer_expired, R2 ; Pickup expired timer flag address
|
||||||
|
MOV.L [R2], R2 ; Pickup actual flag
|
||||||
|
OR R1, R2 ; Or flags together
|
||||||
|
BEQ __tx_timer_nothing_expired ; If Z set, nothing has expired
|
||||||
|
|
||||||
|
__tx_something_expired:
|
||||||
|
; /* Did a timer expire? */
|
||||||
|
; if (_tx_timer_expired)
|
||||||
|
; {
|
||||||
|
MOV.L #__tx_timer_expired,R1 ; Pickup expired flag address
|
||||||
|
MOV.L [R1], R1 ; Pickup expired flag
|
||||||
|
CMP #0,R1 ; Is the expired timer flag set?
|
||||||
|
BEQ __tx_timer_dont_activate ; No, skip timer activation
|
||||||
|
;
|
||||||
|
; /* Process timer expiration. */
|
||||||
|
; _tx_timer_expiration_process();
|
||||||
|
;
|
||||||
|
BSR __tx_timer_expiration_process ; Call the timer expiration handling routine
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
__tx_timer_dont_activate:
|
||||||
|
;
|
||||||
|
; /* Did time slice expire? */
|
||||||
|
; if (_tx_timer_expired_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup time-slice expired flag addr
|
||||||
|
MOV.L [R1], R1 ; Pickup actual flag
|
||||||
|
CMP #0,R1 ; Has time-slice expired?
|
||||||
|
BEQ __tx_timer_not_ts_expiration ; No, skip time-slice expiration
|
||||||
|
;
|
||||||
|
; /* Time slice interrupted thread. */
|
||||||
|
; _tx_thread_time_slice();
|
||||||
|
|
||||||
|
BSR __tx_thread_time_slice ; Call time-slice processing
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_not_ts_expiration:
|
||||||
|
|
||||||
|
__tx_timer_nothing_expired:
|
||||||
|
|
||||||
|
POPM R1-R5
|
||||||
|
POPM R14-R15
|
||||||
|
;
|
||||||
|
RTS ; return to point of interrupt
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
|
||||||
|
.end
|
||||||
|
|
||||||
273
ports/rxv1/iar/inc/tx_port.h
Normal file
273
ports/rxv1/iar/inc/tx_port.h
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
/* */
|
||||||
|
/* This software is licensed under the Microsoft Software License */
|
||||||
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
/* and in the root directory of this software. */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
/** */
|
||||||
|
/** ThreadX Component */
|
||||||
|
/** */
|
||||||
|
/** Port Specific */
|
||||||
|
/** */
|
||||||
|
/**************************************************************************/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||||
|
/* */
|
||||||
|
/* tx_port.h RXv1/IAR */
|
||||||
|
/* 6.1.8 */
|
||||||
|
/* */
|
||||||
|
/* AUTHOR */
|
||||||
|
/* */
|
||||||
|
/* William E. Lamie, Microsoft Corporation */
|
||||||
|
/* */
|
||||||
|
/* DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* This file contains data type definitions that make the ThreadX */
|
||||||
|
/* real-time kernel function identically on a variety of different */
|
||||||
|
/* processor architectures. For example, the size or number of bits */
|
||||||
|
/* in an "int" data type vary between microprocessor architectures and */
|
||||||
|
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||||
|
/* directly use native C data types. Instead, ThreadX creates its */
|
||||||
|
/* own special types that can be mapped to actual data types by this */
|
||||||
|
/* file to guarantee consistency in the interface and functionality. */
|
||||||
|
/* */
|
||||||
|
/* RELEASE HISTORY */
|
||||||
|
/* */
|
||||||
|
/* DATE NAME DESCRIPTION */
|
||||||
|
/* */
|
||||||
|
/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
/* */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TX_PORT_H
|
||||||
|
#define TX_PORT_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <intrinsics.h>
|
||||||
|
|
||||||
|
/* Determine if the optional ThreadX user define file should be used. */
|
||||||
|
|
||||||
|
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||||
|
|
||||||
|
|
||||||
|
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||||
|
alternately be defined on the command line. */
|
||||||
|
|
||||||
|
#include "tx_user.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define ThreadX basic types for this port. */
|
||||||
|
|
||||||
|
#define VOID void
|
||||||
|
typedef char CHAR;
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
typedef long LONG;
|
||||||
|
typedef unsigned long ULONG;
|
||||||
|
typedef short SHORT;
|
||||||
|
typedef unsigned short USHORT;
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the priority levels for ThreadX. Legal values range
|
||||||
|
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||||
|
|
||||||
|
#ifndef TX_MAX_PRIORITIES
|
||||||
|
#define TX_MAX_PRIORITIES 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||||
|
thread creation is less than this value, the thread create call will return an error. */
|
||||||
|
|
||||||
|
#ifndef TX_MINIMUM_STACK
|
||||||
|
#define TX_MINIMUM_STACK 256 /* Minimum stack size for this port */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||||
|
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||||
|
|
||||||
|
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||||
|
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||||
|
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TX_TRACE_TIME_SOURCE
|
||||||
|
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
|
||||||
|
#endif
|
||||||
|
#ifndef TX_TRACE_TIME_MASK
|
||||||
|
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||||
|
how the ThreadX library was built. */
|
||||||
|
|
||||||
|
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the in-line initialization constant so that modules with in-line
|
||||||
|
initialization capabilities can prevent their initialization from being
|
||||||
|
a function call. */
|
||||||
|
|
||||||
|
#define TX_INLINE_INITIALIZATION
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||||
|
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||||
|
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||||
|
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||||
|
logic. */
|
||||||
|
|
||||||
|
#ifdef TX_ENABLE_STACK_CHECKING
|
||||||
|
#undef TX_DISABLE_STACK_FILLING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||||
|
for the multiple macros is so that backward compatibility can be maintained with
|
||||||
|
existing ThreadX kernel awareness modules. */
|
||||||
|
|
||||||
|
#define TX_THREAD_EXTENSION_0
|
||||||
|
#define TX_THREAD_EXTENSION_1
|
||||||
|
#define TX_THREAD_EXTENSION_2
|
||||||
|
#define TX_THREAD_EXTENSION_3
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the port extensions of the remaining ThreadX objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_EXTENSION
|
||||||
|
#define TX_BYTE_POOL_EXTENSION
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||||
|
#define TX_MUTEX_EXTENSION
|
||||||
|
#define TX_QUEUE_EXTENSION
|
||||||
|
#define TX_SEMAPHORE_EXTENSION
|
||||||
|
#define TX_TIMER_EXTENSION
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the user extension field of the thread control block. Nothing
|
||||||
|
additional is needed for this port so it is defined as white space. */
|
||||||
|
|
||||||
|
#ifndef TX_THREAD_USER_EXTENSION
|
||||||
|
#define TX_THREAD_USER_EXTENSION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||||
|
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||||
|
|
||||||
|
|
||||||
|
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||||
|
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||||
|
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||||
|
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||||
|
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||||
|
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||||
|
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||||
|
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||||
|
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||||
|
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||||
|
|
||||||
|
/* Define ThreadX interrupt lockout and restore macros for protection on
|
||||||
|
access of critical kernel information. The restore interrupt macro must
|
||||||
|
restore the interrupt posture of the running thread prior to the value
|
||||||
|
present prior to the disable macro. In most cases, the save area macro
|
||||||
|
is used to define a local function save area for the disable and restore
|
||||||
|
macros. */
|
||||||
|
|
||||||
|
#ifdef TX_DISABLE_INLINE
|
||||||
|
|
||||||
|
UINT _tx_thread_interrupt_disable(VOID);
|
||||||
|
VOID _tx_thread_interrupt_restore(UINT previous_posture);
|
||||||
|
|
||||||
|
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
|
||||||
|
|
||||||
|
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||||
|
|
||||||
|
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TX_INTERRUPT_SAVE_AREA __istate_t interrupt_save;
|
||||||
|
#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();};
|
||||||
|
#define TX_RESTORE {__set_interrupt_state(interrupt_save);};
|
||||||
|
|
||||||
|
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||||
|
|
||||||
|
static void _tx_thread_system_return_inline(void)
|
||||||
|
{
|
||||||
|
TX_INTERRUPT_SAVE_AREA
|
||||||
|
|
||||||
|
TX_DISABLE
|
||||||
|
|
||||||
|
*((volatile UCHAR *)(0x872E0u)) = 1u;
|
||||||
|
|
||||||
|
TX_RESTORE
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||||
|
|
||||||
|
extern volatile ULONG _tx_thread_system_state;
|
||||||
|
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | ((~__get_PSW_register()) & (1u << 17u)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||||
|
|
||||||
|
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||||
|
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||||
|
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||||
|
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||||
|
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||||
|
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||||
|
|
||||||
|
|
||||||
|
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||||
|
|
||||||
|
#ifdef TX_THREAD_INIT
|
||||||
|
CHAR _tx_version_id[] =
|
||||||
|
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX RXv1/IAR Version 6.1.8 *";
|
||||||
|
#else
|
||||||
|
extern CHAR _tx_version_id[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
153
ports/rxv1/iar/readme_threadx.txt
Normal file
153
ports/rxv1/iar/readme_threadx.txt
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
Microsoft's Azure RTOS ThreadX for Renesas RXv1
|
||||||
|
|
||||||
|
Using the IAR Tools
|
||||||
|
|
||||||
|
|
||||||
|
1. Building the ThreadX run-time Library
|
||||||
|
|
||||||
|
Please see the Samples repository on GitHub for the Azure RTOS demonstrations
|
||||||
|
for the RXv1.
|
||||||
|
|
||||||
|
|
||||||
|
2. Demonstration System
|
||||||
|
|
||||||
|
Please see the Samples repository on GitHub for the Azure RTOS demonstrations
|
||||||
|
for the RXv1.
|
||||||
|
|
||||||
|
|
||||||
|
3. System Initialization
|
||||||
|
|
||||||
|
The system entry point using the IAR tools is at the label __iar_program_start.
|
||||||
|
|
||||||
|
The vector area is setup in the file tx_initialize_low_level.s. This file is also
|
||||||
|
responsible for setting up various system data structures, interrupt vectors, and
|
||||||
|
the periodic timer interrupt. This file is also an ideal place add hardware
|
||||||
|
initialization code.
|
||||||
|
|
||||||
|
The ThreadX demonstration for the RXv1 utilizes CMT0 as a periodic timer interrupt
|
||||||
|
source. The CMT0 interrupt is typically setup for 10ms periodic interrupts and the
|
||||||
|
interrupt priority level is set to level 7. You may change any of the timer
|
||||||
|
parameters as needed.
|
||||||
|
|
||||||
|
In addition, _tx_initialize_low_level determines the first available address for use
|
||||||
|
by the application, which is supplied as the sole input parameter to your application
|
||||||
|
definition function, tx_application_define. The first available memory is determined
|
||||||
|
by the location of the FREEMEM section so it should be placed AFTER all other RAM
|
||||||
|
sections in your linker control file.
|
||||||
|
|
||||||
|
|
||||||
|
4. Context Switch, Register Usage and Stack Frames
|
||||||
|
|
||||||
|
The RXv1 port for ThreadX uses the first software interrupt, SWINT, i.e., interrupt #17,
|
||||||
|
to perform context switch. This ISR is thus reserved when using ThreadX and the SWINT
|
||||||
|
should not be manipulated in any way by the application. The port will setup the
|
||||||
|
interrupt within _tx_initialize_low_level and the compiler will automatically install
|
||||||
|
the necessary interrupt vector. As such no additional initialization is necessary by the
|
||||||
|
application.
|
||||||
|
|
||||||
|
The following defines the saved context stack frame used by the ThreadX port. The
|
||||||
|
state of the CPU registers at the time of a context switch is saved on the running
|
||||||
|
thread's stack The top of the suspended thread's stack is pointed to by
|
||||||
|
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
|
||||||
|
|
||||||
|
Offset Interrupted Stack Frame
|
||||||
|
|
||||||
|
0x00 1
|
||||||
|
0x04 ACC0
|
||||||
|
0x0C R6
|
||||||
|
0x10 R7
|
||||||
|
0x14 R8
|
||||||
|
0x18 R9
|
||||||
|
0x1C R10
|
||||||
|
0x20 R11
|
||||||
|
0x24 R12
|
||||||
|
0x28 R13
|
||||||
|
0x30 R14
|
||||||
|
0x34 R15
|
||||||
|
0x38 R3
|
||||||
|
0x3C R4
|
||||||
|
0x40 R5
|
||||||
|
0x44 R1
|
||||||
|
0x48 R2
|
||||||
|
0x4C PC - return address
|
||||||
|
0x50 PSW
|
||||||
|
|
||||||
|
Note: By default IAR does not save the state of the accumulator register ACC0
|
||||||
|
when entering an ISR. This means that if the ISR uses any of the DSP instructions the
|
||||||
|
content of the accumulator could be corrupted. Saving and restoring of the accumulator
|
||||||
|
can be enabled by adding the --save_acc command line option.
|
||||||
|
|
||||||
|
|
||||||
|
5. Improving Performance
|
||||||
|
|
||||||
|
The distribution version of ThreadX is built without any compiler optimizations. This
|
||||||
|
makes it easy to debug because you can trace or set breakpoints inside of ThreadX itself.
|
||||||
|
Of course, this costs some performance. To make ThreadX run faster, you can change the
|
||||||
|
ThreadX Library project to disable debug information and enable the desired optimizations.
|
||||||
|
|
||||||
|
In addition, you can eliminate the ThreadX basic API error checking by compiling your
|
||||||
|
application code with the symbol TX_DISABLE_ERROR_CHECKING defined before tx_api.h
|
||||||
|
is included.
|
||||||
|
|
||||||
|
|
||||||
|
6. Timer Processing
|
||||||
|
|
||||||
|
Timer procession is performed by calling __tx_timer_interrupt(). This should usually be done
|
||||||
|
from within the callback of a periodic timer with a period of 100Hz. In the sample projects
|
||||||
|
a Renesas Fit CMT periodic timer module (rx_cmt) is used as the timer source.
|
||||||
|
|
||||||
|
|
||||||
|
7. Interrupt Handling
|
||||||
|
|
||||||
|
Interrupt handling is unaffected by the ThreadX port as such user interrupts can be
|
||||||
|
written according to the toolchain's documentation. It is recommended not to use interrupt
|
||||||
|
priority 15 as this is the priority of the context switch interrupt. However using interrupt
|
||||||
|
priority 15 won't cause any negative side effects but doing so may slightly reduce
|
||||||
|
performance. Please refer to the toolchain documentation for additional details on how to
|
||||||
|
define interrupt service routines.
|
||||||
|
|
||||||
|
|
||||||
|
8. Execution Profiling
|
||||||
|
|
||||||
|
The RX port adds support for the Execution Profiling Kit (EPK). The EPK consists
|
||||||
|
of the files tx_execution_profile.c and tx_execution_profile.h. See the documentation
|
||||||
|
of the EPK for generic usage details.
|
||||||
|
|
||||||
|
To add the EPK to your RXv1 release make the following modifications:
|
||||||
|
|
||||||
|
* Enable the following define for both the Threadx library and the application
|
||||||
|
TX_EXECUTION_PROFILE_ENABLE
|
||||||
|
|
||||||
|
* Setup CMT1 as a free running 16 bit timer.
|
||||||
|
|
||||||
|
* In tx_execution_profile.h, change following around line 52:
|
||||||
|
|
||||||
|
#ifdef TX_EXECUTION_64BIT_TIME
|
||||||
|
typedef unsigned long long EXECUTION_TIME;
|
||||||
|
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFFFFFFFFFF
|
||||||
|
#else
|
||||||
|
typedef unsigned long EXECUTION_TIME;
|
||||||
|
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define basic constants for the execution profile kit. */
|
||||||
|
|
||||||
|
#define TX_EXECUTION_TIME_SOURCE (EXECUTION_TIME) *((USHORT *) 0x8800A)
|
||||||
|
|
||||||
|
Rebuild the Threadx library and the application.
|
||||||
|
Refer to the EPK documentation how to interpret the results.
|
||||||
|
|
||||||
|
|
||||||
|
9. Revision History
|
||||||
|
|
||||||
|
For generic code revision information, please refer to the readme_threadx_generic.txt
|
||||||
|
file, which is included in your distribution. The following details the revision
|
||||||
|
information associated with this specific port of ThreadX:
|
||||||
|
|
||||||
|
08-02-2021 Initial ThreadX release for the RXv1using IAR tools, version 6.1.8
|
||||||
|
|
||||||
|
|
||||||
|
Copyright(c) 1996-2021 Microsoft Corporation
|
||||||
|
|
||||||
|
|
||||||
|
https://azure.com/rtos
|
||||||
99
ports/rxv1/iar/src/tx_initialize_low_level.s
Normal file
99
ports/rxv1/iar/src/tx_initialize_low_level.s
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Initialize */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
|
||||||
|
extern __tx_initialize_unused_memory
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_low_level RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is responsible for any low-level processor */
|
||||||
|
;/* initialization, including setting up interrupt vectors, setting */
|
||||||
|
;/* up a periodic timer interrupt source, saving the system stack */
|
||||||
|
;/* pointer for use in ISR processing later, and finding the first */
|
||||||
|
;/* available RAM memory address for tx_application_define. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
public __tx_initialize_low_level
|
||||||
|
|
||||||
|
__tx_initialize_low_level:
|
||||||
|
|
||||||
|
; /* Save the first available memory address. */
|
||||||
|
; _tx_initialize_unused_memory = (VOID_PTR) &free_mem_start;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_free_memory_start, R1 ; Pickup unused memory address
|
||||||
|
MOV.L #__tx_initialize_unused_memory,R2
|
||||||
|
MOV.L R1,[R2] ; Save first free memory address
|
||||||
|
|
||||||
|
; /* Set priority of SWINT to 1. */
|
||||||
|
MOV.L #0x87303, r1
|
||||||
|
MOV.L #1, r2
|
||||||
|
MOV.B r2, [r1]
|
||||||
|
|
||||||
|
; /* Enable SWINT. */
|
||||||
|
MOV.L #0x87203, r1
|
||||||
|
MOV.B [r1], r2
|
||||||
|
OR #(1 << 3), r2
|
||||||
|
MOV.B r2, [r1]
|
||||||
|
|
||||||
|
RTS
|
||||||
|
|
||||||
|
section FREEMEM:DATA
|
||||||
|
public __tx_free_memory_start
|
||||||
|
__tx_free_memory_start
|
||||||
|
DS32 4
|
||||||
|
|
||||||
|
END
|
||||||
187
ports/rxv1/iar/src/tx_thread_context_restore.s
Normal file
187
ports/rxv1/iar/src/tx_thread_context_restore.s
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
extern __tx_thread_system_state
|
||||||
|
extern __tx_thread_current_ptr
|
||||||
|
extern __tx_thread_preempt_disable
|
||||||
|
extern __tx_thread_execute_ptr
|
||||||
|
extern __tx_timer_time_slice
|
||||||
|
extern __tx_thread_schedule
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_context_restore RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function restores the interrupt context if it is processing a */
|
||||||
|
;/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||||
|
;/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||||
|
;/* if no thread was running, the function returns to the scheduler. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule Thread scheduling routine */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ISRs Interrupt Service Routines */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
public __tx_thread_context_restore
|
||||||
|
|
||||||
|
__tx_thread_context_restore:
|
||||||
|
;
|
||||||
|
; /* Lockout interrupts. */
|
||||||
|
|
||||||
|
CLRPSW I ; disable interrupts
|
||||||
|
|
||||||
|
; /* Determine if interrupts are nested. */
|
||||||
|
; if (--_tx_thread_system_state)
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_system_state, R1
|
||||||
|
MOV.L [R1], R2
|
||||||
|
SUB #1, R2
|
||||||
|
MOV.L R2,[R1]
|
||||||
|
BEQ __tx_thread_not_nested_restore
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Interrupts are nested. */
|
||||||
|
;
|
||||||
|
; /* Recover the saved registers from the interrupt stack
|
||||||
|
; and return to the point of interrupt. */
|
||||||
|
;
|
||||||
|
__tx_thread_nested_restore:
|
||||||
|
POPM R14-R15 ; restore R14-R15
|
||||||
|
POPM R3-R5 ; restore R3-R5
|
||||||
|
POPM R1-R2 ; restore R1-R2
|
||||||
|
RTE ; return to point of interrupt, restore PSW including IPL
|
||||||
|
; }
|
||||||
|
|
||||||
|
__tx_thread_not_nested_restore:
|
||||||
|
;
|
||||||
|
; /* Determine if a thread was interrupted and no preemption is required. */
|
||||||
|
; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||||
|
; || (_tx_thread_preempt_disable))
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_current_ptr, R1 ; Pickup current thread ptr address
|
||||||
|
MOV.L [R1], R2
|
||||||
|
CMP #0, R2
|
||||||
|
BEQ __tx_thread_idle_system_restore
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_preempt_disable, R3 ; pick up preempt disable flag
|
||||||
|
MOV.L [R3], R3
|
||||||
|
CMP #0, R3
|
||||||
|
BNE __tx_thread_no_preempt_restore ; if pre-empt disable flag set, we simply return to the original point of interrupt regardless
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_execute_ptr, R3 ; (_tx_thread_current_ptr != _tx_thread_execute_ptr)
|
||||||
|
CMP [R3], R2
|
||||||
|
BNE __tx_thread_preempt_restore ; jump to pre-empt restoring
|
||||||
|
;
|
||||||
|
__tx_thread_no_preempt_restore:
|
||||||
|
SETPSW U ; user stack
|
||||||
|
POPM R14-R15 ; restore R14-R15
|
||||||
|
POPM R3-R5 ; restore R3-R5
|
||||||
|
POPM R1-R2 ; restore R1-R2
|
||||||
|
RTE ; return to point of interrupt, restore PSW including IPL
|
||||||
|
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
|
||||||
|
__tx_thread_preempt_restore:
|
||||||
|
|
||||||
|
; /* Save the remaining time-slice and disable it. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_time_slice, R3 ; Pickup time-slice address
|
||||||
|
MOV.L [R3],R4 ; Pickup actual time-slice
|
||||||
|
CMP #0, R4
|
||||||
|
BEQ __tx_thread_dont_save_ts ; no time slice to save
|
||||||
|
;
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||||
|
; _tx_timer_time_slice = 0;
|
||||||
|
;
|
||||||
|
MOV.L R4,24[R2] ; Save thread's time slice
|
||||||
|
MOV.L #0,R4 ; Clear value
|
||||||
|
MOV.L R4,[R3] ; Disable global time slice flag
|
||||||
|
; }
|
||||||
|
__tx_thread_dont_save_ts:
|
||||||
|
;
|
||||||
|
; /* Now store the remaining registers! */
|
||||||
|
|
||||||
|
SETPSW U ; user stack
|
||||||
|
PUSHM R6-R13
|
||||||
|
|
||||||
|
MVFACHI R5
|
||||||
|
MVFACMI R6
|
||||||
|
PUSHM R5-R6
|
||||||
|
|
||||||
|
MOV.L #1, R3 ; indicate interrupt stack frame
|
||||||
|
PUSH.L R3
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Clear the current task pointer. */
|
||||||
|
; _tx_thread_current_ptr = TX_NULL;
|
||||||
|
; R1 -> _tx_thread_current_ptr
|
||||||
|
; R2 -> *_tx_thread_current_ptr
|
||||||
|
|
||||||
|
MOV.L R0,8[R2] ; Save thread's stack pointer in thread control block
|
||||||
|
MOV.L #0,R2 ; Build NULL value
|
||||||
|
MOV.L R2,[R1] ; Set current thread to NULL
|
||||||
|
|
||||||
|
; /* Return to the scheduler. */
|
||||||
|
; _tx_thread_schedule();
|
||||||
|
|
||||||
|
__tx_thread_idle_system_restore:
|
||||||
|
MVTC #0, PSW ; reset interrupt priority level to 0
|
||||||
|
BRA __tx_thread_schedule ; jump to scheduler
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
;
|
||||||
|
END
|
||||||
157
ports/rxv1/iar/src/tx_thread_context_save.s
Normal file
157
ports/rxv1/iar/src/tx_thread_context_save.s
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
extern __tx_thread_system_state
|
||||||
|
extern __tx_thread_current_ptr
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_context_save RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function saves the context of an executing thread in the */
|
||||||
|
;/* beginning of interrupt processing. The function also ensures that */
|
||||||
|
;/* the system stack is used upon return to the calling ISR. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ISRs */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_context_save(VOID)
|
||||||
|
;{
|
||||||
|
public __tx_thread_context_save
|
||||||
|
|
||||||
|
__tx_thread_context_save:
|
||||||
|
;
|
||||||
|
; /* Upon entry to this routine, it is assumed that interrupts are locked
|
||||||
|
; out and the (interrupt) stack frame looks like the following:
|
||||||
|
;
|
||||||
|
; (lower address) SP -> [return address of this call]
|
||||||
|
; SP+4 -> Saved R1
|
||||||
|
; SP+8 -> Saved R2
|
||||||
|
; SP+12-> Interrupted PC
|
||||||
|
; SP+16-> Interrupted PSW
|
||||||
|
;
|
||||||
|
; /* Check for a nested interrupt condition. */
|
||||||
|
; if (_tx_thread_system_state++)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_system_state, R1 ; pick up address of system state
|
||||||
|
MOV.L [R1], R2 ; pick up system state
|
||||||
|
CMP #0, R2 ; 0 -> no nesting
|
||||||
|
BEQ __tx_thread_not_nested_save
|
||||||
|
;
|
||||||
|
; /* Nested interrupt condition. */
|
||||||
|
;
|
||||||
|
ADD #1, r2 ; _tx_thread_system_state++
|
||||||
|
MOV.L r2, [r1]
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Save the rest of the scratch registers on the interrupt stack and return to the
|
||||||
|
; calling ISR. */
|
||||||
|
POP R1 ; recuperate return address from stack
|
||||||
|
PUSHM R3-R5
|
||||||
|
PUSHM R14-R15
|
||||||
|
JMP R1 ; return address was preserved in R1
|
||||||
|
|
||||||
|
;
|
||||||
|
__tx_thread_not_nested_save:
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; /* Otherwise, not nested, check to see if a thread was running. */
|
||||||
|
; else if (_tx_thread_current_ptr)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
ADD #1, R2 ; _tx_thread_system_state++
|
||||||
|
MOV.L R2, [R1]
|
||||||
|
|
||||||
|
MOV.L #__tx_thread_current_ptr, R2 ; Pickup current thread pointer
|
||||||
|
MOV.L [R2], R2
|
||||||
|
CMP #0,R2 ; Is it NULL?
|
||||||
|
BEQ __tx_thread_idle_system_save ; Yes, idle system is running - idle restore
|
||||||
|
;
|
||||||
|
; /* Move stack frame over to the current threads stack. */
|
||||||
|
; /* complete stack frame with registers not saved yet (R3-R5, R14-R15, FPSW) */
|
||||||
|
;
|
||||||
|
MVFC USP, R1 ; pick up user stack pointer
|
||||||
|
MOV.L 16[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save PSW on thread stack
|
||||||
|
MOV.L 12[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save PC on thread stack
|
||||||
|
MOV.L 8[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save R2 on thread stack
|
||||||
|
MOV.L 4[R0], R2
|
||||||
|
MOV.L R2, [-R1] ; save R1 on thread stack
|
||||||
|
MOV.L R5, [-R1] ; save R5 on thread stack
|
||||||
|
MOV.L R4, [-R1] ; save R4 on thread stack
|
||||||
|
MOV.L R3, [-R1] ; save R3 on thread stack
|
||||||
|
MOV.L R15, [-R1] ; save R15 on thread stack
|
||||||
|
MOV.L R14, [-R1] ; save R14 on thread stack
|
||||||
|
|
||||||
|
POP R2 ; pick up return address from interrupt stack
|
||||||
|
ADD #16, R0, R0 ; correct interrupt stack pointer back to the bottom
|
||||||
|
MVTC R1, USP ; set user/thread stack pointer
|
||||||
|
JMP R2 ; return to ISR
|
||||||
|
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
__tx_thread_idle_system_save:
|
||||||
|
;
|
||||||
|
; /* Interrupt occurred in the scheduling loop. */
|
||||||
|
;
|
||||||
|
POP R1 ; pick up return address
|
||||||
|
ADD #16, R0, R0 ; correct interrupt stack pointer back to the bottom (PC), don't care about saved registers
|
||||||
|
JMP R1 ; return to caller
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
;}
|
||||||
|
END
|
||||||
85
ports/rxv1/iar/src/tx_thread_interrupt_control.s
Normal file
85
ports/rxv1/iar/src/tx_thread_interrupt_control.s
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_interrupt_control RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is responsible for changing the interrupt lockout */
|
||||||
|
;/* posture of the system. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* new_posture New interrupt lockout posture */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* old_posture Old interrupt lockout posture */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* Application Code */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||||
|
;{
|
||||||
|
public __tx_thread_interrupt_control
|
||||||
|
__tx_thread_interrupt_control:
|
||||||
|
;
|
||||||
|
; /* Pickup current interrupt lockout posture. */
|
||||||
|
;
|
||||||
|
|
||||||
|
MVFC PSW, R2 ; Save PSW to R2
|
||||||
|
MOV.L R2, R3 ; Make a copy of PSW in r3
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Apply the new interrupt posture. */
|
||||||
|
;
|
||||||
|
|
||||||
|
BTST #16, R1 ; test I bit of PSW of "new posture"
|
||||||
|
BMNE #16, R2 ; conditionally set I bit of intermediate posture
|
||||||
|
|
||||||
|
MVTC R2, PSW ; save intermediate posture to PSW
|
||||||
|
|
||||||
|
MOV.L R3,R1 ; Get original SR
|
||||||
|
RTS ; Return to caller
|
||||||
|
;}
|
||||||
|
END
|
||||||
162
ports/rxv1/iar/src/tx_thread_schedule.s
Normal file
162
ports/rxv1/iar/src/tx_thread_schedule.s
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
extern __tx_thread_execute_ptr
|
||||||
|
extern __tx_thread_current_ptr
|
||||||
|
extern __tx_timer_time_slice
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function waits for a thread control block pointer to appear in */
|
||||||
|
;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||||
|
;/* in the variable, the corresponding thread is resumed. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||||
|
;/* _tx_thread_system_return Return to system from thread */
|
||||||
|
;/* _tx_thread_context_restore Restore thread's context */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;VOID _tx_thread_schedule(VOID)
|
||||||
|
;{
|
||||||
|
public __tx_thread_schedule
|
||||||
|
|
||||||
|
__tx_thread_schedule:
|
||||||
|
;
|
||||||
|
; /* Enable interrupts. */
|
||||||
|
;
|
||||||
|
SETPSW I
|
||||||
|
;
|
||||||
|
; /* Wait for a thread to execute. */
|
||||||
|
; do
|
||||||
|
; {
|
||||||
|
MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr
|
||||||
|
__tx_thread_schedule_loop:
|
||||||
|
MOV.L [R1],R2 ; Pickup next thread to execute
|
||||||
|
CMP #0,R2 ; Is it NULL?
|
||||||
|
BEQ __tx_thread_schedule_loop ; Yes, idle system, keep checking
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
; while(_tx_thread_execute_ptr == TX_NULL);
|
||||||
|
;
|
||||||
|
; /* Yes! We have a thread to execute. Lockout interrupts and
|
||||||
|
; transfer control to it. */
|
||||||
|
;
|
||||||
|
CLRPSW I ; disable interrupts
|
||||||
|
;
|
||||||
|
; /* Setup the current thread pointer. */
|
||||||
|
; _tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_thread_current_ptr, R3
|
||||||
|
MOV.L R2,[R3] ; Setup current thread pointer
|
||||||
|
;
|
||||||
|
; /* Increment the run count for this thread. */
|
||||||
|
; _tx_thread_current_ptr -> tx_thread_run_count++;
|
||||||
|
;
|
||||||
|
MOV.L 4[R2],R3 ; Pickup run count
|
||||||
|
ADD #1,R3 ; Increment run counter
|
||||||
|
MOV.L R3,4[R2] ; Store it back in control block
|
||||||
|
;
|
||||||
|
; /* Setup time-slice, if present. */
|
||||||
|
; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||||
|
;
|
||||||
|
MOV.L 24[R2],R3 ; Pickup thread time-slice
|
||||||
|
MOV.L #__tx_timer_time_slice,R4 ; Pickup pointer to time-slice
|
||||||
|
MOV.L R3, [R4] ; Setup time-slice
|
||||||
|
;
|
||||||
|
; /* Switch to the thread's stack. */
|
||||||
|
; SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr;
|
||||||
|
SETPSW U ; user stack mode
|
||||||
|
MOV.L 8[R2],R0 ; Pickup stack pointer
|
||||||
|
;
|
||||||
|
; /* Determine if an interrupt frame or a synchronous task suspension frame
|
||||||
|
; is present. */
|
||||||
|
;
|
||||||
|
POP R1 ; Pickup stack type
|
||||||
|
CMP #1, R1 ; Is it an interrupt stack?
|
||||||
|
BNE __tx_thread_synch_return ; No, a synchronous return frame is present.
|
||||||
|
|
||||||
|
POPM R1-R2 ; Restore accumulator.
|
||||||
|
MVTACLO R2
|
||||||
|
MVTACHI R1
|
||||||
|
|
||||||
|
POPM R6-R13 ; Recover interrupt stack frame
|
||||||
|
POPM R14-R15
|
||||||
|
POPM R3-R5
|
||||||
|
POPM R1-R2
|
||||||
|
RTE ; return to point of interrupt, this restores PC and PSW
|
||||||
|
|
||||||
|
__tx_thread_synch_return:
|
||||||
|
POPC PSW
|
||||||
|
POPM R6-R13 ; Recover solicited stack frame
|
||||||
|
RTS
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
|
||||||
|
extern __tx_thread_context_save
|
||||||
|
extern __tx_thread_context_restore
|
||||||
|
|
||||||
|
; Software triggered interrupt used to perform context switches.
|
||||||
|
; The priority of this interrupt is set to the lowest priority within
|
||||||
|
; tx_initialize_low_level() and triggered by ThreadX when calling
|
||||||
|
; _tx_thread_system_return().
|
||||||
|
public ___interrupt_27
|
||||||
|
___interrupt_27:
|
||||||
|
|
||||||
|
PUSHM R1-R2
|
||||||
|
|
||||||
|
BSR __tx_thread_context_save
|
||||||
|
|
||||||
|
BRA __tx_thread_context_restore
|
||||||
|
|
||||||
|
END
|
||||||
137
ports/rxv1/iar/src/tx_thread_stack_build.s
Normal file
137
ports/rxv1/iar/src/tx_thread_stack_build.s
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_stack_build RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function builds a stack frame on the supplied thread's stack. */
|
||||||
|
;/* The stack frame results in a fake interrupt return to the supplied */
|
||||||
|
;/* function pointer. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* thread_ptr Pointer to thread control blk */
|
||||||
|
;/* function_ptr Pointer to return function */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_create Create thread service */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
public __tx_thread_stack_build
|
||||||
|
|
||||||
|
__tx_thread_stack_build:
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; /* Build an interrupt frame. The form of the fake interrupt stack
|
||||||
|
; on the Renesas RX should look like the following after it is built:
|
||||||
|
;
|
||||||
|
; Stack Top: 1 Interrupt stack frame type
|
||||||
|
; ACC0
|
||||||
|
; R6
|
||||||
|
; R7
|
||||||
|
; R8
|
||||||
|
; R9
|
||||||
|
; R10
|
||||||
|
; R11
|
||||||
|
; R12
|
||||||
|
; R13
|
||||||
|
; R14
|
||||||
|
; R15
|
||||||
|
; R3
|
||||||
|
; R4
|
||||||
|
; R5
|
||||||
|
; R1
|
||||||
|
; R2
|
||||||
|
; PC
|
||||||
|
; PSW
|
||||||
|
|
||||||
|
;
|
||||||
|
; Stack Bottom: (higher memory address) */
|
||||||
|
;
|
||||||
|
MOV.L 16[R1],R3 ; Pickup end of stack area
|
||||||
|
BCLR #0, R3 ; mask for 4-byte alignment
|
||||||
|
BCLR #1, R3
|
||||||
|
;
|
||||||
|
; /* Build the stack frame. */
|
||||||
|
;
|
||||||
|
MOV.L #30000h, R4
|
||||||
|
MOV.L R4, [-R3] ; initial PSW (SVC mode, U flag set)
|
||||||
|
MOV.L R2, [-R3] ; initial PC
|
||||||
|
MOV.L #0, R4
|
||||||
|
MOV.L R4,[-R3] ; initial R2 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R1 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R5 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R4 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R3 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R15 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R14 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R13 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R12 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R11 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R10 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R9 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R8 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R7 ...
|
||||||
|
MOV.L R4,[-R3] ; initial R6 ...
|
||||||
|
|
||||||
|
MOV.L R4,[-R3] ; Accumulator 0
|
||||||
|
MOV.L R4,[-R3]
|
||||||
|
|
||||||
|
MOV.L #1, R4
|
||||||
|
MOV.L R4,[-R3] ; indicate interrupt stack frame
|
||||||
|
; /* Setup stack pointer. */
|
||||||
|
; thread_ptr -> tx_thread_stack_ptr = R1;
|
||||||
|
MOV.L R3, 8[R1]
|
||||||
|
; store initial SP in thread control block
|
||||||
|
RTS
|
||||||
|
|
||||||
|
;}
|
||||||
|
|
||||||
|
END
|
||||||
74
ports/rxv1/iar/src/tx_thread_system_return.s
Normal file
74
ports/rxv1/iar/src/tx_thread_system_return.s
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_system_return RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* AUTHOR */
|
||||||
|
;/* */
|
||||||
|
;/* William E. Lamie, Microsoft Corporation */
|
||||||
|
;/* */
|
||||||
|
;/* DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* This function is target processor specific. It is used to transfer */
|
||||||
|
;/* control from a thread back to the system. Only a minimal context */
|
||||||
|
;/* is saved since the compiler assumes temp registers are going to get */
|
||||||
|
;/* slicked by a function call anyway. */
|
||||||
|
;/* */
|
||||||
|
;/* INPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* OUTPUT */
|
||||||
|
;/* */
|
||||||
|
;/* None */
|
||||||
|
;/* */
|
||||||
|
;/* CALLS */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_thread_schedule Thread scheduling loop */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* ThreadX components */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
public __tx_thread_system_return
|
||||||
|
|
||||||
|
__tx_thread_system_return:
|
||||||
|
|
||||||
|
BRA __tx_thread_system_return
|
||||||
|
|
||||||
|
RTS
|
||||||
|
|
||||||
|
END
|
||||||
235
ports/rxv1/iar/src/tx_timer_interrupt.s
Normal file
235
ports/rxv1/iar/src/tx_timer_interrupt.s
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||||
|
;/* */
|
||||||
|
;/* This software is licensed under the Microsoft Software License */
|
||||||
|
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||||
|
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||||
|
;/* and in the root directory of this software. */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/** */
|
||||||
|
;/** ThreadX Component */
|
||||||
|
;/** */
|
||||||
|
;/** Thread */
|
||||||
|
;/** */
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
extern __tx_timer_expiration_process
|
||||||
|
extern __tx_timer_system_clock
|
||||||
|
extern __tx_timer_expired_time_slice
|
||||||
|
extern __tx_timer_current_ptr
|
||||||
|
extern __tx_timer_expired
|
||||||
|
extern __tx_timer_list_start
|
||||||
|
extern __tx_timer_time_slice
|
||||||
|
extern __tx_timer_list_end
|
||||||
|
extern __tx_thread_time_slice
|
||||||
|
|
||||||
|
section .text:CODE:ROOT
|
||||||
|
|
||||||
|
;/**************************************************************************/
|
||||||
|
;/* */
|
||||||
|
;/* FUNCTION RELEASE */
|
||||||
|
;/* */
|
||||||
|
;/* _tx_timer_interrupt RXv1/IAR */
|
||||||
|
;/* 6.1.8 */
|
||||||
|
;/* 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 Save interrupted context */
|
||||||
|
;/* _tx_timer_expiration_process Timer expiration processing */
|
||||||
|
;/* _tx_thread_time_slice Time slice interrupted thread */
|
||||||
|
;/* _tx_thread_context_restore Restore interrupted context */
|
||||||
|
;/* */
|
||||||
|
;/* CALLED BY */
|
||||||
|
;/* */
|
||||||
|
;/* interrupt vector */
|
||||||
|
;/* */
|
||||||
|
;/* RELEASE HISTORY */
|
||||||
|
;/* */
|
||||||
|
;/* DATE NAME DESCRIPTION */
|
||||||
|
;/* */
|
||||||
|
;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */
|
||||||
|
;/* */
|
||||||
|
;/**************************************************************************/
|
||||||
|
|
||||||
|
public __tx_timer_interrupt
|
||||||
|
__tx_timer_interrupt:
|
||||||
|
;
|
||||||
|
; /* Upon entry to this routine, it is assumed that all interrupts are locked
|
||||||
|
; out and the stack looks like the following:
|
||||||
|
; SP+4 -> Interrupted PC
|
||||||
|
; SP+8-> Interrupted SR
|
||||||
|
; */
|
||||||
|
;
|
||||||
|
; /* Increment the system clock. */
|
||||||
|
; _tx_timer_system_clock++;
|
||||||
|
;
|
||||||
|
PUSHM R14-R15
|
||||||
|
PUSHM R1-R5
|
||||||
|
|
||||||
|
MOV.L #__tx_timer_system_clock, R1 ; Pickup address of system clock
|
||||||
|
MOV.L [R1], R2 ; Pickup system clock
|
||||||
|
ADD #1, R2 ; Increment system clock
|
||||||
|
MOV.L R2,[R1] ; Store new system clock
|
||||||
|
;
|
||||||
|
; /* Test for time-slice expiration. */
|
||||||
|
; if (_tx_timer_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_time_slice, R1 ; Pickup address of time slice
|
||||||
|
MOV.L [R1], R2 ; Pickup the current time slice
|
||||||
|
CMP #0, R2 ; Is a time slice active?
|
||||||
|
BEQ __tx_timer_no_time_slice ; No, skip timer slice processing
|
||||||
|
;
|
||||||
|
; /* Decrement the time_slice. */
|
||||||
|
; _tx_timer_time_slice--;
|
||||||
|
;
|
||||||
|
SUB #1, R2 ; Decrement the time-slice
|
||||||
|
MOV.L R2, [R1] ; Store time-slice
|
||||||
|
;
|
||||||
|
; /* Check for expiration. */
|
||||||
|
; if (__tx_timer_time_slice == 0)
|
||||||
|
;
|
||||||
|
CMP #0, R2 ; Has it expired?
|
||||||
|
BNE __tx_timer_no_time_slice ; No, time-slice has not expired
|
||||||
|
;
|
||||||
|
; /* Set the time-slice expired flag. */
|
||||||
|
; _tx_timer_expired_time_slice = TX_TRUE;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup address of expired time-slice
|
||||||
|
MOV.L #1, R2 ; Build expired value
|
||||||
|
MOV.L R2, [R1] ; Set expired time slice variable
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_no_time_slice:
|
||||||
|
;
|
||||||
|
; /* Test for timer expiration. */
|
||||||
|
; if (*_tx_timer_current_ptr)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_current_ptr, R1 ; Pickup address of current timer ptr
|
||||||
|
MOV.L [R1], R2 ; Pickup current pointer
|
||||||
|
MOV.L [R2+], R1 ; pickup timer list entry, _tx_timer_current_ptr++
|
||||||
|
CMP #0, R1 ; Is timer pointer NULL?
|
||||||
|
BEQ __tx_timer_no_timer ; Yes, no timer has expired
|
||||||
|
|
||||||
|
;
|
||||||
|
; /* Set expiration flag. */
|
||||||
|
; _tx_timer_expired = TX_TRUE;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired,R2 ; Build address of expired flag
|
||||||
|
MOV.L #1, R1 ; Build expired value
|
||||||
|
MOV.L R1, [R2]
|
||||||
|
BRA __tx_timer_done ; Finished with timer processing
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
; else
|
||||||
|
; {
|
||||||
|
__tx_timer_no_timer:
|
||||||
|
;
|
||||||
|
; /* No timer expired, increment the timer pointer. */
|
||||||
|
; _tx_timer_current_ptr++;
|
||||||
|
;
|
||||||
|
; /* R2 already contains __tx_timer_current_ptr++ */
|
||||||
|
;
|
||||||
|
; /* Check for wrap-around. */
|
||||||
|
; if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_list_end, R1 ; Pickup the timer list end ptr
|
||||||
|
MOV.L [R1], R1 ; Pickup actual timer list end
|
||||||
|
CMP R1, R2 ; Are we at list end?
|
||||||
|
BNE __tx_timer_skip_wrap ; No, don't move pointer to the
|
||||||
|
; top of the list
|
||||||
|
;
|
||||||
|
; /* Wrap to beginning of list. */
|
||||||
|
; _tx_timer_current_ptr = _tx_timer_list_start;
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_list_start, R2 ; Pickup the timer list start ptr
|
||||||
|
MOV.L [R2], R2 ; Pickup the start of the list
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_skip_wrap:
|
||||||
|
MOV.L #__tx_timer_current_ptr,R1
|
||||||
|
MOV.L R2, [R1] ; store in updated pointer in _tx_timer_current_ptr
|
||||||
|
|
||||||
|
__tx_timer_done:
|
||||||
|
;
|
||||||
|
; /* See if anything has expired. */
|
||||||
|
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup expired time slice addr
|
||||||
|
MOV.L [R1], R1 ; Pickup expired time slice
|
||||||
|
MOV.L #__tx_timer_expired, R2 ; Pickup expired timer flag address
|
||||||
|
MOV.L [R2], R2 ; Pickup actual flag
|
||||||
|
OR R1, R2 ; Or flags together
|
||||||
|
BEQ __tx_timer_nothing_expired ; If Z set, nothing has expired
|
||||||
|
|
||||||
|
__tx_something_expired:
|
||||||
|
; /* Did a timer expire? */
|
||||||
|
; if (_tx_timer_expired)
|
||||||
|
; {
|
||||||
|
MOV.L #__tx_timer_expired,R1 ; Pickup expired flag address
|
||||||
|
MOV.L [R1], R1 ; Pickup expired flag
|
||||||
|
CMP #0,R1 ; Is the expired timer flag set?
|
||||||
|
BEQ __tx_timer_dont_activate ; No, skip timer activation
|
||||||
|
;
|
||||||
|
; /* Process timer expiration. */
|
||||||
|
; _tx_timer_expiration_process();
|
||||||
|
;
|
||||||
|
BSR __tx_timer_expiration_process ; Call the timer expiration handling routine
|
||||||
|
;
|
||||||
|
; }
|
||||||
|
__tx_timer_dont_activate:
|
||||||
|
;
|
||||||
|
; /* Did time slice expire? */
|
||||||
|
; if (_tx_timer_expired_time_slice)
|
||||||
|
; {
|
||||||
|
;
|
||||||
|
MOV.L #__tx_timer_expired_time_slice, R1 ; Pickup time-slice expired flag addr
|
||||||
|
MOV.L [R1], R1 ; Pickup actual flag
|
||||||
|
CMP #0,R1 ; Has time-slice expired?
|
||||||
|
BEQ __tx_timer_not_ts_expiration ; No, skip time-slice expiration
|
||||||
|
;
|
||||||
|
; /* Time slice interrupted thread. */
|
||||||
|
; _tx_thread_time_slice();
|
||||||
|
|
||||||
|
BSR __tx_thread_time_slice ; Call time-slice processing
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
__tx_timer_not_ts_expiration:
|
||||||
|
|
||||||
|
__tx_timer_nothing_expired:
|
||||||
|
|
||||||
|
POPM R1-R5
|
||||||
|
POPM R14-R15
|
||||||
|
;
|
||||||
|
RTS ; return to point of interrupt
|
||||||
|
;
|
||||||
|
;}
|
||||||
|
END
|
||||||
Reference in New Issue
Block a user