summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorScott Larson <[email protected]>2021-01-08 13:31:36 -0800
committerScott Larson <[email protected]>2021-01-08 13:31:36 -0800
commitf108ebdbafc16dc1725f4afbab73ac6084ee4302 (patch)
treef1b857b03a3b7d787761523d51f53b7eb30d7b4e /ports
parentb0e9b132b59ab703f19b4588ed785c9c8e7a1072 (diff)
update to v6.1.3
Diffstat (limited to 'ports')
-rw-r--r--ports/arc_em/metaware/src/tx_timer_interrupt.s7
-rw-r--r--ports/arc_hs/metaware/src/tx_timer_interrupt.s7
-rw-r--r--ports/cortex_a35/ac6/example_build/sample_threadx/.settings/language.settings.xml48
-rw-r--r--ports/cortex_a35/ac6/example_build/tx/.settings/language.settings.xml48
-rw-r--r--ports/cortex_m23/gnu/example_build/build_threadx.bat235
-rw-r--r--ports/cortex_m23/gnu/inc/tx_port.h82
-rw-r--r--ports/cortex_m23/gnu/readme_threadx.txt16
-rw-r--r--ports/cortex_m23/gnu/src/tx_thread_secure_stack.c98
-rw-r--r--ports/rxv2/ccrx/inc/tx_port.h281
-rw-r--r--ports/rxv2/ccrx/readme_threadx.txt175
-rw-r--r--ports/rxv2/ccrx/src/tx_initialize_low_level.src101
-rw-r--r--ports/rxv2/ccrx/src/tx_thread_context_restore.src207
-rw-r--r--ports/rxv2/ccrx/src/tx_thread_context_save.src171
-rw-r--r--ports/rxv2/ccrx/src/tx_thread_interrupt_control.src96
-rw-r--r--ports/rxv2/ccrx/src/tx_thread_schedule.src180
-rw-r--r--ports/rxv2/ccrx/src/tx_thread_stack_build.src155
-rw-r--r--ports/rxv2/ccrx/src/tx_thread_system_return.src127
-rw-r--r--ports/rxv2/ccrx/src/tx_timer_interrupt.src251
-rw-r--r--ports/rxv2/gnu/inc/tx_port.h264
-rw-r--r--ports/rxv2/gnu/readme_threadx.txt168
-rw-r--r--ports/rxv2/gnu/src/tx_initialize_low_level.S93
-rw-r--r--ports/rxv2/gnu/src/tx_thread_context_restore.S207
-rw-r--r--ports/rxv2/gnu/src/tx_thread_context_save.S171
-rw-r--r--ports/rxv2/gnu/src/tx_thread_interrupt_control.S96
-rw-r--r--ports/rxv2/gnu/src/tx_thread_schedule.S180
-rw-r--r--ports/rxv2/gnu/src/tx_thread_stack_build.S155
-rw-r--r--ports/rxv2/gnu/src/tx_thread_system_return.S127
-rw-r--r--ports/rxv2/gnu/src/tx_timer_interrupt.S251
-rw-r--r--ports/rxv2/iar/inc/tx_port.h273
-rw-r--r--ports/rxv2/iar/readme_threadx.txt163
-rw-r--r--ports/rxv2/iar/src/tx_initialize_low_level.s99
-rw-r--r--ports/rxv2/iar/src/tx_thread_context_restore.s205
-rw-r--r--ports/rxv2/iar/src/tx_thread_context_save.s170
-rw-r--r--ports/rxv2/iar/src/tx_thread_interrupt_control.s93
-rw-r--r--ports/rxv2/iar/src/tx_thread_schedule.s179
-rw-r--r--ports/rxv2/iar/src/tx_thread_stack_build.s147
-rw-r--r--ports/rxv2/iar/src/tx_thread_system_return.s74
-rw-r--r--ports/rxv2/iar/src/tx_timer_interrupt.s235
-rw-r--r--ports/xtensa/xcc/CMakeLists.txt36
-rw-r--r--ports/xtensa/xcc/example_build/demo_threadx.c377
-rw-r--r--ports/xtensa/xcc/inc/tx_api_asm.h67
-rw-r--r--ports/xtensa/xcc/inc/tx_port.h479
-rw-r--r--ports/xtensa/xcc/inc/tx_user.h257
-rw-r--r--ports/xtensa/xcc/inc/xtensa_api.h125
-rw-r--r--ports/xtensa/xcc/inc/xtensa_context.h561
-rw-r--r--ports/xtensa/xcc/inc/xtensa_rtos.h204
-rw-r--r--ports/xtensa/xcc/inc/xtensa_timer.h157
-rw-r--r--ports/xtensa/xcc/readme_threadx.txt1015
-rw-r--r--ports/xtensa/xcc/src/tx_clib_lock.c406
-rw-r--r--ports/xtensa/xcc/src/tx_initialize_low_level.c187
-rw-r--r--ports/xtensa/xcc/src/tx_thread_context_restore.S216
-rw-r--r--ports/xtensa/xcc/src/tx_thread_context_save.S157
-rw-r--r--ports/xtensa/xcc/src/tx_thread_interrupt_control.c81
-rw-r--r--ports/xtensa/xcc/src/tx_thread_schedule.S253
-rw-r--r--ports/xtensa/xcc/src/tx_thread_stack_build.S158
-rw-r--r--ports/xtensa/xcc/src/tx_thread_system_return.S287
-rw-r--r--ports/xtensa/xcc/src/tx_timer_interrupt.S277
-rw-r--r--ports/xtensa/xcc/src/tx_xtensa_stack_error_handler.c123
-rw-r--r--ports/xtensa/xcc/src/xtensa_context.S433
-rw-r--r--ports/xtensa/xcc/src/xtensa_coproc_handler.S578
-rw-r--r--ports/xtensa/xcc/src/xtensa_init.c67
-rw-r--r--ports/xtensa/xcc/src/xtensa_intr.c213
-rw-r--r--ports/xtensa/xcc/src/xtensa_intr_asm.S156
-rw-r--r--ports/xtensa/xcc/src/xtensa_intr_wrapper.c125
-rw-r--r--ports/xtensa/xcc/src/xtensa_overlay_os_hook.c109
-rw-r--r--ports/xtensa/xcc/src/xtensa_vectors.S1696
-rw-r--r--ports/xtensa/xcc/src/xtensa_vectors_xea3.S392
67 files changed, 14657 insertions, 170 deletions
diff --git a/ports/arc_em/metaware/src/tx_timer_interrupt.s b/ports/arc_em/metaware/src/tx_timer_interrupt.s
index 67b06941..27141e01 100644
--- a/ports/arc_em/metaware/src/tx_timer_interrupt.s
+++ b/ports/arc_em/metaware/src/tx_timer_interrupt.s
@@ -35,7 +35,7 @@
;/* FUNCTION RELEASE */
;/* */
;/* _tx_timer_interrupt ARCv2_EM/MetaWare */
-;/* 6.1 */
+;/* 6.1.3 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
@@ -72,6 +72,10 @@
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+;/* 12-31-2020 Scott Larson Modified comment(s), remove */
+;/* unneeded load of */
+;/* _tx_thread_preempt_disable, */
+;/* resulting in version 6.1.3 */
;/* */
;/**************************************************************************/
;VOID _tx_timer_interrupt(VOID)
@@ -187,7 +191,6 @@ __tx_something_expired:
; {
;
ld r2, [gp, _tx_timer_expired@sda] ; Pickup timer expired flag
- ld r4, [gp, _tx_thread_preempt_disable@sda] ; Pickup preempt disable
breq r2, 0, __tx_timer_dont_activate ; If not set, skip expiration processing
;
; /* Process the timer expiration. */
diff --git a/ports/arc_hs/metaware/src/tx_timer_interrupt.s b/ports/arc_hs/metaware/src/tx_timer_interrupt.s
index 663e9060..fdb70898 100644
--- a/ports/arc_hs/metaware/src/tx_timer_interrupt.s
+++ b/ports/arc_hs/metaware/src/tx_timer_interrupt.s
@@ -35,7 +35,7 @@
;/* FUNCTION RELEASE */
;/* */
;/* _tx_timer_interrupt ARC_HS/MetaWare */
-;/* 6.1 */
+;/* 6.1.3 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
@@ -72,6 +72,10 @@
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+;/* 12-31-2020 Scott Larson Modified comment(s), remove */
+;/* unneeded load of */
+;/* _tx_thread_preempt_disable, */
+;/* resulting in version 6.1.3 */
;/* */
;/**************************************************************************/
;VOID _tx_timer_interrupt(VOID)
@@ -187,7 +191,6 @@ __tx_something_expired:
; {
;
ld r2, [gp, _tx_timer_expired@sda] ; Pickup timer expired flag
- ld r4, [gp, _tx_thread_preempt_disable@sda] ; Pickup preempt disable
breq r2, 0, __tx_timer_dont_activate ; If not set, skip expiration processing
;
; /* Process the timer expiration. */
diff --git a/ports/cortex_a35/ac6/example_build/sample_threadx/.settings/language.settings.xml b/ports/cortex_a35/ac6/example_build/sample_threadx/.settings/language.settings.xml
deleted file mode 100644
index 16ac1af8..00000000
--- a/ports/cortex_a35/ac6/example_build/sample_threadx/.settings/language.settings.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project>
-
- <configuration id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" name="Debug">
-
- <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
-
- <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
-
- <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-890320463837788586" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="Arm Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.c.ac6"/>
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.cpp.ac6"/>
-
- </provider>
-
- </extension>
-
- </configuration>
-
- <configuration id="com.arm.eclipse.build.config.v6.exe.release.base.262471578" name="Release">
-
- <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
-
- <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
-
- <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-936373864897685072" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="Arm Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.c.ac6"/>
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.cpp.ac6"/>
-
- </provider>
-
- </extension>
-
- </configuration>
-
-</project>
diff --git a/ports/cortex_a35/ac6/example_build/tx/.settings/language.settings.xml b/ports/cortex_a35/ac6/example_build/tx/.settings/language.settings.xml
deleted file mode 100644
index 830dd5dd..00000000
--- a/ports/cortex_a35/ac6/example_build/tx/.settings/language.settings.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project>
-
- <configuration id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" name="Debug">
-
- <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
-
- <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
-
- <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-890320463837788586" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="Arm Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.c.ac6"/>
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.cpp.ac6"/>
-
- </provider>
-
- </extension>
-
- </configuration>
-
- <configuration id="com.arm.eclipse.build.config.v6.lib.release.base.979090268" name="Release">
-
- <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
-
- <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
-
- <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-
- <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-936373864897685072" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="Arm Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.c.ac6"/>
-
- <language-scope id="com.arm.eclipse.builder.armcc.lang.cpp.ac6"/>
-
- </provider>
-
- </extension>
-
- </configuration>
-
-</project>
diff --git a/ports/cortex_m23/gnu/example_build/build_threadx.bat b/ports/cortex_m23/gnu/example_build/build_threadx.bat
new file mode 100644
index 00000000..822d45f2
--- /dev/null
+++ b/ports/cortex_m23/gnu/example_build/build_threadx.bat
@@ -0,0 +1,235 @@
+del tx.a
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_initialize_low_level.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_context_restore.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_context_save.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_interrupt_control.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_interrupt_disable.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_interrupt_restore.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_schedule.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_secure_stack_allocate.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_secure_stack_free.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_stack_build.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_thread_system_return.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE ../src/tx_timer_interrupt.S
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../src/txe_thread_secure_stack_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../src/txe_thread_secure_stack_free.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../src/tx_thread_stack_error_handler.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../src/tx_thread_stack_error_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_block_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_pool_search.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_byte_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_set.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_event_flags_set_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_initialize_high_level.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_initialize_kernel_enter.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_initialize_kernel_setup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_priority_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_mutex_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_flush.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_front_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_receive.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_queue_send_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_ceiling_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_cleanup.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_semaphore_put_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_entry_exit_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_identify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_preemption_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_priority_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_relinquish.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_reset.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_resume.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_shell_entry.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_sleep.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_stack_analyze.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_suspend.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_system_preempt_check.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_system_resume.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_system_suspend.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_terminate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_time_slice.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_time_slice_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_timeout.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_thread_wait_abort.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_time_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_time_set.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_activate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_deactivate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_expiration_process.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_performance_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_performance_system_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_system_activate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_system_deactivate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_timer_thread_entry.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_enable.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_disable.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_initialize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_interrupt_control.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_isr_enter_insert.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_isr_exit_insert.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_object_register.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_object_unregister.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_user_event_insert.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_buffer_full_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_event_filter.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/tx_trace_event_unfilter.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_block_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_block_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_block_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_block_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_block_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_block_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_byte_allocate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_byte_pool_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_byte_pool_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_byte_pool_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_byte_pool_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_byte_release.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_event_flags_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_event_flags_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_event_flags_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_event_flags_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_event_flags_set.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_event_flags_set_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_mutex_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_mutex_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_mutex_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_mutex_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_mutex_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_mutex_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_flush.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_front_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_receive.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_send.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_queue_send_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_ceiling_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_prioritize.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_put.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_semaphore_put_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_entry_exit_notify.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_info_get.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_preemption_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_priority_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_relinquish.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_reset.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_resume.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_suspend.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_terminate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_time_slice_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_thread_wait_abort.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_timer_activate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_timer_change.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_timer_create.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_timer_deactivate.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_timer_delete.c
+arm-none-eabi-gcc -c -g -mcpu=cortex-m23 -DTX_SINGLE_MODE_NON_SECURE -I../../../../common/inc -I../inc ../../../../common/src/txe_timer_info_get.c
+arm-none-eabi-ar -r tx.a tx_thread_secure_stack_allocate.o txe_thread_secure_stack_allocate.o tx_thread_secure_stack_free.o txe_thread_secure_stack_free.o
+arm-none-eabi-ar -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o
+arm-none-eabi-ar -r tx.a tx_thread_interrupt_disable.o tx_thread_interrupt_restore.o tx_initialize_low_level.o
+arm-none-eabi-ar -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o
+arm-none-eabi-ar -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o
+arm-none-eabi-ar -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o
+arm-none-eabi-ar -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o
+arm-none-eabi-ar -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o
+arm-none-eabi-ar -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o
+arm-none-eabi-ar -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o
+arm-none-eabi-ar -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o
+arm-none-eabi-ar -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o
+arm-none-eabi-ar -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o
+arm-none-eabi-ar -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o
+arm-none-eabi-ar -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o
+arm-none-eabi-ar -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o
+arm-none-eabi-ar -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o
+arm-none-eabi-ar -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o
+arm-none-eabi-ar -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o
+arm-none-eabi-ar -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o
+arm-none-eabi-ar -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o
+arm-none-eabi-ar -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o
+arm-none-eabi-ar -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o
+arm-none-eabi-ar -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o
+arm-none-eabi-ar -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o
+arm-none-eabi-ar -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o
+arm-none-eabi-ar -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o
+arm-none-eabi-ar -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o
+arm-none-eabi-ar -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o
+arm-none-eabi-ar -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o
+arm-none-eabi-ar -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o
+arm-none-eabi-ar -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o
+arm-none-eabi-ar -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o
+arm-none-eabi-ar -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o
+arm-none-eabi-ar -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o
+arm-none-eabi-ar -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o
diff --git a/ports/cortex_m23/gnu/inc/tx_port.h b/ports/cortex_m23/gnu/inc/tx_port.h
index 69acde04..bb9c05a9 100644
--- a/ports/cortex_m23/gnu/inc/tx_port.h
+++ b/ports/cortex_m23/gnu/inc/tx_port.h
@@ -26,7 +26,7 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M23/GNU */
-/* 6.1 */
+/* 6.1.3 */
/* */
/* AUTHOR */
/* */
@@ -48,6 +48,10 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 Scott Larson Initial Version 6.1 */
+/* 12-31-2020 Scott Larson Modified comment(s), */
+/* remove unneeded headers, */
+/* use builtins, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -67,8 +71,6 @@
#include <stdlib.h>
#include <string.h>
-#include <arm_compat.h>
-#include "ARMCM23_TZ.h" /* For intrinsic functions. */
/* Define ThreadX basic types for this port. */
@@ -275,8 +277,6 @@ ULONG _tx_misra_time_stamp_get(VOID);
#ifndef TX_MISRA_ENABLE
-//register unsigned int _ipsr __asm ("MRS %[result], ipsr" : [result] "=r" (_ipsr) : );
-inline static unsigned int _get_ipsr(void);
inline static unsigned int _get_ipsr(void)
{
unsigned int _ipsr;
@@ -352,7 +352,7 @@ extern void _tx_thread_secure_stack_initialize(void);
#ifndef TX_DISABLE_INLINE
-#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __builtin_ctz(m);
#endif
@@ -364,41 +364,73 @@ extern void _tx_thread_secure_stack_initialize(void);
is used to define a local function save area for the disable and restore
macros. */
-#ifdef TX_DISABLE_INLINE
+#ifndef TX_DISABLE_INLINE
-UINT _tx_thread_interrupt_disable(VOID);
-VOID _tx_thread_interrupt_restore(UINT previous_posture);
+/* Define GNU specific macros, with in-line assembly for performance. */
-#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
-#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
+unsigned int primask_value;
-#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ __asm__ volatile (" CPSID i" : : : "memory" );
+ return(primask_value);
+}
-#else
+__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
+{
-#define TX_INTERRUPT_SAVE_AREA unsigned int was_masked;
-#define TX_DISABLE was_masked = __disable_irq();
-#define TX_RESTORE if (was_masked == 0) __enable_irq();
+ __asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
+}
-#define _tx_thread_system_return _tx_thread_system_return_inline
+__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
+{
+
+unsigned int primask_value;
+ __asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
+ return(primask_value);
+}
-static void _tx_thread_system_return_inline(void)
+__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
-unsigned int was_masked;
+ __asm__ volatile (" CPSIE i": : : "memory" );
+}
+
+
+__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
+{
+unsigned int interrupt_save;
- /* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_get_ipsr() == 0)
{
- was_masked = __disable_irq();
- __enable_irq();
- if (was_masked != 0)
- __disable_irq();
+ interrupt_save = __get_primask_value();
+ __enable_interrupts();
+ __restore_interrupts(interrupt_save);
}
}
+
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupts(interrupt_save);
+
+
+/* Redefine _tx_thread_system_return for improved performance. */
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
#endif
@@ -406,7 +438,7 @@ unsigned int was_masked;
#ifdef TX_THREAD_INIT
CHAR _tx_version_id[] =
- "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/GNU Version 6.1 *";
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/GNU Version 6.1.3 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
diff --git a/ports/cortex_m23/gnu/readme_threadx.txt b/ports/cortex_m23/gnu/readme_threadx.txt
index fa581684..e5dacfec 100644
--- a/ports/cortex_m23/gnu/readme_threadx.txt
+++ b/ports/cortex_m23/gnu/readme_threadx.txt
@@ -5,12 +5,12 @@
1. Building the ThreadX run-time Library
-
+An example .bat file is in the example_build directory.
2. Demonstration System
-
+No demonstration example is provided.
3. System Initialization
@@ -127,6 +127,18 @@ For generic code revision information, please refer to the readme_threadx_generi
file, which is included in your distribution. The following details the revision
information associated with this specific port of ThreadX:
+12-31-2020 The following files were
+ changed/added for port specific version 6.1.3:
+
+
+ tx_port.h Remove unneeded include files,
+ use builtin functions,
+ modified comments.
+
+ tx_thread_secure_stack.c Remove unneeded include file,
+ use inline get/set functions,
+ modified comments.
+
09-30-2020 Initial ThreadX 6.1 version for Cortex-M23 using GNU tools.
diff --git a/ports/cortex_m23/gnu/src/tx_thread_secure_stack.c b/ports/cortex_m23/gnu/src/tx_thread_secure_stack.c
index 9ca7ccff..0e8cbde0 100644
--- a/ports/cortex_m23/gnu/src/tx_thread_secure_stack.c
+++ b/ports/cortex_m23/gnu/src/tx_thread_secure_stack.c
@@ -29,7 +29,6 @@
#define TX_SOURCE_CODE
-#include "ARMCM23_TZ.h" /* For intrinsic functions. */
#include "tx_secure_interface.h" /* Interface for NS code. */
/* Minimum size of secure stack. */
@@ -63,7 +62,7 @@ typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
/* FUNCTION RELEASE */
/* */
/* _tx_thread_secure_stack_initialize Cortex-M23/GNU */
-/* 6.1.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
@@ -82,10 +81,7 @@ typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
/* */
/* CALLS */
/* */
-/* __get_CONTROL Intrinsic to get CONTROL */
-/* __set_CONTROL Intrinsic to set CONTROL */
-/* __set_PSPLIM Intrinsic to set PSP limit */
-/* __set_PSP Intrinsic to set PSP */
+/* None */
/* */
/* CALLED BY */
/* */
@@ -98,19 +94,25 @@ typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
/* 09-30-2020 Scott Larson Initial Version 6.1 */
/* 10-16-2020 Scott Larson Modified comment(s), */
/* resulting in version 6.1.1 */
+/* 12-31-2020 Scott Larson Modified comment(s), and */
+/* fixed M23 GCC build, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
__attribute__((cmse_nonsecure_entry))
void _tx_thread_secure_stack_initialize(void)
{
+ ULONG control;
/* Set secure mode to use PSP. */
- __set_CONTROL(__get_CONTROL() | 2);
+ asm volatile("MRS %0, CONTROL" : "=r" (control)); /* Get CONTROL register. */
+ control |= 2; /* Use PSP. */
+ asm volatile("MSR CONTROL, %0" :: "r" (control)); /* Set CONTROL register. */
/* Set process stack pointer and stack limit to 0 to throw exception when a thread
without a secure stack calls a secure function that tries to use secure stack. */
- __set_PSPLIM(0);
- __set_PSP(0);
+ asm volatile("MSR PSPLIM, %0" :: "r" (0));
+ asm volatile("MSR PSP, %0" :: "r" (0));
return;
}
@@ -122,7 +124,7 @@ void _tx_thread_secure_stack_initialize(void)
/* FUNCTION RELEASE */
/* */
/* _tx_thread_secure_mode_stack_allocate Cortex-M23/GNU */
-/* 6.1.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
@@ -145,13 +147,9 @@ void _tx_thread_secure_stack_initialize(void)
/* */
/* CALLS */
/* */
-/* __get_IPSR Intrinsic to get IPSR */
/* calloc Compiler's calloc function */
/* malloc Compiler's malloc function */
/* free Compiler's free() function */
-/* __set_PSPLIM Intrinsic to set PSP limit */
-/* __set_PSP Intrinsic to set PSP */
-/* __TZ_get_PSPLIM_NS Intrinsic to get NS PSP */
/* */
/* CALLED BY */
/* */
@@ -165,6 +163,10 @@ void _tx_thread_secure_stack_initialize(void)
/* 10-16-2020 Scott Larson Modified comment(s), */
/* added stack sealing, */
/* resulting in version 6.1.1 */
+/* 12-31-2020 Scott Larson Modified comment(s), and */
+/* fixed M23 GCC build, */
+/* resulting in version 6.1.3 */
+
/* */
/**************************************************************************/
__attribute__((cmse_nonsecure_entry))
@@ -173,12 +175,14 @@ UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack
UINT status;
TX_THREAD_SECURE_STACK_INFO *info_ptr;
UCHAR *stack_mem;
-ULONG sp;
+ULONG ipsr;
+ULONG psplim_ns;
status = TX_SUCCESS;
/* Make sure function is called from interrupt (threads should not call). */
- if (__get_IPSR() == 0)
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
{
status = TX_CALLER_ERROR;
}
@@ -217,14 +221,13 @@ ULONG sp;
/* Save info pointer in thread. */
thread_ptr -> tx_thread_secure_stack_context = info_ptr;
- /* Check if this thread is running by looking at PSP_NS and seeing if it is within
- the stack_start and stack_end range. */
- sp = __TZ_get_PSP_NS();
- if(sp > ((ULONG) thread_ptr -> tx_thread_stack_start) && sp < ((ULONG) thread_ptr -> tx_thread_stack_end))
+ /* Check if this thread is running by looking at its stack start and PSPLIM_NS */
+ asm volatile("MRS %0, PSPLIM_NS" : "=r" (psplim_ns)); /* Get PSPLIM_NS register. */
+ if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == psplim_ns)
{
/* If this thread is running, set Secure PSP and PSPLIM. */
- __set_PSPLIM((ULONG)(info_ptr -> tx_thread_secure_stack_limit));
- __set_PSP((ULONG)(info_ptr -> tx_thread_secure_stack_ptr));
+ asm volatile("MSR PSPLIM, %0" :: "r" ((ULONG)(info_ptr -> tx_thread_secure_stack_limit)));
+ asm volatile("MSR PSP, %0" :: "r" ((ULONG)(info_ptr -> tx_thread_secure_stack_ptr)));
}
}
@@ -252,7 +255,7 @@ ULONG sp;
/* FUNCTION RELEASE */
/* */
/* _tx_thread_secure_mode_stack_free Cortex-M23/GNU */
-/* 6.1.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
@@ -273,7 +276,6 @@ ULONG sp;
/* */
/* CALLS */
/* */
-/* __get_IPSR Intrinsic to get IPSR */
/* free Compiler's free() function */
/* */
/* CALLED BY */
@@ -287,6 +289,9 @@ ULONG sp;
/* 09-30-2020 Scott Larson Initial Version 6.1 */
/* 10-16-2020 Scott Larson Modified comment(s), */
/* resulting in version 6.1.1 */
+/* 12-31-2020 Scott Larson Modified comment(s), and */
+/* fixed M23 GCC build, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
__attribute__((cmse_nonsecure_entry))
@@ -294,14 +299,16 @@ UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr)
{
UINT status;
TX_THREAD_SECURE_STACK_INFO *info_ptr;
-
+ULONG ipsr;
+
status = TX_SUCCESS;
/* Pickup stack info from thread. */
info_ptr = thread_ptr -> tx_thread_secure_stack_context;
/* Make sure function is called from interrupt (threads should not call). */
- if (__get_IPSR() == 0)
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
{
status = TX_CALLER_ERROR;
}
@@ -335,7 +342,7 @@ TX_THREAD_SECURE_STACK_INFO *info_ptr;
/* FUNCTION RELEASE */
/* */
/* _tx_thread_secure_stack_context_save Cortex-M23/GNU */
-/* 6.1.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
@@ -354,10 +361,7 @@ TX_THREAD_SECURE_STACK_INFO *info_ptr;
/* */
/* CALLS */
/* */
-/* __get_IPSR Intrinsic to get IPSR */
-/* __get_PSP Intrinsic to get PSP */
-/* __set_PSPLIM Intrinsic to set PSP limit */
-/* __set_PSP Intrinsic to set PSP */
+/* None */
/* */
/* CALLED BY */
/* */
@@ -370,6 +374,9 @@ TX_THREAD_SECURE_STACK_INFO *info_ptr;
/* 09-30-2020 Scott Larson Initial Version 6.1 */
/* 10-16-2020 Scott Larson Modified comment(s), */
/* resulting in version 6.1.1 */
+/* 12-31-2020 Scott Larson Modified comment(s), and */
+/* fixed M23 GCC build, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
__attribute__((cmse_nonsecure_entry))
@@ -377,9 +384,11 @@ void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr)
{
TX_THREAD_SECURE_STACK_INFO *info_ptr;
ULONG sp;
-
+ULONG ipsr;
+
/* This function should be called from scheduler only. */
- if (__get_IPSR() == 0)
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
{
return;
}
@@ -394,7 +403,7 @@ ULONG sp;
}
/* Check that stack pointer is in range */
- sp = __get_PSP();
+ asm volatile("MRS %0, PSP" : "=r" (sp)); /* Get PSP register. */
if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) ||
(sp > (ULONG)info_ptr -> tx_thread_secure_stack_start))
{
@@ -406,8 +415,8 @@ ULONG sp;
/* Set process stack pointer and stack limit to 0 to throw exception when a thread
without a secure stack calls a secure function that tries to use secure stack. */
- __set_PSPLIM(0);
- __set_PSP(0);
+ asm volatile("MSR PSPLIM, %0" :: "r" (0));
+ asm volatile("MSR PSP, %0" :: "r" (0));
return;
}
@@ -419,7 +428,7 @@ ULONG sp;
/* FUNCTION RELEASE */
/* */
/* _tx_thread_secure_stack_context_restore Cortex-M23/GNU */
-/* 6.1.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
@@ -438,9 +447,7 @@ ULONG sp;
/* */
/* CALLS */
/* */
-/* __get_IPSR Intrinsic to get IPSR */
-/* __set_PSPLIM Intrinsic to set PSP limit */
-/* __set_PSP Intrinsic to set PSP */
+/* None */
/* */
/* CALLED BY */
/* */
@@ -453,15 +460,20 @@ ULONG sp;
/* 09-30-2020 Scott Larson Initial Version 6.1 */
/* 10-16-2020 Scott Larson Modified comment(s), */
/* resulting in version 6.1.1 */
+/* 12-31-2020 Scott Larson Modified comment(s), and */
+/* fixed M23 GCC build, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
__attribute__((cmse_nonsecure_entry))
void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr)
{
TX_THREAD_SECURE_STACK_INFO *info_ptr;
+ULONG ipsr;
/* This function should be called from scheduler only. */
- if (__get_IPSR() == 0)
+ asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */
+ if (ipsr == 0)
{
return;
}
@@ -476,8 +488,8 @@ TX_THREAD_SECURE_STACK_INFO *info_ptr;
}
/* Set stack pointer and limit. */
- __set_PSPLIM((ULONG)info_ptr -> tx_thread_secure_stack_limit);
- __set_PSP ((ULONG)info_ptr -> tx_thread_secure_stack_ptr);
+ asm volatile("MSR PSPLIM, %0" :: "r" ((ULONG)info_ptr -> tx_thread_secure_stack_limit));
+ asm volatile("MSR PSP, %0" :: "r" ((ULONG)info_ptr -> tx_thread_secure_stack_ptr));
return;
}
diff --git a/ports/rxv2/ccrx/inc/tx_port.h b/ports/rxv2/ccrx/inc/tx_port.h
new file mode 100644
index 00000000..21931297
--- /dev/null
+++ b/ports/rxv2/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 RX/CCRX */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Express Logic, Inc. */
+/* */
+/* 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 */
+/* */
+/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#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 unsigned int 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 RX/CCRX Version 6.1.3 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
diff --git a/ports/rxv2/ccrx/readme_threadx.txt b/ports/rxv2/ccrx/readme_threadx.txt
new file mode 100644
index 00000000..c496fbb3
--- /dev/null
+++ b/ports/rxv2/ccrx/readme_threadx.txt
@@ -0,0 +1,175 @@
+ Microsoft's Azure RTOS ThreadX for Renesas RXv2
+
+ 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 RXv2.
+
+
+2. Demonstration System
+
+Please see the Samples repository on GitHub for the Azure RTOS demonstrations
+for the RXv2
+
+
+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 RXv2 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
+ 0x08 ACC1
+ 0x0C R6
+ 0x10 R7
+ 0x14 R8
+ 0x18 R9
+ 0x1C R10
+ 0x20 R11
+ 0x24 R12
+ 0x28 R13
+ 0x2C FPSW
+ 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 registers ACC0 and ACC1
+when entering an ISR. This means that if the ISR uses any of the DSP instructions the
+content of those registers could be corrupted. Saving and restoring of the acummulators
+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 RXv2 release make the following modifications:
+
+* Enable the following define for both the Threadx library and the application
+TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+* in tx_port.h, change around line 183
+change #define TX_THREAD_EXTENSION_3
+into #include "tx_execution_profile.h"
+
+* Setup CMT1 as a free running 16 bit timer.
+
+* In tx_execution_profile.h, change following around line 74:
+
+#ifdef TX_EXECUTION_64BIT_TIME
+typedef unsigned long long EXECUTION_TIME;
+#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
+ unsigned long long tx_thread_execution_time_last_start;
+#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFFFFFFFFFF
+#else
+typedef unsigned long EXECUTION_TIME;
+#define TX_THREAD_EXTENSION_3 unsigned long tx_thread_execution_time_total; \
+ unsigned long tx_thread_execution_time_last_start;
+#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:
+
+
+12-31-2020 Initial ThreadX release for the RXv2 using CC-RXX tools, version 6.1.3
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
+
+
+www.expresslogic.com \ No newline at end of file
diff --git a/ports/rxv2/ccrx/src/tx_initialize_low_level.src b/ports/rxv2/ccrx/src/tx_initialize_low_level.src
new file mode 100644
index 00000000..72b297bf
--- /dev/null
+++ b/ports/rxv2/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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+
+ .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/rxv2/ccrx/src/tx_thread_context_restore.src b/ports/rxv2/ccrx/src/tx_thread_context_restore.src
new file mode 100644
index 00000000..9601dfda
--- /dev/null
+++ b/ports/rxv2/ccrx/src/tx_thread_context_restore.src
@@ -0,0 +1,207 @@
+;/**************************************************************************/
+;/* */
+;/* 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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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:
+ POPC FPSW ; restore FPU status
+ 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
+ POPC FPSW ; restore FPU status
+ 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
+
+ MVFACGU #0, A1, R4 ; Save accumulators.
+ MVFACHI #0, A1, R5
+ MVFACLO #0, A1, R6
+ PUSHM R4-R6
+ MVFACGU #0, A0, R4
+ MVFACHI #0, A0, R5
+ MVFACLO #0, A0, R6
+ PUSHM R4-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/rxv2/ccrx/src/tx_thread_context_save.src b/ports/rxv2/ccrx/src/tx_thread_context_save.src
new file mode 100644
index 00000000..26e94078
--- /dev/null
+++ b/ports/rxv2/ccrx/src/tx_thread_context_save.src
@@ -0,0 +1,171 @@
+;/**************************************************************************/
+;/* */
+;/* 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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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
+ PUSHC FPSW ; (top) FPSW, R14, R15, R3, R4, R5, R1, R2, PC, PSW (bottom)
+ 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
+ MVFC FPSW, R3
+ MOV.L R3, [-R1] ; save FPSW 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/rxv2/ccrx/src/tx_thread_interrupt_control.src b/ports/rxv2/ccrx/src/tx_thread_interrupt_control.src
new file mode 100644
index 00000000..39168c1d
--- /dev/null
+++ b/ports/rxv2/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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/ccrx/src/tx_thread_schedule.src b/ports/rxv2/ccrx/src/tx_thread_schedule.src
new file mode 100644
index 00000000..a34c12f5
--- /dev/null
+++ b/ports/rxv2/ccrx/src/tx_thread_schedule.src
@@ -0,0 +1,180 @@
+;/**************************************************************************/
+;/* */
+;/* 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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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-R3 ; Restore accumulators.
+ MVTACLO R3, A0
+ MVTACHI R2, A0
+ MVTACGU R1, A0
+ POPM R1-R3
+ MVTACLO R3, A1
+ MVTACHI R2, A1
+ MVTACGU R1, A1
+
+ POPM R6-R13 ; Recover interrupt stack frame
+ POPC FPSW
+ 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/rxv2/ccrx/src/tx_thread_stack_build.src b/ports/rxv2/ccrx/src/tx_thread_stack_build.src
new file mode 100644
index 00000000..38da71c9
--- /dev/null
+++ b/ports/rxv2/ccrx/src/tx_thread_stack_build.src
@@ -0,0 +1,155 @@
+;/**************************************************************************/
+;/* */
+;/* 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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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
+; 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 ...
+ MVFC FPSW, r4
+ MOV.L R4, [-R3] ; initial FPSW
+ MOV.L #0, R4
+ 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 1
+ MOV.L R4,[-R3]
+ MOV.L R4,[-R3]
+
+ MOV.L R4,[-R3] ; Accumulator 0
+ MOV.L R4,[-R3]
+ 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/rxv2/ccrx/src/tx_thread_system_return.src b/ports/rxv2/ccrx/src/tx_thread_system_return.src
new file mode 100644
index 00000000..fb70a970
--- /dev/null
+++ b/ports/rxv2/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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/ccrx/src/tx_timer_interrupt.src b/ports/rxv2/ccrx/src/tx_timer_interrupt.src
new file mode 100644
index 00000000..cf88b6c1
--- /dev/null
+++ b/ports/rxv2/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 RX/CCRX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/gnu/inc/tx_port.h b/ports/rxv2/gnu/inc/tx_port.h
new file mode 100644
index 00000000..57841625
--- /dev/null
+++ b/ports/rxv2/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 RX/GNURX */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Express Logic, Inc. */
+/* */
+/* 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 */
+/* */
+/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+#include <string.h>
+//#include <intrinsics.h>
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 256 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#define TX_INLINE_INITIALIZATION
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+/* Define ThreadX interrupt lockout and restore macros for protection on
+ access of critical kernel information. The restore interrupt macro must
+ restore the interrupt posture of the running thread prior to the value
+ present prior to the disable macro. In most cases, the save area macro
+ is used to define a local function save area for the disable and restore
+ macros. */
+
+#ifdef TX_DISABLE_INLINE
+
+UINT _tx_thread_interrupt_disable(VOID);
+VOID _tx_thread_interrupt_restore(UINT previous_posture);
+
+#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
+
+#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA UCHAR interrupt_save;
+#define TX_DISABLE {interrupt_save = ((UCHAR)__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 RX/GNURX Version 6.1.3 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+#endif
+
diff --git a/ports/rxv2/gnu/readme_threadx.txt b/ports/rxv2/gnu/readme_threadx.txt
new file mode 100644
index 00000000..5baf5961
--- /dev/null
+++ b/ports/rxv2/gnu/readme_threadx.txt
@@ -0,0 +1,168 @@
+ Microsoft's Azure RTOS ThreadX for Renesas RXv2
+
+ 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 RXv2.
+
+
+2. Demonstration System
+
+
+Please see the Samples repository on GitHub for the Azure RTOS demonstrations
+for the RXv2.
+
+
+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 RXv2 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 RXv2 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
+ 0x08 ACC1
+ 0x0C R6
+ 0x10 R7
+ 0x14 R8
+ 0x18 R9
+ 0x1C R10
+ 0x20 R11
+ 0x24 R12
+ 0x28 R13
+ 0x2C FPSW
+ 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 registers ACC0 and ACC1
+when entering an ISR. This means that if the ISR uses any of the DSP instructions the
+content of those registers could be corrupted. Saving and restoring of the acummulators
+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 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 RXv2 release make the following modifications:
+
+* Enable the following define for both the Threadx library and the application
+TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+* in tx_port.h, change around line 183
+change #define TX_THREAD_EXTENSION_3
+into #include "tx_execution_profile.h"
+
+* Setup CMT1 as a free running 16 bit timer.
+
+* In tx_execution_profile.h, change following around line 74:
+
+#ifdef TX_EXECUTION_64BIT_TIME
+typedef unsigned long long EXECUTION_TIME;
+#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
+ unsigned long long tx_thread_execution_time_last_start;
+#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFFFFFFFFFF
+#else
+typedef unsigned long EXECUTION_TIME;
+#define TX_THREAD_EXTENSION_3 unsigned long tx_thread_execution_time_total; \
+ unsigned long tx_thread_execution_time_last_start;
+#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:
+
+
+12-31-2020 Initial ThreadX release for the RXv2 using GNURX tools, version 6.1.3
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports/rxv2/gnu/src/tx_initialize_low_level.S b/ports/rxv2/gnu/src/tx_initialize_low_level.S
new file mode 100644
index 00000000..197ae936
--- /dev/null
+++ b/ports/rxv2/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 RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+ .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/rxv2/gnu/src/tx_thread_context_restore.S b/ports/rxv2/gnu/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..c2799838
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,207 @@
+;/**************************************************************************/
+;/* */
+;/* 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 RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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:
+ POPC FPSW ; restore FPU status
+ 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
+ POPC FPSW ; restore FPU status
+ 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
+
+ MVFACGU #0, A1, R4 ; Save accumulators.
+ MVFACHI #0, A1, R5
+ MVFACLO #0, A1, R6
+ PUSHM R4-R6
+ MVFACGU #0, A0, R4
+ MVFACHI #0, A0, R5
+ MVFACLO #0, A0, R6
+ PUSHM R4-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/rxv2/gnu/src/tx_thread_context_save.S b/ports/rxv2/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..cae38615
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,171 @@
+;/**************************************************************************/
+;/* */
+;/* 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
+
+ .text
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_context_save RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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
+ PUSHC FPSW ; (top) FPSW, R14, R15, R3, R4, R5, R1, R2, PC, PSW (bottom)
+ 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
+ MVFC FPSW, R3
+ MOV.L R3, [-R1] ; save FPSW 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/rxv2/gnu/src/tx_thread_interrupt_control.S b/ports/rxv2/gnu/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..096c0568
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_thread_interrupt_control.S
@@ -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"
+;
+;
+ .text
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_interrupt_control RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/gnu/src/tx_thread_schedule.S b/ports/rxv2/gnu/src/tx_thread_schedule.S
new file mode 100644
index 00000000..c48840e7
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,180 @@
+;/**************************************************************************/
+;/* */
+;/* 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_execute_ptr
+ .global __tx_thread_current_ptr
+ .global __tx_timer_time_slice
+;
+ .text
+
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_schedule RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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-R3 ; Restore accumulators.
+ MVTACLO R3, A0
+ MVTACHI R2, A0
+ MVTACGU R1, A0
+ POPM R1-R3
+ MVTACLO R3, A1
+ MVTACHI R2, A1
+ MVTACGU R1, A1
+
+ POPM R6-R13 ; Recover interrupt stack frame
+ POPC FPSW
+ 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/rxv2/gnu/src/tx_thread_stack_build.S b/ports/rxv2/gnu/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..752372bf
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,155 @@
+;/**************************************************************************/
+;/* */
+;/* 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"
+;
+;
+ .text
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_stack_build RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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 ...
+ MVFC FPSW, r4
+ MOV.L R4, [-R3] ; initial FPSW
+ MOV.L #0, R4
+ 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 1
+ MOV.L R4,[-R3]
+ MOV.L R4,[-R3]
+
+ MOV.L R4,[-R3] ; Accumulator 0
+ MOV.L R4,[-R3]
+ 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/rxv2/gnu/src/tx_thread_system_return.S b/ports/rxv2/gnu/src/tx_thread_system_return.S
new file mode 100644
index 00000000..baa5314a
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_thread_system_return.S
@@ -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"
+;
+;
+ .global __tx_thread_current_ptr
+ .global __tx_timer_time_slice
+ .global __tx_thread_schedule
+
+ .text
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_system_return RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/gnu/src/tx_timer_interrupt.S b/ports/rxv2/gnu/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..3511e2c8
--- /dev/null
+++ b/ports/rxv2/gnu/src/tx_timer_interrupt.S
@@ -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...
+;
+ .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 RX/GNURX */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/iar/inc/tx_port.h b/ports/rxv2/iar/inc/tx_port.h
new file mode 100644
index 00000000..14b9728f
--- /dev/null
+++ b/ports/rxv2/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 RX/IAR */
+/* 6.1.3 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Express Logic, Inc. */
+/* */
+/* 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 */
+/* */
+/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+#include <string.h>
+#include <intrinsics.h>
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 256 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#define TX_INLINE_INITIALIZATION
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+/* Define ThreadX interrupt lockout and restore macros for protection on
+ access of critical kernel information. The restore interrupt macro must
+ restore the interrupt posture of the running thread prior to the value
+ present prior to the disable macro. In most cases, the save area macro
+ is used to define a local function save area for the disable and restore
+ macros. */
+
+#ifdef TX_DISABLE_INLINE
+
+UINT _tx_thread_interrupt_disable(VOID);
+VOID _tx_thread_interrupt_restore(UINT previous_posture);
+
+#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
+
+#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
+
+#else
+
+#define TX_INTERRUPT_SAVE_AREA __istate_t interrupt_save;
+#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();};
+#define TX_RESTORE {__set_interrupt_state(interrupt_save);};
+
+#define _tx_thread_system_return _tx_thread_system_return_inline
+
+static void _tx_thread_system_return_inline(void)
+{
+ TX_INTERRUPT_SAVE_AREA
+
+ TX_DISABLE
+
+ *((volatile UCHAR *)(0x872E0u)) = 1u;
+
+ TX_RESTORE
+}
+
+#endif
+
+
+#ifndef TX_THREAD_GET_SYSTEM_STATE
+
+extern volatile ULONG _tx_thread_system_state;
+#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | ((~__get_PSW_register()) & (1u << 17u)))
+#endif
+
+
+
+/* Define the interrupt lockout macros for each ThreadX object. */
+
+#define TX_BLOCK_POOL_DISABLE TX_DISABLE
+#define TX_BYTE_POOL_DISABLE TX_DISABLE
+#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
+#define TX_MUTEX_DISABLE TX_DISABLE
+#define TX_QUEUE_DISABLE TX_DISABLE
+#define TX_SEMAPHORE_DISABLE TX_DISABLE
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX RX/IAR Version 6.1.3 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
diff --git a/ports/rxv2/iar/readme_threadx.txt b/ports/rxv2/iar/readme_threadx.txt
new file mode 100644
index 00000000..0c0afd29
--- /dev/null
+++ b/ports/rxv2/iar/readme_threadx.txt
@@ -0,0 +1,163 @@
+ Microsoft's Azure RTOS ThreadX for Renesas RXv2
+
+ 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 RXv2.
+
+
+2. Demonstration System
+
+Please see the Samples repository on GitHub for the Azure RTOS demonstrations
+for the RXv2.
+
+
+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 RXv2 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 RXv2 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
+ 0x08 ACC1
+ 0x0C R6
+ 0x10 R7
+ 0x14 R8
+ 0x18 R9
+ 0x1C R10
+ 0x20 R11
+ 0x24 R12
+ 0x28 R13
+ 0x2C FPSW
+ 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 registers ACC0 and ACC1
+when entering an ISR. This means that if the ISR uses any of the DSP instructions the
+content of those registers could be corrupted. Saving and restoring of the acummulators
+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 RXv2 release make the following modifications:
+
+* Enable the following define for both the Threadx library and the application
+TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+* in tx_port.h, change around line 183
+change #define TX_THREAD_EXTENSION_3
+into #include "tx_execution_profile.h"
+
+* Setup CMT1 as a free running 16 bit timer.
+
+* In tx_execution_profile.h, change following around line 74:
+
+#ifdef TX_EXECUTION_64BIT_TIME
+typedef unsigned long long EXECUTION_TIME;
+#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
+ unsigned long long tx_thread_execution_time_last_start;
+#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFFFFFFFFFF
+#else
+typedef unsigned long EXECUTION_TIME;
+#define TX_THREAD_EXTENSION_3 unsigned long tx_thread_execution_time_total; \
+ unsigned long tx_thread_execution_time_last_start;
+#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:
+
+12-31-2020 Initial ThreadX release for the RXv2using IAR tools, version 6.1.3
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos \ No newline at end of file
diff --git a/ports/rxv2/iar/src/tx_initialize_low_level.s b/ports/rxv2/iar/src/tx_initialize_low_level.s
new file mode 100644
index 00000000..49336a57
--- /dev/null
+++ b/ports/rxv2/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 RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+ 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/rxv2/iar/src/tx_thread_context_restore.s b/ports/rxv2/iar/src/tx_thread_context_restore.s
new file mode 100644
index 00000000..491dae82
--- /dev/null
+++ b/ports/rxv2/iar/src/tx_thread_context_restore.s
@@ -0,0 +1,205 @@
+;/**************************************************************************/
+;/* */
+;/* 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"
+;
+;
+ 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 RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+ 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:
+ POPC FPSW ; restore FPU status
+ 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
+ POPC FPSW ; restore FPU status
+ 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
+
+ MVFACGU #0, A1, R4 ; Save accumulators.
+ MVFACHI #0, A1, R5
+ MVFACLO #0, A1, R6
+ PUSHM R4-R6
+ MVFACGU #0, A0, R4
+ MVFACHI #0, A0, R5
+ MVFACLO #0, A0, R6
+ PUSHM R4-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/rxv2/iar/src/tx_thread_context_save.s b/ports/rxv2/iar/src/tx_thread_context_save.s
new file mode 100644
index 00000000..218f65cd
--- /dev/null
+++ b/ports/rxv2/iar/src/tx_thread_context_save.s
@@ -0,0 +1,170 @@
+;/**************************************************************************/
+;/* */
+;/* 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"
+;
+ extern __tx_thread_system_state
+ extern __tx_thread_current_ptr
+
+ section .text:CODE:ROOT
+ ;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_context_save RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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
+ PUSHC FPSW ; (top) FPSW, R14, R15, R3, R4, R5, R1, R2, PC, PSW (bottom)
+ 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
+ MVFC FPSW, R3
+ MOV.L R3, [-R1] ; save FPSW 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/rxv2/iar/src/tx_thread_interrupt_control.s b/ports/rxv2/iar/src/tx_thread_interrupt_control.s
new file mode 100644
index 00000000..bd8474df
--- /dev/null
+++ b/ports/rxv2/iar/src/tx_thread_interrupt_control.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 */
+;/** */
+;/** Thread */
+;/** */
+;/**************************************************************************/
+;/**************************************************************************/
+;
+;#define TX_SOURCE_CODE
+;
+;
+;/* Include necessary system files. */
+;
+;#include "tx_api.h"
+;#include "tx_thread.h"
+;
+ section .text:CODE:ROOT
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_interrupt_control RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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/rxv2/iar/src/tx_thread_schedule.s b/ports/rxv2/iar/src/tx_thread_schedule.s
new file mode 100644
index 00000000..9de14be1
--- /dev/null
+++ b/ports/rxv2/iar/src/tx_thread_schedule.s
@@ -0,0 +1,179 @@
+;/**************************************************************************/
+;/* */
+;/* 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"
+;
+;
+ extern __tx_thread_execute_ptr
+ extern __tx_thread_current_ptr
+ extern __tx_timer_time_slice
+
+ section .text:CODE:ROOT
+
+;/**************************************************************************/
+;/* */
+;/* FUNCTION RELEASE */
+;/* */
+;/* _tx_thread_schedule RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+;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-R3 ; Restore accumulators.
+ MVTACLO R3, A0
+ MVTACHI R2, A0
+ MVTACGU R1, A0
+ POPM R1-R3
+ MVTACLO R3, A1
+ MVTACHI R2, A1
+ MVTACGU R1, A1
+
+ POPM R6-R13 ; Recover interrupt stack frame
+ POPC FPSW
+ 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/rxv2/iar/src/tx_thread_stack_build.s b/ports/rxv2/iar/src/tx_thread_stack_build.s
new file mode 100644
index 00000000..688f0bc8
--- /dev/null
+++ b/ports/rxv2/iar/src/tx_thread_stack_build.s
@@ -0,0 +1,147 @@
+;/**************************************************************************/
+;/* */
+;/* 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 RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+
+ 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
+; 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 ...
+ MVFC FPSW, r4
+ MOV.L R4, [-R3] ; initial FPSW
+ MOV.L #0, R4
+ 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 1
+ MOV.L R4,[-R3]
+ MOV.L R4,[-R3]
+
+ MOV.L R4,[-R3] ; Accumulator 0
+ MOV.L R4,[-R3]
+ 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/rxv2/iar/src/tx_thread_system_return.s b/ports/rxv2/iar/src/tx_thread_system_return.s
new file mode 100644
index 00000000..808e345e
--- /dev/null
+++ b/ports/rxv2/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 RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+
+ public __tx_thread_system_return
+
+__tx_thread_system_return:
+
+ BRA __tx_thread_system_return
+
+ RTS
+
+ END
diff --git a/ports/rxv2/iar/src/tx_timer_interrupt.s b/ports/rxv2/iar/src/tx_timer_interrupt.s
new file mode 100644
index 00000000..645f73b4
--- /dev/null
+++ b/ports/rxv2/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 RX/IAR */
+;/* 6.1.3 */
+;/* 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 */
+;/* */
+;/* 12-31-2020 William E. Lamie Initial Version 6.1.3 */
+;/* */
+;/**************************************************************************/
+
+ 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
diff --git a/ports/xtensa/xcc/CMakeLists.txt b/ports/xtensa/xcc/CMakeLists.txt
new file mode 100644
index 00000000..31768e58
--- /dev/null
+++ b/ports/xtensa/xcc/CMakeLists.txt
@@ -0,0 +1,36 @@
+
+target_sources(${PROJECT_NAME}
+ PRIVATE
+ # {{BEGIN_TARGET_SOURCES}}
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_clib_lock.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/tx_xtensa_stack_error_handler.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_context.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_coproc_handler.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_init.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_intr_asm.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_intr.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_intr_wrapper.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_overlay_os_hook.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_vectors.S
+ ${CMAKE_CURRENT_LIST_DIR}/src/xtensa_vectors_xea3.S
+
+ # {{END_TARGET_SOURCES}}
+)
+
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/inc
+)
+
+set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/src/xtensa_vectors_xea3.S
+ TARGET_DIRECTORY ${PROJECT_NAME}
+ PROPERTIES COMPILE_OPTIONS "-mtext-section-literals")
+
diff --git a/ports/xtensa/xcc/example_build/demo_threadx.c b/ports/xtensa/xcc/example_build/demo_threadx.c
new file mode 100644
index 00000000..5bec9cc8
--- /dev/null
+++ b/ports/xtensa/xcc/example_build/demo_threadx.c
@@ -0,0 +1,377 @@
+/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
+ threads of different priorities, using a message queue, semaphore, mutex, event flags group,
+ byte pool, and block pool. */
+
+#include <stdio.h>
+#include <xtensa/xtutil.h>
+
+#include "tx_api.h"
+
+#define DEMO_STACK_SIZE 1024
+#define DEMO_BYTE_POOL_SIZE 9120
+#define DEMO_BLOCK_POOL_SIZE 100
+#define DEMO_QUEUE_SIZE 100
+
+
+/* Define the ThreadX object control blocks... */
+
+TX_THREAD thread_0;
+TX_THREAD thread_1;
+TX_THREAD thread_2;
+TX_THREAD thread_3;
+TX_THREAD thread_4;
+TX_THREAD thread_5;
+TX_THREAD thread_6;
+TX_THREAD thread_7;
+TX_QUEUE queue_0;
+TX_SEMAPHORE semaphore_0;
+TX_MUTEX mutex_0;
+TX_EVENT_FLAGS_GROUP event_flags_0;
+TX_BYTE_POOL byte_pool_0;
+TX_BLOCK_POOL block_pool_0;
+UCHAR memory_area[DEMO_BYTE_POOL_SIZE];
+
+
+/* Define the counters used in the demo application... */
+
+ULONG thread_0_counter;
+ULONG thread_1_counter;
+ULONG thread_1_messages_sent;
+ULONG thread_2_counter;
+ULONG thread_2_messages_received;
+ULONG thread_3_counter;
+ULONG thread_4_counter;
+ULONG thread_5_counter;
+ULONG thread_6_counter;
+ULONG thread_7_counter;
+
+
+/* Define thread prototypes. */
+
+void thread_0_entry(ULONG thread_input);
+void thread_1_entry(ULONG thread_input);
+void thread_2_entry(ULONG thread_input);
+void thread_3_and_4_entry(ULONG thread_input);
+void thread_5_entry(ULONG thread_input);
+void thread_6_and_7_entry(ULONG thread_input);
+
+
+/* Define main entry point. */
+
+int main()
+{
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+CHAR *pointer = TX_NULL;
+
+
+ /* Create a byte memory pool from which to allocate the thread stacks. */
+ tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE);
+
+ /* Put system definition stuff in here, e.g. thread creates and other assorted
+ create information. */
+
+ /* Allocate the stack for thread 0. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create the main thread. */
+ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
+ pointer, DEMO_STACK_SIZE,
+ 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+
+ /* Allocate the stack for thread 1. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 1 and 2. These threads pass information through a ThreadX
+ message queue. It is also interesting to note that these threads have a time
+ slice. */
+ tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
+ pointer, DEMO_STACK_SIZE,
+ 16, 16, 4, TX_AUTO_START);
+
+ /* Allocate the stack for thread 2. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
+ pointer, DEMO_STACK_SIZE,
+ 16, 16, 4, TX_AUTO_START);
+
+ /* Allocate the stack for thread 3. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
+ An interesting thing here is that both threads share the same instruction area. */
+ tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 4. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 5. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create thread 5. This thread simply pends on an event flag which will be set
+ by thread_0. */
+ tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
+ pointer, DEMO_STACK_SIZE,
+ 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 6. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
+ tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 7. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the message queue. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
+
+ /* Create the message queue shared by threads 1 and 2. */
+ tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
+
+ /* Create the semaphore used by threads 3 and 4. */
+ tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
+
+ /* Create the event flags group used by threads 1 and 5. */
+ tx_event_flags_create(&event_flags_0, "event flags 0");
+
+ /* Create the mutex used by thread 6 and 7 without priority inheritance. */
+ tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
+
+ /* Allocate the memory for a small block pool. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
+
+ /* Create a block memory pool to allocate a message buffer from. */
+ tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
+
+ /* Allocate a block and release the block memory. */
+ tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
+
+ /* Release the block back to the pool. */
+ tx_block_release(pointer);
+}
+
+
+
+/* Define the test threads. */
+
+void thread_0_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This thread simply sits in while-forever-sleep loop. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_0_counter++;
+
+ /* Sleep for 10 ticks. */
+ tx_thread_sleep(10);
+
+ /* Set event flag 0 to wakeup thread 5. */
+ status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Print something to show we are making progress. This should use the print
+ function from libxtutil which is thread-safe. */
+ printf("%u %u %u\n", thread_0_counter, thread_1_counter, thread_2_counter);
+ }
+}
+
+
+void thread_1_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This thread simply sends messages to a queue shared by thread 2. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_1_counter++;
+
+ /* Send message to queue 0. */
+ status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
+
+ /* Check completion status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Increment the message sent. */
+ thread_1_messages_sent++;
+ }
+}
+
+
+void thread_2_entry(ULONG thread_input)
+{
+
+ULONG received_message;
+UINT status;
+
+ /* This thread retrieves messages placed on the queue by thread 1. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_2_counter++;
+
+ /* Retrieve a message from the queue. */
+ status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
+
+ /* Check completion status and make sure the message is what we
+ expected. */
+ if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
+ break;
+
+ /* Otherwise, all is okay. Increment the received message count. */
+ thread_2_messages_received++;
+ }
+}
+
+
+void thread_3_and_4_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This function is executed from thread 3 and thread 4. As the loop
+ below shows, these function compete for ownership of semaphore_0. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ if (thread_input == 3)
+ thread_3_counter++;
+ else
+ thread_4_counter++;
+
+ /* Get the semaphore with suspension. */
+ status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Sleep for 2 ticks to hold the semaphore. */
+ tx_thread_sleep(2);
+
+ /* Release the semaphore. */
+ status = tx_semaphore_put(&semaphore_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
+
+
+void thread_5_entry(ULONG thread_input)
+{
+
+UINT status;
+ULONG actual_flags;
+
+
+ /* This thread simply waits for an event in a forever loop. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_5_counter++;
+
+ /* Wait for event flag 0. */
+ status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
+ &actual_flags, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if ((status != TX_SUCCESS) || (actual_flags != 0x1))
+ break;
+ }
+}
+
+
+void thread_6_and_7_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This function is executed from thread 6 and thread 7. As the loop
+ below shows, these function compete for ownership of mutex_0. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ if (thread_input == 6)
+ thread_6_counter++;
+ else
+ thread_7_counter++;
+
+ /* Get the mutex with suspension. */
+ status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Get the mutex again with suspension. This shows
+ that an owning thread may retrieve the mutex it
+ owns multiple times. */
+ status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Sleep for 2 ticks to hold the mutex. */
+ tx_thread_sleep(2);
+
+ /* Release the mutex. */
+ status = tx_mutex_put(&mutex_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Release the mutex again. This will actually
+ release ownership since it was obtained twice. */
+ status = tx_mutex_put(&mutex_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
diff --git a/ports/xtensa/xcc/inc/tx_api_asm.h b/ports/xtensa/xcc/inc/tx_api_asm.h
new file mode 100644
index 00000000..1840ffce
--- /dev/null
+++ b/ports/xtensa/xcc/inc/tx_api_asm.h
@@ -0,0 +1,67 @@
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains macro constants for ThreadX API structures */
+/* and enums that need to be used in assembly coded port sources. */
+/* Most of these constants are derived from definitions in tx_api.h. */
+/* Only the constants that are needed are included here to reduce */
+/* the maintenance required when the structures or enums change. */
+/* Structure offsets depend on the compiler, so are tools-specific, */
+/* which usually means port-specific since a compiler's struct */
+/* packing rules depend on properties of the target architecture. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_API_ASM_H
+#define TX_API_ASM_H
+
+#include "tx_port.h"
+
+/* API input parameters and general constants. */
+
+#define TX_TRUE 1
+#define TX_FALSE 0
+#define TX_NULL 0
+
+/* ThreadX thread control block structure. */
+// typedef struct TX_THREAD_STRUCT
+// {
+
+#define tx_thread_run_count 0x04
+#define tx_thread_stack_ptr 0x08
+#define tx_thread_stack_end 0x10
+#define tx_thread_time_slice 0x18
+#define tx_thread_new_time_slice 0x1C
+#define tx_thread_solicited 0x28
+
+#ifdef TX_THREAD_SAFE_CLIB
+ #define tx_real_thread_entry 0x2C
+ #define tx_thread_clib_ptr 0x30
+ #define tx_thread_cp_state 0x34
+#else
+ #define tx_thread_cp_state 0x2C
+#endif
+
+// }
+
+#endif /* TX_API_ASM_H */
+
diff --git a/ports/xtensa/xcc/inc/tx_port.h b/ports/xtensa/xcc/inc/tx_port.h
new file mode 100644
index 00000000..9438a7c8
--- /dev/null
+++ b/ports/xtensa/xcc/inc/tx_port.h
@@ -0,0 +1,479 @@
+
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* 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 */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#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
+#include "tx_user.h"
+#endif
+
+/* Comment this out to disable thread-safe C library support. */
+#define TX_THREAD_SAFE_CLIB 1
+
+/* Include the glue to Xtensa-generic parts of this ThreadX port. */
+#include "xtensa_rtos.h"
+
+/* Parts of this file should not been seen by assembler sources. */
+#ifndef __ASSEMBLER__
+
+/* Some generic C sources call memset() and need this (else compiler warns).
+ Until the generic sources take care of this, do it here. */
+
+#include <string.h>
+
+
+/* Define compiler library include files and library-specific macros. */
+
+/*
+ Thread-safety support for the supported C libraries. At this time
+ only the newlib and Xtensa C libraries are supported.
+
+ The C library reent structure can be quite large so it is placed
+ at the end of TX_THREAD, and a pointer to it is defined near the
+ beginning of TX_THREAD where assembly code can easily get to it
+ at a fixed offset.
+*/
+
+#ifdef TX_THREAD_SAFE_CLIB
+struct TX_THREAD_STRUCT;
+
+extern char *_tx_clib_heap_start, *_tx_clib_heap_end;
+extern void _tx_clib_reent_init (struct TX_THREAD_STRUCT *thread_ptr);
+extern void _tx_clib_reent_cleanup (struct TX_THREAD_STRUCT *thread_ptr, int partial);
+extern void _tx_clib_thread_setup(struct TX_THREAD_STRUCT *thread_ptr);
+
+#include <sys/reent.h>
+
+#define TX_CLIB_THREAD_EXTENSION \
+ VOID (*tx_real_thread_entry)(ULONG id); /* Actual entry point */ \
+ struct _reent * tx_thread_clib_ptr; /* C lib reentrancy ptr */
+#define TX_CLIB_THREAD_EXTENSION_END \
+ struct _reent tx_thread_clib_reent; /* C lib reentrancy struct */
+#define TX_CLIB_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_CLIB_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_CLIB_THREAD_EXIT_EXTENSION(thread_ptr)
+#define TX_THREAD_CLIB_EXTENSION(thread_ptr) \
+ _tx_clib_thread_setup(thread_ptr);
+#else
+#define TX_CLIB_THREAD_EXTENSION
+#define TX_CLIB_THREAD_EXTENSION_END
+#define TX_CLIB_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_CLIB_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_CLIB_THREAD_EXIT_EXTENSION(thread_ptr)
+#define TX_THREAD_CLIB_EXTENSION(thread_ptr)
+#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;
+
+
+#endif /* #ifndef __ASSEMBLER__ */
+
+
+/* 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 size for a thread on this processor.
+ If the size supplied during thread creation is less than TX_MINIMUM_STACK,
+ the thread create call will return an error. The minimum allows for a
+ thread whose entry function makes no calls and needs no local frame.
+ TX_MINIMUM_STACK_BASIC allows the entry function to at least call
+ tx_thread_relinquish(). An extra 0x10 bytes is allowed in all cases to
+ allow for stack pointer alignment to 16 bytes. There is an additional premium
+ for the stack checking functionality of TX_ENABLE_STACK_CHECKING.
+ In Xtensa, all these amounts depend on the function call ABI used by the
+ configuration (in general, Call0 ABI needs about 0x20 bytes less stack space
+ per function call frame). These amounts assume no compiler optimization (-O0).
+ Optimization usually requires less stack.
+
+ TX_MINIMUM_STACK_BASIC is a MINIMUM for threads that call tx_thread_relinquish()
+ only. Threads that do more, and in particular call C library functions such as
+ printf(), need much more stack space and it is up to the application developer
+ to determine how much.
+*/
+
+#ifdef __XTENSA_CALL0_ABI__
+ /* Call0 ABI */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK (XT_STK_FRMSZ + 0x10)
+#endif
+#ifdef TX_ENABLE_STACK_CHECKING
+#define TX_STACK_CHECK_PREMIUM 0x30
+#else
+#define TX_STACK_CHECK_PREMIUM 0
+#endif
+#ifndef TX_MINIMUM_STACK_BASIC
+#define TX_MINIMUM_STACK_BASIC (XT_STK_FRMSZ + 0x70 + TX_STACK_CHECK_PREMIUM)
+#endif
+
+#else /* Windowed ABI */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK (XT_STK_FRMSZ + 0x20)
+#endif
+#ifdef TX_ENABLE_STACK_CHECKING
+#define TX_STACK_CHECK_PREMIUM 0x50
+#else
+#define TX_STACK_CHECK_PREMIUM 0
+#endif
+#ifndef TX_MINIMUM_STACK_BASIC
+#define TX_MINIMUM_STACK_BASIC (XT_STK_FRMSZ + 0x100 + TX_STACK_CHECK_PREMIUM)
+#endif
+
+#endif
+
+/*
+ Minimum stack size for the ThreadX system stack on this processor.
+ This is just a useful starting point for an application, it is not
+ checked by ThreadX. The minimum system stack size allows for the
+ possible depth of interrupt nesting (XCHAL_EXCM_LEVEL-1 interrupt
+ stack frames and XCHAL_EXCM_LEVEL interrupt handlers including timer),
+ assuming very basic interrupt handlers (allows 1 call12). It needs to
+ be increased to support the application's real interrupt handlers (and
+ timer interrupt if TX_TIMER_PROCESS_IN_ISR). The system stack is located
+ where the stack pointer is inside tx_kernel_enter() which is usually from
+ main(), and so is determined by the development tools. It grows downward
+ toward the first available memory pointer passed to tx_application_define().
+ An application should allow sufficient space for the system stack.
+
+ For XEA3, allow a minimum of XCHAL_NUM_INTLEVELS nested interrupts. The stack
+ frames are minimal-sized and may need to be increased to support real applications.
+*/
+
+#if XCHAL_HAVE_XEA3
+#define TX_SYSTEM_STACK_MINIMUM (XCHAL_NUM_INTLEVELS * 0x40)
+#ifndef TX_SYSTEM_STACK_SIZE
+#if TX_SYSTEM_STACK_MINIMUM > 2048
+#define TX_SYSTEM_STACK_SIZE TX_SYSTEM_STACK_MINIMUM
+#else
+#define TX_SYSTEM_STACK_SIZE 2048
+#endif
+#endif
+#else
+#define TX_SYSTEM_STACK_MINIMUM (((XCHAL_EXCM_LEVEL-1) * (0x40 + XT_STK_FRMSZ)) + 0x40)
+#ifndef TX_SYSTEM_STACK_SIZE
+#define TX_SYSTEM_STACK_SIZE 4096
+#endif
+#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
+#ifdef __XTENSA_CALL0_ABI__
+#define TX_TIMER_THREAD_STACK_SIZE (TX_MINIMUM_STACK_BASIC + 0x100)
+#else
+#define TX_TIMER_THREAD_STACK_SIZE (TX_MINIMUM_STACK_BASIC + 0x200)
+#endif
+#endif
+
+
+/* Parts of this file should not been seen by assembler sources. */
+#ifndef __ASSEMBLER__
+
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX Xtensa port. */
+
+#if XCHAL_HAVE_XEA3
+#define TX_INT_DISABLE 0x8 /* Disable interrupts value */
+#define TX_INT_ENABLE 0x0 /* Enable interrupt value */
+#else
+#define TX_INT_DISABLE XCHAL_EXCM_LEVEL /* Disable interrupts value */
+#define TX_INT_ENABLE 0x0 /* Enable interrupt value */
+#endif
+
+
+/*
+ Define the clock source for trace event entry time stamp. The following
+ two item are port specific. For example, if the time source is at the
+ address 0x0a800024 and is 16-bits in size, the clock source constants
+ would be:
+
+ #define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+ #define TX_TRACE_TIME_MASK 0x0000FFFFUL
+*/
+
+#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.
+*/
+
+#if defined(XT_SIMULATOR) || !defined(XT_BOARD)
+#define TX_XT_OPT_SIMULATOR (1UL << 0)
+#else
+#define TX_XT_OPT_SIMULATOR 0
+#endif
+
+#if defined(XT_BOARD)
+#define TX_XT_OPT_BOARD (1UL << 1)
+#else
+#define TX_XT_OPT_BOARD 0
+#endif
+
+#if defined(XT_INTEXC_HOOKS)
+#define TX_XT_OPT_INTEXC_HOOKS (1UL << 2)
+#else
+#define TX_XT_OPT_INTEXC_HOOKS 0
+#endif
+
+#if defined(TX_THREAD_SAFE_CLIB)
+#define TX_XT_OPT_CLIB (1UL << 3)
+#else
+#define TX_XT_OPT_CLIB 0
+#endif
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS (TX_XT_OPT_SIMULATOR | TX_XT_OPT_BOARD \
+ | TX_XT_OPT_INTEXC_HOOKS | TX_XT_OPT_CLIB)
+
+
+/*
+ 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 enabled (TX_ENABLE_STACK_CHECKING is defined),
+ the TX_DISABLE_STACK_FILLING define is canceled, 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.
+*/
+
+#if XCHAL_CP_NUM > 0
+#define TX_CP_THREAD_EXTENSION \
+ /* Co-proc state save areas, with padding for alignment: */ \
+ UINT tx_thread_cp_state[(XT_CP_SIZE+3)/4];
+#else
+#define TX_CP_THREAD_EXTENSION
+#endif
+
+#define TX_THREAD_EXTENSION_0 \
+ /* These extensions needs to be accessed from assembly code at context switches */ \
+ UINT tx_thread_solicited; /* Non-zero indicates solicited entry */ \
+ TX_CLIB_THREAD_EXTENSION /* Ptr to C library re-ent struct */ \
+ TX_CP_THREAD_EXTENSION /* Coprocessor state save areas */
+
+#define TX_THREAD_EXTENSION_1 \
+ TX_CLIB_THREAD_EXTENSION_END
+
+#define TX_THREAD_EXTENSION_2
+
+/* Execution profile related */
+#define TX_THREAD_EXTENSION_3 \
+ unsigned long long tx_thread_execution_time_total; \
+ unsigned long tx_thread_execution_time_last_start;
+
+
+/* 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. */
+
+#if XCHAL_CP_NUM > 0
+extern void _xt_coproc_release(void * coproc_sa_base);
+
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr) \
+ _xt_coproc_release(&thread_ptr->tx_thread_cp_state);
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) \
+ _xt_coproc_release(&thread_ptr->tx_thread_cp_state);
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) \
+ _xt_coproc_release(&thread_ptr->tx_thread_cp_state);
+#define TX_THREAD_CP_EXTENSION(thread_ptr) \
+ /* Initialize XT_CP_ASA ptr to aligned save area: */ \
+ /* NOTE: keep this matched with xtensa_context.h. */ \
+ thread_ptr->tx_thread_cp_state[0] = 0; \
+ thread_ptr->tx_thread_cp_state[1] = 0; \
+ thread_ptr->tx_thread_cp_state[2] = \
+ ((((UINT)thread_ptr->tx_thread_cp_state)+12+XCHAL_TOTAL_SA_ALIGN-1) \
+ & -XCHAL_TOTAL_SA_ALIGN);
+#else
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_CP_EXTENSION(thread_ptr)
+#endif
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr) \
+ TX_THREAD_CLIB_EXTENSION(thread_ptr) \
+ TX_THREAD_CP_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.
+*/
+
+extern unsigned int _tx_thread_interrupt_control(unsigned int new_posture);
+
+#define TX_INTERRUPT_SAVE_AREA register unsigned int interrupt_save;
+
+#ifdef TX_DISABLE_INLINE_MACROS
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
+#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
+#else
+#define TX_DISABLE interrupt_save = xthal_disable_interrupts();
+#define TX_RESTORE xthal_restore_interrupts(interrupt_save);
+#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
+
+
+#if XCHAL_HAVE_XEA3
+/* Variables that keep track of the timer and software interrupt numbers in use. */
+extern int xt_sw_intnum;
+extern int xt_timer_intnum;
+#endif
+
+
+/* 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. * Azure RTOS Xtensa Version 6.1.3 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+#endif /* #ifndef __ASSEMBLER__ */
+
+#endif
+
diff --git a/ports/xtensa/xcc/inc/tx_user.h b/ports/xtensa/xcc/inc/tx_user.h
new file mode 100644
index 00000000..db17d428
--- /dev/null
+++ b/ports/xtensa/xcc/inc/tx_user.h
@@ -0,0 +1,257 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/** User Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_user.h PORTABLE C */
+/* 6.0.1 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains user defines for configuring ThreadX in specific */
+/* ways. This file will have an effect only if the application and */
+/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */
+/* Note that all the defines in this file may also be made on the */
+/* command line when building ThreadX library and application objects. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_USER_H
+#define TX_USER_H
+
+
+/* Define various build options for the ThreadX port. The application should either make changes
+ here by commenting or un-commenting the conditional compilation defined OR supply the defines
+ though the compiler's equivalent of the -D option.
+
+ For maximum speed, the following should be defined:
+
+ TX_MAX_PRIORITIES 32
+ TX_DISABLE_PREEMPTION_THRESHOLD
+ TX_DISABLE_REDUNDANT_CLEARING
+ TX_DISABLE_NOTIFY_CALLBACKS
+ TX_NOT_INTERRUPTABLE
+ TX_TIMER_PROCESS_IN_ISR
+ TX_REACTIVATE_INLINE
+ TX_DISABLE_STACK_FILLING
+ TX_INLINE_THREAD_RESUME_SUSPEND
+
+ For minimum size, the following should be defined:
+
+ TX_MAX_PRIORITIES 32
+ TX_DISABLE_PREEMPTION_THRESHOLD
+ TX_DISABLE_REDUNDANT_CLEARING
+ TX_DISABLE_NOTIFY_CALLBACKS
+ TX_NOT_INTERRUPTABLE
+ TX_TIMER_PROCESS_IN_ISR
+
+ Of course, many of these defines reduce functionality and/or change the behavior of the
+ system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR
+ results in faster and smaller code, however, it increases the amount of processing in the ISR.
+ In addition, some services that are available in timers are not available from ISRs and will
+ therefore return an error if this option is used. This may or may not be desirable for a
+ given application. */
+
+
+/* Override various options with default values already assigned in tx_port.h. Please also refer
+ to tx_port.h for descriptions on each of these options. */
+
+/*
+#define TX_MAX_PRIORITIES 32
+#define TX_MINIMUM_STACK ????
+#define TX_THREAD_USER_EXTENSION ????
+#define TX_TIMER_THREAD_STACK_SIZE ????
+#define TX_TIMER_THREAD_PRIORITY ????
+*/
+
+/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls
+ should be processed within the a system timer thread or directly in the timer ISR.
+ By default, the timer thread is used. When the following is defined, the timer expiration
+ processing is done directly from the timer ISR, thereby eliminating the timer thread control
+ block, stack, and context switching to activate it. */
+
+/*
+#define TX_TIMER_PROCESS_IN_ISR
+*/
+
+/* Determine if in-line timer reactivation should be used within the timer expiration processing.
+ By default, this is disabled and a function call is used. When the following is defined,
+ reactivating is performed in-line resulting in faster timer processing but slightly larger
+ code size. */
+
+/*
+#define TX_REACTIVATE_INLINE
+*/
+
+/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled,
+ which places an 0xEF pattern in each byte of each thread's stack. This is used by
+ debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */
+
+/*
+#define TX_DISABLE_STACK_FILLING
+*/
+
+/* 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. */
+
+/*
+#define TX_ENABLE_STACK_CHECKING
+*/
+
+/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is
+ enabled. If the application does not use preemption-threshold, it may be disabled to reduce
+ code size and improve performance. */
+
+/*
+#define TX_DISABLE_PREEMPTION_THRESHOLD
+*/
+
+/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears
+ the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary
+ clearing of ThreadX global variables. */
+
+/*
+#define TX_DISABLE_REDUNDANT_CLEARING
+*/
+
+/* Determine if no timer processing is required. This option will help eliminate the timer
+ processing when not needed. The user will also have to comment out the call to
+ tx_timer_interrupt, which is typically made from assembly language in
+ tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR
+ must also be used. */
+
+/*
+#define TX_NO_TIMER
+#ifndef TX_TIMER_PROCESS_IN_ISR
+#define TX_TIMER_PROCESS_IN_ISR
+#endif
+*/
+
+/* Determine if the notify callback option should be disabled. By default, notify callbacks are
+ enabled. If the application does not use notify callbacks, they may be disabled to reduce
+ code size and improve performance. */
+
+/*
+#define TX_DISABLE_NOTIFY_CALLBACKS
+*/
+
+
+/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal
+ code in-line. This results in a larger image, but improves the performance of the thread
+ resume and suspend services. */
+
+/*
+#define TX_INLINE_THREAD_RESUME_SUSPEND
+*/
+
+
+/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code
+ size and less processing overhead, but increases the interrupt lockout time. */
+
+/*
+#define TX_NOT_INTERRUPTABLE
+*/
+
+
+/* Determine if the trace event logging code should be enabled. This causes slight increases in
+ code size and overhead, but provides the ability to generate system trace information which
+ is available for viewing in TraceX. */
+
+/*
+#define TX_ENABLE_EVENT_TRACE
+*/
+
+
+/* Determine if block pool performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various block pool performance information. */
+
+/*
+#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if byte pool performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various byte pool performance information. */
+
+/*
+#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if event flags performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various event flags performance information. */
+
+/*
+#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if mutex performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various mutex performance information. */
+
+/*
+#define TX_MUTEX_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if queue performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various queue performance information. */
+
+/*
+#define TX_QUEUE_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if semaphore performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various semaphore performance information. */
+
+/*
+#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if thread performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various thread performance information. */
+
+/*
+#define TX_THREAD_ENABLE_PERFORMANCE_INFO
+*/
+
+/* Determine if timer performance gathering is required by the application. When the following is
+ defined, ThreadX gathers various timer performance information. */
+
+/*
+#define TX_TIMER_ENABLE_PERFORMANCE_INFO
+*/
+
+#endif
+
diff --git a/ports/xtensa/xcc/inc/xtensa_api.h b/ports/xtensa/xcc/inc/xtensa_api.h
new file mode 100644
index 00000000..10255838
--- /dev/null
+++ b/ports/xtensa/xcc/inc/xtensa_api.h
@@ -0,0 +1,125 @@
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Xtensa-specific API for RTOS ports. */
+/**************************************************************************/
+
+#ifndef XTENSA_API_H
+#define XTENSA_API_H
+
+#include <xtensa/hal.h>
+
+#include "xtensa_context.h"
+
+
+/* Typedef for C-callable interrupt handler function */
+typedef void (*xt_handler)(void *);
+
+/* Typedef for C-callable exception handler function */
+typedef void (*xt_exc_handler)(XtExcFrame *);
+
+
+/*
+-------------------------------------------------------------------------------
+ Call this function to set a handler for the specified exception.
+
+ n - Exception number (type)
+ f - Handler function address, NULL to uninstall handler.
+
+ The handler will be passed a pointer to the exception frame, which is created
+ on the stack of the thread that caused the exception.
+
+ If the handler returns, the thread context will be restored and the faulting
+ instruction will be retried. Any values in the exception frame that are
+ modified by the handler will be restored as part of the context. For details
+ of the exception frame structure see xtensa_context.h.
+-------------------------------------------------------------------------------
+*/
+extern xt_exc_handler xt_set_exception_handler(uint32_t n, xt_exc_handler f);
+
+
+/*
+-------------------------------------------------------------------------------
+ Call this function to set a handler for the specified interrupt.
+
+ n - Interrupt number.
+ f - Handler function address, NULL to uninstall handler.
+ arg - Argument to be passed to handler.
+-------------------------------------------------------------------------------
+*/
+extern xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg);
+
+
+/*
+-------------------------------------------------------------------------------
+ Call this function to enable the specified interrupt.
+
+ intnum - Interrupt number to be enabled.
+
+ Returns: Nothing.
+-------------------------------------------------------------------------------
+*/
+extern void xt_interrupt_enable(uint32_t intnum);
+
+
+/*
+-------------------------------------------------------------------------------
+ Call this function to disable the specified interrupt.
+
+ intnum - Interrupt number to be disabled.
+
+ Returns: Nothing.
+-------------------------------------------------------------------------------
+*/
+extern void xt_interrupt_disable(uint32_t intnum);
+
+
+/*
+-------------------------------------------------------------------------------
+ Call this function to trigger the specified (s/w) interrupt.
+
+ intnum - Interrupt number to be triggered.
+
+ Returns: Nothing.
+-------------------------------------------------------------------------------
+*/
+extern void xt_interrupt_trigger(uint32_t intnum);
+
+
+/*
+-------------------------------------------------------------------------------
+ Call this function to clear the specified (s/w or edge-triggered)
+ interrupt.
+
+ intnum - Interrupt number to be cleared.
+
+Returns: Nothing.
+-------------------------------------------------------------------------------
+*/
+extern void xt_interrupt_clear(uint32_t intnum);
+
+
+#endif /* XTENSA_API_H */
+
diff --git a/ports/xtensa/xcc/inc/xtensa_context.h b/ports/xtensa/xcc/inc/xtensa_context.h
new file mode 100644
index 00000000..c2f76afa
--- /dev/null
+++ b/ports/xtensa/xcc/inc/xtensa_context.h
@@ -0,0 +1,561 @@
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************
+
+ XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
+
+ This header contains definitions and macros for use primarily by Xtensa
+ RTOS assembly source files. It includes and uses the Xtensa hardware
+ abstraction layer (HAL) to deal with config specifics. It may also be
+ included in C source files.
+
+ NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
+
+***************************************************************************/
+
+#ifndef XTENSA_CONTEXT_H
+#define XTENSA_CONTEXT_H
+
+#ifdef __ASSEMBLER__
+#include <xtensa/coreasm.h>
+#endif
+
+#include <xtensa/config/tie.h>
+#include <xtensa/corebits.h>
+#include <xtensa/config/system.h>
+
+#if defined (__ASSEMBLER__)
+#include "tx_api_asm.h"
+#endif
+
+
+/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
+#define ALIGNUP(n, val) (((val) + (n)-1) & -(n))
+
+
+/*
+-------------------------------------------------------------------------------
+ Macros that help define structures for both C and assembler.
+-------------------------------------------------------------------------------
+*/
+#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
+
+#define XSTRUCT_BEGIN .pushsection .text; .struct 0
+#define XSTRUCT_FIELD(ctype,size,asname,name) asname: .space size
+#define XSTRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
+#define XSTRUCT_END(sname) sname##Size:; .popsection
+
+#else
+
+#define XSTRUCT_BEGIN typedef struct {
+#define XSTRUCT_FIELD(ctype,size,asname,name) ctype name;
+#define XSTRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
+#define XSTRUCT_END(sname) } sname;
+
+#endif //_ASMLANGUAGE || __ASSEMBLER__
+
+
+/*
+-------------------------------------------------------------------------------
+ INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
+
+ A stack frame of this structure is allocated for any interrupt or exception.
+ It goes on the current stack. If the RTOS has a system stack for handling
+ interrupts, every thread stack must allow space for just one interrupt stack
+ frame, then nested interrupt stack frames go on the system stack.
+
+ The frame includes basic registers (explicit) and "extra" registers introduced
+ by user TIE or the use of the MAC16 option in the user's Xtensa config.
+ The frame size is minimized by omitting regs not applicable to user's config.
+
+ For Windowed ABI, this stack frame includes the interruptee's base save area,
+ another base save area to manage gcc nested functions, and a little temporary
+ space to help manage the spilling of the register windows.
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_HAVE_XEA2
+
+XSTRUCT_BEGIN
+XSTRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */
+XSTRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */
+XSTRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */
+XSTRUCT_FIELD (long, 4, XT_STK_A0, a0)
+XSTRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
+XSTRUCT_FIELD (long, 4, XT_STK_A2, a2)
+XSTRUCT_FIELD (long, 4, XT_STK_A3, a3)
+XSTRUCT_FIELD (long, 4, XT_STK_A4, a4)
+XSTRUCT_FIELD (long, 4, XT_STK_A5, a5)
+XSTRUCT_FIELD (long, 4, XT_STK_A6, a6)
+XSTRUCT_FIELD (long, 4, XT_STK_A7, a7)
+XSTRUCT_FIELD (long, 4, XT_STK_A8, a8)
+XSTRUCT_FIELD (long, 4, XT_STK_A9, a9)
+XSTRUCT_FIELD (long, 4, XT_STK_A10, a10)
+XSTRUCT_FIELD (long, 4, XT_STK_A11, a11)
+XSTRUCT_FIELD (long, 4, XT_STK_A12, a12)
+XSTRUCT_FIELD (long, 4, XT_STK_A13, a13)
+XSTRUCT_FIELD (long, 4, XT_STK_A14, a14)
+XSTRUCT_FIELD (long, 4, XT_STK_A15, a15)
+XSTRUCT_FIELD (long, 4, XT_STK_SAR, sar)
+XSTRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
+XSTRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
+#if XCHAL_HAVE_LOOPS
+XSTRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
+XSTRUCT_FIELD (long, 4, XT_STK_LEND, lend)
+XSTRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
+#endif
+#if XCHAL_HAVE_EXCLUSIVE
+XSTRUCT_FIELD (long, 4, XT_STK_ATOMCTL, atomctl)
+#endif
+#ifndef __XTENSA_CALL0_ABI__
+/* Temporary space for saving stuff during window spill */
+XSTRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
+XSTRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
+XSTRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
+#endif
+#ifdef XT_USE_SWPRI
+/* Storage for virtual priority mask */
+XSTRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
+#endif
+#ifdef XT_USE_OVLY
+/* Storage for overlay state */
+XSTRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
+#endif
+XSTRUCT_END(XtExcFrame)
+
+#endif /* XCHAL_HAVE_XEA2 */
+
+#if XCHAL_HAVE_XEA3
+
+XSTRUCT_BEGIN
+XSTRUCT_FIELD (long, 4, XT_STK_ATOMCTL, atomctl)
+XSTRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
+XSTRUCT_FIELD (long, 4, XT_STK_LEND, lend)
+XSTRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
+XSTRUCT_FIELD (long, 4, XT_STK_PC, pc)
+XSTRUCT_FIELD (long, 4, XT_STK_PS, ps)
+XSTRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
+XSTRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
+#ifdef __XTENSA_CALL0_ABI__
+XSTRUCT_FIELD (long, 4, XT_STK_A0, a0)
+XSTRUCT_FIELD (long, 4, XT_STK_A1, a1)
+XSTRUCT_FIELD (long, 4, XT_STK_A2, a2)
+XSTRUCT_FIELD (long, 4, XT_STK_A3, a3)
+XSTRUCT_FIELD (long, 4, XT_STK_A4, a4)
+XSTRUCT_FIELD (long, 4, XT_STK_A5, a5)
+XSTRUCT_FIELD (long, 4, XT_STK_A6, a6)
+XSTRUCT_FIELD (long, 4, XT_STK_A7, a7)
+#endif
+XSTRUCT_FIELD (long, 4, XT_STK_A8, a8)
+XSTRUCT_FIELD (long, 4, XT_STK_A9, a9)
+XSTRUCT_FIELD (long, 4, XT_STK_A10, a10)
+XSTRUCT_FIELD (long, 4, XT_STK_A11, a11)
+XSTRUCT_FIELD (long, 4, XT_STK_A12, a12)
+XSTRUCT_FIELD (long, 4, XT_STK_A13, a13)
+XSTRUCT_FIELD (long, 4, XT_STK_A14, a14)
+XSTRUCT_FIELD (long, 4, XT_STK_A15, a15)
+#ifdef __XTENSA_WINDOWED_ABI__
+XSTRUCT_AFIELD(long, 4, XT_STK_SPILL, spill, 8)
+#endif
+XSTRUCT_END(XtExcFrame)
+
+#endif /* XCHAL_HAVE_XEA3 */
+
+#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
+#define XT_STK_NEXT1 XtExcFrameSize
+#else
+#define XT_STK_NEXT1 sizeof(XtExcFrame)
+#endif
+
+
+/* Allocate extra storage if needed for non-CP TIE state. Allow for alignment
+ padding as needed.
+ */
+#if XCHAL_EXTRA_SA_SIZE != 0
+
+#if XCHAL_EXTRA_SA_ALIGN <= 16
+#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
+#else
+/* If need more alignment than stack, add space for dynamic alignment */
+#define XT_STK_EXTRA (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN)
+#endif
+#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
+
+#else
+
+/* No extra storage required */
+#define XT_STK_NEXT2 XT_STK_NEXT1
+
+#endif
+
+
+#if XCHAL_HAVE_XEA3
+
+/* Total frame size */
+#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2))
+
+/* Exception/interrupt frame size */
+#define XT_STK_XFRM_SZ XT_STK_NEXT1
+
+/* Extra save area size (including alignment padding) */
+#define XT_STK_XTRA_SZ (XT_STK_FRMSZ - XT_STK_XFRM_SZ)
+
+/* Alignment padding area size */
+#if XCHAL_EXTRA_SA_SIZE != 0
+#define XT_STK_ALIGN_SZ (XT_STK_EXTRA - XT_STK_NEXT1)
+#endif
+
+#else
+
+/*
+-------------------------------------------------------------------------------
+ This is the frame size. Add space for 4 registers (interruptee's base save
+ area) and some space for gcc nested functions if any.
+-------------------------------------------------------------------------------
+*/
+#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20)
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+ CO-PROCESSOR STATE SAVE AREA FOR A THREAD
+
+ The RTOS must provide an area per thread to save the state of co-processors
+ when that thread does not have control. Co-processors are context-switched
+ lazily (on demand) only when a new thread uses a co-processor instruction,
+ otherwise a thread retains ownership of the co-processor even when it loses
+ control of the processor. An Xtensa co-processor exception is triggered when
+ any co-processor instruction is executed by a thread that is not the owner,
+ and the context switch of that co-processor is then peformed by the handler.
+ Ownership represents which thread's state is currently in the co-processor.
+
+ Co-processors may not be used by interrupt or exception handlers. If an
+ co-processor instruction is executed by an interrupt or exception handler,
+ the co-processor exception handler will trigger a kernel panic and freeze.
+ This restriction is introduced to reduce the overhead of saving and restoring
+ co-processor state (which can be quite large) and in particular remove that
+ overhead from interrupt handlers.
+
+ The co-processor state save area may be in any convenient per-thread location
+ such as in the thread control block or above the thread stack area. It need
+ not be in the interrupt stack frame since interrupts don't use co-processors.
+
+ Along with the save area for each co-processor, two bitmasks with flags per
+ co-processor (laid out as in the CPENABLE reg) help manage context-switching
+ co-processors as efficiently as possible:
+
+ XT_CPENABLE
+ The contents of a non-running thread's CPENABLE register.
+ It represents the co-processors owned (and whose state is still needed)
+ by the thread. When a thread is preempted, its CPENABLE is saved here.
+ When a thread solicits a context-swtich, its CPENABLE is cleared - the
+ compiler has saved the (caller-saved) co-proc state if it needs to.
+ When a non-running thread loses ownership of a CP, its bit is cleared.
+ When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg.
+ Avoids co-processor exceptions when no change of ownership is needed.
+
+ XT_CPSTORED
+ A bitmask with the same layout as CPENABLE, a bit per co-processor.
+ Indicates whether the state of each co-processor is saved in the state
+ save area. When a thread enters the kernel, only the state of co-procs
+ still enabled in CPENABLE is saved. When the co-processor exception
+ handler assigns ownership of a co-processor to a thread, it restores
+ the saved state only if this bit is set, and clears this bit.
+
+ XT_CP_CS_ST
+ A bitmask with the same layout as CPENABLE, a bit per co-processor.
+ Indicates whether callee-saved state is saved in the state save area.
+ Callee-saved state is saved by itself on a solicited context switch,
+ and restored when needed by the coprocessor exception handler.
+ Unsolicited switches will cause the entire coprocessor to be saved
+ when necessary.
+
+ XT_CP_ASA
+ Pointer to the aligned save area. Allows it to be aligned more than
+ the overall save area (which might only be stack-aligned or TCB-aligned).
+ Especially relevant for Xtensa cores configured with a very large data
+ path that requires alignment greater than 16 bytes (ABI stack alignment).
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_CP_NUM > 0
+
+/* Offsets of each coprocessor save area within the 'aligned save area': */
+#define XT_CP0_SA 0
+#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE)
+#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE)
+#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE)
+#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE)
+#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE)
+#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE)
+#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE)
+#define XT_CP_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE)
+
+/* Offsets within the overall save area: */
+#define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */
+#define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */
+#define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */
+#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */
+/* Overall size allows for dynamic alignment: */
+#define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)
+#else
+#define XT_CP_SIZE 0
+#endif
+
+
+/*
+-------------------------------------------------------------------------------
+ MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
+
+ Convenient where the frame size requirements are the same for both ABIs.
+ ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
+ ENTRY0, RET0 are for frameless functions (no locals, no calls).
+
+ where size = size of stack frame in bytes (must be >0 and aligned to 16).
+ For framed functions the frame is created and the return address saved at
+ base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
+ For frameless functions, there is no frame and return address remains in a0.
+ Note: Because CPP macros expand to a single line, macros requiring multi-line
+ expansions are implemented as assembler macros.
+-------------------------------------------------------------------------------
+*/
+
+#ifdef __ASSEMBLER__
+#ifdef __XTENSA_CALL0_ABI__
+ /* Call0 */
+ #define ENTRY(sz) entry1 sz
+ .macro entry1 size=0x10
+ addi sp, sp, -\size
+ s32i a0, sp, 0
+ .endm
+ #define ENTRY0
+ #define RET(sz) ret1 sz
+ .macro ret1 size=0x10
+ l32i a0, sp, 0
+ addi sp, sp, \size
+ ret
+ .endm
+ #define RET0 ret
+#else
+ /* Windowed */
+#if XCHAL_HAVE_XEA3
+ #define ENTRY(sz) entry sp, (sz + 0x20)
+ #define ENTRY0 entry sp, 0x20
+#else
+ #define ENTRY(sz) entry sp, (sz + 0x10)
+ #define ENTRY0 entry sp, 0x10
+#endif
+ #define RET(sz) retw
+ #define RET0 retw
+#endif
+#endif
+
+
+/*
+-------------------------------------------------------------------------------
+ This flag is meant for internal use. Have all interrupts be dispatched via a
+ common wrapper, which takes care of doing some OS-specific stuff common to
+ all interrupt handlers. Said stuff cannot safely be handled in the RTOS_ENTER
+ and RTOS_EXIT macros.
+-------------------------------------------------------------------------------
+*/
+#if (defined TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || (defined XT_INTEXC_HOOKS)
+#define XT_USE_INT_WRAPPER 1
+#else
+#define XT_USE_INT_WRAPPER 0
+#endif
+
+#if XCHAL_HAVE_XEA3
+#ifdef XT_USE_SWPRI
+//#warning "Software prioritization of interrupts (XT_USE_SWPRI) not supported for XEA3."
+#endif
+
+#ifdef __ASSEMBLER__
+
+ // RTOS-specific entry macro. Use only a8, a12-a14.
+
+ .macro XT_RTOS_INT_ENTER
+
+ .endm
+
+ // RTOS-specific exit macro. Use only a8-a14.
+ // (In call0, a15 holds user SP, must be preserved)
+
+ .macro XT_RTOS_INT_EXIT
+
+ // Check nesting count and branch on nest state.
+ movi a8, _tx_thread_system_state
+ movi a9, _tx_thread_execute_ptr // a9 <- &_tx_thread_execute_ptr (new)
+ movi a10, _tx_thread_preempt_disable // a10 <- &_tx_thread_preempt_disable
+ l32i a8, a8, 0
+ bnez a8, .Lnested // state != 0 means nested
+
+ movi a8, _tx_thread_current_ptr // a8 <- &_tx_thread_current_ptr (old)
+ l32i a9, a9, 0 // a9 <- _tx_thread_execute_ptr
+ l32i a11, a8, 0 // a11 <- _tx_thread_current_ptr
+ beqz a11, .Lsched // no old thread, go to scheduler
+ l32i a10, a10, 0 // a10 <- _tx_thread_preempt_disable
+ beq a11, a9, .Lnested // no change, restore current thread
+ bgei a10, 1, .Lnested // no preemption, restore current thread
+
+ // Preemption, save remaining state of current (outgoing) thread
+
+ movi a12, _tx_timer_time_slice // a12 <- &_tx_timer_time_slice
+ addi a10, a1, -XT_STK_FRMSZ
+ s32i a10, a11, tx_thread_stack_ptr // save outgoing thread stack pointer
+ l32i a10, a12, 0 // a10 <- _tx_timer_time_slice
+ s32i a10, a11, tx_thread_time_slice // save outgoing time slice value
+ movi a10, 0
+ s32i a10, a12, 0 // disable time slice
+ s32i a10, a11, tx_thread_solicited // mark as preempted
+ s32i a10, a8, 0 // Clear _tx_thread_current_ptr
+#if XCHAL_CP_NUM > 0
+ rsr a12, CPENABLE // Save and clear CPENABLE
+ s16i a12, a11, tx_thread_cp_state + XT_CPENABLE
+ wsr a10, CPENABLE
+#endif
+
+ // Save non-CP TIE state if any
+#if XCHAL_EXTRA_SA_SIZE > 0
+ addi a10, a1, -XT_STK_FRMSZ + XT_STK_ALIGN_SZ // where to save
+#if XCHAL_EXTRA_SA_ALIGN > 16
+ movi a12, -XCHAL_EXTRA_SA_ALIGN
+ and a10, a10, a12 // align dynamically >16 bytes
+#endif
+ xchal_ncp_store a10, a11, a12, a13, a14
+#endif
+
+ // If windowed ABI, a0-a7 was not saved by dispatch code.
+ // These don't go into the exception frame, but below the
+ // exception frame pointer.
+
+#ifdef __XTENSA_WINDOWED_ABI__
+ addi a10, a1, -XT_STK_FRMSZ -32
+ s32i a0, a10, 0
+ s32i a2, a10, 8
+ s32i a3, a10, 12
+ s32i a4, a10, 16
+ s32i a5, a10, 20
+ s32i a6, a10, 24
+ s32i a7, a10, 28
+#endif
+
+.Lsched:
+ // When we get here, interrupts are disabled, a8 = &_tx_thread_current_ptr,
+ // a9 = _tx_thread_execute_ptr
+ movi a9, _tx_thread_execute_ptr // a9 <- &_tx_thread_execute_ptr (new)
+ l32i a9, a9, 0 // a9 <- _tx_thread_execute_ptr
+ s32i a9, a8, 0 // _tx_thread_current_ptr = _tx_thread_execute_ptr
+ beqz a9, _xt_idle // go idle if _tx_thread_execute_ptr == 0
+ l32i a10, a9, tx_thread_run_count
+ l32i a11, a9, tx_thread_time_slice
+ movi a12, _tx_timer_time_slice
+ addi a10, a10, 1
+ s32i a10, a9, tx_thread_run_count
+ s32i a11, a12, 0 // _tx_timer_time_slice = _tx_thread_current_ptr->tx_thread_time_slice
+
+#ifdef TX_THREAD_SAFE_CLIB
+ #if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+ movi a10, _impure_ptr
+ #elif XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ movi a10, _reent_ptr
+ #else
+ #error TX_THREAD_SAFE_CLIB defined with unsupported C library.
+ #endif
+ l32i a11, a9, tx_thread_clib_ptr
+ s32i a11, a10, 0
+#endif
+
+#if XCHAL_CP_NUM > 0
+ l16ui a10, a9, tx_thread_cp_state + XT_CPENABLE
+ wsr a10, CPENABLE // restore CPENABLE
+#endif
+
+ l32i a1, a9, tx_thread_stack_ptr // SP = _tx_thread_execute_ptr->tx_thread_stack_ptr
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ // Call the thread entry function to indicate the thread is executing.
+ // SP should be pointing to a safe region at this point.
+#ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_execution_thread_enter
+#else
+ call8 _tx_execution_thread_enter
+#endif
+#endif
+
+ l32i a2, a9, tx_thread_solicited // a2 = solicited flag
+ beqz a2, 1f
+
+ // Solicited restore
+ addi a1, a1, XT_STK_FRMSZ // restore original SP
+ addi a2, a1, -XT_STK_XFRM_SZ
+ l32i a3, a2, XT_STK_PC // a3 = return PC
+
+ movi a2, PS_DI
+ xps a2, a2 // disable interrupts
+ movi a2, 0
+ wsr.ms a2 // restore normal DISPST
+ rsync
+ jx a3 // return to yield point
+
+1:
+ // Preempt restore
+#if XCHAL_EXTRA_SA_SIZE > 0
+ addi a10, a1, XT_STK_ALIGN_SZ // where to restore from
+#if XCHAL_EXTRA_SA_ALIGN > 16
+ movi a12, -XCHAL_EXTRA_SA_ALIGN
+ and a10, a10, a12 // align dynamically >16 bytes
+#endif
+ xchal_ncp_load a10, a11, a12, a13, a14
+#endif
+
+#ifdef __XTENSA_WINDOWED_ABI__
+ // Restore a0-a7 for windowed ABI
+ addi a8, a1, -32
+ l32i a0, a8, 0
+ l32i a2, a8, 8
+ l32i a3, a8, 12
+ l32i a4, a8, 16
+ l32i a5, a8, 20
+ l32i a6, a8, 24
+ l32i a7, a8, 28
+#else
+ // For call0, dispatch exit code expects a15 = original SP
+ addi a15, a1, XT_STK_FRMSZ
+#endif
+
+ addi a1, a1, XT_STK_FRMSZ // set up SP for dispatch exit
+
+.Lnested:
+ // Return to the current saved context.
+
+ .endm
+
+#endif /* __ASSEMBLER__ */
+#endif /* XCHAL_HAVE_XEA3 */
+
+#endif /* XTENSA_CONTEXT_H */
+
diff --git a/ports/xtensa/xcc/inc/xtensa_rtos.h b/ports/xtensa/xcc/inc/xtensa_rtos.h
new file mode 100644
index 00000000..03db1849
--- /dev/null
+++ b/ports/xtensa/xcc/inc/xtensa_rtos.h
@@ -0,0 +1,204 @@
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************
+
+ RTOS-SPECIFIC INFORMATION FOR XTENSA RTOS ASSEMBLER SOURCES
+
+ This header is the primary glue between generic Xtensa RTOS support
+ sources and a specific RTOS port for Xtensa. It contains definitions
+ and macros for use primarily by Xtensa assembly coded source files.
+
+ Macros in this header map callouts from generic Xtensa files to specific
+ RTOS functions. It may also be included in C source files.
+
+ Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa
+ architecture, using the Xtensa hardware abstraction layer (HAL) to deal
+ with configuration specifics.
+
+ Should be included by all Xtensa generic and RTOS port-specific sources.
+
+***************************************************************************/
+
+#ifndef XTENSA_RTOS_H
+#define XTENSA_RTOS_H
+
+#ifdef __ASSEMBLER__
+#include <xtensa/coreasm.h>
+#else
+#include <stdint.h>
+#include <xtensa/config/core.h>
+#endif
+
+#include <xtensa/corebits.h>
+#include <xtensa/config/system.h>
+#include <xtensa/simcall.h>
+
+/*
+Include any RTOS specific definitions that are needed by this header.
+*/
+#include "tx_user.h"
+
+/*
+Name of RTOS (for messages).
+*/
+#define XT_RTOS_NAME ThreadX
+
+/*
+Check some Xtensa configuration requirements and report error if not met.
+Error messages can be customize to the RTOS port.
+*/
+
+#if !XCHAL_HAVE_XEA2 && !XCHAL_HAVE_XEA3
+#error "ThreadX/Xtensa requires Xtensa Exception Architecture v2 (XEA2) or higher."
+#endif
+
+
+/***************************************************************************
+
+RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS.
+
+Define callout macros used in generic Xtensa code to interact with the RTOS.
+The macros are simply the function names for use in calls from assembler code.
+Some of these functions may call back to generic functions in xtensa_context.h .
+
+***************************************************************************/
+
+/*
+Inform RTOS of entry into an interrupt handler that will affect it.
+Allows RTOS to manage switch to any system stack and count nesting level.
+Called after minimal context has been saved, with interrupts disabled.
+RTOS port can call0 _xt_context_save to save the rest of the context.
+May only be called from assembly code by the 'call0' instruction.
+*/
+// void XT_RTOS_INT_ENTER(void)
+#define XT_RTOS_INT_ENTER _tx_thread_context_save
+
+/*
+Inform RTOS of completion of an interrupt handler, and give control to
+RTOS to perform thread/task scheduling, switch back from any system stack
+and restore the context, and return to the exit dispatcher saved in the
+stack frame at XT_STK_EXIT. RTOS port can call0 _xt_context_restore
+to save the context saved in XT_RTOS_INT_ENTER via _xt_context_save,
+leaving only a minimal part of the context to be restored by the exit
+dispatcher. This function does not return to the place it was called from.
+May only be called from assembly code by the 'call0' instruction.
+*/
+// void XT_RTOS_INT_EXIT(void)
+#define XT_RTOS_INT_EXIT _tx_thread_context_restore
+
+/*
+Convenience macros to disable and enable interrupts.
+*/
+#if XCHAL_HAVE_XEA3
+#define XT_INTS_DISABLE(reg) movi reg, PS_DI; xps reg, reg
+#define XT_INTS_ENABLE(reg) wsr reg, PS; rsync
+#else
+#define XT_INTS_DISABLE(reg) rsil reg, XCHAL_EXCM_LEVEL
+#define XT_INTS_ENABLE(reg) wsr reg, PS; rsync
+#endif
+
+/*
+Inform RTOS of the occurrence of a tick timer interrupt.
+If RTOS has no tick timer, leave XT_RTOS_TIMER_INT undefined.
+May be coded in or called from C or assembly, per ABI conventions.
+*/
+#ifndef TX_NO_TIMER
+// void XT_RTOS_TIMER_INT(void)
+#define XT_RTOS_TIMER_INT _tx_timer_interrupt
+#endif
+
+/*
+Return in a15 the base address of the co-processor state save area for the
+thread that triggered a co-processor exception, or 0 if no thread was running.
+The state save area is structured as defined in xtensa_context.h and has size
+XT_CP_SIZE. Co-processor instructions should only be used in thread code, never
+in interrupt handlers or the RTOS kernel. May only be called from assembly code
+and by the 'call0' instruction. A result of 0 indicates an unrecoverable error.
+The implementation may use only a2-4, a15 (all other regs must be preserved).
+*/
+// void* XT_RTOS_CP_STATE(void)
+#define XT_RTOS_CP_STATE _tx_thread_coproc_state
+
+
+/***************************************************************************
+
+HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL.
+
+This Xtensa RTOS port provides hooks for dynamically installing exception
+and interrupt handlers to facilitate automated testing where each test
+case can install its own handler for user exceptions and each interrupt
+priority (level). This consists of an array of function pointers indexed
+by interrupt priority, with index 0 being the user exception handler hook.
+Each entry in the array is initially 0, and may be replaced by a function
+pointer of type XT_INTEXC_HOOK. A handler may be uninstalled by installing 0.
+
+The handler for low and medium priority obeys ABI conventions so may be coded
+in C. For the exception handler, the cause is the contents of the EXCCAUSE
+reg, and the result is -1 if handled, else the cause (still needs handling).
+For interrupt handlers, the cause is a mask of pending enabled interrupts at
+that level, and the result is the same mask with the bits for the handled
+interrupts cleared (those not cleared still need handling). This allows a test
+case to either pre-handle or override the default handling for the exception
+or interrupt level (see xtensa_vectors.S).
+
+High priority handlers (including NMI) must be coded in assembly, are always
+called by 'call0' regardless of ABI, must preserve all registers except a0,
+and must not use or modify the interrupted stack. The hook argument 'cause'
+is not passed and the result is ignored, so as not to burden the caller with
+saving and restoring a2 (it assumes only one interrupt per level - see the
+discussion in high priority interrupts in xtensa_vectors.S). The handler
+therefore should be coded to prototype 'void h(void)' even though it plugs
+into an array of handlers of prototype 'uint32_t h(uint32_t)'.
+
+To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'.
+
+***************************************************************************/
+
+#define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI)
+
+#ifndef __ASSEMBLER__
+typedef uint32_t (*XT_INTEXC_HOOK)(uint32_t cause);
+extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
+#endif
+
+
+/***************************************************************************
+
+CONVENIENCE INCLUSIONS.
+
+Ensures RTOS specific files need only include this one Xtensa-generic header.
+These headers are included last so they can use the RTOS definitions above.
+
+***************************************************************************/
+
+#include "xtensa_context.h"
+
+#ifdef XT_RTOS_TIMER_INT
+#include "xtensa_timer.h"
+#endif
+
+
+#endif /* XTENSA_RTOS_H */
+
diff --git a/ports/xtensa/xcc/inc/xtensa_timer.h b/ports/xtensa/xcc/inc/xtensa_timer.h
new file mode 100644
index 00000000..d5a29ed5
--- /dev/null
+++ b/ports/xtensa/xcc/inc/xtensa_timer.h
@@ -0,0 +1,157 @@
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************
+ XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY
+
+ This header contains timer related definitions and macros for use by
+ Xtensa RTOS source files. It includes and uses the Xtensa hardware
+ abstraction layer (HAL) to deal with config specifics.
+
+ If the RTOS has no timer interrupt, then there is no tick timer and the
+ clock frequency is irrelevant, so all of these macros are left undefined
+ and the Xtensa core configuration need not have a timer.
+***************************************************************************/
+
+#ifndef XTENSA_TIMER_H
+#define XTENSA_TIMER_H
+
+#include "xtensa_rtos.h" /* in case this wasn't included directly */
+
+#ifdef XT_RTOS_TIMER_INT /* skip all this stuff if no timer int */
+
+#ifdef __ASSEMBLER__
+#include <xtensa/coreasm.h>
+#else
+#include <xtensa/tie/xt_timer.h>
+#endif
+
+#include <xtensa/corebits.h>
+#include <xtensa/config/system.h>
+
+
+#if XCHAL_HAVE_XEA3
+
+/*
+If the user has not specified a timer by defining XT_TIMER_INDEX, then
+select timer 0.
+*/
+#ifndef XT_TIMER_INDEX
+#define XT_TIMER_INDEX 0
+#endif
+
+#else /* XEA2 */
+
+/*
+Select timer to use for periodic tick, and determine its interrupt number
+and priority. User may specify a timer by defining XT_TIMER_INDEX with -D,
+in which case its validity is checked (it must exist in this core and must
+not be on a high priority interrupt - an error will be reported in invalid).
+Otherwise select the first low or medium priority interrupt timer available.
+*/
+#ifndef XT_TIMER_INDEX
+ #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+ #if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL
+ #undef XT_TIMER_INDEX
+ #define XT_TIMER_INDEX 3
+ #endif
+ #endif
+ #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+ #if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
+ #undef XT_TIMER_INDEX
+ #define XT_TIMER_INDEX 2
+ #endif
+ #endif
+ #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+ #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
+ #undef XT_TIMER_INDEX
+ #define XT_TIMER_INDEX 1
+ #endif
+ #endif
+ #if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+ #if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
+ #undef XT_TIMER_INDEX
+ #define XT_TIMER_INDEX 0
+ #endif
+ #endif
+#endif
+
+#endif /* XCHAL_HAVE_XEA3 */
+
+#ifndef XT_TIMER_INDEX
+ #error "There is no suitable timer in this Xtensa configuration."
+#endif
+
+#define XT_CCOMPARE (CCOMPARE + XT_TIMER_INDEX)
+#define XT_TIMER_INTNUM XCHAL_TIMER_INTERRUPT(XT_TIMER_INDEX)
+#define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM)
+
+#if XCHAL_HAVE_XEA2
+#define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM)
+#endif
+
+#if XT_TIMER_INDEX == 0
+#define XT_WSR_CCOMPARE XT_WSR_CCOMPARE0
+#elif XT_TIMER_INDEX == 1
+#define XT_WSR_CCOMPARE XT_WSR_CCOMPARE1
+#elif XT_TIMER_INDEX == 2
+#define XT_WSR_CCOMPARE XT_WSR_CCOMPARE2
+#endif
+
+#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
+ #error "The timer selected by XT_TIMER_INDEX does not exist in this core."
+#elif !XCHAL_HAVE_XEA3 && (XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL)
+ #error "The timer interrupt cannot be high priority (use medium or low)."
+#endif
+
+/*
+Default number of timer ticks per second. This can be redefined as required
+either by editing here or by overriding from the command line during build.
+*/
+#ifndef XT_TICK_PER_SEC
+#define XT_TICK_PER_SEC 100
+#endif
+
+/*
+Set processor clock frequency and determine clock divisor for timer tick.
+If using a supported board via the board-independent API defined in xtbsp.h,
+this may be left undefined but XT_BOARD must be defined. The frequency and
+tick divisor will be computed during run-time initialization.
+*/
+#ifndef XT_BOARD
+#ifndef XT_CLOCK_FREQ
+#define XT_CLOCK_FREQ 1000000
+#endif
+#define XT_TICK_DIVISOR (XT_CLOCK_FREQ / XT_TICK_PER_SEC)
+#else
+#ifndef __ASSEMBLER__
+extern uint32_t xt_tick_divisor;
+extern void xt_tick_divisor_init(void);
+#endif
+#define XT_TICK_DIVISOR xt_tick_divisor
+#endif /* XT_BOARD */
+
+#endif /* XT_RTOS_TIMER_INT */
+#endif /* XTENSA_TIMER_H */
+
diff --git a/ports/xtensa/xcc/readme_threadx.txt b/ports/xtensa/xcc/readme_threadx.txt
new file mode 100644
index 00000000..90fc92d7
--- /dev/null
+++ b/ports/xtensa/xcc/readme_threadx.txt
@@ -0,0 +1,1015 @@
+ Microsoft's ThreadX for Xtensa Configurable Processors
+
+ Using the Xtensa Tools
+
+1. Xtensa Configuration Requirements and Restrictions
+
+The Xtensa configurable architecture supports a vast space of processor
+features. This port of ThreadX to the Xtensa architecture is based on
+a Cadence Design Systems RTOS porting layer that takes care of Xtensa specifics
+that are common to most embedded real-time operating systems. It supports all
+Xtensa features (including context-switching custom processor extensions
+defined in the TIE language) with certain minimum requirements. You
+must use Xtensa Tools to compile and link ThreadX for your particular
+configuration. ThreadX uses the Xtensa Hardware Abstraction Layer (HAL)
+to adapt your ThreadX compilation to your particular Xtensa processor
+configuration. ThreadX also provides optional thread-safe support for
+the Xtensa C library and the newlib C library distributed with Xtensa Tools
+(for use in threads only, not in interrupt handlers).
+
+ThreadX for Xtensa configurable processors requires the following minimum
+processor configuration options:
+- Timer interrupt option with at least one interruptible timer for ThreadX.
+- Interrupt option (implied by the timer interrupt option).
+- Xtensa Exception Architecture 2 (XEA2) or Exception Architecture 3 (XEA3).
+ Please note that XEA1 is NOT supported.
+
+Minimal support for certain evaluation boards is provided via a board
+independent "XTBSP" API implemented by a board specific library. This
+provides the board clock frequency and basic polled drivers for the display
+and console I/O device (usually a UART), and ThreadX can be built to
+take advantage of these (note: it is not specific to ThreadX and is not a
+traditional RTOS "board support package" with RTOS specific interrupt-driven
+drivers). Note that ThreadX can run on any Xtensa board without
+this board support (a "raw" platform), but you will have to provide the
+clock frequency and drivers for any on-board devices you want to use.
+
+
+2. Building the ThreadX run-time Library
+
+By default, you will build for the Xtensa instruction set simulator. If
+you have a supported emulation board, you can build to run on that. You
+can also build to run on a raw Xtensa core with no "board support", a
+good starting point for supporting your own target platform. Cadence Design Systems
+recommends doing functional development on the simulator because it
+is easier to debug with, then move to a board if/when you need to test
+hardware drivers or real-time performance.
+
+ThreadX/Xtensa comes with a Makefile as well as DOS .bat file, taking
+advantage of xt-make, a version of GNU make that comes with Xtensa Tools
+(you can just as well use generic GNU make if you have it installed).
+The Makefile works on any host platform and provides for incremental builds.
+The .bat file works on DOS/Windows only and always cleans before building.
+The build for each target platform is placed in a sub-directory so several
+platform builds can coexist even with incremental rebuilds.
+
+First, make sure you have installed Xtensa Tools and your processor
+configuration, and be sure that Xtensa Tools are in your search path.
+
+If you wish to build for an evaluation board that is supported by an
+external package, be sure the appropriate package is installed. See the
+introduction (section 0) to determine if you need an external package.
+If you are using an external board package, set the environment variable
+XTENSA_BOARDS to the absolute path of the root of the installed support
+package (or you can pass this to xt-make commands on the command line).
+eg. XTENSA_BOARDS = C:\usr\xtensa\RB-2007.1-xtav60 for Avnet LX60 board.
+You do not need to set XTENSA_BOARDS if using a Cadence Design Systems supported
+board with Xtensa Tools RB-2007.2 and up (support is bundled with the tools).
+
+Next, change directories to the ThreadX installation directory, as follows:
+
+> cd c:\threadx\xtensa\gnu
+
+Now build the ThreadX library (tx.a) by executing the build_threadx.bat
+batch file (or using the Makefile directly) while inside the threadx
+directory, as follows:
+
+> build_threadx.bat
+
+which always builds for the simulator (but you can edit it), or
+
+> xt-make
+
+which by default builds for the simulator (PLATFORM=sim), or either of
+
+> xt-make PLATFORM=board BOARD=<board>
+or
+> xt-make BOARD=<board>
+
+which builds for a specified supported board (note PLATFORM=board is
+default when BOARD is defined). eg. BOARD=xtav60 for the Avnet LX60
+(XT-AV60) board.
+
+> xt-make PLATFORM=raw
+
+which builds for a raw Xtensa core with no "board support".
+
+> xt-make PLATFORM=gdbio
+
+Provides some very slow I/O support through the xt-gdb debugger.
+For GDBIO to work, xt-gdb must remain connected to the target.
+
+If you are building for an Xtensa processor configuration that is not the
+default you selected when you installed Xtensa Tools, you need to define the
+environment variable XTENSA_CORE. If your configuration is not in the
+default registry you selected when you installed Xtensa Tools, you also
+need to define the environment variable XTENSA_SYSTEM. See tools manuals.
+You can avoid defining these in your environment if you pass the variables
+you need to redefine into xt-make as follows:
+
+> xt-make XTENSA_CORE=<your_config_name> XTENSA_SYSTEM=<your_registry> ...
+
+There are more details about build options in the comment in the Makefile.
+
+At this point, all the ThreadX objects are located in a library file: tx.a .
+This file must be linked with your application in order to use ThreadX.
+This library and all the intermediate object files are placed in a platform
+specific sub-directory named the same as BOARD or PLATFORM (if BOARD is not
+defined), for example "sim", "xtkc705".
+
+To build ThreadX with thread-safe C library support, define TX_THREAD_SAFE_CLIB
+in your build, as described in section 5 and in the Makefile. Please note
+that the C library is only safe for use in threads, not in interrupt handlers.
+It may also safely be used in tx_application_define (after tx_kernel_enter,
+before threads are running).
+
+
+3. Demonstration System
+
+The ThreadX demonstration is designed to execute under Xtensa instruction set
+simulator (ISS) or on a supported evaluation board programmed with your Xtensa
+processor configuration.
+
+Building the demonstration is easy, simply execute the build_threadx_demo.bat
+batch file while inside threadx directory, as follows:
+
+> build_threadx_demo.bat
+
+or
+
+> xt-make demo
+
+Be sure to set or pass into xt-make the variables described in section 2 above
+for building the ThreadX library, including the PLATFORM or BOARD you want to
+run on.
+
+This compiles demo_threadx.c (which is the demonstration application) and links
+it with the ThreadX objects in tx.a. The resulting file demo_threadx.out is a
+ELF binary file that can be downloaded and executed on the target.
+
+The demo binary appears in the platform specific sub-directory described earlier.
+For the following commands, change to that directory or prepend it as the path
+of demo_threadx.out.
+
+
+To execute on the simulator:
+
+> xt-run [--turbo] demo_threadx.out
+
+The option --turbo provides much faster, but non-cycle-accurate simulation.
+Refer to the Xtensa simulator user manual for further simulator options.
+
+
+To execute on the simulator using the Xplorer GUI based debugger:
+
+> xplorer --debug demo_threadx.out
+
+
+To execute on a supported evaluation board, download demo_threadx.out per
+instructions in the tools manuals. Be sure the board has been programmed
+with the correct configuration and is set up to boot from RAM and debug
+a downloaded program! Optionally you may connect a terminal or terminal
+emulator to the serial port on the board with settings as described in
+the board user manual, and see the output of printf on the terminal (if
+the demo was compiled with DEMO_USE_PRINTF or DEMO_USE_XTUTIL).
+
+To obtain I/O on a "raw" platform such as an unsupported board, you need
+to provide low level I/O drivers (eg. inbyte() and outbyte() for character
+I/O if you want to use printf etc.). You can run "raw" executables on
+any Xtensa platform, including simulator and any board, but you will not
+see any behavior specific to the platform (eg. display, printed output,
+stopping simulation at end of program). You can, while debugging, use a
+debugger mechanism called GDBIO to obtain basic I/O. Use PLATFORM=GDBIO
+on your xt-make command line - this is the same as "raw" except it links
+some stubs that communicate through the debugger. It is very slow!
+
+WARNING: It is tempting to add printf calls to other threads in the demo.
+If you modify the code in any way, you may need adjust affected threads'
+stack sizes. This is especially true if you add a printf call. See 4.5.
+
+
+4. System Initialization
+
+4.1 ThreadX Kernel
+
+ThreadX uses the reset vector and low level initialization from the Xtensa
+libraries provided by the linker support package (LSP). It does not provide
+its own reset vector (which would have to be maintained with tools upgrades).
+
+ThreadX is initialized by tx_kernel_enter which is usually called from
+main. The primary initialization function is _tx_initialize_low_level
+and is located in the file tx_initialize_low_level.c. This function is
+responsible for setting up various system data structures. Interrupt and
+exception vectors are linked into your program and installed at load time
+(they are not dynamically installed). The interrupt and exception vectors
+for the ThreadX Xtensa port are defined in xtensa_vectors.S (for XEA2) and
+xtensa_vectors_xea3.S (for XEA3).
+
+4.2 Memory Allocation
+
+In addition, _tx_initialize_low_level also determines the first available
+address for use by the application. By default, the first available address
+is assumed to be above all linker-allocated sections at symbol _end. This
+is passed to the application definition function, tx_application_define.
+This is a convenience to the application developer. Ultimately the developer
+has full control over memory allocation and can choose to use this or not.
+The top of available memory is not provided and should be obtained from the
+tools if needed.
+
+4.3 Location and Extent of System (Interrupt) Stack
+
+ThreadX/Xtensa supports a user-definable system stack. By default, the
+top of the system stack is defined by the symbol _xt_interrupt_stack_top.
+See the file xtensa_intr_asm.S for the default system stack definition.
+This stack may be resized and/or relocated according to the application
+needs. The application developer must ensure that the system stack is
+sized appropriately for the application. All interrupts handled by
+ThreadX will use the system stack. Handlers written in assembly must
+not switch to the system stack, since it will not be possible to detect
+whether the stack is currently in use.
+
+The macro TX_SYSTEM_STACK_SIZE defines the size of the system stack.
+As a convenience, a macro TX_MINIMUM_STACK_SYSTEM is provided with the
+minimum size required for the system stack. This is based on the maximum
+possible interrupt nesting level per the Xtensa processor configuration,
+assuming very simple C handlers that do not call deeper than one or two
+levels. If the application uses more complex handlers, it will be
+necessary to add to this value (accounting for nesting) to determine
+the space required for the system stack.
+
+4.4 Location and Extent of C Library Heap
+
+If the optional thread-safe support for the C library is used, memory
+for the heap is allocated like this: by default, half the space between
+the first available memory address and the end of system memory is
+made available to the heap.
+
+The heap location and limit are available in two global variables, and
+can be fully customized in tx_application_define by assigning to them:
+
+ _tx_clib_heap_start Base address of heap.
+ _tx_clib_heap_end Upper limit address to which heap can grow.
+
+This must be done BEFORE any C library calls. It is advised that it be
+done at the beginning of tx_application_define.
+
+Please note that when the thread-safe C library support is used, the heap
+is not initialized before tx_kernel_enter has been called, so malloc will
+fail. It is recommended to avoid C library calls that use the heap (such
+as printf) outside of ThreadX (eg. in main). The C library is NOT safe
+for use in interrupt or exception handlers, so this should be avoided.
+
+4.5 Thread Stack Sizes
+
+The application must ensure that every thread has enough space for its
+stack. This must account for the deepest call depth and allow for one
+interrupt stack frame as defined in xtensa_context.h . Several factors
+influence the size of the stack required, including compiler optimization
+level (-O0 is worst), use of TX_ENABLE_STACK_CHECKING option, and of
+course your Xtensa configuration. Some stack size guidelines and macros
+are provided in tx_port.h assuming no optimization (default, -O0).
+
+Threads that call C library functions may need larger stacks than those
+that don't. In particular, use of printf requires a very large stack and
+will usually cause a stack overflow if inserted in a thread without
+enlarging its stack size. See DEMO_STACK_SIZE_PRINTF in demo_threadx.c
+for a guideline. Use printf with care!
+
+
+5. Assembler / Compiler Switches
+
+The following are compiler switches used in building the ThreadX library
+and demonstration system. These can be supplied by editing the Makefile
+or by overriding the COPT or CFLAGS variables in the make command line
+(eg. make COPT="-O2 -DTX_THREAD_SAFE_CLIB"). More details in Makefile.
+
+Compiler Switch Meaning
+
+ -g Specifies debug information.
+ -c Specifies object code generation.
+ -On Sets compiler optimization level n (default -O0).
+ -mlongcalls Allows assembler and linker to convert call
+ instructions to longer indirect call sequences
+ when target is out of range.
+ -x assembler-with-cpp Passes .s and .S files through C preprocessor.
+ -Dmacro Define a preprocessor macro with no value.
+ -Dmacro=value Define a preprocessor macro with a value.
+
+Application Defines (preprocessor macros definable with the -D option):
+
+ TX_THREAD_SAFE_CLIB Enable support for thread-safe C library.
+ Only the Xtensa C library and the newlib library
+ are supported for thread-safe operation.
+ When this is enabled, half the available memory
+ space is allocated by default, below the system
+ stack, for the heap. The heap size and location
+ can be customized in tx_application_define.
+ Default off.
+
+ NOTE: Thread safe support for Xtensa C library requires Xtensa Tools
+ version RF-2015.2 or later.
+
+ TX_ENABLE_STACK_CHECKING Enable generic ThreadX support for stack
+ overflow checking. This can help avoid long
+ debugging sessions or customer support calls
+ by identifying many crashes caused by stack
+ overflow. Use of this option adds a small
+ premium to the required thread stack sizes
+ (the premium is included by the stack size
+ convenience macros defined in tx_port.h).
+
+ TX_NO_TIMER Enable generic ThreadX footprint reduction when
+ no periodic tick is needed. The Xtensa port also
+ reduces footprint by removing all code related
+ to timer interrupts. Related XT_* options below
+ (XT_CLOCK_FREQ, XT_TICK_PER_SEC, XT_TIMER_INDEX)
+ have no effect under TX_NO_TIMER.
+
+ All generic ThreadX options in tx_user.h may also be defined with -D.
+
+ Note, the above defines are not specific to Xtensa processors, so
+ their names begin with "TX_". Defines below are unique to the Xtensa
+ port so have names beginning with "XT_".
+
+ XT_SIMULATOR Set this if building to run on the simulator.
+ Takes advantage of certain simulator control
+ and reporting facilities, and adjusts timing
+ of periodic tick to provide a more acceptable
+ performance in simulation (see XT_CLOCK_FREQ).
+ Set by default unless PLATFORM is overridden.
+
+ XT_BOARD=board Set this if building for a supported board.
+ The value should be the identifier of a board
+ supported in the Xtensa Tools or an external
+ package (eg. XT_BOARD=xtkc705 for the Xilinx
+ KC705 board). If the board is supported by an
+ external package, the variable XTENSA_BOARDS
+ should point to the root of the package. Set by
+ provided Makefile when PLATFORM=board and BOARD
+ is defined (eg. PLATFORM=board BOARD=xtkc705).
+
+ XT_CLOCK_FREQ=freq Specifies the target processor's clock
+ frequency in Hz. Used primarily to set the
+ timer that generates the periodic interrupt.
+ Defaults are provided and may be edited in
+ xtensa_timer.h (see comments there also).
+ Default for simulator provides more acceptable
+ performance, but cannot provide real-time
+ performance due to variation in simulation
+ speed per host platform and insufficient
+ cycles between interrupts to process them.
+ Supported board platforms by default leave
+ this undefined and compute the clock frequency
+ at initialization unless this is explicitly
+ defined.
+
+ XT_TICK_PER_SEC=n Specifies the frequency of the periodic tick.
+
+ XT_TIMER_INDEX=n Specifies which timer to use for ThreadX.
+ Set this if your Xtensa processor configuration
+ provides more than one suitable timer and you
+ want to override the default. See xtensa_timer.h.
+
+ XT_INTEXC_HOOKS Enables hooks in interrupt vector handlers
+ to support dynamic installation of exception
+ and interrupt handlers. Used by automatic
+ regression test programs. Disabled by default.
+
+ XT_USE_OVLY Enable code overlay support.
+
+ XT_USE_SWPRI Enable software prioritization of interrupts.
+ Enabling this will prioritize interrupts with
+ higher bit numbers over those with lower bit
+ numbers at the same level. This works only for
+ low and medium priority interrupts that can be
+ dispatched to C handlers.
+
+ TX_SYSTEM_STACK_SIZE=n Specify the size of the interrupt stack, which
+ is the stack that all interrupt handlers switch
+ to while handling interrupts. See the section
+ describing the interrupt stack for more details.
+
+
+6. Register Usage and Stack Frames
+
+The Xtensa architecture specifies two ABIs that determine how the general
+purpose registers a0-a15 are used: the windowed ABI, and the Call0 ABI.
+The choice of ABI is made when configuring the processor or its associated
+software. Xtensa processors may have other special registers (including
+coprocessor registers and other TIE "states") that are independent of this
+choice of ABI. See Xtensa documentation for more details.
+
+In the windowed ABI the registers of the current window are used as follows:
+ a0 = return address
+ a1 = stack pointer (alias sp)
+ a2 = first argument and result of call (in simple cases)
+ a3-7 = second through sixth arguments of call (in simple cases).
+ Note that complex or large arguments are passed on the
+ stack. Details are in the Xtensa Tools manuals.
+ a8-a15 = available for use as temporaries.
+
+There are no callee-save registers. The windowed hardware automatically
+saves registers a0-a3 on a call4, a0-a8 on a call8, a0-a12 on a call12,
+by rotating the register window. Hardware triggers window overflow and
+underflow exceptions as necessary when registers outside the current
+window need to be spilled to preallocated space in the stack frame, or
+restored. Complete details are in the Xtensa manuals. The entire windowed
+register file is saved and restored on interrupt or thread context switch.
+Note that only call0 and call8 are available in XEA3 Windowed ABI.
+
+The Call0 ABI does not make use of register windows, relying instead
+on a fixed set of 16 registers without window rotation.
+The Call0 ABI is more conventional and uses registers as follows:
+ a0 = return address
+ a1 = stack pointer (alias sp)
+ a2 = first argument and result of call (in simple cases)
+ a3-7 = second through sixth arguments of call (in simple cases).
+ Note that complex or large arguments are passed on the
+ stack. Details are in the Xtensa Tools manuals.
+ a8-a11 = scratch.
+ a12-a15 = callee-save (a function must preserve these for its caller).
+
+On a ThreadX API call, callee-save registers are saved only when a thread
+context switch occurs, and other registers are not saved at all (the caller
+does not expect them to be preserved). On an interrupt, callee-saved
+registers might only be saved and restored when a thread context-switch
+occurs, but all other registers are always saved and restored.
+
+An Xtensa processor has other special registers independent of the ABI,
+depending on the configuration (including coprocessor registers and other
+TIE state) that are part of the thread context. ThreadX preserves all such
+registers over an unsolicited context-switch triggered by an interrupt
+(including time-slice expiry). However it does NOT preserve these over
+a solicited context-switch during a ThreadX API call. This bears some
+explanation. These special registers are either ignored by the compiler
+or treated as caller-saved, meaning that if kept "live" over a function
+call (ie. need to be preserved) they must be saved and restored by the
+caller. Since solicited entry to ThreadX is always made by a function
+call, ThreadX assumes the caller has saved any of these registers that are
+"live". ThreadX avoids a lot of overhead by not having to save and restore
+every special register (there can be many) on every solicited context switch.
+
+As a consequence, the application developer should NOT assume that special
+registers are preserved over a ThreadX API call such as tx_thread_sleep.
+If multiple threads use a register, the caller must save and restore it.
+
+The saved context stack frames for context switches that occur as a result
+of interrupt handling (interrupt frame) or from thread-level API calls
+(solicited frame) are described in human readable form in xtensa_context.h .
+All suspended threads have one of these two types of stack frames. The top
+of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the
+associated thread control block TX_THREAD. An Xtensa architecture port-specific
+extension to the thread control block tx_thread_solicited contains 1 for a
+thread that is currently suspended from an API call, otherwise contains 0.
+
+
+7. Improving Performance, Footprint, or Ease of Debugging
+
+The distribution version of ThreadX is built with debug (-g) and without
+compiler optimizations (-O0). This makes debugging easier inside ThreadX
+itself. Of course, -O0 costs some performance. To make ThreadX run faster,
+you can change the Makefile to enable the desired optimizations or set
+a predefined optimization level (-O<level>) .
+
+Maximum performance is achieved with -O3, but that might increase footprint
+substantially. A good compromise is -O2. If code size is a concern, -Os may
+yield better results. See the compiler manual for details.
+
+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.
+
+The Xtensa architecture port-specific assembly files are coded with no
+file-scope labels inside functions (all labels inside functions begin with
+".L"). This allows a profiler to accurately associate an address with a
+function, and also allows the debugger's stack trace to show the correct
+function wherever the program counter is within that function. However
+there are some tradeoffs in debugging. Local (".L") labels are not
+visible to the debugger, so the following limitations may be observed
+during debugging:
+- You cannot set a breakpoint on a local label inside a function.
+- Disassembly will show the entire function, but will get out of sync and
+ show incorrect opcodes if it crosses any padding before an aligned local
+ branch target (".L" label, not ".Ln"). Restart disassembly specifying an
+ address range explicitly between points where there is padding.
+Since ThreadX is provided in source form, it is not difficult to remove
+the ".L" and ".Ln" prefixes from local labels if you want them visible.
+They can also be made visible by passing the '-L' option to the assembler
+and linker (see the assembler and linker manuals for details).
+
+
+8. Interrupt and Exception Handling
+
+NOTE: The material in this section is mostly an overview. For a more
+detailed explanation please refer to the Xtensa ISA manual and the System
+Software manual.
+
+ThreadX provides a complete set of efficient exception and first-level
+interrupt handlers installed at the appropriate exception and interrupt
+vector locations. The XEA2 architecture supports several different
+classes of exceptions and interrupts. Being a configurable architecture,
+many of these are optional, and the vector locations are determined by
+your processor configuration. The handlers provided use conditional
+compilation to adapt to your processor configuration and include only
+the code that is needed.
+
+Xtensa vector locations may reside almost anywhere, including in ROM.
+And the amount of code space available at each of these locations is
+often very small (e.g. due to following vectors). A small stub of code
+installed at the vector jumps to the corresponding handler, usually in RAM.
+The exception and interrupt handlers are defined in xtensa_vectors.S .
+They are not specific to ThreadX, but call into ThreadX where appropriate
+via macros defined in xtensa_rtos.h .
+
+Interrupt/Exception Handling in XEA2
+------------------------------------
+
+The handlers provided for low and medium priority interrupts are just
+dispatchers that save relevant state and call user-definable handlers.
+See the files xtensa_vectors.S and xtensa_api.h for more details of how
+to create and install application-specific user interrupt handlers.
+Similarly, user-defined handlers can be installed for exceptions (other
+than a few which are always handled by the OS).
+
+The high priority interrupt handlers provided may be considered templates
+into which the application adds code to service specific interrupts.
+The places where application handlers should be inserted are tagged with
+the comment "USER_EDIT" in xtensa_vectors.S.
+
+This ThreadX port supports strict priority-based nesting of interrupts.
+An interrupt may only nest on top of one of strictly lower priority.
+Equal priority interrupts concurrently pending are handled in an
+application-defined sequence before any lower priority interrupts
+are handled. During interrupt and exception handling, the processor's
+interrupt level (PS.INTLEVEL) is used to control the interrupt priority
+level that can be accepted; interrupt sources are not controlled
+individually by ThreadX (the application is free to access the INTENABLE
+register directly to enable/disable individual interrupts, e.g. using
+Xtensa HAL services). This approach provides the most deterministic
+bounds on interrupt latency (for a given priority) and system stack depth.
+
+Software prioritization of interrupts at the same priority is controlled
+by the definition of XT_USE_SWPRI. See above for a description of this
+parameter.
+
+Interrupt and Exception Handling in XEA3
+----------------------------------------
+
+In XEA3 no distinction is made between low, medium and high priority interrupt
+levels. Interrupts at all levels up to the highest (NMI) level can be dispatched
+to handlers written in C. Interrupts are dispatched by the XEA3 dispatcher and
+the handlers are found from a handler table. Handlers are installed into the
+handler table by calling xt_set_interrupt_handler. As there is no concept of
+a high priority interrupt any longer, handlers can only be specified per
+interrupt, not per level. Since all levels can be handled in C, the value of
+EXCM_LEVEL is set to the highest possible level (NMI level).
+Software prioritization is not available for XEA3.
+
+
+The following subsections describe the handling of each class of exception
+and interrupt in more detail. Many have nothing to do with ThreadX but are
+mentioned because there is code to handle them in xtensa_vectors.S.
+
+8.1 User Exception and Interrupt Handler (Low/Medium Priority)
+
+ All Xtensa 'general exceptions' come to the user, kernel, or double
+ exception vector. The exception type is identified by the EXCCAUSE
+ special register (level 1 interrupts are one particular cause of a
+ general exception). This port sets up PS to direct all such exceptions
+ to the user vector. Exceptions taken at the other two vectors usually
+ indicate a kernel or application bug.
+
+ In XEA3, everything except a double exception will come to a common
+ vector. This vector saves the requisite processor state and then checks
+ for the highest priority interrupt to dispatch. If no interrupts are
+ pending then a check is made for exceptions.
+
+ Level 1 interrupts are identified at the beginning of the handler
+ and are dispatched to a dedicated handler. Then, syscall and alloca
+ exceptions are identified and dispatched to special handlers described
+ below. After this, coprocessor exceptions are identified and dispatched
+ to the coprocessor handler.
+
+ Any remaining exceptions are processed as follows:
+
+ Having allocated the exception stack frame, the user exception handler
+ calls _tx_thread_context_save, which saves the rest of the interrupt
+ context. After this the handler sets up a C environment and enables
+ the high-priority class of interrupts (which do not interact with
+ ThreadX), then reads EXCCAUSE and uses the cause (number) to index
+ into a table of user-specified handlers. The correct handler is then
+ called. If the handler returns, the context is restored and control
+ is returned to the code that caused the exception. The user-defined
+ handler may alter the saved context, or any other system state, that
+ allows the faulting instruction to be retried.
+
+ If the cause is a level 1 (low-priority) or medium-priority interrupt,
+ the handler enables all interrupts above that priority level after
+ saving the thread context and switching to the interrupt stack if it
+ is not a nested interrupt. It then sets up the environment for C code
+ and then calls the handler (found in the handler table) for the
+ interrupt number. If the user has not specified a handler, then the
+ default handler will be called, which will terminate the program.
+
+ If the interrupt is for the system timer, it calls a special interrupt
+ handler for the system timer tick, which calls _tx_timer_interrupt then
+ clears its bit from the mask. This interrupt cannot be hooked by the
+ user-defined handler.
+
+ Finally, the handler calls _tx_thread_context_restore to allow ThreadX
+ to perform any scheduling necessary and return either to the interrupted
+ thread or another.
+
+ If software prioritization is enabled, the handler will re-enable all
+ interrupts at the same level that are numerically higher than the current
+ one, before calling the user handler. This allows a higher priority
+ interrupt to pre-empt the lower priority handler.
+
+8.2 Medium Priority Interrupt Handlers (XEA2)
+
+ Medium priority interrupts are those at levels 2 up to XCHAL_EXCM_LEVEL,
+ a configuration-specific maximum interrupt level affected by the global
+ 'exception mode' bit in the processor status word (PS.EXCM).
+ Interrupt levels above XCHAL_EXCM_LEVEL are of the high-priority class.
+ The Xtensa hardware documentation considers medium priority interrupts
+ to be a special case of high-priority interrupts, but from a software
+ perspective they are very different.
+
+ Dispatch of medium-priority interrupts is discussed in the section
+ above.
+
+8.3 High Priority Interrupt Handlers (XEA2)
+
+ High priority interrupts are those strictly above XCHAL_EXCM_LEVEL,
+ a configuration-specific maximum interrupt level affected by the
+ global 'exception mode' bit in the processor status word (PS.EXCM).
+ High priority handlers may not directly interact with ThreadX at all,
+ and are described here only for the sake of completeness. They must
+ be coded in assembler (may not be coded in C) and are intended to be
+ used for handling extremely high frequency hardware events that need
+ to be handled in only a few cycles. A high priority interrupt handler
+ may trigger a software interrupt at a medium or low priority level to
+ occasionally signal ThreadX. Please see Xtensa documentation.
+
+ There is a separate vector and a few special registers for each high
+ priority interrupt, providing for fast dispatch and efficient nesting
+ on top of lower priority interrupts. Handlers are templates included
+ only for the vectors that exist in your Xtensa processor configuration.
+ These templates are written for only one interrupt per high priority
+ level to minimize latency servicing very fast time-critical interrupts.
+ The vector code jumps to the corresponding first-level interrupt handler,
+ which then executes application-provided assembler code before returning
+ quickly to the interrupted thread or lower priority handler.
+
+8.4 Kernel Exception Handler (XEA2)
+
+ Kernel mode is not used in this port of ThreadX, and therefore kernel
+ exceptions should not happen. A stub is provided for the vector that
+ triggers the debugger (if connected) or calls _xt_panic to freeze the
+ processor should a kernel exception occur.
+
+8.5 Alloca Exception Handler
+
+ Alloca exceptions are generated by the 'movsp' instruction, which
+ is used only in the windowed ABI. Its purpose is to allocate some
+ space on top of the stack. Because the window hardware may have
+ spilled some registers to the 16 byte "base save" area below the
+ stack pointer, it is necessary to protect those values. The alloca
+ handler accomplishes this quickly without setting up an interrupt
+ frame or entering ThreadX, by emulating a register underflow and
+ re-executing 'movsp'.
+
+8.6 Syscall Exception Handler
+
+ Syscall exceptions are generated by a 'syscall' instruction.
+ The windowed ABI specifies that executing this instruction with
+ a value of zero in register a2 must spill any unsaved registers
+ in the windowed register file to their pre-determined locations
+ on the caller's stack. The handler does exactly that, and skips
+ over the 'syscall' instruction before returning to the caller.
+ If a2 is non-zero, the handler returns a2 == -1 to the caller.
+
+8.7 Co-Processor Exception Handler
+
+ A coprocessor exception is generated when a thread accesses a
+ coprocessor that it does not "own". Ownership represents which
+ thread's state is currently in the coprocessor. Co-processors are
+ context-switched "lazily" (on demand) only when a non-owning thread
+ uses a coprocessor instruction, otherwise a thread retains ownership
+ even when it is preempted from the main processor. The coprocessor
+ exception handler performs the context-switch and manages ownership.
+
+ Co-processors may not be used by any code outside the context of a
+ thread. A coprocessor exception triggered by code that is not part
+ of a running thread is a fatal error and ThreadX/Xtensa will panic.
+ This restriction is intended to reduce the overhead of saving and
+ restoring coprocessor state (which can be quite large) and in
+ particular remove that overhead from interrupt handlers. It also
+ reduces the thread stack size requirement by allowing coprocessor
+ state to be saved in the thread control block rather than the stack.
+
+8.8 Debug Exception Handler
+
+ A debug exception is caused as a result of running code, such as by
+ a 'break' instruction or hardware breakpoints and watchpoints, or
+ as a result of an external debug interrupt, such as from an OCD based
+ debugger or multiprocessor debug events ("breakin/breakout"). If the
+ processor is running in OCD mode under control of an OCD-based debugger,
+ the trigger event immediately halts the processor and gives control to
+ the OCD debugger. Otherwise control is transferred to the debug vector.
+ The debug vector handler calls the simulator if running on the ISS,
+ which then takes control and interacts with any attached debugger.
+ If running on hardware and not in OCD mode, debug exceptions are not
+ expected, so the debug handler calls _xt_panic to freeze the processor.
+
+8.9 Double Exception Handler
+
+ A double exception is a general exception that happens while the
+ processor is in exception mode (PS.EXCM set), and thus indicates a
+ bug in kernel code. The double exception vector handler triggers
+ the debugger (if connected) or calls _xt_panic to freeze the
+ processor.
+
+8.10 Window Overflow and Underflow Exception Handlers
+
+ Window overflow and underflow handlers are required for use of the
+ windowed ABI. Each has its own dedicated vector and highly optimized
+ code that is independent of OS. See Xtensa documentation for details.
+
+8.11 Hooks for Dynamic Installation of Handlers
+
+ Optional hooks are provided in the user exception and low level
+ interrupt handler and all medium and high priority interrupt handlers,
+ to dynamically install a handler function (which may be coded in C,
+ unless in a high-priority interrupt handler). These hooks are enabled
+ and used by automatic regression tests, they are not part of a normal
+ ThreadX build. However an application is free to take advantage of
+ them. The interrupt/exception hooks are described in xtensa_rtos.h .
+
+ It is recommended that the application not make use of these hooks, but
+ rather use xt_set_interrupt_handler() and xt_set_exception_handler()
+ to install application-specific handlers. This method is more convenient
+ and allows arguments to be passed to the handlers. Software prioritization
+ of interrupts works only with this method. See xtensa_api.h for details.
+
+9. Overlay Support (XEA2 only)
+
+ThreadX supports the overlay feature of the Xtensa toolsuite. To enable overlay support,
+the ThreadX library should be built with XT_USE_OVLY defined. In addition, the linker
+command line must use the overlay library via the -loverlay linker option and the
+xtensa_overlay_os_hook.o object file must be explicitly specified in order to override
+the overlay libary version.
+
+You will also need to generate a custom LSP for overlay use. Please reference the
+Xtensa System Software Reference and Xtenas Linker Support Packages (LSPs) for more
+information on using overlays.
+
+
+10. 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:
+
+04/26/2019 ThreadX Xtensa version 5.12. This release adds support for the Xtensa XEA3
+ exception architecture and the Xtensa NX processor family. The following
+ changes/enhancements are included:
+
+ Makefile Changes to support building for Xtensa
+ XEA3 configurations.
+ xtensa_vectors_xea3.S New file added, interrupt and exception
+ dispatch code for XEA3.
+
+ tx_api_asm.h Changes and additions to support the Xtensa
+ tx_port.h XEA3 exception architecture.
+ xtensa_api.h
+ xtensa_context.h
+ xtensa_rtos.h
+ xtensa_timer.h
+ tx_initialize_low_level.c
+ tx_thread_context_restore.S
+ tx_thread_context_save.S
+ tx_thread_interrupt_control.c
+ tx_thread_schedule.S
+ tx_thread_stack_build.S
+ tx_thread_system_return.S
+ tx_timer_interrupt.S
+ tx_xtensa_stack_error_handler.c
+ xtensa_context.S
+ xtensa_coproc_handler.S
+ xtensa_init.c
+ xtensa_intr.c
+ xtensa_intr_asm.S
+ xtensa_intr_wrapper.c
+ xtensa_vectors.S
+
+08/01/2017 ThreadX Xtensa version 5.11. This release includes the following changes
+ and enhancements/modifications:
+
+ Makefile Build execution profile module only
+ if the module has been selected.
+ tx_api_asm.h Changed field offsets for Xtensa-
+ specific fields in TCB.
+ tx_clib_lock.c Added thread wrapper function to handle
+ C library setup and cleanup properly.
+ tx_port.h Redefined macros as required as part of
+ the redesigned C library thread safety support.
+ tx_xtensa_stack_error_handler.c Included required headers.
+ xtensa_intr_asm.S Placed interrupt stack explicitly in .data
+ section.
+ xtensa_intr.c Fixed return values for set exception handler
+ and set interrupt handler functions.
+ xtensa_overlay_os_hook.c Added conditions so that code is now compiled
+ only if overlay option is selected.
+ xtensa_timer.h Include TIE header files conditionally.
+ *.h Modified comment(s).
+ *.S Modified comment(s).
+
+03/22/2016 ThreadX Xtensa version 5.10. This release includes the following changes
+ and enhancements: separate user-configurable interrupt stack, support for
+ Xtensa C library (xclib) thread safety, minor changes to the support for
+ the Execution Profile kit, and minor changes to remove some compiler warnings.
+ This release includes the following modifications:
+
+ tx_port.h Added support for XCLIB C library thread safety,
+ added support for separate interrupt stack,
+ added support Execution Profile Kit (EPK), and
+ updated version string.
+ tx_initialize_low_level.S Replaced by tx_initialize_low_level.c, added
+ support for XCLIB C library thread safety,
+ added support for separate interrupt stack and
+ moved setup of thread stack check callback in here
+ from demo program.
+ tx_thread_context_restore.S Added support for Execution Profile Kit (EPK).
+ tx_thread_schedule.S Added support for Execution Profile Kit (EPK), and
+ added support for XCLIB C library thread safety.
+ tx_thread_system_return.S Added support for Execution Profile Kit (EPK).
+ tx_api_asm.h Added support for XCLIB C library thread safety.
+ tx_clib_lock.c Added support for XCLIB C library thread safety.
+ xtensa_api.h Corrected issues with function declarations.
+ xtensa_context.h Corrected build errors when TX_NO_TIMER defined.
+ xtensa_intr_asm.S Added support for separate interrupt stack.
+ xtensa_overlay_os_hook.c Corrected compiler warnings.
+ xtensa_vectors.S Added support for Execution Profile Kit (EPK), and
+ added compiler warnings.
+ xtensa_timer.h Added timer related defines to simplify timer setup code.
+ Makefile Various misc updates, removed some obsolete targets.
+ tx_intr_demo.c Added support for XCLIB C library thread safety.
+ *.h Modified comment(s).
+ *.S Modified comment(s).
+
+06/01/2015 ThreadX Xtensa version 5.9. This release includes the following modifications:
+
+ tx_port.h Changed default timer thread stack size logic,
+ updated coprocessor support, and updated
+ version string.
+ tx_initialize_low_level.S Modified timer setup.
+ tx_thread_schedule.S Added setup for timing test option.
+ tx_thread_stack_build.S Added virtual priority mask setup.
+ tx_thread_system_return.S Added support for coprocessor save.
+ xtensa_context.h Added additional interrupt support, including
+ coprocessor save/restore.
+ xtensa_context.S Added additional interrupt support, including
+ coprocessor save/restore.
+ xtensa_overlay_os_hook.c Added include of overlay.h.
+ xtensa_vectors.S Added new interrupt support and functionality.
+ xtensa_api.h Added new file for this release.
+ xtensa_intr.c Added new file for this release.
+ xtensa_intr_asm.S Added new file for this release.
+ *.h Modified comment(s).
+ *.S Modified comment(s).
+
+07/31/2014 ThreadX Xtensa version 5.8. This release includes the following modifications:
+
+ tx_port.h Added in-line interrupt disable and
+ restore macros, and updated version string.
+ tx_thread_system_return.S Added context save optimization.
+ xtensa_context.h Added overlay support.
+ xtensa_context.S Added overlay support.
+ xtensa_overlay_os_hook.c Added new file for overlay support.
+ *.h Modified comment(s).
+ *.S Modified comment(s).
+
+10/01/2011 ThreadX Xtensa version 5.7. This release includes the following modifications:
+
+ tx_port.h Updated version string.
+ tx_thread_context_restore.S Changed to 16-bit save of tx_thread_cp_state.
+ tx_thread_schedule.S Changed to 16-bit restore of tx_thread_cp_state.
+ tx_thread_system_return.S Changed to 16-bit save of tx_thread_cp_state.
+ xtensa_context.h Modified alignment constants and macros.
+ xtensa_context.S Removed initial alignment adjustment.
+ *.h Modified comment(s).
+ *.S Modified comment(s).
+
+07/15/2011 ThreadX Xtensa version 5.6. This release includes the following modifications:
+
+ tx_port.h Modified control block and thread processing
+ extensions to be compatible with all cores,
+ and updated version string.
+
+ tx_clib_lock.c Added code to not use priority inheritance when
+ running the regression testsuite.
+ tx_timer_interrupt.S Added code to optionally call user timer ISR.
+ xtensa_timer.h Adjusted timer for testsuite to pass under
+ simulation.
+ xtensa_vectors.S Fixed several issues in coprocessor context
+ switch code.
+ *.S Modified comment(s).
+
+01/28/2011 ThreadX Xtensa version 5.5. This release includes the following modifications:
+
+ tx_port.h Changed version ID and added alignment padding.
+ tx_thread_stack_build.s Added code to clear solicited stack frame flag.
+ xtensa_context.h Added logic to support Xtensa processors with
+ load/store units wider than 128-bits
+ xtensa_context.s Added logic to support Xtensa processors with
+ load/store units wider than 128-bits
+ xtensa_vectors.s Added logic to support Xtensa processors with
+ load/store units wider than 128-bits
+ *.s Modified comment(s).
+
+05/01/2010 ThreadX Xtensa version 5.4. This release includes the following modifications:
+
+ tx_port.h Changed version ID.
+ tx_thread_system_return.s Changed code to preserve current time-slice value.
+ *.s Modified comment(s).
+
+07/15/2009 ThreadX Xtensa version 5.3. It includes the following modifications:
+
+ tx_port.h Added include of string.h, added GDBIO
+ constants, and modified version ID string.
+ tx_clib_lock.c Added include of stdlib.h.
+ tx_thread_context_save.S Added "XCHAL_CP_NUM > 0" conditional around
+ _tx_thread_coproc_state function definition.
+ tx_thread_schedule.S Removed #else conditional and replaced RET
+ macro with assembly code.
+ tx_thread_system_return.S Replaced ENTRY macro with assembly code.
+ xtensa_context.h Modified call frame offsets.
+ xtensa_timer.h Modified timer constants and added extern
+ for _xt_tick_diviso_init function.
+ xtensa_vectors.S Replaced exit macros.
+ tx*.h Modified comment(s).
+ tx*.c Modified comment(s).
+ tx*.S Modified comment(s).
+
+06/18/2008 ThreadX Xtensa version 5.2. It includes the following modifications:
+
+ tx_port.h Added "extern" to the interrupt control
+ function prototype, and modified
+ version ID string.
+ tx_api_asm.h Fixed bug whereby tx_thread_cp_state
+ was off by 1 word and overlapped
+ tx_thread_name if TX_THREAD_SAFE_CLIB
+ was not defined.
+ xtensa_vectors.S Strengthened syncs for strict ISA
+ conformance. Aligned exit dispatchers.
+ tx*.h Modified comment(s).
+ tx*.c Modified comment(s).
+ tx*.S Modified comment(s).
+
+04/02/2007 ThreadX Xtensa version 5.1. This release adds minor enhancements
+ and supports evaluation boards via a new board independent "XTBSP"
+ API (allowing ThreadX to take advantage of any supported board)
+ and deprecates board-specific code for the obsolete XT2000.
+ It includes the following modifications:
+
+ tx_port.h Co-proc check uses XCHAL_CP_NUM,
+ deprecated XT_XT2000 option,
+ included tx_user.h first, and
+ made TX_MAX_PRIORITIES visible
+ to assembler code.
+ tx_xtensa_stack_error_handler.c Accessed board's display via API
+ and deprecated XT_XT2000 option.
+ tx_initialize_low_level.S Co-proc check uses XCHAL_CP_NUM,
+ modified timer setup and
+ supported TX_NO_TIMER.
+ tx_thread_context_restore.S Co-proc check uses XCHAL_CP_NUM.
+ tx_thread_schedule.S Co-proc check uses XCHAL_CP_NUM.
+ tx_thread_system_return.S Co-proc check uses XCHAL_CP_NUM.
+ tx_timer_interrupt.S Use tick divisor computed via
+ API and support TX_NO_TIMER.
+ xtensa_context.h Co-proc check uses XCHAL_CP_NUM.
+ xtensa_context.S Co-proc check uses XCHAL_CP_NUM.
+ xtensa_init.c Added new initialization code to
+ set tick timer using board API.
+ xtensa_rtos.h Allowed tx_user.h macros to
+ affect Xtensa-generic macros and
+ supported TX_NO_TIMER.
+ xtensa_timer.h Updated timer configuration
+ logic and supported TX_NO_TIMER.
+ xtensa_vectors.S Co-proc check uses XCHAL_CP_NUM
+ and updated logic for long jumps
+ and supported TX_NO_TIMER.
+ tx*.h Modified comment(s).
+ tx*.c Modified comment(s).
+ tx*.S Modified comment(s).
+
+10/10/2006 Initial ThreadX version for Xtensa configurable processors
+ and Diamond pre-configured processors using Xtensa Tools.
+
+
+Copyright(c) 1996-2020 Microsoft Corporation
+
+
+https://azure.com/rtos
+
diff --git a/ports/xtensa/xcc/src/tx_clib_lock.c b/ports/xtensa/xcc/src/tx_clib_lock.c
new file mode 100644
index 00000000..072cbd52
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_clib_lock.c
@@ -0,0 +1,406 @@
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains the interface functions to provide thread-safe */
+/* operation of the C library. Both newlib and the Xtensa C Library */
+/* are supported. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+#include "tx_api.h" /* TX_THREAD_SAFE_CLIB may be defined by tx_port.h */
+#include "tx_thread.h"
+#include "tx_initialize.h"
+
+/* Xtensa specific */
+#include <xtensa/config/system.h>
+
+#ifdef TX_THREAD_SAFE_CLIB /* this file is only needed if using C lib */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+
+#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+
+#include <malloc.h>
+
+/* NOTE: should have been declared in reent.h... */
+extern void _wrapup_reent(struct _reent * ptr);
+
+/* Mutex used for all C library protection */
+TX_MUTEX clib_lock_mutex;
+
+
+/**************************************************************************/
+/* __malloc_lock - called by the malloc() family of routines when they */
+/* need to lock the memory pool. A call to malloc() may call this */
+/* function recursively. */
+/**************************************************************************/
+void
+__malloc_lock (struct _reent * ptr)
+{
+ if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
+ return;
+ }
+
+ tx_mutex_get (&clib_lock_mutex, TX_WAIT_FOREVER);
+}
+
+/**************************************************************************/
+/* __malloc_unlock - called by the malloc() family of routines when */
+/* need to unlock the memory pool. */
+/**************************************************************************/
+void
+__malloc_unlock (struct _reent * ptr)
+{
+ if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
+ return;
+ }
+
+#ifndef THREADX_TESTSUITE /* see THREADX_TESTSUITE comments below */
+ tx_mutex_prioritize (&clib_lock_mutex); /* is this at all necessary? */
+#endif
+ tx_mutex_put (&clib_lock_mutex);
+}
+
+
+/**************************************************************************/
+/* __env_lock - called by the setenv() family of routines when they */
+/* need to modify the environment. A call to setenv() may call this */
+/* function recursively. */
+/**************************************************************************/
+void
+__env_lock (struct _reent * ptr)
+{
+ if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
+ return;
+ }
+
+ tx_mutex_get (&clib_lock_mutex, TX_WAIT_FOREVER);
+}
+
+/**************************************************************************/
+/* __env_unlock - called by the setenv() family of routines when they */
+/* need to unlock the environment. */
+/**************************************************************************/
+void
+__env_unlock (struct _reent * ptr)
+{
+ if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
+ return;
+ }
+
+ tx_mutex_prioritize (&clib_lock_mutex);
+ tx_mutex_put (&clib_lock_mutex);
+}
+
+#endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
+
+#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
+
+#include <errno.h>
+#include <sys/reent.h>
+
+#define XT_NUM_CLIB_LOCKS (_MAX_LOCK + FOPEN_MAX)
+
+typedef TX_MUTEX * _Rmtx;
+
+static TX_MUTEX xclib_locks[XT_NUM_CLIB_LOCKS];
+static uint32_t lcnt;
+
+/* Override this and set to nonzero to enable locking. */
+int32_t _xclib_use_mt = 1;
+
+
+/**************************************************************************/
+/* _Mtxinit - initialize a lock. Called once for each lock. */
+/**************************************************************************/
+void
+_Mtxinit (_Rmtx * mtx)
+{
+ TX_MUTEX * lock;
+
+ if (lcnt >= XT_NUM_CLIB_LOCKS) {
+ /* Fatal error */
+ }
+
+ lock = &(xclib_locks[lcnt]);
+ lcnt++;
+
+ /* See notes for newlib case below. */
+#ifdef THREADX_TESTSUITE
+ tx_mutex_create (lock, "Clib lock", 0);
+#else
+ tx_mutex_create (lock, "Clib lock", TX_INHERIT);
+#endif
+
+ *mtx = lock;
+}
+
+/**************************************************************************/
+/* _Mtxdst - destroy a lock. Called once for each lock. */
+/**************************************************************************/
+void
+_Mtxdst (_Rmtx * mtx)
+{
+ if ((mtx) && (*mtx)) {
+ tx_mutex_delete (*mtx);
+ }
+}
+
+/**************************************************************************/
+/* _Mtxlock - acquire lock. */
+/**************************************************************************/
+void
+_Mtxlock (_Rmtx * mtx)
+{
+ if ((mtx) && (*mtx)) {
+ tx_mutex_get (*mtx, TX_WAIT_FOREVER);
+ }
+}
+
+/**************************************************************************/
+/* _Mtxunlock - release a lock. */
+/**************************************************************************/
+void
+_Mtxunlock (_Rmtx * mtx)
+{
+ if ((mtx) && (*mtx)) {
+ tx_mutex_put (*mtx);
+ }
+}
+
+#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
+
+
+/**************************************************************************/
+/* _sbrk_r - heap allocator. This function is called when the memory */
+/* allocator needs a new chunk of memory. */
+/* The bounds of the heap area are global variables so that customer */
+/* startup code can easily override them if needed. */
+/* */
+/* _tx_clib_heap_start is the start of memory assigned to the heap */
+/* or 0 (NULL) if no memory is assigned (in */
+/* that case all calls to malloc will fail). */
+/* */
+/* _tx_clib_heap_end is the end of memory assigned to the heap */
+/* or 0 (NULL) if no memory is assigned. If a */
+/* nonzero start value is set then a nonzero */
+/* end value must be set. */
+/**************************************************************************/
+
+char * _tx_clib_heap_start = NULL;
+char * _tx_clib_heap_end = NULL;
+
+void *
+_sbrk_r (struct _reent * reent, int32_t incr)
+{
+ static char * heap_ptr;
+ char * new_heap_ptr;
+ char * alloc_ptr;
+
+ /* The heap is bound by _tx_clib_heap_{start,end}. */
+ if (heap_ptr == NULL) {
+ heap_ptr = _tx_clib_heap_start;
+ }
+
+ new_heap_ptr = heap_ptr + incr;
+ if ((heap_ptr == NULL) || /* no heap */
+ (new_heap_ptr >= _tx_clib_heap_end) || /* heap exhausted */
+ (new_heap_ptr < heap_ptr)) { /* wraparound */
+ reent->_errno = ENOMEM;
+ return (void *) -1;
+ }
+
+ alloc_ptr = heap_ptr;
+ heap_ptr = new_heap_ptr;
+ return (void *) alloc_ptr;
+}
+
+
+/**************************************************************************/
+/* _tx_clib_init - initialize C library thread safety support. */
+/* Called by _tx_initialize_low_level(). */
+/**************************************************************************/
+void
+_tx_clib_init (void)
+{
+#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+#ifdef THREADX_TESTSUITE
+ /* Priority inheritance causes printf() (which calls malloc()
+ which calls __malloc_unlock() which calls tx_mutex_put()
+ which calls _tx_mutex_priority_change() if TX_INHERIT is set)
+ which causes the task to suspend and resume which sometimes
+ changes execution order in the very sensitive testsuite
+ and makes it fail. So, for the testsuite, don't request
+ priority inheritance (it doesn't need it in any case). */
+ tx_mutex_create (&clib_lock_mutex, "Clib lock", 0);
+#else
+ tx_mutex_create (&clib_lock_mutex, "Clib lock", TX_INHERIT);
+#endif
+#endif /* NEWLIB */
+
+#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ /* Nothing. */
+#endif /* XCLIB */
+}
+
+
+/**************************************************************************/
+/* _tx_clib_reent_init - initialize C library thread reent structure. */
+/* Called by tx_thread_create() to init per-thread C library state. */
+/**************************************************************************/
+void
+_tx_clib_reent_init (TX_THREAD * thread_ptr)
+{
+ if (thread_ptr == NULL) {
+ /* Should never happen */
+ return;
+ }
+
+#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+ struct _reent * reent = &(thread_ptr->tx_thread_clib_reent);
+
+ memset (reent, 0, sizeof(struct _reent));
+ _REENT_INIT_PTR (reent);
+ thread_ptr->tx_thread_clib_ptr = reent;
+#endif
+
+#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ thread_ptr->tx_thread_clib_ptr = &(thread_ptr->tx_thread_clib_reent);
+ _init_reent (thread_ptr->tx_thread_clib_ptr);
+#endif
+}
+
+
+/**************************************************************************/
+/* _tx_clib_reent_cleanup - clean up C library thread reent structure. */
+/* Called by tx_thread_delete() to clean up per-thread C library state */
+/* and free any allocated memory (partial = 0). */
+/* Called by tx_thread_shell_entry and tx_thread_terminate to perform */
+/* "atexit" processing and clean up stdio, but leaving the rest of the */
+/* structure intact so the thread can be restarted (partial = 1). */
+/**************************************************************************/
+void
+_tx_clib_reent_cleanup (TX_THREAD * thread_ptr, int32_t partial)
+{
+#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+ struct _reent * reent = &(thread_ptr->tx_thread_clib_reent);
+ FILE * fp = &(reent->__sf[0]);
+ int32_t i;
+
+ /* Avoid closing stdin,stdout,stderr so other threads can still use them. */
+ for (i = 0; i < 3; i++) {
+ fp->_close = NULL;
+ fp++;
+ }
+
+ if (partial != 0) {
+ /* Perform "atexit" processing and clean up stdio. */
+ _wrapup_reent (reent);
+ }
+ else {
+ /* Free all the heap memory allocated in the reent structure.
+ ThreadX requires that the thread has either exited or been
+ terminated before it can be deleted so we can assume that
+ _wrapup_reent has already been called for this thread. */
+ _reclaim_reent (reent);
+ }
+#endif
+
+#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ /* Unused, keep compiler happy */
+ (void) partial;
+
+ /* File handle table is global; no allocated memory in struct. */
+ thread_ptr->tx_thread_clib_ptr = 0;
+#endif
+}
+
+
+/**************************************************************************/
+/* _xt_wrapper - thread wrapper to handle C library init/cleanup. */
+/* If C library thread safety is enabled, every thread is invoked */
+/* via this wrapper in order to handle thread context setup/cleanup. */
+/**************************************************************************/
+void
+_xt_thread_wrapper (ULONG arg)
+{
+ TX_INTERRUPT_SAVE_AREA
+ TX_THREAD * thread_ptr = _tx_thread_current_ptr;
+
+ /* No use for this parameter */
+ (void) arg;
+
+ /* Init the C library thread context */
+ _tx_clib_reent_init (thread_ptr);
+
+ /* Disable interrupts around the global context ptr update */
+ TX_DISABLE
+
+#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+ _impure_ptr = thread_ptr->tx_thread_clib_ptr;
+#endif
+#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ _reent_ptr = thread_ptr->tx_thread_clib_ptr;
+#endif
+
+ TX_RESTORE
+
+ /* Call actual thread entry point */
+ (thread_ptr->tx_real_thread_entry)(thread_ptr->tx_thread_entry_parameter);
+
+ /* Clean up C library thread context */
+ _tx_clib_reent_cleanup(thread_ptr, 1);
+ _tx_clib_reent_cleanup(thread_ptr, 0);
+}
+
+
+/**************************************************************************/
+/* _tx_clib_thread_setup - Xtensa-specific thread setup actions. */
+/* This function will be called only if thread safe C library usage */
+/* is enabled. It inserts the wrapper as the thread entry point and */
+/* saves the actual entry point for later use. */
+/**************************************************************************/
+void
+_tx_clib_thread_setup (TX_THREAD * thread_ptr)
+{
+ thread_ptr->tx_real_thread_entry = thread_ptr->tx_thread_entry;
+ thread_ptr->tx_thread_entry = &(_xt_thread_wrapper);
+}
+
+#endif /* TX_THREAD_SAFE_CLIB */
+
diff --git a/ports/xtensa/xcc/src/tx_initialize_low_level.c b/ports/xtensa/xcc/src/tx_initialize_low_level.c
new file mode 100644
index 00000000..d7082db0
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_initialize_low_level.c
@@ -0,0 +1,187 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+
+#include "tx_api.h"
+#include "tx_port.h"
+#include "xtensa_api.h"
+
+#if XCHAL_HAVE_ISL || XCHAL_HAVE_KSL || XCHAL_HAVE_PSL
+#include <xtensa/tie/xt_exception_dispatch.h>
+#endif
+
+
+#if XCHAL_HAVE_XEA3
+int32_t xt_sw_intnum = -1;
+int32_t xt_timer_intnum = -1;
+#endif
+
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* It also sets the default heap region for the optional C library. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+VOID _tx_initialize_low_level(VOID)
+{
+ extern char _xt_interrupt_stack_top;
+ extern void _tx_timer_interrupt(void *);
+ extern void * _tx_thread_system_stack_ptr;
+ extern void * _tx_initialize_unused_memory;
+ extern char _end;
+
+ #ifdef TX_THREAD_SAFE_CLIB
+ extern char __stack;
+ extern void _tx_clib_init(void);
+ #endif
+
+ #if XCHAL_CP_NUM > 0
+ extern void _xt_coproc_init(void);
+ extern void _xt_coproc_exc(XtExcFrame * fp);
+ #endif
+
+ #ifdef TX_ENABLE_STACK_CHECKING
+ extern VOID _tx_xtensa_stack_error_handler(TX_THREAD * thread);
+ #endif
+
+ #if XCHAL_HAVE_XEA3
+ extern void xt_sched_handler(void * arg);
+ int32_t i;
+ #endif
+
+ TX_INTERRUPT_SAVE_AREA
+
+ /* Disable interrupts - don't want any that interact with ThreadX yet. */
+ TX_DISABLE
+
+ /*
+ Disable stack limit checking if present. Whatever was set up earlier
+ is not going to work for us.
+ */
+#if XCHAL_HAVE_KSL
+ XT_WSR_KSL(0);
+#endif
+#if XCHAL_HAVE_ISL
+ XT_WSR_ISL(0);
+#endif
+
+ /* Save the system stack pointer. */
+ _tx_thread_system_stack_ptr = &(_xt_interrupt_stack_top);
+
+ /* Save the first available memory address. */
+ _tx_initialize_unused_memory = (void *)(((UINT)&_end + 15) & ~0xF);
+
+ #ifdef TX_THREAD_SAFE_CLIB
+ /*
+ Pre-allocate default memory region for the C library heap.
+ Bisect the region from first available memory to end of system memory,
+ align to 16 byte boundary, and allocate the heap in the upper half.
+ */
+ _tx_clib_heap_end = &(__stack);
+ _tx_clib_heap_start =
+ (void *)(((UINT)_tx_initialize_unused_memory/2 + (UINT)_tx_clib_heap_end/2) & ~0xF);
+ #endif
+
+ #if XCHAL_CP_NUM > 0
+ /*
+ Initialize co-processor management for threads. Leave CPENABLE alone.
+ This is called from a normal Xtensa single-threaded run-time environment
+ before multi-threading has commenced. All co-processors are enabled.
+ It is important NOT to clear CPENABLE yet because tx_application_define()
+ is user code which might use a co-processor. The co-processor exception
+ handler does not expect to be called outside a thread.
+ */
+ _xt_coproc_init();
+
+ #if XCHAL_HAVE_XEA3
+ /* Install the coprocessor exception handler. */
+ xt_set_exception_handler(EXCCAUSE_CP_DISABLED, _xt_coproc_exc);
+ #endif
+ #endif
+
+ #if XCHAL_HAVE_XEA3
+ /* Select a software interrupt to use for scheduling. */
+ for (i = 0; i < XCHAL_NUM_INTERRUPTS; i++) {
+ if ((Xthal_inttype[i] == XTHAL_INTTYPE_SOFTWARE) && (Xthal_intlevel[i] == 1)) {
+ xt_sw_intnum = i;
+ break;
+ }
+ }
+
+ if (xt_sw_intnum == -1) {
+ __asm__ volatile ("break 1, 1");
+ }
+
+ /* Set the interrupt handler and enable the interrupt. */
+ xt_set_interrupt_handler(xt_sw_intnum, xt_sched_handler, 0);
+ xt_interrupt_enable(xt_sw_intnum);
+ #endif
+
+ #ifndef TX_NO_TIMER
+
+ /* Compute tick divisor if clock freq is not compile-time constant. */
+ #ifndef XT_CLOCK_FREQ
+ _xt_tick_divisor_init();
+ #endif
+
+ /* Set up the periodic tick timer (assume enough time to complete init). */
+ #ifdef XT_CLOCK_FREQ
+ XT_WSR_CCOMPARE(XT_RSR_CCOUNT() + XT_TICK_DIVISOR);
+ #else
+ XT_WSR_CCOMPARE(XT_RSR_CCOUNT() + _xt_tick_divisor);
+ #endif
+
+ #if XCHAL_HAVE_XEA3
+ xt_timer_intnum = XT_TIMER_INTNUM;
+ xt_set_interrupt_handler(xt_timer_intnum, _tx_timer_interrupt, 0);
+ #endif
+
+ /* Enable the timer interrupt at the device level. */
+ xt_interrupt_enable(XT_TIMER_INTNUM);
+
+ #endif /* TX_NO_TIMER */
+
+ /* Initialize C library thread safety support. */
+ #ifdef TX_THREAD_SAFE_CLIB
+ _tx_clib_init();
+ #endif
+
+ /* Install stack overflow notification callback. */
+ #ifdef TX_ENABLE_STACK_CHECKING
+ tx_thread_stack_error_notify(_tx_xtensa_stack_error_handler);
+ #endif
+}
+
diff --git a/ports/xtensa/xcc/src/tx_thread_context_restore.S b/ports/xtensa/xcc/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..aa628751
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_thread_context_restore.S
@@ -0,0 +1,216 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "xtensa_rtos.h"
+#include "tx_api_asm.h"
+
+
+#if XCHAL_HAVE_XEA2
+
+ .text
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/* RELEASE HISTORY */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .globl _tx_thread_context_restore
+ .type _tx_thread_context_restore,@function
+ .align 4
+_tx_thread_context_restore:
+
+ /*
+ Please note: Control flow might seem strange. This is because it has been
+ optimized to avoid taken branches in the longest normal path (the critical
+ one for worst-case latency), presumed to be a non-nested interrupt that
+ preempts) and to hide pipeline interlock cycles where possible.
+ */
+
+ /* Lockout interrupts. */
+ XT_INTS_DISABLE(a0)
+
+ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ #ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_execution_isr_exit
+ #else
+ call8 _tx_execution_isr_exit
+ #endif
+ #endif
+
+ /* Determine if interrupts are nested. */
+ // if (--_tx_thread_system_state)
+ // {
+
+ movi a2, _tx_thread_system_state /* a2 = & interrupt nesting count */
+ l32i a3, a2, 0 /* decrement interrupt nesting count */
+ addi a3, a3, -1
+ s32i a3, a2, 0
+ bnez a3, .L_tx_thread_nested_restore
+
+ // }
+
+.Ln_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))
+ // {
+
+ movi a0, _tx_thread_current_ptr /* a0 = &_tx_thread_current_ptr */
+ l32i a2, a0, 0 /* a2 = _tx_thread_current_ptr (old) */
+ movi a3, _tx_thread_execute_ptr
+ beqz a2, .L_tx_thread_idle_system_restore
+
+ l32i a3, a3, 0 /* a3 = _tx_thread_execute_ptr (new) */
+ beq a3, a2, .L_tx_thread_no_preempt_restore
+
+ movi a3, _tx_thread_preempt_disable
+ l32i a3, a3, 0 /* a3 = _tx_thread_preempt_disable */
+
+ // /* the no-preempt case has moved down so we fall-thru to preempt */
+ bgei a3, 1, .L_tx_thread_no_preempt_restore
+
+ // }
+ // else
+ // {
+
+.Ln_tx_thread_preempt_restore:
+
+ /* Save remaining context on the thread's stack. */
+ l32i a3, a2, tx_thread_stack_ptr /* a3 = thread's stack ptr */
+
+ /* Store standard preserved registers. */
+ /*
+ Call0 ABI callee-saved regs a12-15 need to be saved before preemption.
+ However a12-13 were saved for scratch by _tx_thread_context_save().
+ */
+ #ifdef __XTENSA_CALL0_ABI__ /* Call0: now save callee-save regs */
+ s32i a14, a3, XT_STK_A14
+ s32i a15, a3, XT_STK_A15
+ #endif
+
+ /* Save the remaining time-slice and disable it. */
+ // if (_tx_timer_time_slice)
+ // {
+ movi a3, _tx_timer_time_slice /* a3 = &_tx_timer_time_slice */
+ l32i a4, a3, 0 /* a4 = _tx_timer_time_slice */
+ beqz a4, .L_tx_thread_dont_save_ts
+
+ // _tx_thread_current_ptr -> tx_thread_time_slice
+ // = _tx_timer_time_slice;
+ // _tx_timer_time_slice = 0; */
+ s32i a4, a2, tx_thread_time_slice
+ movi a4, 0
+ s32i a4, a3, 0
+
+ // }
+
+.L_tx_thread_dont_save_ts:
+
+ /* Clear the current task pointer. */
+ // _tx_thread_current_ptr = TX_NULL;
+ s32i a4, a0, 0 /* a4 == 0 == TX_NULL */
+
+ #if XCHAL_CP_NUM > 0
+ /* Save CPENABLE in thread's co-processor save area, and clear CPENABLE. */
+ rsr a3, CPENABLE
+ s16i a3, a2, tx_thread_cp_state + XT_CPENABLE
+ wsr a4, CPENABLE /* disable all co-processors */
+ #endif
+
+.L_tx_thread_idle_system_restore:
+
+ /*
+ Return via the scheduler.
+ Scheduler returns eventually to this function's caller as if called by it.
+ At this point we are still on the system stack.
+ */
+ // _tx_thread_schedule();
+ call0 _tx_thread_schedule /* never returns here */
+
+ // }
+
+ /* Flow never falls through here. */
+
+.L_tx_thread_no_preempt_restore:
+
+ /* Restore interrupted thread. */
+
+ /* Pickup the saved stack pointer. */
+ // SP = _tx_thread_current_ptr -> tx_thread_stack_ptr;
+ l32i sp, a2, tx_thread_stack_ptr
+
+.L_tx_thread_nested_restore:
+
+ /* Recover the saved context and return to the point of interrupt. */
+
+ call0 _xt_context_restore
+
+ /*
+ Must return via the exit dispatcher corresponding to the entrypoint
+ from which this was called. Interruptee's A0, A1, PS, PC are restored
+ and the interrupt stack frame is deallocated in the exit dispatcher.
+ At this point we are on the thread's stack.
+ */
+ l32i a0, sp, XT_STK_EXIT
+ ret
+
+// }
+
+#endif /* XCHAL_HAVE_XEA2 */
+
diff --git a/ports/xtensa/xcc/src/tx_thread_context_save.S b/ports/xtensa/xcc/src/tx_thread_context_save.S
new file mode 100644
index 00000000..4025ea66
--- /dev/null
+++ b/ports/xtensa/xcc/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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#include "xtensa_rtos.h"
+#include "tx_api_asm.h"
+
+
+#if XCHAL_HAVE_XEA2
+
+ .text
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/* Interrupts remain disabled and no exceptions are triggered! */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+// VOID _tx_thread_context_save(VOID)
+// {
+ .globl _tx_thread_context_save
+ .type _tx_thread_context_save,@function
+ .align 4
+_tx_thread_context_save:
+
+ /*
+ Please note: Control flow might seem strange. This is because it has been
+ optimized to avoid taken branches in the longest normal path (the critical
+ one for worst-case latency), presumed to be a non-nested interrupt and
+ non-idle) and to hide pipeline interlock cycles where possible.
+ */
+
+ /*
+ Save a couple of scratch regs to work with that are preserved over the
+ call to _xt_context_save. The latter assumes the interruptee's values
+ of these are already saved and these regs contain different data to be
+ preserved, so doesn't save them in the stack frame, and thereby requires
+ that its caller have already saved them in the interrupt stack frame.
+ We end up with a12 = return address, a13 and a0 are scratch.
+ */
+ s32i a12, sp, XT_STK_A12
+ s32i a13, sp, XT_STK_A13
+
+ /* Check for a nested interrupt condition and increment nesting count. */
+ // if (_tx_thread_system_state++)
+ // {
+ movi a13, _tx_thread_system_state /* a13 = & interrupt nesting count */
+ mov a12, a0 /* a12 = save ret addr (free a0) */
+ l32i a0, a13, 0 /* increment interrupt nesting count */
+ addi a0, a0, 1
+ s32i a0, a13, 0
+ bnei a0, 1, .L_tx_thread_nested_save /* was !=0 before increment? */
+
+ // }
+
+.Ln_tx_thread_not_nested_save:
+
+ /* Otherwise, not nested, check to see if a thread was running. */
+ // else
+ // {
+ // if (_tx_thread_current_ptr)
+ // {
+ movi a0, _tx_thread_current_ptr
+ l32i a13, a0, 0 /* a13 = current thread ctrl blk */
+ beqz a13, .L_tx_thread_idle_system_save
+
+ /* Save the rest of the interrupted context. */
+ call0 _xt_context_save
+
+ /* Save the current stack pointer in the thread's control block. */
+ // _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
+ s32i sp, a13, tx_thread_stack_ptr
+
+ // }
+ /* Switch to the system stack and return to ISR. */
+
+.L_tx_thread_idle_system_save:
+
+ /*
+ If interrupted in the idle state, it's not necessary to save any context.
+ But even in the idle case where we are already on the system stack, it is
+ necessary to reset the (system) stack pointer so a series of consecutive
+ interrupts in the idle state do not keep moving the SP downward.
+ */
+
+ // sp = _tx_thread_system_stack_ptr;
+ movi a13, _tx_thread_system_stack_ptr
+ mov a0, a12 /* retrieve return address */
+ l32i sp, a13, 0
+
+ ret
+ // }
+
+.L_tx_thread_nested_save:
+ /* Nested interrupt condition. */
+ /* Save the rest of the interrupted context and return to ISR. */
+ call0 _xt_context_save
+
+ mov a0, a12 /* retrieve return address */
+ ret
+
+// }
+
+#endif /* XCHAL_HAVE_XEA2 */
+
diff --git a/ports/xtensa/xcc/src/tx_thread_interrupt_control.c b/ports/xtensa/xcc/src/tx_thread_interrupt_control.c
new file mode 100644
index 00000000..1a9d42c3
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_thread_interrupt_control.c
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "tx_api.h"
+#include "xtensa_rtos.h"
+
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for changing the interrupt lockout */
+/* posture of the system. */
+/* NOTE: In earlier versions this was implemented in assembly. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+UINT _tx_thread_interrupt_control(UINT new_posture)
+{
+#if XCHAL_HAVE_XEA2
+ UINT ret = XT_RSIL(15);
+
+ XT_WSR_PS((ret & ~0xF) | (new_posture & 0xF));
+ XT_RSYNC();
+ return ret & 0xF;
+#else
+ UINT ret = xthal_disable_interrupts();
+
+ xthal_restore_interrupts(new_posture);
+ return ret;
+#endif
+}
+
diff --git a/ports/xtensa/xcc/src/tx_thread_schedule.S b/ports/xtensa/xcc/src/tx_thread_schedule.S
new file mode 100644
index 00000000..287c3530
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_thread_schedule.S
@@ -0,0 +1,253 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "tx_port.h"
+#include "xtensa_rtos.h"
+#include "tx_api_asm.h"
+
+ .text
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+// VOID _tx_thread_schedule(VOID)
+// {
+ .globl _tx_thread_schedule
+ .type _tx_thread_schedule,@function
+ .align 4
+_tx_thread_schedule:
+
+#if XCHAL_HAVE_XEA3
+
+ /* Skip "entry" - nothing to save, never returns. */
+
+ movi a2, PS_STACK_KERNEL | PS_DI /* Set PS.STACK = Kernel and */
+ movi a3, PS_STACK_MASK | PS_DI_MASK /* disable interrupts. */
+ xps a2, a3
+
+#ifdef __XTENSA_CALL0_ABI__
+ mov a15, a1 /* Dispatch code expects a15 = old SP */
+#endif
+
+ movi a0, _xt_dispatch + 3 /* Jump to dispatch code. It will */
+ ret /* check for ready thread or idle */
+ /* and handle accordingly. */
+
+ ill /* Should never get back here. */
+
+#else
+
+ /*
+ Note on Windowed ABI:
+ Callers of this don't expect it to return to them. Most use 'call0'.
+ The only windowed (C) caller is _tx_initialize_kernel_enter().
+ There are no args or results to pass. So we don't really care if the
+ window gets rotated. We can omit the 'entry' altogether and avoid the
+ need for a special "no entry" entrypoint to this function.
+ */
+
+ #ifdef XT_ENABLE_TIMING_TEST_HACK
+ /* For timing_test "TS" numbers. INTERNAL USE ONLY. */
+ /* Always use CALL0. We may be here with windowing disabled. */
+ .extern scheduler_return
+ call0 scheduler_return
+ #endif
+
+ /*
+ Wait for a thread to execute (Idle Loop).
+ First ensure interrupts (except hi-pri) are disabled so result
+ of reading _tx_thread_execute_ptr can't change before testing.
+ While there's no thread ready, enable interrupts and wait in a
+ low power state, then disable interrupts and repeat the test.
+ */
+ // do
+ // {
+ movi a3, _tx_thread_execute_ptr
+.L_tx_thread_schedule_loop: /* Idle Loop. */
+ XT_INTS_DISABLE(a2) /* disable interrupts if not already */
+ l32i a2, a3, 0 /* a2 = _tx_thread_execute_ptr */
+ bnez a2, .L_tx_thread_schedule_ready
+ waiti 0 /* enable interrupts and wait for */
+ /* interrupt in low power state */
+ j .L_tx_thread_schedule_loop
+
+ // }
+ // while(_tx_thread_execute_ptr == TX_NULL);
+
+.L_tx_thread_schedule_ready:
+
+ /* Yes! We have a thread to execute. Lockout interrupts and
+ transfer control to it. Interrupts are already disabled. */
+
+ /* Setup the current thread pointer. */
+ // _tx_thread_current_ptr = _tx_thread_execute_ptr;
+ movi a3, _tx_thread_current_ptr
+ l32i a0, a2, tx_thread_run_count
+ s32i a2, a3, 0 /* a2 = _tx_thread_current_ptr (TCB) */
+
+ /* Increment the run count for this thread. */
+ // _tx_thread_current_ptr -> tx_thread_run_count++;
+ addi a3, a0, 1
+ movi a0, _tx_timer_time_slice
+ s32i a3, a2, tx_thread_run_count
+
+ /* Setup time-slice, if present. */
+ // _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
+ l32i a3, a2, tx_thread_time_slice
+ s32i a3, a0, 0
+
+ #ifdef TX_THREAD_SAFE_CLIB
+ // Load library-specific global context ptr address. */
+
+ #if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
+ movi a0, _impure_ptr
+ #elif XSHAL_CLIB == XTHAL_CLIB_XCLIB
+ movi a0, _reent_ptr
+ #else
+ #error TX_THREAD_SAFE_CLIB defined with unsupported C library.
+ #endif
+
+ l32i a3, a2, tx_thread_clib_ptr
+ s32i a3, a0, 0 /* point to thread's reent struct */
+ #endif
+
+ /* Switch to the thread's stack. */
+ // SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr;
+ l32i sp, a2, tx_thread_stack_ptr
+
+ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the thread entry function to indicate the thread is executing. */
+ #ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_execution_thread_enter
+ #else
+ call8 _tx_execution_thread_enter
+ #endif
+ #endif
+
+ /* Determine if an interrupt frame or a synchronous task suspension frame
+ is present. */
+ l32i a3, a2, tx_thread_solicited
+ bnez a3, .L_tx_thread_synch_return
+
+.Ln_tx_thread_asynch_return:
+
+ #if XCHAL_CP_NUM > 0
+ /* Restore thread's CPENABLE (enable co-processors this thread owns). */
+ l16ui a3, a2, tx_thread_cp_state + XT_CPENABLE
+ wsr a3, CPENABLE
+ #endif
+
+ /* Here we return from unsolicited entry with an interrupt stack frame. */
+ call0 _xt_context_restore
+
+ /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */
+ #ifdef __XTENSA_CALL0_ABI__
+ l32i a14, sp, XT_STK_A14
+ l32i a15, sp, XT_STK_A15
+ #endif
+
+ #if XCHAL_CP_NUM > 0
+ rsync /* ensure wsr.CPENABLE has completed */
+ #endif
+
+ /*
+ This does not return to its caller, but to the selected thread.
+ Must return via the exit dispatcher corresponding to the entrypoint
+ from which this was called. Interruptee's A0, A1, PS, PC are restored
+ and the interrupt stack frame is deallocated in the exit dispatcher.
+ */
+ l32i a0, sp, XT_STK_EXIT
+ ret
+
+.L_tx_thread_synch_return:
+
+ /* Here we return from a solicited entry with a solicited stack frame. */
+ movi a0, TX_FALSE
+ l32i a3, sp, XT_STK_PS
+ s32i a0, a2, tx_thread_solicited
+
+ #ifdef __XTENSA_CALL0_ABI__
+ l32i a12, sp, XT_STK_A12
+ l32i a13, sp, XT_STK_A13
+ l32i a14, sp, XT_STK_A14
+ l32i a15, sp, XT_STK_A15
+ #endif
+
+ l32i a0, sp, XT_STK_PC /* return address */
+
+ #if XCHAL_CP_NUM > 0
+ /* CPENABLE should already be clear (it was cleared on entry to kernel). */
+ rsync /* ensure wsr.CPENABLE has completed */
+ #endif
+
+ wsr a3, PS /* no need to sync PS, delay is OK */
+
+ /* This does not return to its caller, but to the selected thread. */
+ #ifdef __XTENSA_CALL0_ABI__
+ /* 'addi sp, sp, imm' could turn into 'addmi, addi' sequence and make */
+ /* the sp briefly point to an illegal stack location. Avoid that. */
+ addi a2, sp, XT_STK_FRMSZ
+ mov sp, a2
+ ret
+ #else
+ retw
+ #endif
+
+#endif /* XCHAL_HAVE_XEA3 */
+// }
+
diff --git a/ports/xtensa/xcc/src/tx_thread_stack_build.S b/ports/xtensa/xcc/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..688e947d
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_thread_stack_build.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "xtensa_rtos.h"
+#include "tx_api_asm.h"
+
+ .text
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* This function builds a stack frame on the supplied thread's stack. */
+/* The stack frame looks like an interrupt frame or a solicited frame */
+/* depending on the exception architecture of the target hardware. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .globl _tx_thread_stack_build
+ .type _tx_thread_stack_build,@function
+ .align 4
+_tx_thread_stack_build:
+
+ ENTRY0
+
+ /* Get logical base of stack area (top). */
+ l32i a5, a2, tx_thread_stack_end /* get top-1 of stack area */
+ addi a5, a5, 1 /* undo the -1 */
+ srli a5, a5, 4 /* force 16-byte alignment */
+ slli a5, a5, 4 /* a5 = post-dispatch SP (frame top) */
+
+ /* Allocate space for the frame (frame size is already 16-byte aligned). */
+ addi a4, a5, -XT_STK_FRMSZ /* a4 = pre-dispatch SP (frame base) */
+
+ /* Set the thread's SP. */
+ s32i a4, a2, tx_thread_stack_ptr
+
+#if !XCHAL_HAVE_XEA2
+ addi a4, a4, XT_STK_XTRA_SZ /* a4 = base of exception frame */
+#endif
+
+ /* Clear the entire frame. (XEA3: only exception frame) */
+ movi a6, 0 /* a6 = 0 */
+ mov a7, a4 /* a7 = ptr to current word */
+1: s32i a6, a7, 0 /* clear current word */
+ addi a7, a7, 4 /* point to next word */
+ bltu a7, a5, 1b /* repeat until frame top */
+
+#if XCHAL_HAVE_XEA2
+ s32i a5, a4, XT_STK_A1 /* save post-dispatch SP in frame */
+#endif
+
+ /* Indicate a solicited or interrupted stack frame. */
+#if XCHAL_HAVE_XEA2
+ movi a7, 0 /* interrupted */
+#else
+ movi a7, 0 /* solicited */
+#endif
+ s32i a7, a2, tx_thread_solicited
+
+ /*
+ Terminate GDB backtrace in this thread at the "return function" by ensuring
+ it's A0 == 0. Since frame was cleared, don't need to do this explicitly.
+ s32i a6, a4, XT_STK_A0
+ */
+
+ /* Set the return address to the return function. */
+ /* Start thread via user exception exit dispatcher (could use any). */
+#if XCHAL_HAVE_XEA2
+ movi a5, _xt_user_exit
+ s32i a5, a4, XT_STK_EXIT
+#else
+ movi a5, 0
+ s32i a5, a4, XT_STK_ATOMCTL
+#endif
+
+ s32i a3, a4, XT_STK_PC
+
+ /*
+ Set thread's initial PS for C code, all int levels enabled.
+ XEA2: Since we dispatch via level 1 (_xt_user_exit), must set PS.EXCM,
+ which will be cleared by 'rfe' after the dispatcher, to prevent
+ interrupts happening when PS is restored during the exit dispatcher.
+ XEA3: nothing special, other than setting the thread stack type.
+ */
+#if XCHAL_HAVE_XEA2
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a6, PS_UM | PS_EXCM
+ #else
+ movi a6, PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1) /* pretend 'call4' */
+ #endif
+#else
+ movi a6, PS_STACK_FIRSTKER
+#endif
+ s32i a6, a4, XT_STK_PS
+
+#if XCHAL_HAVE_XEA2
+ #ifdef XT_USE_SWPRI
+ /* Set the initial virtual priority mask value to all 1's */
+ movi a3, -1
+ s32i a3, a4, XT_STK_VPRI
+ #endif
+#endif
+
+ RET0
+
+// }
+
diff --git a/ports/xtensa/xcc/src/tx_thread_system_return.S b/ports/xtensa/xcc/src/tx_thread_system_return.S
new file mode 100644
index 00000000..e90109c1
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_thread_system_return.S
@@ -0,0 +1,287 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "xtensa_rtos.h"
+#include "tx_api_asm.h"
+
+ .text
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+// VOID _tx_thread_system_return(VOID)
+// {
+ .globl _tx_thread_system_return
+ .type _tx_thread_system_return,@function
+ .align 4
+_tx_thread_system_return:
+ /*
+ Set up solicited stack frame and save minimal context (including a0).
+ Since this is solicited, no need to save regs compiler doesn't preserve.
+ */
+
+#if XCHAL_HAVE_XEA3
+ #ifdef __XTENSA_CALL0_ABI__
+ addi sp, sp, -16
+ #else
+ entry sp, 48
+ #endif
+ s32i a0, sp, 0 /* save return address */
+#else
+ #ifdef __XTENSA_CALL0_ABI__
+ addi a2, sp, -XT_STK_FRMSZ /* avoid addi/addmi relaxation that */
+ mov sp, a2 /* might temporarily move sp up */
+ #else
+ entry sp, XT_STK_FRMSZ
+ #endif
+#endif
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+#ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_execution_thread_exit
+#else
+ call8 _tx_execution_thread_exit
+#endif
+#endif
+
+#if XCHAL_HAVE_XEA3
+
+#ifdef __XTENSA_CALL0_ABI__
+
+#else
+ ssai 0
+ spillw /* spill all registers */
+#endif
+
+ /*
+ Save register state into exception frame. This is safe to do with
+ interrupts enabled, but we will have to revert SP to point above
+ the exception frame because that is what the dispatch code expects.
+ Must disable interrupts before that.
+ */
+
+ movi a0, .Lret
+ rsr.ps a2
+ addi sp, sp, -XT_STK_XFRM_SZ
+ s32i a0, sp, XT_STK_PC /* save return PC */
+ s32i a2, sp, XT_STK_PS /* save PS */
+#ifdef __XTENSA_CALL0_ABI__
+ s32i a12, sp, XT_STK_A12 /* callee-saved registers */
+ s32i a13, sp, XT_STK_A13
+ s32i a14, sp, XT_STK_A14
+ s32i a15, sp, XT_STK_A15
+#endif
+
+ movi a2, PS_STACK_KERNEL | PS_DI /* Set PS.STACK = Kernel and */
+ movi a8, PS_STACK_MASK | PS_DI_MASK /* disable interrupts. */
+ xps a2, a8
+
+ movi a3, _tx_thread_current_ptr /* a3 = &_tx_thread_current_ptr */
+ movi a2, TX_TRUE
+ l32i a4, a3, 0 /* a4 = _tx_thread_current_ptr */
+ movi a5, 0
+ s32i a2, a4, tx_thread_solicited /* mark as solicited switch */
+
+#if XCHAL_CP_NUM > 0
+ /* Save coprocessor callee-saved state (if any). At this point CPENABLE */
+ /* should still reflect which CPs were in use (enabled). */
+ call0 _xt_coproc_savecs
+
+ /* Clear CPENABLE and give up all co-procs. */
+ s16i a5, a4, tx_thread_cp_state + XT_CPENABLE
+ wsr a5, CPENABLE /* disable all co-processors */
+#endif
+
+ addi sp, sp, XT_STK_XFRM_SZ /* restore SP */
+ addi a2, sp, -XT_STK_FRMSZ
+ s32i a2, a4, tx_thread_stack_ptr /* Save SP in TCB */
+
+#ifdef __XTENSA_CALL0_ABI__
+ mov a15, sp /* Dispatch code expects a15 = old a1 */
+#endif
+
+ s32i a5, a3, 0 /* Clear _tx_thread_current_ptr */
+
+ movi a0, _xt_dispatch + 3 /* Jump to dispatch code */
+ ret
+
+ /* Execution returns here. Interrupts should be disabled. */
+ /* NOTE: we expect original SP to have been restored. */
+
+ .align 4
+
+.Lret:
+ addi sp, sp, -XT_STK_XFRM_SZ /* Prepare to restore state */
+ l32i a2, sp, XT_STK_PS /* Retrieve PS value */
+#ifdef __XTENSA_CALL0_ABI__
+ l32i a12, sp, XT_STK_A12 /* Callee-saved registers */
+ l32i a13, sp, XT_STK_A13
+ l32i a14, sp, XT_STK_A14
+ l32i a15, sp, XT_STK_A15
+#endif
+ addi sp, sp, XT_STK_XFRM_SZ
+ wsr.ps a2 /* Safe to enable interrupts */
+ rsync
+
+#ifdef __XTENSA_CALL0_ABI__
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+#else
+ l32i a0, sp, 0
+ retw
+#endif
+
+#else /* XEA1 or XEA2 */
+
+ rsr a2, PS
+ s32i a0, sp, XT_STK_PC
+ s32i a2, sp, XT_STK_PS
+ #ifdef __XTENSA_CALL0_ABI__
+ s32i a12, sp, XT_STK_A12
+ s32i a13, sp, XT_STK_A13
+ s32i a14, sp, XT_STK_A14
+ s32i a15, sp, XT_STK_A15
+ #else
+ /*
+ Spill register windows. Calling xthal_window_spill() causes extra spills and
+ reloads, so we set things up to call the _nw version instead to save cycles.
+ */
+ movi a6, ~(PS_WOE_MASK|PS_INTLEVEL_MASK) // (using a6 ensures any window using this a4..a7 is spilled)
+ mov a4, a0 // save a0
+ and a2, a2, a6 // clear WOE, INTLEVEL
+ addi a2, a2, XCHAL_EXCM_LEVEL // set INTLEVEL
+ wsr a2, PS
+ rsync
+ call0 xthal_window_spill_nw
+ l32i a0, sp, XT_STK_PS
+ wsr a0, PS // Restore PS value
+ rsync
+ #endif
+
+ #if XCHAL_CP_NUM > 0
+ /* Save coprocessor callee-saved state (if any). At this point CPENABLE */
+ /* should still reflect which CPs were in use (enabled). */
+ call0 _xt_coproc_savecs
+ #endif
+
+ /*
+ We do not return directly from this function to its caller.
+ Register usage from here on:
+ a0 = scratch (return address has been saved in stack frame)
+ a1 = stack ptr (thread, then system)
+ a2 = &_tx_thread_current_ptr
+ a3 = _tx_thread_current_ptr (thread control block)
+ a4 = &_tx_timer_time_slice
+ */
+
+ /* Lock out interrupts (except hi-pri). */
+ /* Grab thread control block of current thread. */
+ movi a2, _tx_thread_current_ptr /* a2 = &_tx_thread_current_ptr */
+ XT_INTS_DISABLE(a0)
+ l32i a3, a2, 0 /* a3 points to TCB */
+
+ /* Mark as having solicited entry to kernel (used on exit). */
+ movi a0, TX_TRUE
+ s32i a0, a3, tx_thread_solicited
+
+ /* Save current stack and switch to system stack. */
+ // _tx_thread_current_ptr -> tx_thread_stack_ptr = SP;
+ // SP = _tx_thread_system_stack_ptr;
+ movi a5, _tx_thread_system_stack_ptr /* a5 = & system stack ptr */
+ s32i sp, a3, tx_thread_stack_ptr
+ movi a4, _tx_timer_time_slice /* a4 = &_tx_timer_time_slice */
+ l32i sp, a5, 0 /* sp = system stack ptr */
+
+ /* Determine if the time-slice is active. */
+ // if (_tx_timer_time_slice)
+ // {
+ l32i a0, a4, 0
+ beqz a0, .L_tx_thread_dont_save_ts
+
+ /* Save time-slice for the thread and clear current time-slice. */
+ // _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
+ // _tx_timer_time_slice = 0;
+ s32i a0, a3, tx_thread_time_slice
+ movi a0, 0 /* a0 == 0 == TX_NULL */
+ s32i a0, a4, 0
+
+ // }
+
+.L_tx_thread_dont_save_ts:
+
+ /* Clear the current thread pointer. */
+ // _tx_thread_current_ptr = TX_NULL;
+ s32i a0, a2, 0 /* a0 == 0 == TX_NULL */
+
+ #if XCHAL_CP_NUM > 0
+ /* Clear CPENABLE and give up all co-procs. */
+ s16i a0, a3, tx_thread_cp_state + XT_CPENABLE
+ wsr a0, CPENABLE /* disable all co-processors */
+ #endif
+
+ /*
+ Return via the scheduler.
+ Scheduler returns eventually to this function's caller as if called by it.
+ */
+ call0 _tx_thread_schedule /* never returns here */
+
+#endif /* XCHAL_HAVE_XEA3 */
+// }
+
diff --git a/ports/xtensa/xcc/src/tx_timer_interrupt.S b/ports/xtensa/xcc/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..6fcc5d36
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_timer_interrupt.S
@@ -0,0 +1,277 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "xtensa_rtos.h"
+#include "tx_api_asm.h"
+
+#ifndef TX_NO_TIMER
+
+ .text
+
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+// VOID _tx_timer_interrupt(VOID)
+// {
+ .globl _tx_timer_interrupt
+ .type _tx_timer_interrupt,@function
+ .align 4
+_tx_timer_interrupt:
+
+ #ifdef __XTENSA_CALL0_ABI__
+ /* Define local variable spill offsets in stack frame for Call0 ABI. */
+ #define __tx_timer_interrupt_a0 0 /* ENTRY()/RET() saves/restores */
+ #define __tx_timer_interrupt_a2 4 /* preserve a2 */
+ #define __tx_timer_interrupt_a3 8 /* preserve a3 */
+ #endif
+
+ ENTRY(16)
+
+ .globl tx_timer_user_isr
+ .weak tx_timer_user_isr
+ movi a2, tx_timer_user_isr
+ beqz a2, 1f
+ #ifdef __XTENSA_CALL0_ABI__
+ callx0 a2
+ #else
+ callx8 a2
+ #endif
+1:
+
+ /*
+ Xtensa timers work by comparing a cycle counter with a preset value.
+ Once the match occurs an interrupt is generated, and the handler has
+ to set a new cycle count into the comparator. To avoid clock drift
+ due to interrupt latency, the new cycle count is computed from the old,
+ not the time the interrupt was serviced. However if a timer interrupt
+ is ever serviced more than one tick late, it is necessary to process
+ multiple ticks until the new cycle count is in the future, otherwise
+ the next timer interrupt would not occur until after the cycle counter
+ had wrapped (2^32 cycles later).
+
+ do {
+ ticks++;
+ old_ccompare = read_ccompare_i();
+ write_ccompare_i( old_ccompare + divisor );
+ service one tick;
+ diff = read_ccount() - old_ccompare;
+ } while ( diff > divisor );
+ */
+
+.L_tx_timer_catchup:
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+ movi a2, _tx_timer_system_clock /* a2 = &_tx_timer_system_clock */
+ l32i a3, a2, 0 /* a3 = _tx_timer_system_clock++ */
+ addi a3, a3, 1
+ s32i a3, a2, 0
+
+ /* Update the timer comparator for the next tick. */
+ #ifdef XT_CLOCK_FREQ
+ movi a2, XT_TICK_DIVISOR /* a2 = comparator increment */
+ #else
+ movi a3, _xt_tick_divisor
+ l32i a2, a3, 0 /* a2 = comparator increment */
+ #endif
+ rsr a3, XT_CCOMPARE /* a3 = old comparator value */
+ add a4, a3, a2 /* a4 = new comparator value */
+ wsr a4, XT_CCOMPARE /* update comp. and clear interrupt */
+ esync
+
+ /* Test for time-slice expiration. */
+ // if (_tx_timer_time_slice)
+ // {
+ movi a4, _tx_timer_time_slice /* a4 = &_tx_timer_time_slice */
+ l32i a5, a4, 0 /* a5 = _tx_timer_time_slice */
+ beqz a5, .L_tx_timer_no_time_slice
+
+ /* Decrement the time_slice. */
+ // _tx_timer_time_slice--;
+ addi a5, a5, -1
+ s32i a5, a4, 0
+
+ /* Check for expiration. */
+ // if (_tx_timer_time_slice == 0)
+ bnez a5, .L_tx_timer_no_time_slice
+
+ /* Set the time-slice expired flag. */
+ // _tx_timer_expired_time_slice = TX_TRUE;
+ movi a4, _tx_timer_expired_time_slice
+ movi a5, TX_TRUE
+ s32i a5, a4, 0
+
+ // }
+
+.L_tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+ movi a4, _tx_timer_current_ptr /* a4 = &_tx_timer_current_ptr */
+ l32i a5, a4, 0 /* a5 = _tx_timer_current_ptr */
+ l32i a6, a5, 0 /* a6 = *_tx_timer_current_ptr */
+ beqz a6, .L_tx_timer_no_timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+ movi a6, _tx_timer_expired
+ movi a7, TX_TRUE
+ s32i a7, a6, 0
+ j .L_tx_timer_done
+
+ // }
+ // else
+ // {
+
+.L_tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+ movi a6, _tx_timer_list_end
+ l32i a6, a6, 0 /* a6 = _tx_timer_list_end */
+ addi a5, a5, 4 /* a5 = ++_tx_timer_current_ptr */
+ bne a5, a6, .L_tx_timer_skip_wrap
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+ movi a6, _tx_timer_list_start
+ l32i a5, a6, 0 /* a5 = _tx_timer_list_start */
+
+.L_tx_timer_skip_wrap:
+
+ s32i a5, a4, 0 /* _tx_timer_current_ptr = a5 */
+ // }
+
+.L_tx_timer_done:
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ // {
+
+ #ifdef __XTENSA_CALL0_ABI__
+ /* Preserve a2 and a3 across calls. */
+ s32i a2, sp, __tx_timer_interrupt_a2
+ s32i a3, sp, __tx_timer_interrupt_a3
+ #endif
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+ movi a4, _tx_timer_expired
+ l32i a5, a4, 0
+ beqz a5, .L_tx_timer_dont_activate
+
+ /* Call the timer expiration processing. */
+ // _tx_timer_expiration_process();
+ #ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_timer_expiration_process
+ #else
+ call8 _tx_timer_expiration_process
+ #endif
+
+ // }
+
+.L_tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+ movi a4, _tx_timer_expired_time_slice
+ l32i a5, a4, 0
+ beqz a5, .L_tx_timer_not_ts_expiration
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+ #ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_thread_time_slice
+ #else
+ call8 _tx_thread_time_slice
+ #endif
+
+ // }
+
+.L_tx_timer_not_ts_expiration:
+
+ #ifdef __XTENSA_CALL0_ABI__
+ /* Restore a2 and a3. */
+ l32i a2, sp, __tx_timer_interrupt_a2
+ l32i a3, sp, __tx_timer_interrupt_a3
+ #endif
+
+ // }
+
+.Ln_tx_timer_nothing_expired:
+
+ /* Check if we need to process more ticks to catch up. */
+ esync /* ensure comparator update complete */
+ rsr a4, CCOUNT /* a4 = cycle count */
+ sub a4, a4, a3 /* diff = ccount - old comparator */
+ blt a2, a4, .L_tx_timer_catchup /* repeat while diff > divisor */
+
+ RET(16)
+
+// }
+
+#endif /* TX_NO_TIMER */
+
diff --git a/ports/xtensa/xcc/src/tx_xtensa_stack_error_handler.c b/ports/xtensa/xcc/src/tx_xtensa_stack_error_handler.c
new file mode 100644
index 00000000..2d14dd7a
--- /dev/null
+++ b/ports/xtensa/xcc/src/tx_xtensa_stack_error_handler.c
@@ -0,0 +1,123 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Support for Xtensa applications */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+#include "tx_user.h"
+
+#ifdef TX_ENABLE_STACK_CHECKING
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+
+#include "xtensa_rtos.h"
+#ifdef XT_BOARD
+#include <xtensa/xtbsp.h>
+#endif
+#ifdef XT_SIMULATOR
+#include <xtensa/simcall.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Callback to notify of a stack overflow when registered with */
+/* tx_stack_error_notify and stack checking is enabled (ThreadX */
+/* is compiled with TX_ENABLE_STACK_CHECKING defined). */
+/* */
+/* The handler notifies the user in any/all of the following ways: */
+/* - A message via the simulator (extremely reliable, simulator only). */
+/* - A message on the board's display (emulation board only). */
+/* - A message to stdout (uses low-level write to avoid printf which */
+/* is large and would trash state the user might want to examine). */
+/* The most reliable methods are done first. Several might work. */
+/* */
+/* After notifying the user as best it can, the handler stops the */
+/* application in the most reliable of the following ways: */
+/* - Passes control to the debugger (if attached). */
+/* - Terminates the simulation (simulator only). */
+/* - Panics. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+VOID _tx_xtensa_stack_error_handler(TX_THREAD * thread)
+{
+ #ifdef XT_SIMULATOR
+ register int32_t sc __asm__ ("a2") = SYS_log_msg;
+ register char * msg __asm__ ("a3")
+ = "**** Stack overflow in thread 0x%08x.\n";
+ register TX_THREAD * thd __asm__ ("a4") = thread;
+ __asm__ volatile ("simcall" :: "a" (sc), "a" (msg), "a" (thd) );
+ #endif
+
+ #ifdef XT_BOARD
+ xtbsp_display_string("StkOflow");
+ #endif
+
+ write(1, "**** Stack overflow in thread \"", 31);
+ write(1, thread->tx_thread_name, strlen(thread->tx_thread_name));
+ write(1, "\"\n", 2);
+
+ #ifdef XT_SIMULATOR
+ sc = SYS_gdb_abort;
+ __asm__ volatile ("simcall"); /* control to debugger or exit */
+ #else
+ __asm__ volatile ("break 1, 15"); /* control to debugger or panic */
+ #endif
+}
+
+#endif /* TX_ENABLE_STACK_CHECKING */
+
diff --git a/ports/xtensa/xcc/src/xtensa_context.S b/ports/xtensa/xcc/src/xtensa_context.S
new file mode 100644
index 00000000..af3138aa
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_context.S
@@ -0,0 +1,433 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* XTENSA CONTEXT SAVE AND RESTORE ROUTINES */
+/* */
+/* Low-level functions for handling generic context save and restore of */
+/* registers not specifically addressed by the interrupt vectors and */
+/* handlers. Those registers (not handled by these functions) are PC, PS, */
+/* A0, A1 (SP). Except for the calls to RTOS functions, this code is */
+/* generic to Xtensa. */
+/* */
+/* Note that in Call0 ABI, interrupt handlers are expected to preserve */
+/* the callee-save regs (A12-A15), which is always the case if the */
+/* handlers are coded in C. However A12, A13 are made available as */
+/* scratch registers for interrupt dispatch code, so are presumed saved */
+/* anyway, and are always restored even in Call0 ABI. Only A14, A15 are */
+/* truly handled as callee-save regs. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#include "xtensa_rtos.h"
+
+#ifdef XT_USE_OVLY
+#include <xtensa/overlay_os_asm.h>
+#endif
+
+ .text
+
+#if XCHAL_HAVE_XEA2
+
+/***************************************************************************
+
+ _xt_context_save
+
+ !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
+
+Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the
+interrupt stack frame defined in xtensa_rtos.h.
+Its counterpart is _xt_context_restore (which also restores A12, A13).
+
+Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame.
+This function preserves A12 & A13 in order to provide the caller with 2 scratch
+regs that need not be saved over the call to this function. The choice of which
+2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw,
+to avoid moving data more than necessary. Caller can assign regs accordingly.
+
+Entry Conditions:
+ A0 = Return address in caller.
+ A1 = Stack pointer of interrupted thread or handler ("interruptee").
+ Original A12, A13 have already been saved in the interrupt stack frame.
+ Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the
+ point of interruption.
+ If windowed ABI, PS.EXCM = 1 (exceptions disabled).
+
+Exit conditions:
+ A0 = Return address in caller.
+ A1 = Stack pointer of interrupted thread or handler ("interruptee").
+ A12, A13 as at entry (preserved).
+ If windowed ABI, PS.EXCM = 1 (exceptions disabled).
+
+***************************************************************************/
+
+ .global _xt_context_save
+ .type _xt_context_save,@function
+ .align 4
+_xt_context_save:
+
+ s32i a2, sp, XT_STK_A2
+ s32i a3, sp, XT_STK_A3
+ s32i a4, sp, XT_STK_A4
+ s32i a5, sp, XT_STK_A5
+ s32i a6, sp, XT_STK_A6
+ s32i a7, sp, XT_STK_A7
+ s32i a8, sp, XT_STK_A8
+ s32i a9, sp, XT_STK_A9
+ s32i a10, sp, XT_STK_A10
+ s32i a11, sp, XT_STK_A11
+
+ /*
+ Call0 ABI callee-saved regs a12-15 do not need to be saved here.
+ a12-13 are the caller's responsibility so it can use them as scratch.
+ So only need to save a14-a15 here for Windowed ABI (not Call0).
+ */
+ #ifndef __XTENSA_CALL0_ABI__
+ s32i a14, sp, XT_STK_A14
+ s32i a15, sp, XT_STK_A15
+ #endif
+
+ rsr a3, SAR
+ s32i a3, sp, XT_STK_SAR
+
+ #if XCHAL_HAVE_LOOPS
+ rsr a3, LBEG
+ s32i a3, sp, XT_STK_LBEG
+ rsr a3, LEND
+ s32i a3, sp, XT_STK_LEND
+ rsr a3, LCOUNT
+ s32i a3, sp, XT_STK_LCOUNT
+ #endif
+
+ #if XCHAL_HAVE_EXCLUSIVE
+ /* Save and clear state of ATOMCTL */
+ movi a3, 0
+ getex a3
+ s32i a3, sp, XT_STK_ATOMCTL
+ #endif
+
+ #if XT_USE_SWPRI
+ /* Save virtual priority mask */
+ movi a3, _xt_vpri_mask
+ l32i a3, a3, 0
+ s32i a3, sp, XT_STK_VPRI
+ #endif
+
+ #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
+ mov a9, a0 /* preserve ret addr */
+ #endif
+
+ #ifndef __XTENSA_CALL0_ABI__
+ /*
+ To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15.
+ Need to save a9,12,13 temporarily (in frame temps) and recover originals.
+ Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow
+ and underflow exceptions disabled (assured by PS.EXCM == 1).
+ */
+ s32i a12, sp, XT_STK_TMP0 /* temp. save stuff in stack frame */
+ s32i a13, sp, XT_STK_TMP1
+ s32i a9, sp, XT_STK_TMP2
+
+ /*
+ Save the overlay state if we are supporting overlays. Since we just saved
+ three registers, we can conveniently use them here. Note that as of now,
+ overlays only work for windowed calling ABI.
+ */
+ #ifdef XT_USE_OVLY
+ l32i a9, sp, XT_STK_PC /* recover saved PC */
+ _xt_overlay_get_state a9, a12, a13
+ s32i a9, sp, XT_STK_OVLY /* save overlay state */
+ #endif
+
+ l32i a12, sp, XT_STK_A12 /* recover original a9,12,13 */
+ l32i a13, sp, XT_STK_A13
+ l32i a9, sp, XT_STK_A9
+ addi sp, sp, XT_STK_FRMSZ /* restore the interruptee's SP */
+ call0 xthal_window_spill_nw /* preserves only a4,5,8,9,12,13 */
+ addi sp, sp, -XT_STK_FRMSZ
+ l32i a12, sp, XT_STK_TMP0 /* recover stuff from stack frame */
+ l32i a13, sp, XT_STK_TMP1
+ l32i a9, sp, XT_STK_TMP2
+ #endif
+
+ #if XCHAL_EXTRA_SA_SIZE > 0
+ /*
+ NOTE: Normally the xthal_save_extra_nw macro only affects address
+ registers a2-a5. It is theoretically possible for Xtensa processor
+ designers to write TIE that causes more address registers to be
+ affected, but it is generally unlikely. If that ever happens,
+ more registers need to be saved/restored around this macro invocation.
+ Here we assume a9,12,13 are preserved.
+ Future Xtensa tools releases might limit the regs that can be affected.
+ */
+ addi a2, sp, XT_STK_EXTRA /* where to save it */
+ # if XCHAL_EXTRA_SA_ALIGN > 16
+ movi a3, -XCHAL_EXTRA_SA_ALIGN
+ and a2, a2, a3 /* align dynamically >16 bytes */
+ # endif
+ call0 xthal_save_extra_nw /* destroys a0,2,3,4,5 */
+ #endif
+
+ #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
+ mov a0, a9 /* retrieve ret addr */
+ #endif
+
+ ret
+
+/*******************************************************************************
+
+_xt_context_restore
+
+ !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
+
+Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0
+ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt
+stack frame defined in xtensa_rtos.h .
+Its counterpart is _xt_context_save (whose caller saved A12, A13).
+
+Caller is responsible to restore PC, PS, A0, A1 (SP).
+
+Entry Conditions:
+ A0 = Return address in caller.
+ A1 = Stack pointer of interrupted thread or handler ("interruptee").
+
+Exit conditions:
+ A0 = Return address in caller.
+ A1 = Stack pointer of interrupted thread or handler ("interruptee").
+ Other processor state except PC, PS, A0, A1 (SP), is as at the point
+ of interruption.
+
+*******************************************************************************/
+
+ .global _xt_context_restore
+ .type _xt_context_restore,@function
+ .align 4
+_xt_context_restore:
+
+ #if XCHAL_EXTRA_SA_SIZE > 0
+ /*
+ NOTE: Normally the xthal_restore_extra_nw macro only affects address
+ registers a2-a5. It is theoretically possible for Xtensa processor
+ designers to write TIE that causes more address registers to be
+ affected, but it is generally unlikely. If that ever happens,
+ more registers need to be saved/restored around this macro invocation.
+ Here we only assume a13 is preserved.
+ Future Xtensa tools releases might limit the regs that can be affected.
+ */
+ mov a13, a0 /* preserve ret addr */
+ addi a2, sp, XT_STK_EXTRA /* where to find it */
+ # if XCHAL_EXTRA_SA_ALIGN > 16
+ movi a3, -XCHAL_EXTRA_SA_ALIGN
+ and a2, a2, a3 /* align dynamically >16 bytes */
+ # endif
+ call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */
+ mov a0, a13 /* retrieve ret addr */
+ #endif
+
+ #if XCHAL_HAVE_LOOPS
+ l32i a2, sp, XT_STK_LBEG
+ l32i a3, sp, XT_STK_LEND
+ wsr a2, LBEG
+ l32i a2, sp, XT_STK_LCOUNT
+ wsr a3, LEND
+ wsr a2, LCOUNT
+ #endif
+
+ #if XCHAL_HAVE_EXCLUSIVE
+ /* Restore state of ATOMCTL */
+ l32i a2, sp, XT_STK_ATOMCTL
+ getex a2
+ #endif
+
+ #ifdef XT_USE_OVLY
+ /*
+ If we are using overlays, this is a good spot to check if we need
+ to restore an overlay for the incoming task. Here we have a bunch
+ of registers to spare. Note that this step is going to use a few
+ bytes of storage below SP (SP-20 to SP-32) if an overlay is going
+ to be restored.
+ */
+ l32i a2, sp, XT_STK_PC /* retrieve PC */
+ l32i a3, sp, XT_STK_PS /* retrieve PS */
+ l32i a4, sp, XT_STK_OVLY /* retrieve overlay state */
+ l32i a5, sp, XT_STK_A1 /* retrieve stack ptr */
+ _xt_overlay_check_map a2, a3, a4, a5, a6
+ s32i a2, sp, XT_STK_PC /* save updated PC */
+ s32i a3, sp, XT_STK_PS /* save updated PS */
+ #endif
+
+ #ifdef XT_USE_SWPRI
+ /* Restore virtual interrupt priority and interrupt enable */
+ movi a3, _xt_intdata
+ l32i a4, a3, 0 /* a4 = _xt_intenable */
+ l32i a5, sp, XT_STK_VPRI /* a5 = saved _xt_vpri_mask */
+ and a4, a4, a5
+ wsr a4, INTENABLE /* update INTENABLE */
+ s32i a5, a3, 4 /* restore _xt_vpri_mask */
+ #endif
+
+ l32i a3, sp, XT_STK_SAR
+ l32i a2, sp, XT_STK_A2
+ wsr a3, SAR
+ l32i a3, sp, XT_STK_A3
+ l32i a4, sp, XT_STK_A4
+ l32i a5, sp, XT_STK_A5
+ l32i a6, sp, XT_STK_A6
+ l32i a7, sp, XT_STK_A7
+ l32i a8, sp, XT_STK_A8
+ l32i a9, sp, XT_STK_A9
+ l32i a10, sp, XT_STK_A10
+ l32i a11, sp, XT_STK_A11
+
+ /*
+ Call0 ABI callee-saved regs a12-15 do not need to be restored here.
+ However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(),
+ so need to be restored anyway, despite being callee-saved in Call0.
+ */
+ l32i a12, sp, XT_STK_A12
+ l32i a13, sp, XT_STK_A13
+ #ifndef __XTENSA_CALL0_ABI__
+ l32i a14, sp, XT_STK_A14
+ l32i a15, sp, XT_STK_A15
+ #endif
+
+ ret
+
+#endif /* XCHAL_HAVE_XEA3 */
+
+
+/*******************************************************************************
+
+_xt_coproc_init
+
+Initializes global co-processor management data, setting all co-processors
+to "unowned". Leaves CPENABLE as it found it (does NOT clear it).
+
+Called during initialization of the RTOS, before any threads run.
+
+This may be called from normal Xtensa single-threaded application code which
+might use co-processors. The Xtensa run-time initialization enables all
+co-processors. They must remain enabled here, else a co-processor exception
+might occur outside of a thread, which the exception handler doesn't expect.
+
+Entry Conditions:
+ Xtensa single-threaded run-time environment is in effect.
+ No thread is yet running.
+
+Exit conditions:
+ None.
+
+Obeys ABI conventions per prototype:
+ void _xt_coproc_init(void)
+
+*******************************************************************************/
+
+#if XCHAL_CP_NUM > 0
+
+ .global _xt_coproc_init
+ .type _xt_coproc_init,@function
+ .align 4
+_xt_coproc_init:
+ ENTRY0
+
+ /* Initialize thread co-processor ownerships to 0 (unowned). */
+ movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */
+ addi a3, a2, XCHAL_CP_MAX << 2 /* a3 = top+1 of owner array */
+ movi a4, 0 /* a4 = 0 (unowned) */
+1: s32i a4, a2, 0
+ addi a2, a2, 4
+ bltu a2, a3, 1b
+
+ RET0
+
+#endif
+
+
+/*******************************************************************************
+
+_xt_coproc_release
+
+Releases any and all co-processors owned by a given thread. The thread is
+identified by it's co-processor state save area defined in xtensa_context.h .
+
+Must be called before a thread's co-proc save area is deleted to avoid
+memory corruption when the exception handler tries to save the state.
+May be called when a thread terminates or completes but does not delete
+the co-proc save area, to avoid the exception handler having to save the
+thread's co-proc state before another thread can use it (optimization).
+
+Entry Conditions:
+ A2 = Pointer to base of co-processor state save area.
+
+Exit conditions:
+ None.
+
+Obeys ABI conventions per prototype:
+ void _xt_coproc_release(void * coproc_sa_base)
+
+*******************************************************************************/
+
+#if XCHAL_CP_NUM > 0
+
+ .global _xt_coproc_release
+ .type _xt_coproc_release,@function
+ .align 4
+_xt_coproc_release:
+ ENTRY0 /* a2 = base of save area */
+
+ movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
+ addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array */
+ movi a5, 0 /* a5 = 0 (unowned) */
+
+#if XCHAL_HAVE_XEA3
+ movi a6, PS_DI
+ xps a6, a6 /* lock interrupts */
+#else
+ rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */
+#endif
+
+1: l32i a7, a3, 0 /* a7 = owner at a3 */
+ bne a2, a7, 2f /* if (coproc_sa_base == owner) */
+ s32i a5, a3, 0 /* owner = unowned */
+2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */
+ bltu a3, a4, 1b /* repeat until end of array */
+
+3:
+ wsr a6, PS /* restore interrupts */
+ rsync
+
+ RET0
+
+#endif
+
diff --git a/ports/xtensa/xcc/src/xtensa_coproc_handler.S b/ports/xtensa/xcc/src/xtensa_coproc_handler.S
new file mode 100644
index 00000000..ee55e471
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_coproc_handler.S
@@ -0,0 +1,578 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa coprocessor handling routines. This code is only active if */
+/* one or more coprocessors are present. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#include <xtensa/config/specreg.h>
+#include <xtensa/coreasm.h>
+
+#include "xtensa_context.h"
+#include "xtensa_rtos.h"
+
+
+#if XCHAL_CP_NUM > 0
+
+//-----------------------------------------------------------------------------
+// Coprocessor related state and precomputed values.
+//-----------------------------------------------------------------------------
+
+// Table of coprocessor owners, identified by thread's CP save area pointer.
+// Zero means coprocessor is not owned.
+
+ .data
+ .global _xt_coproc_owner_sa
+ .align 16,,XCHAL_CP_MAX << 2 // minimize crossing cache boundaries
+_xt_coproc_owner_sa:
+ .rept XCHAL_CP_MAX
+ .word 0
+ .endr
+
+// Bitmask table for CP n's enable bit, indexed by coprocessor number.
+
+ .section .rodata, "a"
+ .global _xt_coproc_mask
+ .align 16,,8 // try to keep it all in one cache line
+ .set i, 0
+_xt_coproc_mask:
+ .rept XCHAL_CP_MAX
+ .long (i<<16) | (1<<i) // upper 16-bits = i, lower = bitmask
+ .set i, i+1
+ .endr
+
+// Offset to CP n save area in thread's CP save area.
+
+ .global _xt_coproc_sa_offset
+ .align 16 // minimize crossing cache boundaries
+_xt_coproc_sa_offset:
+ .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
+ .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
+
+
+//-----------------------------------------------------------------------------
+// _xt_coproc_handler
+//
+// Handles coprocessor exceptions and manages lazy context switching between
+// multiple threads sharing the coprocessor(s).
+// Register use:
+// a0 - on entry, return address (must have been called via call0).
+// a1 - pointing to valid exception stack frame.
+// a2 - on entry, must hold coprocessor index. On exit, 0 if OK.
+// a3-a15 - may all be used and trashed by this routine.
+//-----------------------------------------------------------------------------
+
+ .text
+ .align 4
+ .global _xt_coproc_handler
+
+_xt_coproc_handler:
+
+ mov a7, a0 // a7 = return address
+ mov a5, a2 // a5 = CP index n
+
+ // Get coprocessor state save area of new owner thread
+ call0 XT_RTOS_CP_STATE // a15 = new owner's save area
+ beqz a15, .L_xt_coproc_invalid // not in a thread (invalid)
+ l32i a4, a15, XT_CP_ASA // actual save area address
+ beqz a4, .L_xt_coproc_invalid // thread has no save area
+
+ // Enable the co-processor's bit in CPENABLE
+ movi a0, _xt_coproc_mask
+ rsr a4, CPENABLE // a4 = CPENABLE
+ addx4 a0, a5, a0 // a0 = &_xt_coproc_mask[n]
+ l32i a0, a0, 0 // a0 = (n << 16) | (1 << n)
+ movi a3, _xt_coproc_owner_sa
+ extui a2, a0, 0, 16 // coprocessor bitmask portion
+ or a4, a4, a2 // a4 = CPENABLE | (1 << n)
+ wsr a4, CPENABLE
+
+ // Get old coprocessor owner thread (save area ptr) and assign new one
+ addx4 a3, a5, a3 // a3 = &_xt_coproc_owner_sa[n]
+ l32i a2, a3, 0 // a2 = old owner's save area
+ s32i a15, a3, 0 // _xt_coproc_owner_sa[n] = new
+ rsync // ensure wsr.CPENABLE is complete
+
+ // Do we need to context-switch this coprocessor ?
+ beq a15, a2, .L_xt_coproc_done // new owner == old, we're done
+
+ // if no old owner then nothing to save
+ beqz a2, .L_check_new
+
+ // If old owner not actively using CP then nothing to save.
+ l16ui a4, a2, XT_CPENABLE // a4 = old owner's CPENABLE
+ bnone a4, a0, .L_check_new // old owner not using CP
+
+.L_save_old:
+ // We need to save old owner's coprocessor state
+ movi a5, _xt_coproc_sa_offset
+
+ // Mark old owner state as no longer active (CPENABLE bit n clear)
+ xor a4, a4, a0 // clear CP in old owner's CPENABLE
+ s16i a4, a2, XT_CPENABLE // update old owner's CPENABLE
+
+ extui a4, a0, 16, 5 // a4 = CP index = n
+ addx4 a5, a4, a5 // a5 = &_xt_coproc_sa_offset[n]
+
+ // Mark old owner state as saved (CPSTORED bit n set)
+ l16ui a4, a2, XT_CPSTORED // a4 = old owner's CPSTORED
+ l32i a5, a5, 0 // a5 = XT_CP[n]_SA offset
+ or a4, a4, a0 // set CP in old owner's CPSTORED
+ s16i a4, a2, XT_CPSTORED // update old owner's CPSTORED
+ l32i a2, a2, XT_CP_ASA // ptr to actual (aligned) save area
+ extui a3, a0, 16, 5 // a3 = CP index = n
+ add a2, a2, a5 // a2 = old owner's area for CP n
+
+ // The config-specific HAL macro invoked below destroys a2-a6.
+ // It is theoretically possible for Xtensa processor designers to write TIE
+ // that causes more address registers to be affected, but it is generally
+ // unlikely. If that ever happens, more registers needs to be saved/restored
+ // around this macro invocation, and the value in a15 needs to be recomputed.
+
+ xchal_cpi_store_funcbody
+
+.L_check_new:
+ // Check if any state has to be restored for new owner.
+ // NOTE: a15 = new owner's save area, cannot be zero when we get here.
+
+ l16ui a3, a15, XT_CPSTORED // a3 = new owner's CPSTORED
+ movi a4, _xt_coproc_sa_offset
+ bnone a3, a0, .L_check_cs // full CP not saved, check callee-saved
+ xor a3, a3, a0 // CPSTORED bit is set, clear it
+ s16i a3, a15, XT_CPSTORED // update new owner's CPSTORED
+
+ // Adjust new owner's save area pointers to area for CP n.
+ extui a3, a0, 16, 5 // a3 = CP index = n
+ addx4 a4, a3, a4 // a4 = &_xt_coproc_sa_offset[n]
+ l32i a4, a4, 0 // a4 = XT_CP[n]_SA
+ l32i a5, a15, XT_CP_ASA // ptr to actual (aligned) save area
+ add a2, a4, a5 // a2 = new owner's area for CP
+
+ // The config-specific HAL macro invoked below destroys a2-a6.
+ // It is theoretically possible for Xtensa processor designers to write TIE
+ // that causes more address registers to be affected, but it is generally
+ // unlikely. If that ever happens, more registers needs to be saved/restored
+ // around this macro invocation.
+
+ xchal_cpi_load_funcbody
+
+.L_xt_coproc_done:
+ movi a2, 0 // a2 <- 0 == OK
+.L_xt_coproc_err:
+ mov a0, a7 // return address
+ ret
+
+.L_check_cs:
+ // a0 = CP mask in low bits, a15 = new owner's save area.
+ l16ui a2, a15, XT_CP_CS_ST // a2 = mask of CPs saved
+ bnone a2, a0, .L_xt_coproc_done // if no match then done
+ and a2, a2, a0 // a2 = which CPs to restore
+ extui a2, a2, 0, 8 // extract low 8 bits
+ call0 _xt_coproc_restorecs // restore CP registers
+ j .L_xt_coproc_done
+
+.L_xt_coproc_invalid:
+ // Coprocessor exception occurred outside a thread or the thread
+ // did not allocate space to save coprocessor state. Return error.
+ movi a2, 1
+ j .L_xt_coproc_err
+
+
+//-----------------------------------------------------------------------------
+// _tx_thread_coproc_state
+//
+// Helper function to return the save area for the current thread, if any.
+// Returns, in a15, the pointer to the save area if any, else zero.
+// If in interrupt context, returns zero. Only uses a15.
+// Must be called only via call0.
+//-----------------------------------------------------------------------------
+
+ .global _tx_thread_coproc_state
+ .type _tx_thread_coproc_state,@function
+ .align 4
+
+_tx_thread_coproc_state:
+
+ // return ( _tx_thread_system_state == 0 && _tx_thread_current_ptr != 0
+ // ? (&_tx_thread_current_ptr->tx_thread_cp_state) : 0 )
+
+ movi a15, _tx_thread_system_state // check if interrupt state
+ l32i a15, a15, 0
+ bnez a15, 1f
+ movi a15, _tx_thread_current_ptr // check if thread running
+ l32i a15, a15, 0
+ beqz a15, 2f
+
+ // Return base address of current thread's co-prcoessor save area.
+ addi a15, a15, tx_thread_cp_state
+ ret
+1:
+ movi a15, 0 // return error
+2:
+ ret
+
+
+//-----------------------------------------------------------------------------
+// _xt_coproc_savecs
+//
+// If there is a current thread and it has a coprocessor state save area, then
+// save all callee-saved state into this area. This function is called from the
+// solicited context switch handler. It calls a system-specific function to get
+// the coprocessor save area base address.
+//
+// Entry conditions:
+// - The thread being switched out is still the current thread.
+// - CPENABLE state reflects which coprocessors are active.
+// - Registers have been saved/spilled already.
+//
+// Exit conditions:
+// - All necessary CP callee-saved state has been saved.
+// - Registers a7-a15 have been trashed.
+//
+// Must be called from assembly code only, using CALL0.
+//-----------------------------------------------------------------------------
+
+ .global _xt_coproc_savecs
+ .type _xt_coproc_savecs,@function
+ .align 4
+_xt_coproc_savecs:
+
+ // At entry, CPENABLE should be showing which CPs are enabled.
+
+ rsr a11, CPENABLE // a11 = which CPs are enabled
+ beqz a11, .Ldone // quick exit if none
+ mov a14, a0 // save return address
+ call0 XT_RTOS_CP_STATE // get address of CP save area
+ mov a0, a14 // restore return address
+ beqz a15, .Ldone // if none then nothing to do
+ l32i a14, a15, XT_CP_ASA // a14 = base of aligned save area
+ beqz a14, .Ldone // no save area, nothing to do
+ s16i a11, a15, XT_CP_CS_ST // save mask of CPs being stored
+ movi a13, _xt_coproc_sa_offset // array of CP save offsets
+ l32i a15, a15, XT_CP_ASA // a15 = base of aligned save area
+
+#if XCHAL_CP0_SA_SIZE
+ bbci.l a11, 0, 2f // CP 0 not enabled
+ l32i a14, a13, 0 // a14 = _xt_coproc_sa_offset[0]
+ add a12, a14, a15 // a12 = save area for CP 0
+ xchal_cp0_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP1_SA_SIZE
+ bbci.l a11, 1, 2f // CP 1 not enabled
+ l32i a14, a13, 4 // a14 = _xt_coproc_sa_offset[1]
+ add a12, a14, a15 // a12 = save area for CP 1
+ xchal_cp1_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP2_SA_SIZE
+ bbci.l a11, 2, 2f
+ l32i a14, a13, 8
+ add a12, a14, a15
+ xchal_cp2_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP3_SA_SIZE
+ bbci.l a11, 3, 2f
+ l32i a14, a13, 12
+ add a12, a14, a15
+ xchal_cp3_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP4_SA_SIZE
+ bbci.l a11, 4, 2f
+ l32i a14, a13, 16
+ add a12, a14, a15
+ xchal_cp4_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP5_SA_SIZE
+ bbci.l a11, 5, 2f
+ l32i a14, a13, 20
+ add a12, a14, a15
+ xchal_cp5_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP6_SA_SIZE
+ bbci.l a11, 6, 2f
+ l32i a14, a13, 24
+ add a12, a14, a15
+ xchal_cp6_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP7_SA_SIZE
+ bbci.l a11, 7, 2f
+ l32i a14, a13, 28
+ add a12, a14, a15
+ xchal_cp7_store a12, a7, a8, a9, a10 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+.Ldone:
+ ret
+
+
+//-----------------------------------------------------------------------------
+// _xt_coproc_restorecs
+//
+// Restore any callee-saved coprocessor state for the incoming thread.
+// This function is called from coprocessor exception handling, when giving
+// ownership to a thread that solicited a context switch earlier. It calls a
+// system-specific function to get the coprocessor save area base address.
+//
+// Entry conditions:
+// - The incoming thread is set as the current thread.
+// - CPENABLE is set up correctly for all required coprocessors.
+// - a2 = mask of coprocessors to be restored.
+//
+// Exit conditions:
+// - All necessary CP callee-saved state has been restored.
+// - CPENABLE - unchanged.
+// - Registers a2, a8-a15 have been trashed.
+//
+// Must be called from assembly code only, using CALL0.
+//-----------------------------------------------------------------------------
+
+ .global _xt_coproc_restorecs
+ .type _xt_coproc_restorecs,@function
+ .align 4
+_xt_coproc_restorecs:
+
+ mov a14, a0 // save return address
+ call0 XT_RTOS_CP_STATE // get address of CP save area
+ mov a0, a14 // restore return address
+ beqz a15, .Ldone2 // if none then nothing to do
+ l32i a14, a15, XT_CP_ASA // a14 = base of aligned save area
+ beqz a14, .Ldone2 // no save area, nothing to do
+ l16ui a13, a15, XT_CP_CS_ST // a13 = which CPs have been saved
+ xor a13, a13, a2 // clear the ones being restored
+ s16i a13, a15, XT_CP_CS_ST // update saved CP mask
+ movi a13, _xt_coproc_sa_offset // array of CP save offsets
+ l32i a15, a15, XT_CP_ASA // a15 = base of aligned save area
+
+#if XCHAL_CP0_SA_SIZE
+ bbci.l a2, 0, 2f // CP 0 not enabled
+ l32i a14, a13, 0 // a14 = _xt_coproc_sa_offset[0]
+ add a12, a14, a15 // a12 = save area for CP 0
+ xchal_cp0_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP1_SA_SIZE
+ bbci.l a2, 1, 2f // CP 1 not enabled
+ l32i a14, a13, 4 // a14 = _xt_coproc_sa_offset[1]
+ add a12, a14, a15 // a12 = save area for CP 1
+ xchal_cp1_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP2_SA_SIZE
+ bbci.l a2, 2, 2f
+ l32i a14, a13, 8
+ add a12, a14, a15
+ xchal_cp2_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP3_SA_SIZE
+ bbci.l a2, 3, 2f
+ l32i a14, a13, 12
+ add a12, a14, a15
+ xchal_cp3_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP4_SA_SIZE
+ bbci.l a2, 4, 2f
+ l32i a14, a13, 16
+ add a12, a14, a15
+ xchal_cp4_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP5_SA_SIZE
+ bbci.l a2, 5, 2f
+ l32i a14, a13, 20
+ add a12, a14, a15
+ xchal_cp5_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP6_SA_SIZE
+ bbci.l a2, 6, 2f
+ l32i a14, a13, 24
+ add a12, a14, a15
+ xchal_cp6_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP7_SA_SIZE
+ bbci.l a2, 7, 2f
+ l32i a14, a13, 28
+ add a12, a14, a15
+ xchal_cp7_load a12, a8, a9, a10, a11 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+.Ldone2:
+ ret
+
+
+#if XCHAL_HAVE_XEA3
+
+//-----------------------------------------------------------------------------
+// For XEA3, coprocessor exceptions come here. This is a wrapper function that
+// calls _xt_coproc_handler() to do the actual work. Since the handler can be
+// interrupted make sure that no context switch occurs.
+//-----------------------------------------------------------------------------
+
+ .text
+ .global _xt_coproc_exc
+ .type _xt_coproc_exc,@function
+ .align 4
+
+_xt_coproc_exc:
+#ifdef __XTENSA_CALL0_ABI__
+ addi a1, a1, -16 // reserve 16 bytes on stack
+ s32i a0, a1, 0 // save return address
+ s32i a2, a1, 4 // save a2
+ s32i a15, a1, 8 // must save a15 (see dispatch)
+ l32i a2, a1, 4
+ l32i a3, a2, XT_STK_EXCCAUSE // a3 <- exccause
+ extui a2, a3, 8, 4 // a2 <- CP index
+ call0 _xt_coproc_handler
+ l32i a0, a1, 0 // restore return address
+ l32i a15, a1, 8 // restore a15
+ addi a1, a1, 16
+ ret
+#else
+ entry a1, 48 // reserve 16 bytes on stack
+ s32i a0, a1, 0 // save return address
+ l32i a3, a2, XT_STK_EXCCAUSE // a3 <- exccause
+ extui a2, a3, 8, 4 // a2 <- CP index
+ call0 _xt_coproc_handler
+ l32i a0, a1, 0 // restore return address
+ retw
+#endif
+
+#endif // XCHAL_HAVE_XEA3
+
+
+#if XCHAL_HAVE_XEA2
+
+//-----------------------------------------------------------------------------
+// XEA2 coprocessor exception dispatcher. Save enough state to be able to call
+// the coprocessor handler, then restore and return.
+//-----------------------------------------------------------------------------
+
+ .text
+ .global _xt_coproc_exc
+ .type _xt_coproc_exc,@function
+ .align 4
+
+_xt_coproc_exc:
+
+ mov a0, sp // Allocate stack frame
+ addi sp, sp, -XT_STK_FRMSZ
+ s32i a0, sp, XT_STK_A1 // save SP
+#if XCHAL_HAVE_WINDOWED
+ s32e a0, sp, -12 // for debug backtrace
+#endif
+ rsr a0, PS
+ s32i a0, sp, XT_STK_PS // save PS
+ rsr a0, EPC_1
+ s32i a0, sp, XT_STK_PC // save PC
+ rsr a0, EXCSAVE_1
+ s32i a0, sp, XT_STK_A0 // retrieve and save a0
+#if XCHAL_HAVE_WINDOWED
+ s32e a0, sp, -16 // for debug backtrace
+#endif
+ s32i a2, sp, XT_STK_A2
+ s32i a3, sp, XT_STK_A3
+ s32i a4, sp, XT_STK_A4
+ s32i a5, sp, XT_STK_A5
+ s32i a6, sp, XT_STK_A6
+ s32i a7, sp, XT_STK_A7
+ s32i a8, sp, XT_STK_A8
+ s32i a9, sp, XT_STK_A9
+ s32i a10, sp, XT_STK_A10
+ s32i a11, sp, XT_STK_A11
+ s32i a12, sp, XT_STK_A12
+ s32i a13, sp, XT_STK_A13
+ s32i a14, sp, XT_STK_A14
+ s32i a15, sp, XT_STK_A15
+
+ rsr a3, EXCCAUSE // a3 <- exccause
+ addi a2, a3, -EXCCAUSE_CP0_DISABLED // a2 <- CP index
+ call0 _xt_coproc_handler
+
+ mov a0, a2 // save return value
+ l32i a2, sp, XT_STK_A2
+ l32i a3, sp, XT_STK_A3
+ l32i a4, sp, XT_STK_A4
+ l32i a5, sp, XT_STK_A5
+ l32i a6, sp, XT_STK_A6
+ l32i a7, sp, XT_STK_A7
+ l32i a8, sp, XT_STK_A8
+ l32i a9, sp, XT_STK_A9
+ l32i a10, sp, XT_STK_A10
+ l32i a11, sp, XT_STK_A11
+ l32i a12, sp, XT_STK_A12
+ l32i a13, sp, XT_STK_A13
+ l32i a14, sp, XT_STK_A14
+ l32i a15, sp, XT_STK_A15
+ bnez a0, .Lfail // abort if failure
+ l32i a0, sp, XT_STK_PC
+ wsr a0, EPC_1 // restore PC
+ l32i a0, sp, XT_STK_PS
+ wsr a0, PS // restore PS
+ l32i a0, sp, XT_STK_A0
+ addi a1, a1, XT_STK_FRMSZ // deallocate stack frame
+ rfe
+
+.Lfail:
+ call0 _xt_panic
+
+#endif // XCHAL_HAVE_XEA2
+
+#endif // XCHAL_CP_NUM > 0
+
diff --git a/ports/xtensa/xcc/src/xtensa_init.c b/ports/xtensa/xcc/src/xtensa_init.c
new file mode 100644
index 00000000..0359028c
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_init.c
@@ -0,0 +1,67 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa initialization routines. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#ifdef XT_BOARD
+#include <xtensa/xtbsp.h>
+#endif
+
+#include "xtensa_rtos.h"
+
+
+#ifdef XT_RTOS_TIMER_INT
+#ifndef XT_CLOCK_FREQ
+
+uint32_t _xt_tick_divisor = 0; /* cached number of cycles per tick */
+
+/*
+Compute and initialize at run-time the tick divisor (the number of
+processor clock cycles in an RTOS tick, used to set the tick timer).
+Called when the processor clock frequency is not known at compile-time.
+*/
+void _xt_tick_divisor_init(void)
+{
+ #ifdef XT_BOARD
+ _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC;
+ #else
+ #error "No way to obtain processor clock frequency"
+ #endif /* XT_BOARD */
+}
+
+#endif /* XT_CLOCK_FREQ */
+#endif /* XT_RTOS_TIMER_INT */
+
diff --git a/ports/xtensa/xcc/src/xtensa_intr.c b/ports/xtensa/xcc/src/xtensa_intr.c
new file mode 100644
index 00000000..c5f320cb
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_intr.c
@@ -0,0 +1,213 @@
+/*******************************************************************************
+Copyright (c) 2006-2019 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+/******************************************************************************
+ Xtensa-specific interrupt and exception functions for RTOS ports.
+ Also see xtensa_intr_asm.S.
+******************************************************************************/
+
+#include <stdlib.h>
+
+#include <xtensa/config/core.h>
+#include <xtensa/core-macros.h>
+
+#include "xtensa_api.h"
+
+
+#if XCHAL_HAVE_EXCEPTIONS
+
+/* Handler table is in xtensa_intr_asm.S */
+
+extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM];
+
+
+/*
+ Default handler for unhandled exceptions.
+*/
+void xt_unhandled_exception(XtExcFrame *frame)
+{
+ (void) frame; /* Keep compiler happy */
+ exit(-1);
+}
+
+
+/*
+ This function registers a handler for the specified exception.
+ The function returns the address of the previous handler.
+ On error, it returns 0.
+*/
+xt_exc_handler xt_set_exception_handler(uint32_t n, xt_exc_handler f)
+{
+ xt_exc_handler old;
+
+ if (n >= XCHAL_EXCCAUSE_NUM) {
+ return 0; /* invalid exception number */
+ }
+
+ old = _xt_exception_table[n];
+
+ if (f != NULL) {
+ _xt_exception_table[n] = f;
+ }
+ else {
+ _xt_exception_table[n] = &xt_unhandled_exception;
+ }
+
+ return old;
+}
+
+#endif
+
+#if XCHAL_HAVE_INTERRUPTS
+
+#if XCHAL_HAVE_XEA2
+/* Defined in xtensa_intr_asm.S */
+extern uint32_t _xt_intenable;
+extern uint32_t _xt_vpri_mask;
+#endif
+
+/* Handler table is in xtensa_intr_asm.S */
+
+typedef struct xt_handler_table_entry {
+ void * handler;
+ void * arg;
+} xt_handler_table_entry;
+
+#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3)
+extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS + 1];
+#else
+extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS];
+#endif
+
+
+/*
+ Default handler for unhandled interrupts.
+*/
+void xt_unhandled_interrupt(void * arg)
+{
+ (void) arg; /* Keep compiler happy */
+ exit(-1);
+}
+
+
+/*
+ This function registers a handler for the specified interrupt. The "arg"
+ parameter specifies the argument to be passed to the handler when it is
+ invoked. The function returns the address of the previous handler.
+ On error, it returns 0.
+*/
+xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg)
+{
+ xt_handler_table_entry * entry;
+ xt_handler old;
+
+ if (n >= XCHAL_NUM_INTERRUPTS) {
+ return 0; /* invalid interrupt number */
+ }
+
+#if XCHAL_HAVE_XEA2
+ if (Xthal_intlevel[n] > XCHAL_EXCM_LEVEL) {
+ return 0; /* priority level too high to safely handle in C */
+ }
+#endif
+
+#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3)
+ entry = _xt_interrupt_table + n + 1;
+#else
+ entry = _xt_interrupt_table + n;
+#endif
+ old = entry->handler;
+
+ if (f != NULL) {
+ entry->handler = f;
+ entry->arg = arg;
+ }
+ else {
+ entry->handler = &xt_unhandled_interrupt;
+ entry->arg = (void*)n;
+ }
+
+ return old;
+}
+
+
+/*
+ This function enables the interrupt whose number is specified as
+ the argument.
+*/
+void xt_interrupt_enable(uint32_t intnum)
+{
+#if XCHAL_HAVE_XEA2
+ uint32_t ps = XT_RSIL(15);
+
+ // New INTENABLE = (_xt_intenable | mask) & _xt_vpri_mask.
+ _xt_intenable |= (1 << intnum);
+ XT_WSR_INTENABLE(_xt_intenable & _xt_vpri_mask);
+ XT_WSR_PS(ps);
+ XT_RSYNC();
+#else
+ xthal_interrupt_enable(intnum);
+#endif
+}
+
+
+/*
+ This function disables the interrupt whose number is specified as
+ the argument.
+*/
+void xt_interrupt_disable(uint32_t intnum)
+{
+#if XCHAL_HAVE_XEA2
+ uint32_t ps = XT_RSIL(15);
+
+ // New INTENABLE = (_xt_intenable & ~mask) & _xt_vpri_mask.
+ _xt_intenable &= ~(1 << intnum);
+ XT_WSR_INTENABLE(_xt_intenable & _xt_vpri_mask);
+ XT_WSR_PS(ps);
+ XT_RSYNC();
+#else
+ xthal_interrupt_disable(intnum);
+#endif
+}
+
+
+/*
+ This function triggers the specified interrupt.
+*/
+void xt_interrupt_trigger(uint32_t intnum)
+{
+ xthal_interrupt_trigger(intnum);
+}
+
+
+/*
+ This function clears the specified interrupt.
+*/
+void xt_interrupt_clear(uint32_t intnum)
+{
+ xthal_interrupt_clear(intnum);
+}
+
+
+#endif /* XCHAL_HAVE_INTERRUPTS */
+
diff --git a/ports/xtensa/xcc/src/xtensa_intr_asm.S b/ports/xtensa/xcc/src/xtensa_intr_asm.S
new file mode 100644
index 00000000..78fd8a70
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_intr_asm.S
@@ -0,0 +1,156 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa interrupt handling data and assembly routines. */
+/* Also see xtensa_intr.c. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#include <xtensa/hal.h>
+#include <xtensa/config/core.h>
+
+#include "tx_port.h"
+#include "xtensa_context.h"
+
+#if XCHAL_HAVE_INTERRUPTS
+
+/*
+-------------------------------------------------------------------------------
+ INTENABLE virtualization information.
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_HAVE_XEA2
+
+ .data
+ .global _xt_intdata
+ .align 8
+_xt_intdata:
+ .global _xt_intenable
+ .type _xt_intenable,@object
+ .size _xt_intenable,4
+ .global _xt_vpri_mask
+ .type _xt_vpri_mask,@object
+ .size _xt_vpri_mask,4
+
+_xt_intenable: .word 0 /* Virtual INTENABLE */
+_xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+ System interrupt stack.
+-------------------------------------------------------------------------------
+*/
+
+#if (XCHAL_HAVE_XEA2 || XCHAL_HAVE_ISB)
+ .data
+#else
+ .section .intr.top, "aw"
+#endif
+
+ .global _xt_interrupt_stack
+ .global _xt_interrupt_stack_top
+ .align 16
+
+_xt_interrupt_stack:
+ .space TX_SYSTEM_STACK_SIZE
+_xt_interrupt_stack_top:
+
+
+/*
+-------------------------------------------------------------------------------
+ Table of C-callable interrupt handlers for each interrupt. For XEA2 configs,
+ not all slots can be filled, because interrupts at level > EXCM_LEVEL will
+ not be dispatched to a C handler by default.
+-------------------------------------------------------------------------------
+*/
+
+#if (XCHAL_HAVE_XEA2 || XCHAL_HAVE_ISB)
+ .data
+#else
+ .section .intr.data, "aw"
+#endif
+
+ .global _xt_interrupt_table
+ .align 16
+
+_xt_interrupt_table:
+
+/*
+-------------------------------------------------------------------------------
+ If using the interrupt wrapper, make the first entry in the interrupt table
+ point to the wrapper (XEA3) or leave it empty (XEA2).
+-------------------------------------------------------------------------------
+*/
+#if XCHAL_HAVE_XEA3
+ .word xt_interrupt_wrapper
+ .word 0
+#elif XT_USE_INT_WRAPPER
+ .word 0
+ .word 0
+#endif
+
+ .set i, 0
+ .rept XCHAL_NUM_INTERRUPTS
+ .word xt_unhandled_interrupt /* handler address */
+ .word i /* handler arg (default: intnum) */
+ .set i, i+1
+ .endr
+
+#endif /* XCHAL_HAVE_INTERRUPTS */
+
+
+#if XCHAL_HAVE_EXCEPTIONS
+
+/*
+-------------------------------------------------------------------------------
+ Table of C-callable exception handlers for each exception. Note that not all
+ slots will be active, because some exceptions (e.g. coprocessor exceptions)
+ are always handled by the OS and cannot be hooked by user handlers.
+-------------------------------------------------------------------------------
+*/
+
+ .data
+ .global _xt_exception_table
+ .align 4
+
+_xt_exception_table:
+ .rept XCHAL_EXCCAUSE_NUM
+ .word xt_unhandled_exception /* handler address */
+ .endr
+
+#endif
+
diff --git a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c
new file mode 100644
index 00000000..ff70f4ea
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c
@@ -0,0 +1,125 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa-specific interrupt handler wrapper. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#include <xtensa/config/core.h>
+#include <xtensa/core-macros.h>
+
+#include "xtensa_rtos.h"
+#include "xtensa_api.h"
+
+#include "tx_api.h"
+#include "tx_thread.h"
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+#include "tx_execution_profile.h"
+#endif
+
+
+#if (XCHAL_HAVE_XEA3 && XCHAL_HAVE_INTERRUPTS)
+
+/* Table of interrupt hooks. Used for testing ONLY. */
+#ifdef XT_INTEXC_HOOKS
+volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
+#endif
+
+
+/* Handler table is in xtensa_intr_asm.S */
+
+typedef struct xt_handler_table_entry {
+ void * handler;
+ void * arg;
+} xt_handler_table_entry;
+
+extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS + 1];
+extern int32_t xt_sw_intnum;
+
+static int32_t xt_wflag;
+
+
+/**************************************************************************/
+/* Wrapper for interrupt handlers. Argument is (intnum << 2). */
+/* Execution comes here from the dispatch code if the wrapper is */
+/* enabled. */
+/**************************************************************************/
+void
+xt_interrupt_wrapper(void * arg)
+{
+ uint32_t intnum = (uint32_t)(arg) >> 2;
+ xt_handler_table_entry * entry;
+ xt_handler handler;
+
+ /* Increment interrupt nest counter. */
+ _tx_thread_system_state++;
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the ISR enter function to indicate an ISR is executing. */
+ _tx_execution_isr_enter();
+#endif
+
+ /* Load handler address and argument from table. Note that the
+ first entry in the table points to this wrapper, so we have
+ to skip ahead one.
+ */
+ entry = _xt_interrupt_table + intnum + 1;
+ handler = (xt_handler) entry->handler;
+
+ (*handler)(entry->arg);
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the ISR exit function to indicate an ISR is complete. */
+ _tx_execution_isr_exit();
+#endif
+
+ /* If a context switch is pending, trigger the SW interrupt
+ to process the switch. Set an internal flag so we don't
+ trigger the sw interrupt again when handling it.
+ */
+ if (xt_wflag != 0) {
+ xt_wflag = 0;
+ }
+ else if (_tx_thread_current_ptr != _tx_thread_execute_ptr) {
+ xt_wflag = 1;
+ xt_interrupt_trigger(xt_sw_intnum);
+ }
+
+ /* Decrement interrupt nest counter. */
+ _tx_thread_system_state--;
+}
+
+#endif /* XCHAL_HAVE_XEA3 && XCHAL_HAVE_INTERRUPTS */
+
diff --git a/ports/xtensa/xcc/src/xtensa_overlay_os_hook.c b/ports/xtensa/xcc/src/xtensa_overlay_os_hook.c
new file mode 100644
index 00000000..8fd92701
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_overlay_os_hook.c
@@ -0,0 +1,109 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa overlay manager OS hooks for ThreadX. XEA2 only. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#ifdef XT_USE_OVLY
+
+#include <xtensa/overlay.h>
+#include "tx_api.h"
+
+
+/* Required to work around a bug in the overlay header. */
+#ifdef XT_DISABLE_OVERLAYS
+#undef xt_overlay_fatal_error
+#define xt_overlay_fatal_error(id)
+#endif
+
+
+/* Mutex object that controls access to the overlay. Currently only one
+ * overlay region is supported so one mutex suffices.
+ */
+static TX_MUTEX xt_overlay_mutex;
+
+
+/**************************************************************************/
+/* This function should be overridden to provide OS specific init such */
+/* as the creation of a mutex lock that can be used for overlay locking. */
+/* Typically this mutex would be set up with priority inheritance. See */
+/* overlay manager documentation for more details. */
+/**************************************************************************/
+void
+xt_overlay_init_os(void)
+{
+ /* Create the mutex for overlay access. Priority inheritance is
+ * required.
+ */
+ UINT status =
+ tx_mutex_create (&xt_overlay_mutex, "xt_overlay_lock", TX_INHERIT);
+
+ if (status != TX_SUCCESS) {
+ xt_overlay_fatal_error (-1);
+ }
+}
+
+
+/**************************************************************************/
+/* This function locks access to shared overlay resources, typically */
+/* by acquiring a mutex. */
+/**************************************************************************/
+void
+xt_overlay_lock(void)
+{
+ UINT status = tx_mutex_get (&xt_overlay_mutex, TX_WAIT_FOREVER);
+
+ if (status != TX_SUCCESS) {
+ xt_overlay_fatal_error (-1);
+ }
+}
+
+
+/**************************************************************************/
+/* This function releases access to shared overlay resources, typically */
+/* by unlocking a mutex. */
+/**************************************************************************/
+void
+xt_overlay_unlock(void)
+{
+ UINT status = tx_mutex_put (&xt_overlay_mutex);
+
+ if (status != TX_SUCCESS) {
+ xt_overlay_fatal_error (-1);
+ }
+}
+
+#endif /* XT_USE_OVLY */
+
diff --git a/ports/xtensa/xcc/src/xtensa_vectors.S b/ports/xtensa/xcc/src/xtensa_vectors.S
new file mode 100644
index 00000000..b115abf5
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_vectors.S
@@ -0,0 +1,1696 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa exception and interrupt dispatch for XEA2. */
+/* */
+/* Interrupt handlers and user exception handlers support interaction */
+/* with the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT */
+/* before and after calling the user's specific interrupt handlers. */
+/* */
+/* Users can install application-specific interrupt handlers for low and */
+/* medium priority interrupts, by calling xt_set_interrupt_handler(). */
+/* These handlers can be written in C and must follow the C calling */
+/* convention. The handler table is indexed by the interrupt number. */
+/* Each handler may be provided with an argument. */
+/* */
+/* Note that the system timer interrupt is handled specially, and is */
+/* dispatched to the RTOS-specific handler. This timer cannot be hooked */
+/* by application code. */
+/* */
+/* Optional hooks are also provided to install a handler per level at */
+/* run-time, made available by compiling this source file with */
+/* '-DXT_INTEXC_HOOKS' (useful for automated testing). */
+/* */
+/* Search for locations marked USER_EDIT for helpful comments on where */
+/* to insert application-specific code and how to write them. */
+/* */
+/* Users can install application-specific exception handlers in the */
+/* same way, by calling xt_set_exception_handler(). One handler slot is */
+/* provided for each exception type. Note that some exceptions are */
+/* handled by the porting layer itself, and cannot be taken over by */
+/* application code. These are the alloca, syscall, and coprocessor */
+/* exceptions. */
+/* */
+/* Exception handlers can be written in C, and must follow C calling */
+/* convention. Each handler is passed a pointer to an exception frame as */
+/* its single argument. The exception frame is created on the stack and */
+/* holds the saved context of the thread that took the exception. If the */
+/* handler returns, the context will be restored and the instruction */
+/* that caused the exception will be retried. If the handler makes any */
+/* changes to the saved state in the exception frame, the changes will */
+/* be applied when restoring the context. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#include "xtensa_rtos.h"
+
+
+#if XCHAL_HAVE_XEA2
+
+/* Enable stack backtrace across exception/interrupt - see below */
+#define XT_DEBUG_BACKTRACE 1
+
+
+/*
+--------------------------------------------------------------------------------
+ Defines used to access _xtos_interrupt_table.
+--------------------------------------------------------------------------------
+*/
+#define XIE_HANDLER 0
+#define XIE_ARG 4
+#define XIE_SIZE 8
+
+/*
+--------------------------------------------------------------------------------
+ Macro extract_msb - return the input with only the highest bit set.
+
+ Input : "ain" - Input value, clobbered.
+ Output : "aout" - Output value, has only one bit set, MSB of "ain".
+ The two arguments must be different AR registers.
+--------------------------------------------------------------------------------
+*/
+
+ .macro extract_msb aout ain
+1:
+ addi \aout, \ain, -1 /* aout = ain - 1 */
+ and \ain, \ain, \aout /* ain = ain & aout */
+ bnez \ain, 1b /* repeat until ain == 0 */
+ addi \aout, \aout, 1 /* return aout + 1 */
+ .endm
+
+/*
+--------------------------------------------------------------------------------
+ Macro dispatch_c_isr - dispatch interrupts to user ISRs.
+ This will dispatch to user handlers (if any) that are registered in the
+ XTOS dispatch table (_xtos_interrupt_table). These handlers would have
+ been registered by calling _xtos_set_interrupt_handler(). There is one
+ exception - the timer interrupt used by the OS will not be dispatched
+ to a user handler - this must be handled by the caller of this macro.
+
+ Level triggered and software interrupts are automatically deasserted by
+ this code.
+
+ ASSUMPTIONS:
+ -- PS.INTLEVEL is set to "level" at entry
+ -- PS.EXCM = 0, C calling enabled
+
+ NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
+
+ NOTE: This macro will use registers a0 and a2-a6. The arguments are:
+ level -- interrupt level
+ mask -- interrupt bitmask for this level
+--------------------------------------------------------------------------------
+*/
+
+ .macro dispatch_c_isr level mask
+
+ /* Get mask of pending, enabled interrupts at this level into a2. */
+
+.L_xt_user_int_&level&:
+ rsr a2, INTENABLE
+ rsr a3, INTERRUPT
+ movi a4, \mask
+ and a2, a2, a3
+ and a2, a2, a4
+ beqz a2, 9f /* nothing to do */
+
+ /* This bit of code provides a nice debug backtrace in the debugger.
+ It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
+ if you want to save the cycles.
+ */
+ #if XT_DEBUG_BACKTRACE
+ #ifndef __XTENSA_CALL0_ABI__
+ rsr a0, EPC_1 + \level - 1 /* return address */
+ movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */
+ or a0, a0, a4 /* set top 2 bits */
+ addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */
+ #endif
+ #endif
+
+ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ /* Call the ISR enter function to indicate an ISR is executing. */
+ #ifdef __XTENSA_CALL0_ABI__
+ call0 _tx_execution_isr_enter
+ #else
+ call4 _tx_execution_isr_enter
+ #endif
+ #endif
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a4, _xt_intexc_hooks
+ l32i a4, a4, \level << 2
+ beqz a4, 2f
+ #ifdef __XTENSA_CALL0_ABI__
+ callx0 a4
+ beqz a2, 9f
+ #else
+ mov a6, a2
+ callx4 a4
+ beqz a6, 9f
+ mov a2, a6
+ #endif
+2:
+ #endif
+
+ /* Now look up in the dispatch table and call user ISR if any. */
+ /* If multiple bits are set then MSB has highest priority. */
+
+ extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
+
+ #ifdef XT_USE_SWPRI
+ /* Enable all interrupts at this level that are numerically higher
+ than the one we just selected, since they are treated as higher
+ priority.
+ */
+ movi a3, \mask /* a3 = all interrupts at this level */
+ add a2, a4, a4 /* a2 = a4 << 1 */
+ addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */
+ and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */
+ movi a3, _xt_intdata
+ l32i a6, a3, 4 /* a6 = _xt_vpri_mask */
+ neg a2, a2
+ addi a2, a2, -1 /* a2 = mask to apply */
+ and a5, a6, a2 /* mask off all bits <= a4 bit */
+ s32i a5, a3, 4 /* update _xt_vpri_mask */
+ rsr a3, INTENABLE
+ and a3, a3, a2 /* mask off all bits <= a4 bit */
+ wsr a3, INTENABLE
+ rsil a3, \level - 1 /* lower interrupt level by 1 */
+ #endif
+
+ wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
+
+ #ifndef TX_NO_TIMER
+ movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
+ beq a3, a4, 7f /* if timer interrupt then skip table */
+ #endif
+
+ find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
+
+ movi a4, _xt_interrupt_table
+ addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
+ l32i a4, a3, XIE_HANDLER /* a4 = handler address */
+ #ifdef __XTENSA_CALL0_ABI__
+ mov a12, a6 /* save in callee-saved reg */
+ l32i a2, a3, XIE_ARG /* a2 = handler arg */
+ callx0 a4 /* call handler */
+ mov a2, a12
+ #else
+ mov a2, a6 /* save in windowed reg */
+ l32i a6, a3, XIE_ARG /* a6 = handler arg */
+ callx4 a4 /* call handler */
+ #endif
+
+ #ifdef XT_USE_SWPRI
+ j 8f
+ #else
+ j .L_xt_user_int_&level& /* check for more interrupts */
+ #endif
+
+7:
+
+ #ifndef TX_NO_TIMER
+ .ifeq XT_TIMER_INTPRI - \level
+.L_xt_user_int_timer_&level&:
+ /*
+ Interrupt handler for the RTOS tick timer if at this level.
+ We'll be reading the interrupt state again after this call
+ so no need to preserve any registers except a6 (vpri_mask).
+ */
+
+ #ifdef __XTENSA_CALL0_ABI__
+ mov a12, a6
+ call0 XT_RTOS_TIMER_INT
+ mov a2, a12
+ #else
+ mov a2, a6
+ call4 XT_RTOS_TIMER_INT
+ #endif
+ .endif
+ #endif
+
+ #ifdef XT_USE_SWPRI
+ j 8f
+ #else
+ j .L_xt_user_int_&level& /* check for more interrupts */
+ #endif
+
+ #ifdef XT_USE_SWPRI
+8:
+ /*
+ Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
+ virtual _xt_intenable which _could_ have changed during interrupt
+ processing. But before that, raise the interrupt level back again.
+ */
+
+ rsil a3, \level
+ movi a3, _xt_intdata
+ l32i a4, a3, 0 /* a4 = _xt_intenable */
+ s32i a2, a3, 4 /* update _xt_vpri_mask */
+ and a4, a4, a2 /* a4 = masked intenable */
+ wsr a4, INTENABLE /* update INTENABLE */
+ #endif
+
+9:
+ /* done */
+
+ #if XCHAL_HAVE_EXCLUSIVE
+ /* Clear any local exclusive monitors. */
+ clrex
+ #endif
+
+ .endm
+
+
+/*
+--------------------------------------------------------------------------------
+ Panic handler.
+ Should be reached by call0 (preferable) or jump only. If call0, a0 says where
+ from. If on simulator, display panic message and abort, else loop indefinitely.
+--------------------------------------------------------------------------------
+*/
+
+ .text
+ .global _xt_panic
+ .type _xt_panic,@function
+ .align 4
+
+_xt_panic:
+ #ifdef XT_SIMULATOR
+ addi a4, a0, -3 /* point to call0 */
+ movi a3, _xt_panic_message
+ movi a2, SYS_log_msg
+ simcall
+ movi a2, SYS_gdb_abort
+ simcall
+ #else
+ rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */
+1: j 1b /* loop infinitely */
+ #endif
+
+ .section .rodata, "a"
+ .align 4
+
+_xt_panic_message:
+ .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n"
+
+
+/*
+--------------------------------------------------------------------------------
+ Hooks to dynamically install handlers for exceptions and interrupts.
+ Allows automated regression frameworks to install handlers per test.
+ Consists of an array of function pointers indexed by interrupt level,
+ with index 0 containing the entry for user exceptions.
+ Initialized with all 0s, meaning no handler is installed at each level.
+ See comment in xtensa_rtos.h for more details.
+--------------------------------------------------------------------------------
+*/
+
+ #ifdef XT_INTEXC_HOOKS
+ .data
+ .global _xt_intexc_hooks
+ .type _xt_intexc_hooks,@object
+ .align 4
+
+_xt_intexc_hooks:
+ .fill XT_INTEXC_HOOK_NUM, 4, 0
+ #endif
+
+
+/*
+--------------------------------------------------------------------------------
+ EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
+ (except window exception vectors).
+
+ Each vector goes at a predetermined location according to the Xtensa
+ hardware configuration, which is ensured by its placement in a special
+ section known to the Xtensa linker support package (LSP). It performs
+ the minimum necessary before jumping to the handler in the .text section.
+
+ The corresponding handler goes in the normal .text section. It sets up
+ the appropriate stack frame, saves a few vector-specific registers and
+ calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
+ and enter the RTOS, then sets up a C environment. It then calls the
+ user's interrupt handler code (which may be coded in C) and finally
+ calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
+
+ While XT_RTOS_INT_EXIT does not return directly to the interruptee,
+ eventually the RTOS scheduler will want to dispatch the interrupted
+ task or handler. The scheduler will return to the exit point that was
+ saved in the interrupt stack frame at XT_STK_EXIT.
+--------------------------------------------------------------------------------
+*/
+
+
+/*
+--------------------------------------------------------------------------------
+Debug Exception.
+--------------------------------------------------------------------------------
+*/
+
+#if XCHAL_HAVE_DEBUG
+
+ .begin literal_prefix .DebugExceptionVector
+ .section .DebugExceptionVector.text, "ax"
+ .global _DebugExceptionVector
+ .align 4
+
+_DebugExceptionVector:
+
+ #ifdef XT_SIMULATOR
+ /*
+ In the simulator, let the debugger (if any) handle the debug exception,
+ or simply stop the simulation:
+ */
+ wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */
+ movi a2, SYS_gdb_enter_sktloop
+ simcall /* have ISS handle debug exc. */
+ #elif 0 /* change condition to 1 to use the HAL minimal debug handler */
+ wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL
+ movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */
+ jx a3
+ #else
+ wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
+ call0 _xt_panic /* does not return */
+ rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
+ #endif
+
+ .end literal_prefix
+
+#endif
+
+/*
+--------------------------------------------------------------------------------
+Double Exception.
+Double exceptions are not a normal occurrence. They indicate a bug of some kind.
+--------------------------------------------------------------------------------
+*/
+
+#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
+
+ .begin literal_prefix .DoubleExceptionVector
+ .section .DoubleExceptionVector.text, "ax"
+ .global _DoubleExceptionVector
+ .align 4
+
+_DoubleExceptionVector:
+
+ #if XCHAL_HAVE_DEBUG
+ break 1, 4 /* unhandled double exception */
+ #endif
+ call0 _xt_panic /* does not return */
+ rfde /* make a0 point here not later */
+
+ .end literal_prefix
+
+#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
+
+/*
+--------------------------------------------------------------------------------
+Kernel Exception (including Level 1 Interrupt from kernel mode).
+--------------------------------------------------------------------------------
+*/
+
+ .begin literal_prefix .KernelExceptionVector
+ .section .KernelExceptionVector.text, "ax"
+ .global _KernelExceptionVector
+ .align 4
+
+_KernelExceptionVector:
+
+ wsr a0, EXCSAVE_1 /* preserve a0 */
+ call0 _xt_kernel_exc /* kernel exception handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .align 4
+
+_xt_kernel_exc:
+ #if XCHAL_HAVE_DEBUG
+ break 1, 0 /* unhandled kernel exception */
+ #endif
+ call0 _xt_panic /* does not return */
+ rfe /* make a0 point here not there */
+
+
+/*
+--------------------------------------------------------------------------------
+User Exception (including Level 1 Interrupt from user mode).
+--------------------------------------------------------------------------------
+*/
+
+ .begin literal_prefix .UserExceptionVector
+ .section .UserExceptionVector.text, "ax"
+ .global _UserExceptionVector
+ .type _UserExceptionVector,@function
+ .align 4
+
+_UserExceptionVector:
+
+ wsr a0, EXCSAVE_1 /* preserve a0 */
+ call0 _xt_user_exc /* user exception handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+/*
+--------------------------------------------------------------------------------
+ Insert some waypoints for jumping beyond the signed 8-bit range of
+ conditional branch instructions, so the conditional branchces to specific
+ exception handlers are not taken in the mainline. Saves some cycles in the
+ mainline.
+--------------------------------------------------------------------------------
+*/
+
+ .text
+
+ #if XCHAL_HAVE_WINDOWED
+ .align 4
+_xt_to_alloca_exc:
+ call0 _xt_alloca_exc /* in window vectors section */
+ /* never returns here - call0 is used as a jump (see note at top) */
+ #endif
+
+ .align 4
+_xt_to_syscall_exc:
+ call0 _xt_syscall_exc
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ #if XCHAL_CP_NUM > 0
+ .align 4
+_xt_to_coproc_exc:
+ call0 _xt_coproc_exc
+ /* never returns here - call0 is used as a jump (see note at top) */
+ #endif
+
+
+/*
+--------------------------------------------------------------------------------
+ User exception handler.
+--------------------------------------------------------------------------------
+*/
+
+ .type _xt_user_exc,@function
+ .align 4
+
+_xt_user_exc:
+
+ /* If level 1 interrupt then jump to the dispatcher */
+ rsr a0, EXCCAUSE
+ beqi a0, EXCCAUSE_LEVEL1_INTERRUPT, _xt_lowint1
+
+ /* Handle any coprocessor exceptions. Rely on the fact that exception
+ numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
+ */
+ #if XCHAL_CP_NUM > 0
+ bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
+ #endif
+
+ /* Handle alloca and syscall exceptions */
+ #if XCHAL_HAVE_WINDOWED
+ beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc
+ #endif
+ beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
+
+ /* Handle all other exceptions. All can have user-defined handlers. */
+ /* NOTE: we'll stay on the user stack for exception handling. */
+
+ /* Allocate exception frame and save minimal context. */
+ mov a0, sp
+ addi sp, sp, -XT_STK_FRMSZ
+ s32i a0, sp, XT_STK_A1
+ #if XCHAL_HAVE_WINDOWED
+ s32e a0, sp, -12 /* for debug backtrace */
+ #endif
+ rsr a0, PS /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_1 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_1 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ #if XCHAL_HAVE_WINDOWED
+ s32e a0, sp, -16 /* for debug backtrace */
+ #endif
+ s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
+ s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
+ call0 _xt_context_save
+
+ /* Save exc cause and vaddr into exception frame */
+ rsr a0, EXCCAUSE
+ s32i a0, sp, XT_STK_EXCCAUSE
+ rsr a0, EXCVADDR
+ s32i a0, sp, XT_STK_EXCVADDR
+
+ /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+
+ #ifdef XT_DEBUG_BACKTRACE
+ #ifndef __XTENSA_CALL0_ABI__
+ rsr a0, EPC_1 /* return address for debug backtrace */
+ movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */
+ rsync /* wait for WSR.PS to complete */
+ or a0, a0, a5 /* set top 2 bits */
+ addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */
+ #else
+ rsync /* wait for WSR.PS to complete */
+ #endif
+ #endif
+
+ rsr a2, EXCCAUSE /* recover exc cause */
+
+ #ifdef XT_INTEXC_HOOKS
+ /*
+ Call exception hook to pre-handle exceptions (if installed).
+ Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
+ */
+ movi a4, _xt_intexc_hooks
+ l32i a4, a4, 0 /* user exception hook index 0 */
+ beqz a4, 1f
+.Ln_xt_user_exc_call_hook:
+ #ifdef __XTENSA_CALL0_ABI__
+ callx0 a4
+ beqi a2, -1, .L_xt_user_done
+ #else
+ mov a6, a2
+ callx4 a4
+ beqi a6, -1, .L_xt_user_done
+ mov a2, a6
+ #endif
+1:
+ #endif
+
+ rsr a2, EXCCAUSE /* recover exc cause */
+ movi a3, _xt_exception_table
+ addx4 a4, a2, a3 /* a4 = address of exception table entry */
+ l32i a4, a4, 0 /* a4 = handler address */
+ #ifdef __XTENSA_CALL0_ABI__
+ mov a2, sp /* a2 = pointer to exc frame */
+ callx0 a4 /* call handler */
+ #else
+ mov a6, sp /* a6 = pointer to exc frame */
+ callx4 a4 /* call handler */
+ #endif
+
+.L_xt_user_done:
+
+ /* Restore context and return */
+ call0 _xt_context_restore
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, PS
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_1
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove exception frame */
+ rsync /* ensure PS and EPC written */
+ rfe /* PS.EXCM is cleared */
+
+
+/*
+--------------------------------------------------------------------------------
+ Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+ on entry and used to return to a thread or interrupted interrupt handler.
+--------------------------------------------------------------------------------
+*/
+
+ .global _xt_user_exit
+ .type _xt_user_exit,@function
+ .align 4
+_xt_user_exit:
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, PS
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_1
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure PS and EPC written */
+ rfe /* PS.EXCM is cleared */
+
+
+/*
+--------------------------------------------------------------------------------
+Syscall Exception Handler (jumped to from User Exception Handler).
+Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
+Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
+--------------------------------------------------------------------------------
+*/
+
+ .text
+ .type _xt_syscall_exc,@function
+ .align 4
+_xt_syscall_exc:
+
+ #ifdef __XTENSA_CALL0_ABI__
+ /*
+ Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
+ Use a minimal stack frame (16B) to save A2 & A3 for scratch.
+ PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
+ rsr a0, PS
+ addi a0, a0, -PS_EXCM_MASK
+ wsr a0, PS
+ */
+ addi sp, sp, -16
+ s32i a2, sp, 8
+ s32i a3, sp, 12
+ #else /* Windowed ABI */
+ /*
+ Save necessary context and spill the register windows.
+ PS.EXCM is still set and must remain set until after the spill.
+ Reuse context save function though it saves more than necessary.
+ For this reason, a full interrupt stack frame is allocated.
+ */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
+ s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
+ call0 _xt_context_save
+ #endif
+
+ /*
+ Grab the interruptee's PC and skip over the 'syscall' instruction.
+ If it's at the end of a zero-overhead loop and it's not on the last
+ iteration, decrement loop counter and skip to beginning of loop.
+ */
+ rsr a2, EPC_1 /* a2 = PC of 'syscall' */
+ addi a3, a2, 3 /* ++PC */
+ #if XCHAL_HAVE_LOOPS
+ rsr a0, LEND /* if (PC == LEND */
+ bne a3, a0, 1f
+ rsr a0, LCOUNT /* && LCOUNT != 0) */
+ beqz a0, 1f /* { */
+ addi a0, a0, -1 /* --LCOUNT */
+ rsr a3, LBEG /* PC = LBEG */
+ wsr a0, LCOUNT /* } */
+ #endif
+1: wsr a3, EPC_1 /* update PC */
+
+ /* Restore interruptee's context and return from exception. */
+ #ifdef __XTENSA_CALL0_ABI__
+ l32i a2, sp, 8
+ l32i a3, sp, 12
+ addi sp, sp, 16
+ #else
+ call0 _xt_context_restore
+ addi sp, sp, XT_STK_FRMSZ
+ #endif
+ movi a0, -1
+ movnez a2, a0, a2 /* return -1 if not syscall 0 */
+ rsr a0, EXCSAVE_1
+ rfe
+
+
+/*
+-------------------------------------------------------------------------------
+ Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet.
+-------------------------------------------------------------------------------
+*/
+
+ .text
+ .type _xt_lowint1,@function
+ .align 4
+
+_xt_lowint1:
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, PS /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_1 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_1 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, _xt_user_exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ /* Save rest of interrupt context and enter RTOS. */
+ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
+
+ /* !! We are now on the RTOS system stack !! */
+
+ /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(1) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(1) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+ rsync
+
+ /* OK to call C code at this point, dispatch user ISRs */
+
+ dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
+
+ /* Done handling interrupts, transfer control to OS */
+ call0 XT_RTOS_INT_EXIT /* does not return directly here */
+
+
+/*
+-------------------------------------------------------------------------------
+ MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS.
+
+ Medium priority interrupts are by definition those with priority greater
+ than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by
+ setting PS.EXCM and therefore can easily support a C environment for
+ handlers in C, and interact safely with an RTOS.
+
+ Each vector goes at a predetermined location according to the Xtensa
+ hardware configuration, which is ensured by its placement in a special
+ section known to the Xtensa linker support package (LSP). It performs
+ the minimum necessary before jumping to the handler in the .text section.
+
+ The corresponding handler goes in the normal .text section. It sets up
+ the appropriate stack frame, saves a few vector-specific registers and
+ calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
+ and enter the RTOS, then sets up a C environment. It then calls the
+ user's interrupt handler code (which may be coded in C) and finally
+ calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
+
+ While XT_RTOS_INT_EXIT does not return directly to the interruptee,
+ eventually the RTOS scheduler will want to dispatch the interrupted
+ task or handler. The scheduler will return to the exit point that was
+ saved in the interrupt stack frame at XT_STK_EXIT.
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_EXCM_LEVEL >= 2
+
+ .begin literal_prefix .Level2InterruptVector
+ .section .Level2InterruptVector.text, "ax"
+ .global _Level2Vector
+ .type _Level2Vector,@function
+ .align 4
+_Level2Vector:
+ wsr a0, EXCSAVE_2 /* preserve a0 */
+ call0 _xt_medint2 /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_medint2,@function
+ .align 4
+_xt_medint2:
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_2 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_2 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_2 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, _xt_medint2_exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ /* Save rest of interrupt context and enter RTOS. */
+ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
+
+ /* !! We are now on the RTOS system stack !! */
+
+ /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(2) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+ rsync
+
+ /* OK to call C code at this point, dispatch user ISRs */
+
+ dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
+
+ /* Done handling interrupts, transfer control to OS */
+ call0 XT_RTOS_INT_EXIT /* does not return directly here */
+
+ /*
+ Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+ on entry and used to return to a thread or interrupted interrupt handler.
+ */
+ .global _xt_medint2_exit
+ .type _xt_medint2_exit,@function
+ .align 4
+_xt_medint2_exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_2
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_2
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 2
+
+#endif /* Level 2 */
+
+#if XCHAL_EXCM_LEVEL >= 3
+
+ .begin literal_prefix .Level3InterruptVector
+ .section .Level3InterruptVector.text, "ax"
+ .global _Level3Vector
+ .type _Level3Vector,@function
+ .align 4
+_Level3Vector:
+ wsr a0, EXCSAVE_3 /* preserve a0 */
+ call0 _xt_medint3 /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_medint3,@function
+ .align 4
+_xt_medint3:
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_3 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_3 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_3 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, _xt_medint3_exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ /* Save rest of interrupt context and enter RTOS. */
+ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
+
+ /* !! We are now on the RTOS system stack !! */
+
+ /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(3) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+ rsync
+
+ /* OK to call C code at this point, dispatch user ISRs */
+
+ dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
+
+ /* Done handling interrupts, transfer control to OS */
+ call0 XT_RTOS_INT_EXIT /* does not return directly here */
+
+ /*
+ Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+ on entry and used to return to a thread or interrupted interrupt handler.
+ */
+ .global _xt_medint3_exit
+ .type _xt_medint3_exit,@function
+ .align 4
+_xt_medint3_exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_3
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_3
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 3
+
+#endif /* Level 3 */
+
+#if XCHAL_EXCM_LEVEL >= 4
+
+ .begin literal_prefix .Level4InterruptVector
+ .section .Level4InterruptVector.text, "ax"
+ .global _Level4Vector
+ .type _Level4Vector,@function
+ .align 4
+_Level4Vector:
+ wsr a0, EXCSAVE_4 /* preserve a0 */
+ call0 _xt_medint4 /* load interrupt handler */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_medint4,@function
+ .align 4
+_xt_medint4:
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_4 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_4 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_4 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, _xt_medint4_exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ /* Save rest of interrupt context and enter RTOS. */
+ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
+
+ /* !! We are now on the RTOS system stack !! */
+
+ /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(4) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+ rsync
+
+ /* OK to call C code at this point, dispatch user ISRs */
+
+ dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
+
+ /* Done handling interrupts, transfer control to OS */
+ call0 XT_RTOS_INT_EXIT /* does not return directly here */
+
+ /*
+ Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+ on entry and used to return to a thread or interrupted interrupt handler.
+ */
+ .global _xt_medint4_exit
+ .type _xt_medint4_exit,@function
+ .align 4
+_xt_medint4_exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_4
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_4
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 4
+
+#endif /* Level 4 */
+
+#if XCHAL_EXCM_LEVEL >= 5
+
+ .begin literal_prefix .Level5InterruptVector
+ .section .Level5InterruptVector.text, "ax"
+ .global _Level5Vector
+ .type _Level5Vector,@function
+ .align 4
+_Level5Vector:
+ wsr a0, EXCSAVE_5 /* preserve a0 */
+ call0 _xt_medint5 /* load interrupt handler */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_medint5,@function
+ .align 4
+_xt_medint5:
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_5 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_5 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_5 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, _xt_medint5_exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ /* Save rest of interrupt context and enter RTOS. */
+ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
+
+ /* !! We are now on the RTOS system stack !! */
+
+ /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(5) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+ rsync
+
+ /* OK to call C code at this point, dispatch user ISRs */
+
+ dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
+
+ /* Done handling interrupts, transfer control to OS */
+ call0 XT_RTOS_INT_EXIT /* does not return directly here */
+
+ /*
+ Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+ on entry and used to return to a thread or interrupted interrupt handler.
+ */
+ .global _xt_medint5_exit
+ .type _xt_medint5_exit,@function
+ .align 4
+_xt_medint5_exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_5
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_5
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 5
+
+#endif /* Level 5 */
+
+#if XCHAL_EXCM_LEVEL >= 6
+
+ .begin literal_prefix .Level6InterruptVector
+ .section .Level6InterruptVector.text, "ax"
+ .global _Level6Vector
+ .type _Level6Vector,@function
+ .align 4
+_Level6Vector:
+ wsr a0, EXCSAVE_6 /* preserve a0 */
+ call0 _xt_medint6 /* load interrupt handler */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_medint6,@function
+ .align 4
+_xt_medint6:
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_6 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_6 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_6 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, _xt_medint6_exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ /* Save rest of interrupt context and enter RTOS. */
+ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
+
+ /* !! We are now on the RTOS system stack !! */
+
+ /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+ #ifdef __XTENSA_CALL0_ABI__
+ movi a0, PS_INTLEVEL(6) | PS_UM
+ #else
+ movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
+ #endif
+ wsr a0, PS
+ rsync
+
+ /* OK to call C code at this point, dispatch user ISRs */
+
+ dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
+
+ /* Done handling interrupts, transfer control to OS */
+ call0 XT_RTOS_INT_EXIT /* does not return directly here */
+
+ /*
+ Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+ on entry and used to return to a thread or interrupted interrupt handler.
+ */
+ .global _xt_medint6_exit
+ .type _xt_medint6_exit,@function
+ .align 4
+_xt_medint6_exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_6
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_6
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 6
+
+#endif /* Level 6 */
+
+
+/*******************************************************************************
+
+HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
+
+High priority interrupts are by definition those with priorities greater
+than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
+interrupts cannot interact with the RTOS, that is they must save all regs
+they use and not call any RTOS function.
+
+A further restriction imposed by the Xtensa windowed architecture is that
+high priority interrupts must not modify the stack area even logically
+"above" the top of the interrupted stack (they need to provide their
+own stack or static save area).
+
+Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
+and used for purposes requiring very short service times.
+
+Here are templates for high priority (level 2+) interrupt vectors.
+They assume only one interrupt per level to avoid the burden of identifying
+which interrupts at this level are pending and enabled. This allows for
+minimum latency and avoids having to save/restore a2 in addition to a0.
+If more than one interrupt per high priority level is configured, this burden
+is on the handler which in any case must provide a way to save and restore
+registers it uses without touching the interrupted stack.
+
+Each vector goes at a predetermined location according to the Xtensa
+hardware configuration, which is ensured by its placement in a special
+section known to the Xtensa linker support package (LSP). It performs
+the minimum necessary before jumping to the handler in the .text section.
+
+*******************************************************************************/
+
+/*
+Currently only shells for high priority interrupt handlers are provided
+here. However a template and example can be found in the Cadence Design Systems tools
+documentation: "Microprocessor Programmer's Guide".
+*/
+
+#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
+
+ .begin literal_prefix .Level2InterruptVector
+ .section .Level2InterruptVector.text, "ax"
+ .global _Level2Vector
+ .type _Level2Vector,@function
+ .align 4
+_Level2Vector:
+ wsr a0, EXCSAVE_2 /* preserve a0 */
+ call0 _xt_highint2 /* load interrupt handler */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_highint2,@function
+ .align 4
+_xt_highint2:
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a0, _xt_intexc_hooks
+ l32i a0, a0, 2<<2
+ beqz a0, 1f
+.Ln_xt_highint2_call_hook:
+ callx0 a0 /* must NOT disturb stack! */
+1:
+ #endif
+
+ /* USER_EDIT:
+ ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
+ */
+
+ .align 4
+.L_xt_highint2_exit:
+ rsr a0, EXCSAVE_2 /* restore a0 */
+ rfi 2
+
+#endif /* Level 2 */
+
+#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
+
+ .begin literal_prefix .Level3InterruptVector
+ .section .Level3InterruptVector.text, "ax"
+ .global _Level3Vector
+ .type _Level3Vector,@function
+ .align 4
+_Level3Vector:
+ wsr a0, EXCSAVE_3 /* preserve a0 */
+ call0 _xt_highint3 /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_highint3,@function
+ .align 4
+_xt_highint3:
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a0, _xt_intexc_hooks
+ l32i a0, a0, 3<<2
+ beqz a0, 1f
+.Ln_xt_highint3_call_hook:
+ callx0 a0 /* must NOT disturb stack! */
+1:
+ #endif
+
+ /* USER_EDIT:
+ ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
+ */
+
+ .align 4
+.L_xt_highint3_exit:
+ rsr a0, EXCSAVE_3 /* restore a0 */
+ rfi 3
+
+#endif /* Level 3 */
+
+#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
+
+ .begin literal_prefix .Level4InterruptVector
+ .section .Level4InterruptVector.text, "ax"
+ .global _Level4Vector
+ .type _Level4Vector,@function
+ .align 4
+_Level4Vector:
+ wsr a0, EXCSAVE_4 /* preserve a0 */
+ call0 _xt_highint4 /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_highint4,@function
+ .align 4
+_xt_highint4:
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a0, _xt_intexc_hooks
+ l32i a0, a0, 4<<2
+ beqz a0, 1f
+.Ln_xt_highint4_call_hook:
+ callx0 a0 /* must NOT disturb stack! */
+1:
+ #endif
+
+ /* USER_EDIT:
+ ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
+ */
+
+ .align 4
+.L_xt_highint4_exit:
+ rsr a0, EXCSAVE_4 /* restore a0 */
+ rfi 4
+
+#endif /* Level 4 */
+
+#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
+
+ .begin literal_prefix .Level5InterruptVector
+ .section .Level5InterruptVector.text, "ax"
+ .global _Level5Vector
+ .type _Level5Vector,@function
+ .align 4
+_Level5Vector:
+ wsr a0, EXCSAVE_5 /* preserve a0 */
+ call0 _xt_highint5 /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_highint5,@function
+ .align 4
+_xt_highint5:
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a0, _xt_intexc_hooks
+ l32i a0, a0, 5<<2
+ beqz a0, 1f
+.Ln_xt_highint5_call_hook:
+ callx0 a0 /* must NOT disturb stack! */
+1:
+ #endif
+
+ /* USER_EDIT:
+ ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
+ */
+
+ .align 4
+.L_xt_highint5_exit:
+ rsr a0, EXCSAVE_5 /* restore a0 */
+ rfi 5
+
+#endif /* Level 5 */
+
+#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
+
+ .begin literal_prefix .Level6InterruptVector
+ .section .Level6InterruptVector.text, "ax"
+ .global _Level6Vector
+ .type _Level6Vector,@function
+ .align 4
+_Level6Vector:
+ wsr a0, EXCSAVE_6 /* preserve a0 */
+ call0 _xt_highint6 /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_highint6,@function
+ .align 4
+_xt_highint6:
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a0, _xt_intexc_hooks
+ l32i a0, a0, 6<<2
+ beqz a0, 1f
+.Ln_xt_highint6_call_hook:
+ callx0 a0 /* must NOT disturb stack! */
+1:
+ #endif
+
+ /* USER_EDIT:
+ ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
+ */
+
+ .align 4
+.L_xt_highint6_exit:
+ rsr a0, EXCSAVE_6 /* restore a0 */
+ rfi 6
+
+#endif /* Level 6 */
+
+#if XCHAL_HAVE_NMI
+
+ .begin literal_prefix .NMIExceptionVector
+ .section .NMIExceptionVector.text, "ax"
+ .global _NMIExceptionVector
+ .type _NMIExceptionVector,@function
+ .align 4
+_NMIExceptionVector:
+ wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
+ call0 _xt_nmi /* load interrupt handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .text
+ .type _xt_nmi,@function
+ .align 4
+_xt_nmi:
+
+ #ifdef XT_INTEXC_HOOKS
+ /* Call interrupt hook if present to (pre)handle interrupts. */
+ movi a0, _xt_intexc_hooks
+ l32i a0, a0, XCHAL_NMILEVEL<<2
+ beqz a0, 1f
+.Ln_xt_nmi_call_hook:
+ callx0 a0 /* must NOT disturb stack! */
+1:
+ #endif
+
+ /* USER_EDIT:
+ ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
+ */
+
+ .align 4
+.L_xt_nmi_exit:
+ rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
+ rfi XCHAL_NMILEVEL
+
+#endif /* NMI */
+
+
+/*******************************************************************************
+
+WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
+
+Here is the code for each window overflow/underflow exception vector and
+(interspersed) efficient code for handling the alloca exception cause.
+Window exceptions are handled entirely in the vector area and are very
+tight for performance. The alloca exception is also handled entirely in
+the window vector area so comes at essentially no cost in code size.
+Users should never need to modify them and Cadence Design Systems recommends
+they do not.
+
+Window handlers go at predetermined vector locations according to the
+Xtensa hardware configuration, which is ensured by their placement in a
+special section known to the Xtensa linker support package (LSP). Since
+their offsets in that section are always the same, the LSPs do not define
+a section per vector.
+
+These things are coded for XEA2 only (XEA1 is not supported).
+
+Note on Underflow Handlers:
+The underflow handler for returning from call[i+1] to call[i]
+must preserve all the registers from call[i+1]'s window.
+In particular, a0 and a1 must be preserved because the RETW instruction
+will be reexecuted (and may even underflow if an intervening exception
+has flushed call[i]'s registers).
+Registers a2 and up may contain return values.
+
+*******************************************************************************/
+
+#if XCHAL_HAVE_WINDOWED
+
+ .section .WindowVectors.text, "ax"
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call4.
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call4 to call[j+1].
+On entry here:
+ window rotated to call[j] start point;
+ a0-a3 are registers to be saved;
+ a4-a15 must be preserved;
+ a5 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+ .org 0x0
+ .global _WindowOverflow4
+_WindowOverflow4:
+
+ s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */
+ s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */
+ s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */
+ s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */
+ rfwo /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call4
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call4 to call[i+1].
+On entry here:
+ window rotated to call[i] start point;
+ a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
+ a4-a15 must be preserved (they are call[i+1].reg[0..11]);
+ a5 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+ .org 0x40
+ .global _WindowUnderflow4
+_WindowUnderflow4:
+
+ l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */
+ l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */
+ l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */
+ l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */
+ rfwu
+
+/*
+--------------------------------------------------------------------------------
+Handle alloca exception generated by interruptee executing 'movsp'.
+This uses space between the window vectors, so is essentially "free".
+All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
+and PS.EXCM has been set by the exception hardware (can't be interrupted).
+The fact the alloca exception was taken means the registers associated with
+the base-save area have been spilled and will be restored by the underflow
+handler, so those 4 registers are available for scratch.
+The code is optimized to avoid unaligned branches and minimize cache misses.
+--------------------------------------------------------------------------------
+*/
+
+ .align 4
+ .global _xt_alloca_exc
+_xt_alloca_exc:
+
+ rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */
+ rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */
+ rsr a2, PS
+ extui a3, a2, PS_OWB_SHIFT, PS_OWB_BITS
+ xor a3, a3, a4 /* bits changed from old to current windowbase */
+ rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */
+ slli a3, a3, PS_OWB_SHIFT
+ xor a2, a2, a3 /* flip changed bits in old window base */
+ wsr a2, PS /* update PS.OWB to new window base */
+ rsync
+
+ _bbci.l a4, 31, _WindowUnderflow4
+ rotw -1 /* original a0 goes to a8 */
+ _bbci.l a8, 30, _WindowUnderflow8
+ rotw -1
+ j _WindowUnderflow12
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call8
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call8 to call[j+1].
+On entry here:
+ window rotated to call[j] start point;
+ a0-a7 are registers to be saved;
+ a8-a15 must be preserved;
+ a9 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+ .org 0x80
+ .global _WindowOverflow8
+_WindowOverflow8:
+
+ s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */
+ l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
+ (used to find end of call[j]'s frame) */
+ s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */
+ s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */
+ s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */
+ s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */
+ s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */
+ s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */
+ s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */
+ rfwo /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call8
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call8 to call[i+1].
+On entry here:
+ window rotated to call[i] start point;
+ a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
+ a8-a15 must be preserved (they are call[i+1].reg[0..7]);
+ a9 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+ .org 0xC0
+ .global _WindowUnderflow8
+_WindowUnderflow8:
+
+ l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */
+ l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */
+ l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */
+ l32e a7, a1, -12 /* a7 <- call[i-1]'s sp
+ (used to find end of call[i]'s frame) */
+ l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */
+ l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */
+ l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */
+ l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */
+ l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */
+ rfwu
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call12
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call12 to call[j+1].
+On entry here:
+ window rotated to call[j] start point;
+ a0-a11 are registers to be saved;
+ a12-a15 must be preserved;
+ a13 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+ .org 0x100
+ .global _WindowOverflow12
+_WindowOverflow12:
+
+ s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */
+ l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
+ (used to find end of call[j]'s frame) */
+ s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */
+ s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */
+ s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */
+ s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */
+ s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */
+ s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */
+ s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */
+ s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */
+ s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */
+ s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */
+ s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */
+ rfwo /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call12
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call12 to call[i+1].
+On entry here:
+ window rotated to call[i] start point;
+ a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
+ a12-a15 must be preserved (they are call[i+1].reg[0..3]);
+ a13 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+ .org 0x140
+ .global _WindowUnderflow12
+_WindowUnderflow12:
+
+ l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */
+ l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */
+ l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */
+ l32e a11, a1, -12 /* a11 <- call[i-1]'s sp
+ (used to find end of call[i]'s frame) */
+ l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */
+ l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */
+ l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */
+ l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */
+ l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */
+ l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */
+ l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */
+ l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */
+ l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */
+ rfwu
+
+#endif /* XCHAL_HAVE_WINDOWED */
+
+#endif /* XCHAL_HAVE_XEA2 */
+
diff --git a/ports/xtensa/xcc/src/xtensa_vectors_xea3.S b/ports/xtensa/xcc/src/xtensa_vectors_xea3.S
new file mode 100644
index 00000000..5596a75c
--- /dev/null
+++ b/ports/xtensa/xcc/src/xtensa_vectors_xea3.S
@@ -0,0 +1,392 @@
+/**************************************************************************/
+/* Copyright (c) Cadence Design Systems, Inc. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* DESCRIPTION */
+/* */
+/* Xtensa exception and interrupt dispatch for XEA3. */
+/* */
+/* Interrupt handlers and user exception handlers support interaction */
+/* with the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT */
+/* before and after calling the user's specific interrupt handlers. */
+/* */
+/* Users can install application-specific interrupt handlers by calling */
+/* xt_set_interrupt_handler(). These handlers can be written in C and */
+/* must follow the C calling convention. The handler table is indexed by */
+/* the interrupt number. Each handler may be provided with an argument. */
+/* */
+/* Users can install application-specific exception handlers in the */
+/* same way, by calling xt_set_exception_handler(). One handler slot is */
+/* provided for each exception type. Note that some exceptions are */
+/* handled by the porting layer itself, and cannot be taken over by */
+/* application code. These are the alloca, syscall, and coprocessor */
+/* exceptions. */
+/* */
+/* Exception handlers can be written in C, and must follow C calling */
+/* convention. Each handler is passed a pointer to an exception frame as */
+/* its single argument. The exception frame is created on the stack and */
+/* holds the saved context of the thread that took the exception. If the */
+/* handler returns, the context will be restored and the instruction */
+/* that caused the exception will be retried. If the handler makes any */
+/* changes to the saved state in the exception frame, the changes will */
+/* be applied when restoring the context. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 12-31-2020 Cadence Design Systems Initial Version 6.1.3 */
+/* */
+/**************************************************************************/
+
+
+#include <xtensa/config/core.h>
+#include <xtensa/coreasm.h>
+
+#if XCHAL_HAVE_XEA3
+
+#include "xtensa_context.h"
+
+#if (XCHAL_HW_VERSION < XTENSA_HWVERSION_RH_2016_2)
+#error Xtensa HW earlier than RH_2016.2 not supported.
+#endif
+
+
+//-----------------------------------------------------------------------------
+// The entry point vectors are common for call0 and windowed configurations.
+//-----------------------------------------------------------------------------
+
+ .extern _DoubleExceptionHandler
+ .extern _xtos_exc_dispatch
+
+ .section .DispatchVector.text, "ax"
+#if XCHAL_HAVE_VECBASE
+ .align 64 // 64-byte alignment needed when vecbase
+#else // is relocatable
+ .align 4
+#endif
+
+ .org 0 // Fixed offset for Reset Vector
+ .global _DispatchVector
+ .weak _DispatchVector
+
+_DispatchVector:
+ j _JumpToResetHandler
+
+ .org 3 // Reserved
+ .local _Reserved1
+
+_Reserved1:
+ ill
+
+ .org 6 // Fixed offset for Double Exception Vector
+ .global _DoubleExceptionVector
+ .weak _DoubleExceptionVector
+
+_DoubleExceptionVector:
+ j _DoubleExceptionHandler
+
+ .org 9 // Reserved
+ .local _Reserved2
+
+_Reserved2:
+ ill
+
+//-----------------------------------------------------------------------------
+// Start of dispatch code.
+//-----------------------------------------------------------------------------
+
+ .org 12 // Fixed offset for Tailchain entry point
+ .global _xt_dispatch
+
+_xt_dispatch:
+#ifdef __XTENSA_CALL0_ABI__
+
+ // NOTE: for call0, a15 is expected to be holding the previous stack pointer
+ // when we get to the Tailchain segment.
+
+ s32si.x4 a2, a15 // Select interrupt, a2 <- (intnum << 2)
+ movi a0, 0
+ l32dis.it a0, a0 // a0 <- wrapper addr (handler_table[0])
+ s32stk a9, a15, 96 // Set new stack pointer
+#if XT_STK_XTRA_SZ
+ addi a1, a1, -XT_STK_XTRA_SZ // Adjust for extra save area
+#endif
+ s32dis.h a0, a0 // Jump to handler if interrupt else fall through
+ // Note this also clears local exclusive monitor
+
+#else // windowed
+
+ s32si.x4 a10, a1 // Select interrupt, a10 <- (intnum << 2)
+ movi a8, 0
+ l32dis.it a8, a8 // a8 <- wrapper addr (handler_table[0])
+ s32stk a9, a1, 96 // Set new stack pointer
+#if XT_STK_XTRA_SZ
+ addi a9, a9, -XT_STK_XTRA_SZ // Adjust for extra save area
+#endif
+ s32dis.h a8, a8 // Jump to handler if interrupt else fall through
+ // Note this also clears local exclusive monitor
+
+#endif // __XTENSA_CALL0_ABI__
+
+.Lexit:
+ j _xt_exit
+
+#ifndef __XTENSA_CALL0_ABI__
+ .org 36 // Fixed offset for Underflow segment
+ .global _xt_underflow
+
+_xt_underflow:
+ l32e a8, a1, -64 // a8 <- [a1-32]
+ l32e a9, a1, -64 // a9 <- [a1-28]
+ l32e a10, a1, -64 // a10 <- [a1-24]
+ l32e a11, a1, -64 // a11 <- [a1-20]
+ l32e a12, a1, -64 // a12 <- [a1-16]
+ l32e a13, a1, -64 // a13 <- [a1-12]
+ l32e a14, a1, -64 // a14 <- [a1-8]
+ l32e a15, a1, -64 // a15 <- [a1-4] ; Return (branch to EPC)
+#endif
+
+ .org 60 // Fixed offset for Save/Overflow segment
+ .global _xt_save
+
+_xt_save:
+#ifdef __XTENSA_CALL0_ABI__
+ s32e a0, a1, -64 // [a1-64] <- a0
+ s32e a2, a1, -48 // [a1-56] <- a2 ; a2 <- EPC
+ s32e a3, a1, -64 // [a1-52] <- a3
+ s32e a4, a1, -64 // [a1-48] <- a4
+ s32e a5, a1, -64 // [a1-44] <- a5
+ s32e a6, a1, -64 // [a1-40] <- a6
+ s32e a7, a1, -64 // [a1-36] <- a7
+#else
+ .global _xt_overflow
+_xt_overflow:
+#endif
+ s32e a8, a1, -52 // [a1-32] <- a8 ; a8 <- ExcVAddr
+ s32e a9, a1, -28 // [a1-28] <- a9 ; a9 <- PS/SAR
+ s32e a10, a1, -48 // [a1-24] <- a10 ; a10 <- EPC
+ s32e a11, a1, -24 // [a1-20] <- a11 ; a11 <- ExcCause
+ s32e a12, a1, -44 // [a1-16] <- a12 ; a12 <- LBEG
+ s32e a13, a1, -40 // [a1-12] <- a13 ; a13 <- LEND
+ s32e a14, a1, -36 // [a1-8] <- a14 ; a14 <- LCOUNT
+ s32e a15, a1, -32 // [a1-4] <- a15 ; a15 <- a1
+ // If Overflow then return (branch to EPC)
+
+_xt_entry:
+ s32e a8, a1, -4 // [a1-68] <- a8 (ExcVAddr)
+ s32e a11, a1, -8 // [a1-72] <- a11 (ExcCause)
+#if XCHAL_HAVE_LOOPS
+ s32e a12, a1, -20 // [a1-84] <- a12 (LBEG)
+ s32e a13, a1, -24 // [a1-88] <- a13 (LEND)
+ s32e a14, a1, -28 // [a1-92] <- a14 (LCOUNT)
+#endif
+#if XCHAL_HAVE_EXCLUSIVE
+ movi a12, 0
+ getex a12
+ s32e a12, a1, -32 // [a1-96] <- a12 (ATOMCTL)
+#endif
+
+ j 1f // make room for literals
+
+ .align 4
+ .literal_position
+
+.Le1:
+ .word _xt_exception_table
+
+1:
+ // Call OS-specific code for additional work to be done. Stay on interruptee's
+ // stack in case more saves are required into stack frame.
+ // NOTE: OS-specific code can use a8, a12-a14, (+a2-a7: call0, a15: windowed).
+ // ALL other registers must be preserved.
+
+ XT_RTOS_INT_ENTER
+
+ // This sequence checks the interrupt controller and loads the interrupt
+ // number if available, and also loads the wrapper handler address.
+ // If there is an interrupt, execution will branch to the wrapper which
+ // will then forward to the correct handler.
+ // All this happens only if there is a pending interrupt. If not, execution
+ // falls through to exception handling.
+
+#ifdef __XTENSA_CALL0_ABI__
+
+ s32si.x4 a2, a1 // [a1-80] <- a2 (EPC) ; a2 <- (intnum << 2)
+ movi a0, 0
+ l32dis.it a0, a0 // a0 <- wrapper addr (handler_table[0])
+ s32stk a9, a1, 96 // [a1-76] <- a9 (PS/SAR) ; a1 = a1-96
+#if XT_STK_XTRA_SZ
+ addi a1, a1, -XT_STK_XTRA_SZ // Adjust for extra save area
+#endif
+ s32dis.h a0, a0 // Jump to handler if interrupt else fall through
+
+#else // windowed
+
+ s32si.x4 a10, a1 // [a1-80] <- a10 (EPC) ; a10 <- (intnum << 2)
+ movi a8, 0
+ l32dis.it a8, a8 // a8 <- wrapper addr (handler_table[0])
+ s32stk a9, a1, 96 // [a1-76] <- a9 (PS/SAR) ; a9 = a1-96
+#if XT_STK_XTRA_SZ
+ addi a9, a9, -XT_STK_XTRA_SZ // Adjust for extra save area
+#endif
+ s32dis.h a8, a8 // Jump to handler if interrupt else fall through
+
+#endif // __XTENSA_CALL0_ABI__
+
+ // At this point we have:
+ // (note window has rotated for windowed ABI)
+ // a0 holds return address (Tailchain+3)
+ // For call0:
+ // a11 holds ExcCause, also saved in [oldsp - 72]
+ // a15 holds exception SP, a1 points to exception frame
+ // For windowed:
+ // a3 holds ExcCause, also saved in [oldsp - 72]
+ // a1 points to exception frame
+
+ .global _xt_exception
+
+_xt_exception:
+ l32r a2, .Le1 // Load exc table address
+#ifdef __XTENSA_CALL0_ABI__
+ mov a3, a11 // Copy exception cause to a3
+#endif
+ extui a4, a3, 0, 4 // Extract exception cause
+ addx4 a2, a4, a2 // Index into exc table
+ l32i a4, a2, 0 // Load handler address
+#if XT_STK_XTRA_SZ
+ addi a2, a1, XT_STK_XTRA_SZ // Argument = Exception frame ptr
+#else
+ mov a2, a1 // Argument = Exception frame ptr
+#endif
+ jx a4 // Return directly from handler
+
+ // Exit/restore sequence
+
+ .global _xt_exit
+
+_xt_exit:
+#ifdef __XTENSA_CALL0_ABI__
+ mov a1, a15 // Restore stack pointer
+#endif
+
+ // Run OS-specific code to determine what to restore.
+ // Interrupts will remain disabled through this sequence.
+ // WARNING: stack pointer may change within this macro
+ // so all restores off the stack must happen afterwards.
+
+ XT_RTOS_INT_EXIT
+
+ .global _xt_restore
+
+_xt_restore:
+ // Some loads must happen before DISPST = Restore, as these
+ // will not be accessible via L32E once DISPST = Restore.
+
+#if XCHAL_HAVE_EXCLUSIVE
+ l32e a12, a1, -32 // a12 <- [a1-96] (ATOMCTL)
+ getex a12
+#endif
+ l32e a10, a1, -12 // a10 <- [a1-76] (PS/SAR)
+ l32e a12, a1, -20 // a12 <- [a1-84] (LBEG)
+ l32e a13, a1, -24 // a13 <- [a1-88] (LEND)
+ l32e a14, a1, -28 // a14 <- [a1-92] (LCOUNT)
+ l32dis.epc a11, a1 // a11 <- [a1-80] (EPC)
+ // If interrupt goto tailchain else fall through
+
+#ifdef __XTENSA_CALL0_ABI__
+ l32e a0, a1, -64 // a0 <- [a1-64]
+ l32e a2, a1, -64 // a2 <- [a1-56]
+ l32e a3, a1, -64 // a3 <- [a1-52]
+ l32e a4, a1, -64 // a4 <- [a1-48]
+ l32e a5, a1, -64 // a5 <- [a1-44]
+ l32e a6, a1, -64 // a6 <- [a1-40]
+ l32e a7, a1, -64 // a7 <- [a1-36]
+#endif
+
+ // Important: the following restrictions must be observed:
+ // 1) The LCOUNT register must be restored after LBEG/LEND.
+ // 2) There must be at least 3 instructions between the LCOUNT
+ // restore and the last L32E (the one that branches).
+
+ l32e a12, a1, -44 // LBEG <- a12, a12 <- [a1-16]
+ l32e a13, a1, -40 // LEND <- a13, a13 <- [a1-12]
+ l32e a14, a1, -36 // LCOUNT <- a14, a14 <- [a1-8]
+ l32e a8, a1, -64 // a8 <- [a1-32]
+ l32e a9, a1, -64 // a9 <- [a1-28]
+ l32e a10, a1, -60 // PS/SAR <- a10, a10 <- [a1-24]
+ l32e a11, a1, -48 // EPC <- a11, a11 <- [a1-20]
+ l32e a15, a1, -64 // a15 <- [a1-4], Branch to EPC if no interrupt
+ // If interrupt, branch to Tailchain
+
+
+//-----------------------------------------------------------------------------
+// Branch to reset handler code from here. Use CALL0 as a branch, will expand
+// to CALLX0 if needed when built with the -mlongcalls option.
+//-----------------------------------------------------------------------------
+
+ .align 4
+ .local _JumpToResetHandler
+
+_JumpToResetHandler:
+ call0 _ResetHandler
+
+
+//-----------------------------------------------------------------------------
+// Idle loop. On interrupt, no state needs saving.
+//-----------------------------------------------------------------------------
+
+ .align 4
+ .global _xt_idle
+
+_xt_idle:
+ movi a14, _xt_interrupt_stack_top
+ mov a1, a14 // a1 <- Top of interrupt stack
+ movi a14, 0 // 0 = Normal
+ wsr.ms a14 // Set DISPST = Normal
+ rsync
+ waiti 0 // Wait for interrupt
+ memw // HW erratum 569
+
+
+//-----------------------------------------------------------------------------
+// Scheduler interrupt handler. Triggered by context switch. At this time only
+// useful for windowed ABI to spill register windows.
+//-----------------------------------------------------------------------------
+
+ .align 4
+ .global xt_sched_handler
+
+xt_sched_handler:
+#ifdef __XTENSA_WINDOWED_ABI__
+ entry a1, 32
+ ssai 1
+ spillw
+ retw
+#else
+ ret
+#endif
+
+#endif // XCHAL_HAVE_XEA3
+