From 06064828eff72aa906b6f0b02d86fd1db39c5987 Mon Sep 17 00:00:00 2001 From: Tiejun Zhou Date: Fri, 24 Sep 2021 10:52:11 +0800 Subject: [PATCH] Add RXv1 port. --- ports/rxv1/ccrx/inc/tx_port.h | 281 ++++++++++++++++++ ports/rxv1/ccrx/readme_threadx.txt | 164 ++++++++++ .../rxv1/ccrx/src/tx_initialize_low_level.src | 101 +++++++ .../ccrx/src/tx_thread_context_restore.src | 200 +++++++++++++ .../rxv1/ccrx/src/tx_thread_context_save.src | 168 +++++++++++ .../ccrx/src/tx_thread_interrupt_control.src | 96 ++++++ ports/rxv1/ccrx/src/tx_thread_schedule.src | 174 +++++++++++ ports/rxv1/ccrx/src/tx_thread_stack_build.src | 145 +++++++++ .../rxv1/ccrx/src/tx_thread_system_return.src | 127 ++++++++ ports/rxv1/ccrx/src/tx_timer_interrupt.src | 251 ++++++++++++++++ ports/rxv1/gnu/inc/tx_port.h | 264 ++++++++++++++++ ports/rxv1/gnu/readme_threadx.txt | 157 ++++++++++ ports/rxv1/gnu/src/tx_initialize_low_level.S | 93 ++++++ .../rxv1/gnu/src/tx_thread_context_restore.S | 200 +++++++++++++ ports/rxv1/gnu/src/tx_thread_context_save.S | 158 ++++++++++ .../gnu/src/tx_thread_interrupt_control.S | 87 ++++++ ports/rxv1/gnu/src/tx_thread_schedule.S | 163 ++++++++++ ports/rxv1/gnu/src/tx_thread_stack_build.S | 137 +++++++++ ports/rxv1/gnu/src/tx_thread_system_return.S | 117 ++++++++ ports/rxv1/gnu/src/tx_timer_interrupt.S | 239 +++++++++++++++ ports/rxv1/iar/inc/tx_port.h | 273 +++++++++++++++++ ports/rxv1/iar/readme_threadx.txt | 153 ++++++++++ ports/rxv1/iar/src/tx_initialize_low_level.s | 99 ++++++ .../rxv1/iar/src/tx_thread_context_restore.s | 187 ++++++++++++ ports/rxv1/iar/src/tx_thread_context_save.s | 157 ++++++++++ .../iar/src/tx_thread_interrupt_control.s | 85 ++++++ ports/rxv1/iar/src/tx_thread_schedule.s | 162 ++++++++++ ports/rxv1/iar/src/tx_thread_stack_build.s | 137 +++++++++ ports/rxv1/iar/src/tx_thread_system_return.s | 74 +++++ ports/rxv1/iar/src/tx_timer_interrupt.s | 235 +++++++++++++++ 30 files changed, 4884 insertions(+) create mode 100644 ports/rxv1/ccrx/inc/tx_port.h create mode 100644 ports/rxv1/ccrx/readme_threadx.txt create mode 100644 ports/rxv1/ccrx/src/tx_initialize_low_level.src create mode 100644 ports/rxv1/ccrx/src/tx_thread_context_restore.src create mode 100644 ports/rxv1/ccrx/src/tx_thread_context_save.src create mode 100644 ports/rxv1/ccrx/src/tx_thread_interrupt_control.src create mode 100644 ports/rxv1/ccrx/src/tx_thread_schedule.src create mode 100644 ports/rxv1/ccrx/src/tx_thread_stack_build.src create mode 100644 ports/rxv1/ccrx/src/tx_thread_system_return.src create mode 100644 ports/rxv1/ccrx/src/tx_timer_interrupt.src create mode 100644 ports/rxv1/gnu/inc/tx_port.h create mode 100644 ports/rxv1/gnu/readme_threadx.txt create mode 100644 ports/rxv1/gnu/src/tx_initialize_low_level.S create mode 100644 ports/rxv1/gnu/src/tx_thread_context_restore.S create mode 100644 ports/rxv1/gnu/src/tx_thread_context_save.S create mode 100644 ports/rxv1/gnu/src/tx_thread_interrupt_control.S create mode 100644 ports/rxv1/gnu/src/tx_thread_schedule.S create mode 100644 ports/rxv1/gnu/src/tx_thread_stack_build.S create mode 100644 ports/rxv1/gnu/src/tx_thread_system_return.S create mode 100644 ports/rxv1/gnu/src/tx_timer_interrupt.S create mode 100644 ports/rxv1/iar/inc/tx_port.h create mode 100644 ports/rxv1/iar/readme_threadx.txt create mode 100644 ports/rxv1/iar/src/tx_initialize_low_level.s create mode 100644 ports/rxv1/iar/src/tx_thread_context_restore.s create mode 100644 ports/rxv1/iar/src/tx_thread_context_save.s create mode 100644 ports/rxv1/iar/src/tx_thread_interrupt_control.s create mode 100644 ports/rxv1/iar/src/tx_thread_schedule.s create mode 100644 ports/rxv1/iar/src/tx_thread_stack_build.s create mode 100644 ports/rxv1/iar/src/tx_thread_system_return.s create mode 100644 ports/rxv1/iar/src/tx_timer_interrupt.s diff --git a/ports/rxv1/ccrx/inc/tx_port.h b/ports/rxv1/ccrx/inc/tx_port.h new file mode 100644 index 00000000..662975d1 --- /dev/null +++ b/ports/rxv1/ccrx/inc/tx_port.h @@ -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 + diff --git a/ports/rxv1/ccrx/readme_threadx.txt b/ports/rxv1/ccrx/readme_threadx.txt new file mode 100644 index 00000000..8035a79e --- /dev/null +++ b/ports/rxv1/ccrx/readme_threadx.txt @@ -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 \ No newline at end of file diff --git a/ports/rxv1/ccrx/src/tx_initialize_low_level.src b/ports/rxv1/ccrx/src/tx_initialize_low_level.src new file mode 100644 index 00000000..1a439a09 --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_initialize_low_level.src @@ -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 diff --git a/ports/rxv1/ccrx/src/tx_thread_context_restore.src b/ports/rxv1/ccrx/src/tx_thread_context_restore.src new file mode 100644 index 00000000..b92a2e0b --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_thread_context_restore.src @@ -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 + diff --git a/ports/rxv1/ccrx/src/tx_thread_context_save.src b/ports/rxv1/ccrx/src/tx_thread_context_save.src new file mode 100644 index 00000000..8d84f9a1 --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_thread_context_save.src @@ -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 + diff --git a/ports/rxv1/ccrx/src/tx_thread_interrupt_control.src b/ports/rxv1/ccrx/src/tx_thread_interrupt_control.src new file mode 100644 index 00000000..d2c75fca --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_thread_interrupt_control.src @@ -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 + diff --git a/ports/rxv1/ccrx/src/tx_thread_schedule.src b/ports/rxv1/ccrx/src/tx_thread_schedule.src new file mode 100644 index 00000000..88018528 --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_thread_schedule.src @@ -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 diff --git a/ports/rxv1/ccrx/src/tx_thread_stack_build.src b/ports/rxv1/ccrx/src/tx_thread_stack_build.src new file mode 100644 index 00000000..93408c72 --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_thread_stack_build.src @@ -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 + diff --git a/ports/rxv1/ccrx/src/tx_thread_system_return.src b/ports/rxv1/ccrx/src/tx_thread_system_return.src new file mode 100644 index 00000000..2c3a73e4 --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_thread_system_return.src @@ -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 + diff --git a/ports/rxv1/ccrx/src/tx_timer_interrupt.src b/ports/rxv1/ccrx/src/tx_timer_interrupt.src new file mode 100644 index 00000000..1236ec95 --- /dev/null +++ b/ports/rxv1/ccrx/src/tx_timer_interrupt.src @@ -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 + diff --git a/ports/rxv1/gnu/inc/tx_port.h b/ports/rxv1/gnu/inc/tx_port.h new file mode 100644 index 00000000..33d4b886 --- /dev/null +++ b/ports/rxv1/gnu/inc/tx_port.h @@ -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 +//#include + +/* 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 + diff --git a/ports/rxv1/gnu/readme_threadx.txt b/ports/rxv1/gnu/readme_threadx.txt new file mode 100644 index 00000000..9f252a5f --- /dev/null +++ b/ports/rxv1/gnu/readme_threadx.txt @@ -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 + diff --git a/ports/rxv1/gnu/src/tx_initialize_low_level.S b/ports/rxv1/gnu/src/tx_initialize_low_level.S new file mode 100644 index 00000000..181688a6 --- /dev/null +++ b/ports/rxv1/gnu/src/tx_initialize_low_level.S @@ -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 diff --git a/ports/rxv1/gnu/src/tx_thread_context_restore.S b/ports/rxv1/gnu/src/tx_thread_context_restore.S new file mode 100644 index 00000000..e6d7d4cf --- /dev/null +++ b/ports/rxv1/gnu/src/tx_thread_context_restore.S @@ -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 diff --git a/ports/rxv1/gnu/src/tx_thread_context_save.S b/ports/rxv1/gnu/src/tx_thread_context_save.S new file mode 100644 index 00000000..e7a4cd4b --- /dev/null +++ b/ports/rxv1/gnu/src/tx_thread_context_save.S @@ -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 + diff --git a/ports/rxv1/gnu/src/tx_thread_interrupt_control.S b/ports/rxv1/gnu/src/tx_thread_interrupt_control.S new file mode 100644 index 00000000..87b5ebe3 --- /dev/null +++ b/ports/rxv1/gnu/src/tx_thread_interrupt_control.S @@ -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 + diff --git a/ports/rxv1/gnu/src/tx_thread_schedule.S b/ports/rxv1/gnu/src/tx_thread_schedule.S new file mode 100644 index 00000000..1a6779da --- /dev/null +++ b/ports/rxv1/gnu/src/tx_thread_schedule.S @@ -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 diff --git a/ports/rxv1/gnu/src/tx_thread_stack_build.S b/ports/rxv1/gnu/src/tx_thread_stack_build.S new file mode 100644 index 00000000..dd0f42f5 --- /dev/null +++ b/ports/rxv1/gnu/src/tx_thread_stack_build.S @@ -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 + diff --git a/ports/rxv1/gnu/src/tx_thread_system_return.S b/ports/rxv1/gnu/src/tx_thread_system_return.S new file mode 100644 index 00000000..d1393744 --- /dev/null +++ b/ports/rxv1/gnu/src/tx_thread_system_return.S @@ -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 + diff --git a/ports/rxv1/gnu/src/tx_timer_interrupt.S b/ports/rxv1/gnu/src/tx_timer_interrupt.S new file mode 100644 index 00000000..bec00c57 --- /dev/null +++ b/ports/rxv1/gnu/src/tx_timer_interrupt.S @@ -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 + diff --git a/ports/rxv1/iar/inc/tx_port.h b/ports/rxv1/iar/inc/tx_port.h new file mode 100644 index 00000000..880ff6d7 --- /dev/null +++ b/ports/rxv1/iar/inc/tx_port.h @@ -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 +#include + +/* 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 + diff --git a/ports/rxv1/iar/readme_threadx.txt b/ports/rxv1/iar/readme_threadx.txt new file mode 100644 index 00000000..c36fb88f --- /dev/null +++ b/ports/rxv1/iar/readme_threadx.txt @@ -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 \ No newline at end of file diff --git a/ports/rxv1/iar/src/tx_initialize_low_level.s b/ports/rxv1/iar/src/tx_initialize_low_level.s new file mode 100644 index 00000000..9d33e8d3 --- /dev/null +++ b/ports/rxv1/iar/src/tx_initialize_low_level.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_thread_context_restore.s b/ports/rxv1/iar/src/tx_thread_context_restore.s new file mode 100644 index 00000000..cb1746e2 --- /dev/null +++ b/ports/rxv1/iar/src/tx_thread_context_restore.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_thread_context_save.s b/ports/rxv1/iar/src/tx_thread_context_save.s new file mode 100644 index 00000000..4b07ffeb --- /dev/null +++ b/ports/rxv1/iar/src/tx_thread_context_save.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_thread_interrupt_control.s b/ports/rxv1/iar/src/tx_thread_interrupt_control.s new file mode 100644 index 00000000..17de512c --- /dev/null +++ b/ports/rxv1/iar/src/tx_thread_interrupt_control.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_thread_schedule.s b/ports/rxv1/iar/src/tx_thread_schedule.s new file mode 100644 index 00000000..14b42907 --- /dev/null +++ b/ports/rxv1/iar/src/tx_thread_schedule.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_thread_stack_build.s b/ports/rxv1/iar/src/tx_thread_stack_build.s new file mode 100644 index 00000000..d52a40e9 --- /dev/null +++ b/ports/rxv1/iar/src/tx_thread_stack_build.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_thread_system_return.s b/ports/rxv1/iar/src/tx_thread_system_return.s new file mode 100644 index 00000000..de17e189 --- /dev/null +++ b/ports/rxv1/iar/src/tx_thread_system_return.s @@ -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 diff --git a/ports/rxv1/iar/src/tx_timer_interrupt.s b/ports/rxv1/iar/src/tx_timer_interrupt.s new file mode 100644 index 00000000..35591477 --- /dev/null +++ b/ports/rxv1/iar/src/tx_timer_interrupt.s @@ -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 \ No newline at end of file